feat(项目管理): 环境管理环境页面接口对接
This commit is contained in:
parent
222a6901f4
commit
a6c8adf1e4
|
@ -0,0 +1,69 @@
|
||||||
|
import MSR from '@/api/http/index';
|
||||||
|
import * as envURL from '@/api/requrls/project-management/envManagement';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
EnvDetailItem,
|
||||||
|
EnvGroupListItem,
|
||||||
|
EnvGroupProjectListItem,
|
||||||
|
EnvListItem,
|
||||||
|
} from '@/models/projectManagement/environmental';
|
||||||
|
import { OptionsItem } from '@/models/setting/log';
|
||||||
|
|
||||||
|
export function updateEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.updateEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function listEnv(data: { projectId: string; keyword: string }) {
|
||||||
|
return MSR.post<EnvListItem[]>({ url: envURL.listEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function importEnv(data: { request: EnvListItem; fileList: File[] }) {
|
||||||
|
return MSR.uploadFile({ url: envURL.importEnvUrl }, data, '', true);
|
||||||
|
}
|
||||||
|
export function getEntryEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.getEntryEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function exportEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.exportEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function editPosEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.editPosEnvUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 测试数据库连接 */
|
||||||
|
export function validateDatabaseEnv(data: object) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.validateDatabaseEnvUrl, data });
|
||||||
|
}
|
||||||
|
/** 获取数据库驱动option */
|
||||||
|
export function driverOptionFun(organizationId: string) {
|
||||||
|
return MSR.get<OptionsItem[]>({ url: envURL.driverOptionUrl + organizationId });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.addEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function getDetailEnv(id: string) {
|
||||||
|
return MSR.get<EnvDetailItem>({ url: envURL.detailEnvUrl + id });
|
||||||
|
}
|
||||||
|
export function deleteEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.deleteEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function groupUpdateEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.groupUpdateEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function groupListEnv(data: EnvGroupListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.groupListEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function groupEditPosEnv(data: EnvGroupListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.groupEditPosEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function groupAddEnv(data: EnvGroupListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.groupAddEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function groupDetailEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.groupDetailEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function groupDeleteEnv(data: EnvListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.groupDeleteEnvUrl, data });
|
||||||
|
}
|
||||||
|
export function groupProjectEnv(data: EnvGroupProjectListItem) {
|
||||||
|
return MSR.post<EnvListItem>({ url: envURL.groupProjectEnvUrl, data });
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
export const updateEnvUrl = '/project/environment/update';
|
||||||
|
export const listEnvUrl = '/project/environment/list';
|
||||||
|
export const importEnvUrl = '/project/environment/import';
|
||||||
|
export const getEntryEnvUrl = '/project/environment/get/entry';
|
||||||
|
export const exportEnvUrl = '/project/environment/export';
|
||||||
|
export const editPosEnvUrl = '/project/environment/edit/pos';
|
||||||
|
export const validateDatabaseEnvUrl = '/project/environment/database/validate';
|
||||||
|
export const addEnvUrl = '/project/environment/add';
|
||||||
|
export const detailEnvUrl = '/project/environment/get/';
|
||||||
|
export const deleteEnvUrl = '/project/environment/delete/';
|
||||||
|
export const driverOptionUrl = '/project/environment/database/driver-options/';
|
||||||
|
export const groupUpdateEnvUrl = '/project/environment/group/update';
|
||||||
|
export const groupListEnvUrl = '/project/environment/group/list';
|
||||||
|
export const groupEditPosEnvUrl = '/project/environment/group/edit/pos';
|
||||||
|
export const groupAddEnvUrl = '/project/environment/group/add';
|
||||||
|
export const groupDetailEnvUrl = '/project/environment/group/get/';
|
||||||
|
export const groupDeleteEnvUrl = '/project/environment/group/delete/';
|
||||||
|
export const groupProjectEnvUrl = '/project/environment/group/get-project';
|
|
@ -0,0 +1,22 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-[8px]">
|
||||||
|
<div class="flex flex-row items-center gap-[8px]">
|
||||||
|
<span class="text-[var(--color-text-1)]">{{ t('ms.assertion.responseTime') }}</span>
|
||||||
|
<span class="text-[var(--color-text-4)]">(ms)</span>
|
||||||
|
</div>
|
||||||
|
<a-input-number v-model:model-value="value" :step="100" mode="button" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const value = defineModel('modelValue', {
|
||||||
|
default: 1000,
|
||||||
|
type: Number,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -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.variableName', // 变量名
|
||||||
|
dataIndex: 'name',
|
||||||
|
slotName: 'name',
|
||||||
|
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: 'value',
|
||||||
|
slotName: 'value',
|
||||||
|
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>
|
|
@ -8,15 +8,19 @@
|
||||||
</div>
|
</div>
|
||||||
</a-button>
|
</a-button>
|
||||||
<template #content>
|
<template #content>
|
||||||
<a-doption v-for="item in assertOption" :key="item.value" :value="item.value">{{ item.label }}</a-doption>
|
<a-doption v-for="item in assertOptionSource" :key="item.value" :value="item.value">{{ item.label }}</a-doption>
|
||||||
</template>
|
</template>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
<div v-if="showBody" class="ms-assertion-body">
|
<div v-if="showBody" class="ms-assertion-body">
|
||||||
<article class="ms-assertion-body-left">
|
<VueDraggable v-model="selectItems" class="ms-assertion-body-left" ghost-class="ghost" handle=".sort-handle">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in activeOption"
|
v-for="(item, index) in selectItems"
|
||||||
:key="item.value"
|
:key="item.id"
|
||||||
class="ms-assertion-body-left-item"
|
class="ms-assertion-body-left-item"
|
||||||
|
:class="{
|
||||||
|
'ms-assertion-body-left-item-active': activeKey === item.id,
|
||||||
|
'ms-assertion-body-left-item-active-focus': focusKey === item.id,
|
||||||
|
}"
|
||||||
@click="handleItemClick(item)"
|
@click="handleItemClick(item)"
|
||||||
>
|
>
|
||||||
<div class="ms-assertion-body-left-item-row">
|
<div class="ms-assertion-body-left-item-row">
|
||||||
|
@ -24,38 +28,92 @@
|
||||||
<span class="ms-assertion-body-left-item-row-title">{{ item.label }}</span>
|
<span class="ms-assertion-body-left-item-row-title">{{ item.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-assertion-body-left-item-switch">
|
<div class="ms-assertion-body-left-item-switch">
|
||||||
|
<div class="ms-assertion-body-left-item-switch-action">
|
||||||
|
<MsIcon
|
||||||
|
type="icon-icon_drag"
|
||||||
|
class="action-btn-move sort-handle cursor-move text-[12px] text-[var(--color-text-4)]"
|
||||||
|
/>
|
||||||
|
<MsTableMoreAction
|
||||||
|
:list="itemMoreActions"
|
||||||
|
trigger="click"
|
||||||
|
@select="handleMoreActionSelect($event, item)"
|
||||||
|
@close="focusKey = ''"
|
||||||
|
>
|
||||||
|
<MsButton type="icon" size="mini" class="action-btn-more">
|
||||||
|
<MsIcon
|
||||||
|
type="icon-icon_more_outlined"
|
||||||
|
size="14"
|
||||||
|
class="text-[var(--color-text-4)]"
|
||||||
|
@click="focusKey = item.id"
|
||||||
|
/>
|
||||||
|
</MsButton>
|
||||||
|
</MsTableMoreAction>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a-switch type="line" size="small" />
|
<a-switch type="line" size="small" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</VueDraggable>
|
||||||
<section class="ms-assertion-body-right">
|
<section class="ms-assertion-body-right">
|
||||||
<MsAssertionStatusCodeTab
|
<StatusCodeTab
|
||||||
v-if="activeKey === 'statusCode'"
|
v-if="valueKey === 'statusCode'"
|
||||||
v-model:selectValue="codeTabState.selectValue"
|
v-model:selectValue="codeTabState.selectValue"
|
||||||
v-model:statusCode="codeTabState.statusCode"
|
v-model:statusCode="codeTabState.statusCode"
|
||||||
/>
|
/>
|
||||||
<ResponseHeaderTab v-if="activeKey === 'responseHeader'" />
|
<ResponseHeaderTab v-if="valueKey === 'responseHeader'" />
|
||||||
|
<ResponseTimeTab v-if="valueKey === 'responseTime'" />
|
||||||
|
<VariableTab v-if="valueKey === 'variable'" />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { VueDraggable } from 'vue-draggable-plus';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import ResponseHeaderTab from './comp/ResponseHeaderTab.vue';
|
import ResponseHeaderTab from './comp/ResponseHeaderTab.vue';
|
||||||
import MsAssertionStatusCodeTab from './comp/StatusCodeTab.vue';
|
import ResponseTimeTab from './comp/ResponseTimeTab.vue';
|
||||||
|
import StatusCodeTab from './comp/StatusCodeTab.vue';
|
||||||
|
import VariableTab from './comp/VariableTab.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { MsAssertionItem } from './type';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MsAssertion',
|
name: 'MsAssertion',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
// 当前鼠标所在的key
|
||||||
|
const focusKey = ref<string>('');
|
||||||
|
// 选中的选项
|
||||||
|
const selectItems = ref<MsAssertionItem[]>([]);
|
||||||
|
// Item点击的key
|
||||||
|
const activeKey = ref<string>('');
|
||||||
|
// valueKey
|
||||||
|
const valueKey = computed(() => {
|
||||||
|
return activeKey.value && selectItems.value.find((item) => item.id === activeKey.value)?.value;
|
||||||
|
});
|
||||||
|
|
||||||
const codeTabState = reactive({
|
const codeTabState = reactive({
|
||||||
selectValue: '',
|
selectValue: '',
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
});
|
});
|
||||||
|
const itemMoreActions: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'common.copy',
|
||||||
|
eventTag: 'copy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'project.fileManagement.delete',
|
||||||
|
eventTag: 'delete',
|
||||||
|
},
|
||||||
|
];
|
||||||
// 源选项
|
// 源选项
|
||||||
const assertOptionSource = [
|
const assertOptionSource = [
|
||||||
{
|
{
|
||||||
|
@ -76,37 +134,53 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.assertion.param'),
|
label: t('ms.assertion.param'),
|
||||||
value: 'param',
|
value: 'variable',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('ms.assertion.script'),
|
label: t('ms.assertion.script'),
|
||||||
value: 'script',
|
value: 'script',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
// 选中的选项
|
|
||||||
const selectIds = ref<string[]>([]);
|
|
||||||
// Item点击的key
|
|
||||||
const activeKey = ref<string>('');
|
|
||||||
|
|
||||||
// 未选中的选项
|
|
||||||
const assertOption = computed(() => {
|
|
||||||
return assertOptionSource.filter((item) => !selectIds.value.includes(item.value));
|
|
||||||
});
|
|
||||||
// 选中的选项
|
|
||||||
const activeOption = computed(() => {
|
|
||||||
return assertOptionSource.filter((item) => selectIds.value.includes(item.value));
|
|
||||||
});
|
|
||||||
// 是否显示主体
|
// 是否显示主体
|
||||||
const showBody = computed(() => {
|
const showBody = computed(() => {
|
||||||
return selectIds.value.length > 0;
|
return selectItems.value.length > 0;
|
||||||
});
|
});
|
||||||
// dropdown选择
|
// 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);
|
const tmpObj = {
|
||||||
|
label: assertOptionSource.find((item) => item.value === value)?.label || '',
|
||||||
|
value: value as string,
|
||||||
|
id: new Date().getTime().toString(),
|
||||||
};
|
};
|
||||||
|
if (activeKey.value) {
|
||||||
|
const currentIndex = selectItems.value.findIndex((item) => item.id === activeKey.value);
|
||||||
|
const tmpArr = selectItems.value;
|
||||||
|
tmpArr.splice(currentIndex, 0, tmpObj);
|
||||||
|
selectItems.value = tmpArr;
|
||||||
|
} else {
|
||||||
|
selectItems.value.push(tmpObj);
|
||||||
|
}
|
||||||
|
activeKey.value = tmpObj.id;
|
||||||
|
};
|
||||||
|
const handleMoreActionSelect = (event: ActionsItem, item: MsAssertionItem) => {
|
||||||
|
const currentIndex = selectItems.value.findIndex((tmpItem) => tmpItem.id === item.id);
|
||||||
|
if (event.eventTag === 'delete') {
|
||||||
|
selectItems.value.splice(currentIndex, 1);
|
||||||
|
activeKey.value = currentIndex > 0 ? selectItems.value[currentIndex - 1].id : '';
|
||||||
|
} else {
|
||||||
|
// copy 当前item
|
||||||
|
const tmpObj = { ...selectItems.value[currentIndex], id: new Date().getTime().valueOf().toString() };
|
||||||
|
const tmpArr = selectItems.value;
|
||||||
|
tmpArr.splice(currentIndex, 0, tmpObj);
|
||||||
|
selectItems.value = tmpArr;
|
||||||
|
activeKey.value = tmpObj.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// item点击
|
// item点击
|
||||||
const handleItemClick = (item: { label: string; value: string }) => {
|
const handleItemClick = (item: MsAssertionItem) => {
|
||||||
activeKey.value = item.value;
|
activeKey.value = item.id;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -153,12 +227,23 @@
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
}
|
}
|
||||||
&-title {
|
&-title {
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&-switch {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
&-action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&-right {
|
&-right {
|
||||||
|
@ -171,4 +256,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.action-btn-move,
|
||||||
|
.action-btn-more {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
.ms-assertion-body-left-item-active {
|
||||||
|
background-color: rgb(var(--primary-1)) !important;
|
||||||
|
.ms-assertion-body-left-item-row {
|
||||||
|
&-num {
|
||||||
|
color: rgb(var(--primary-5)) !important;
|
||||||
|
background-color: var(--color-text-fff) !important;
|
||||||
|
}
|
||||||
|
&-title {
|
||||||
|
color: rgb(var(--primary-5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ms-assertion-body-left-item:hover {
|
||||||
|
background-color: rgb(var(--primary-1));
|
||||||
|
.action-btn-move,
|
||||||
|
.action-btn-more {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ms-assertion-body-left-item-active-focus {
|
||||||
|
background-color: rgb(var(--primary-1));
|
||||||
|
.action-btn-move,
|
||||||
|
.action-btn-more {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -9,4 +9,5 @@ export default {
|
||||||
'ms.assertion.noValidation': '不校验',
|
'ms.assertion.noValidation': '不校验',
|
||||||
'ms.assertion.matchCondition': '匹配条件',
|
'ms.assertion.matchCondition': '匹配条件',
|
||||||
'ms.assertion.matchValue': '匹配值',
|
'ms.assertion.matchValue': '匹配值',
|
||||||
|
'ms.assertion.variableName': '变量名',
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface MsAssertionItem {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { key } from 'localforage';
|
||||||
|
|
||||||
export interface EnvListItem {
|
export interface EnvListItem {
|
||||||
name: string;
|
name: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -14,3 +16,37 @@ export interface EnvGroupListItem {
|
||||||
id: string;
|
id: string;
|
||||||
projectList: EnvGroupProjectListItem[];
|
projectList: EnvGroupProjectListItem[];
|
||||||
}
|
}
|
||||||
|
export interface DataSourceItem {
|
||||||
|
id?: string;
|
||||||
|
name: string;
|
||||||
|
driverId?: string;
|
||||||
|
dbUrl: string;
|
||||||
|
username: string;
|
||||||
|
password?: string;
|
||||||
|
poolMax?: number;
|
||||||
|
timeout?: number;
|
||||||
|
enable?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EnvConfigItem {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
export interface EnvConfig {
|
||||||
|
commonParams?: EnvConfigItem;
|
||||||
|
commmonVariables?: EnvConfigItem[];
|
||||||
|
httpConfig?: EnvConfigItem[];
|
||||||
|
dataSource?: DataSourceItem[];
|
||||||
|
hostConfig?: EnvConfigItem;
|
||||||
|
authConfig?: EnvConfigItem;
|
||||||
|
preScript?: EnvConfigItem;
|
||||||
|
postScript?: EnvConfigItem;
|
||||||
|
assertions?: EnvConfigItem;
|
||||||
|
}
|
||||||
|
export interface EnvDetailItem {
|
||||||
|
id?: string;
|
||||||
|
projectId: string;
|
||||||
|
name: string;
|
||||||
|
config: EnvConfig;
|
||||||
|
mock?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import { EnvGroupListItem } from '@/models/projectManagement/environmental';
|
import { getDetailEnv } from '@/api/modules/project-management/envManagement';
|
||||||
|
|
||||||
|
import { EnvDetailItem, EnvGroupListItem } from '@/models/projectManagement/environmental';
|
||||||
|
|
||||||
export const ALL_PARAM = 'allParam';
|
export const ALL_PARAM = 'allParam';
|
||||||
|
export const NEW_ENV_PARAM = 'newEnvParam';
|
||||||
|
|
||||||
const useProjectEnvStore = defineStore(
|
const useProjectEnvStore = defineStore(
|
||||||
'projectEnv',
|
'projectEnv',
|
||||||
() => {
|
() => {
|
||||||
const currentId = ref<string | number>(1);
|
const currentId = ref<string>('');
|
||||||
|
const currentEnvDetailInfo = ref<EnvDetailItem>();
|
||||||
const httpNoWarning = ref(true);
|
const httpNoWarning = ref(true);
|
||||||
const envGroupList = ref<EnvGroupListItem[]>([]);
|
const envGroupList = ref<EnvGroupListItem[]>([]);
|
||||||
|
|
||||||
|
@ -16,22 +20,41 @@ const useProjectEnvStore = defineStore(
|
||||||
const getGroupLength = computed(() => 1);
|
const getGroupLength = computed(() => 1);
|
||||||
|
|
||||||
const getDatabaseList = computed(() => [{ id: 1, name: 'test' }]);
|
const getDatabaseList = computed(() => [{ id: 1, name: 'test' }]);
|
||||||
function setCurrentId(id: string | number) {
|
function setCurrentId(id: string) {
|
||||||
currentId.value = id;
|
currentId.value = id;
|
||||||
}
|
}
|
||||||
function setHttpNoWarning(noWarning: boolean) {
|
function setHttpNoWarning(noWarning: boolean) {
|
||||||
httpNoWarning.value = noWarning;
|
httpNoWarning.value = noWarning;
|
||||||
}
|
}
|
||||||
|
function setEnvDetailInfo(item: EnvDetailItem) {
|
||||||
|
currentEnvDetailInfo.value = item;
|
||||||
|
}
|
||||||
|
async function initEnvDetail() {
|
||||||
|
const id = currentId.value;
|
||||||
|
try {
|
||||||
|
if (id === NEW_ENV_PARAM) {
|
||||||
|
currentEnvDetailInfo.value = undefined;
|
||||||
|
} else if (id !== ALL_PARAM && id) {
|
||||||
|
currentEnvDetailInfo.value = await getDetailEnv(id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getCurrentId,
|
getCurrentId,
|
||||||
currentId,
|
currentId,
|
||||||
httpNoWarning,
|
httpNoWarning,
|
||||||
setCurrentId,
|
setCurrentId,
|
||||||
setHttpNoWarning,
|
setHttpNoWarning,
|
||||||
|
setEnvDetailInfo,
|
||||||
getHttpNoWarning,
|
getHttpNoWarning,
|
||||||
getDatabaseList,
|
getDatabaseList,
|
||||||
envGroupList,
|
envGroupList,
|
||||||
getGroupLength,
|
getGroupLength,
|
||||||
|
initEnvDetail,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -183,17 +183,17 @@
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #responseHeader="{ record, columnConfig }">
|
<template #responseHeader="{ record, columnConfig }">
|
||||||
<a-select v-model="record.responseHeader" @change="(val) => addTableLine(val as string)">
|
<a-select v-model="record.responseHeader" class="param-input" @change="(val) => addTableLine(val as string)">
|
||||||
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
|
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</template>
|
</template>
|
||||||
<template #matchCondition="{ record, columnConfig }">
|
<template #matchCondition="{ record, columnConfig }">
|
||||||
<a-select v-model="record.condition" @change="(val) => addTableLine(val as string)">
|
<a-select v-model="record.condition" class="param-input" @change="(val) => addTableLine(val as string)">
|
||||||
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
|
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</template>
|
</template>
|
||||||
<template #matchValue="{ record }">
|
<template #matchValue="{ record }">
|
||||||
<a-input-number v-model="record.matchValue" hide-button @change="(val) => addTableLine(val)" />
|
<a-input v-model="record.matchValue" class="param-input" @change="(val) => addTableLine(val)" />
|
||||||
</template>
|
</template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
<a-modal
|
<a-modal
|
||||||
|
|
|
@ -54,12 +54,17 @@
|
||||||
import TcpTab from './envParams/TcpTab.vue';
|
import TcpTab from './envParams/TcpTab.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { useAppStore } from '@/store';
|
||||||
|
import useProjectEnvStore, { NEW_ENV_PARAM } from '@/store/modules/setting/useProjectEnvStore';
|
||||||
|
|
||||||
const activeKey = ref('tcp');
|
const activeKey = ref('assert');
|
||||||
const envForm = ref();
|
const envForm = ref();
|
||||||
const canSave = ref(false);
|
const canSave = ref(false);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const store = useProjectEnvStore();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
name: '',
|
name: '',
|
||||||
});
|
});
|
||||||
|
@ -112,6 +117,20 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const initData = async () => {
|
||||||
|
await store.initEnvDetail();
|
||||||
|
};
|
||||||
|
watchEffect(() => {
|
||||||
|
if (store.currentId === NEW_ENV_PARAM) {
|
||||||
|
store.setEnvDetailInfo({
|
||||||
|
name: '',
|
||||||
|
projectId: appStore.currentProjectId,
|
||||||
|
config: {},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -21,7 +21,12 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
<AddDatabaseModal v-model:visible="addVisible" :current-id="currentId" @close="addVisible = false" />
|
<AddDatabaseModal
|
||||||
|
v-model:visible="addVisible"
|
||||||
|
v-model="currentDatabase"
|
||||||
|
:current-id="currentId"
|
||||||
|
@close="addVisible = false"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" async setup>
|
<script lang="ts" async setup>
|
||||||
|
@ -40,6 +45,7 @@
|
||||||
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
|
import useProjectEnvStore from '@/store/modules/setting/useProjectEnvStore';
|
||||||
|
|
||||||
import { BugListItem } from '@/models/bug-management';
|
import { BugListItem } from '@/models/bug-management';
|
||||||
|
import { DataSourceItem } from '@/models/projectManagement/environmental';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -51,6 +57,18 @@
|
||||||
const addVisible = ref(false);
|
const addVisible = ref(false);
|
||||||
const currentId = ref('');
|
const currentId = ref('');
|
||||||
|
|
||||||
|
const currentDatabase = ref<DataSourceItem>({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
driverId: '',
|
||||||
|
dbUrl: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
poolMax: 1,
|
||||||
|
timeout: 1000,
|
||||||
|
enable: true,
|
||||||
|
});
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
title: 'project.environmental.database.name',
|
title: 'project.environmental.database.name',
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<template #title>
|
<template #title>
|
||||||
<span v-if="isEdit">
|
<span v-if="isEdit">
|
||||||
{{ t('project.environmental.database.updateDatabase') }}
|
{{ t('project.environmental.database.updateDatabase') }}
|
||||||
<span class="text-[var(--color-text-4)]">({{ props.currentProject?.name }})</span>
|
<span class="text-[var(--color-text-4)]">({{ form.name }})</span>
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ t('project.environmental.database.addDatabase') }}
|
{{ t('project.environmental.database.addDatabase') }}
|
||||||
|
@ -26,20 +26,18 @@
|
||||||
>
|
>
|
||||||
<a-input v-model="form.name" allow-clear :placeholder="t('project.environmental.database.namePlaceholder')" />
|
<a-input v-model="form.name" allow-clear :placeholder="t('project.environmental.database.namePlaceholder')" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="driver" asterisk-position="end" :label="t('project.environmental.database.driver')">
|
<a-form-item field="driverId" asterisk-position="end" :label="t('project.environmental.database.driver')">
|
||||||
<a-select v-model="form.driver">
|
<a-select v-model="form.driverId" :options="driverOption" />
|
||||||
<a-option value="mysql">MySQL</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="url"
|
field="dbUrl"
|
||||||
required
|
required
|
||||||
:label="t('project.environmental.database.url')"
|
:label="t('project.environmental.database.url')"
|
||||||
asterisk-position="end"
|
asterisk-position="end"
|
||||||
:extra="t('project.environmental.database.urlExtra')"
|
:extra="t('project.environmental.database.urlExtra')"
|
||||||
:rules="[{ required: true, message: t('project.environmental.database.urlIsRequire') }]"
|
:rules="[{ required: true, message: t('project.environmental.database.urlIsRequire') }]"
|
||||||
>
|
>
|
||||||
<a-input v-model="form.url" allow-clear :placeholder="t('common.pleaseInput')" />
|
<a-input v-model="form.dbUrl" allow-clear :placeholder="t('common.pleaseInput')" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="username"
|
field="username"
|
||||||
|
@ -48,10 +46,16 @@
|
||||||
asterisk-position="end"
|
asterisk-position="end"
|
||||||
:rules="[{ required: true, message: t('project.environmental.database.usernameIsRequire') }]"
|
:rules="[{ required: true, message: t('project.environmental.database.usernameIsRequire') }]"
|
||||||
>
|
>
|
||||||
<a-input v-model="form.username" allow-clear :placeholder="t('common.pleaseInput')" />
|
<a-input
|
||||||
|
v-model="form.username"
|
||||||
|
:max-length="255"
|
||||||
|
show-word-limit
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.pleaseInput')"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="password" :label="t('project.environmental.database.password')">
|
<a-form-item field="password" :label="t('project.environmental.database.password')">
|
||||||
<a-input
|
<a-input-password
|
||||||
v-model="form.password"
|
v-model="form.password"
|
||||||
:placeholder="t('common.pleaseInput')"
|
:placeholder="t('common.pleaseInput')"
|
||||||
allow-clear
|
allow-clear
|
||||||
|
@ -59,12 +63,25 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="poolMax" :label="t('project.environmental.database.poolMax')">
|
<a-form-item field="poolMax" :label="t('project.environmental.database.poolMax')">
|
||||||
<a-input-number v-model:model-value="form.poolMax" :min="1" :default-value="1" />
|
<a-input-number
|
||||||
|
v-model:model-value="form.poolMax"
|
||||||
|
class="w-[152px]"
|
||||||
|
mode="button"
|
||||||
|
:min="1"
|
||||||
|
:default-value="1"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="timeout" :label="t('project.environmental.database.timeout')">
|
<a-form-item field="timeout" :label="t('project.environmental.database.timeout')">
|
||||||
<a-input-number v-model:model-value="form.timeout" :default-value="1000" />
|
<a-input-number
|
||||||
|
v-model:model-value="form.timeout"
|
||||||
|
class="w-[152px]"
|
||||||
|
mode="button"
|
||||||
|
:step="100"
|
||||||
|
:min="0"
|
||||||
|
:default-value="1000"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-button type="outline" class="w-[88px]">
|
<a-button type="outline" class="w-[88px]" @click="testConnection">
|
||||||
{{ t('project.environmental.database.testConnection') }}
|
{{ t('project.environmental.database.testConnection') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
@ -85,28 +102,29 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, reactive, ref, watchEffect } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import { driverOptionFun, validateDatabaseEnv } from '@/api/modules/project-management/envManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import useLicenseStore from '@/store/modules/setting/license';
|
import useLicenseStore from '@/store/modules/setting/license';
|
||||||
|
|
||||||
import { CreateOrUpdateSystemProjectParams, SystemOrgOption } from '@/models/setting/system/orgAndProject';
|
import { DataSourceItem } from '@/models/projectManagement/environmental';
|
||||||
|
|
||||||
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
modelValue: DataSourceItem;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
currentProject?: CreateOrUpdateSystemProjectParams;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const isEdit = computed(() => props.currentProject && props.currentProject.id);
|
const driverOption = ref<{ label: string; value: string }[]>([]);
|
||||||
const driverOption = ref<SystemOrgOption[]>([]);
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const licenseStore = useLicenseStore();
|
const licenseStore = useLicenseStore();
|
||||||
|
|
||||||
|
@ -114,33 +132,86 @@
|
||||||
(e: 'cancel', shouldSearch: boolean): void;
|
(e: 'cancel', shouldSearch: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const form = reactive({
|
const currentVisible = defineModel('visible', {
|
||||||
id: '',
|
default: false,
|
||||||
name: '',
|
type: Boolean,
|
||||||
driver: 'mysql',
|
|
||||||
url: '',
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
poolMax: 1,
|
|
||||||
timeout: 1000,
|
|
||||||
enable: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentVisible = ref(props.visible);
|
const form = defineModel<DataSourceItem>('modelValue', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const isEdit = computed(() => form.value.id);
|
||||||
|
|
||||||
|
const getDriverOption = async () => {
|
||||||
|
try {
|
||||||
|
const res = (await driverOptionFun(appStore.currentOrgId)) || [];
|
||||||
|
driverOption.value = res.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}));
|
||||||
|
if (res.length && !isEdit.value) {
|
||||||
|
// 创建模式下默认选中第一个
|
||||||
|
form.value.driverId = res[0].id;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const testConnection = async () => {
|
||||||
|
await formRef.value?.validateField(
|
||||||
|
['url', 'username'],
|
||||||
|
async (errors: undefined | Record<string, ValidatedError>) => {
|
||||||
|
if (errors) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
await validateDatabaseEnv({
|
||||||
|
name: form.value.name,
|
||||||
|
driverId: form.value.driverId,
|
||||||
|
dbUrl: form.value.dbUrl,
|
||||||
|
username: form.value.username,
|
||||||
|
password: form.value.password,
|
||||||
|
poolMax: form.value.poolMax,
|
||||||
|
timeout: form.value.timeout,
|
||||||
|
});
|
||||||
|
Message.success(t('project.environmental.database.testConnectionSuccess'));
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const isXpack = computed(() => {
|
const isXpack = computed(() => {
|
||||||
return licenseStore.hasLicense();
|
return licenseStore.hasLicense();
|
||||||
});
|
});
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
currentVisible.value = props.visible;
|
|
||||||
});
|
|
||||||
|
|
||||||
const formReset = () => {
|
const formReset = () => {
|
||||||
form.name = '';
|
if (!isEdit.value) {
|
||||||
|
form.value = {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
driverId: '',
|
||||||
|
dbUrl: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
poolMax: 1,
|
||||||
|
timeout: 1000,
|
||||||
|
enable: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const handleCancel = (shouldSearch: boolean) => {
|
const handleCancel = (shouldSearch: boolean) => {
|
||||||
emit('cancel', shouldSearch);
|
emit('cancel', shouldSearch);
|
||||||
|
currentVisible.value = false;
|
||||||
|
formReset();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBeforeOk = async () => {
|
const handleBeforeOk = async () => {
|
||||||
|
@ -150,6 +221,7 @@
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
Message.success(
|
Message.success(
|
||||||
isEdit.value
|
isEdit.value
|
||||||
? t('project.environmental.database.updateProjectSuccess')
|
? t('project.environmental.database.updateProjectSuccess')
|
||||||
|
@ -164,29 +236,12 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const initDriverOption = async () => {
|
const initData = () => {
|
||||||
try {
|
getDriverOption();
|
||||||
const res = [];
|
|
||||||
driverOption.value = res;
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (isEdit.value && props.currentProject) {
|
if (props.visible) {
|
||||||
form.name = props.currentProject.name;
|
initData();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(val) => {
|
|
||||||
currentVisible.value = val;
|
|
||||||
if (!val) {
|
|
||||||
formReset();
|
|
||||||
} else {
|
|
||||||
initDriverOption();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -9,9 +9,10 @@
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
<template v-if="showType === 'PROJECT'">
|
<template v-if="showType === 'PROJECT'">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
|
v-model="keyword"
|
||||||
:placeholder="t('project.environmental.searchHolder')"
|
:placeholder="t('project.environmental.searchHolder')"
|
||||||
allow-clear
|
allow-clear
|
||||||
@press-enter="enterData"
|
@press-enter="searchData"
|
||||||
@search="searchData"
|
@search="searchData"
|
||||||
/>
|
/>
|
||||||
<!-- 全局参数-->
|
<!-- 全局参数-->
|
||||||
|
@ -42,7 +43,7 @@
|
||||||
@select="(value) => handleMoreAction(value, 'all', EnvAuthTypeEnum.ENVIRONMENT)"
|
@select="(value) => handleMoreAction(value, 'all', EnvAuthTypeEnum.ENVIRONMENT)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<MsButton type="icon" class="!mr-0 p-[2px]">
|
<MsButton type="icon" class="!mr-0 p-[2px]" @click="handleCreateEnv">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
type="icon-icon_create_planarity"
|
type="icon-icon_create_planarity"
|
||||||
size="18"
|
size="18"
|
||||||
|
@ -54,7 +55,7 @@
|
||||||
<div>
|
<div>
|
||||||
<!-- 环境list-->
|
<!-- 环境list-->
|
||||||
<div v-if="envList.length">
|
<div v-if="envList.length">
|
||||||
<VueDraggable v-model="envList" ghost-class="ghost">
|
<VueDraggable v-model="envList" ghost-class="ghost" handle=".drag-handle">
|
||||||
<div
|
<div
|
||||||
v-for="element in envList"
|
v-for="element in envList"
|
||||||
:key="element.id"
|
:key="element.id"
|
||||||
|
@ -66,7 +67,7 @@
|
||||||
:type="(showType as EnvAuthScopeEnum)"
|
:type="(showType as EnvAuthScopeEnum)"
|
||||||
v-bind="popVisible[element.id]"
|
v-bind="popVisible[element.id]"
|
||||||
@cancel="handleRenameCancel(element)"
|
@cancel="handleRenameCancel(element)"
|
||||||
@submit="handleRenameCancel(element, element.id)"
|
@submit="handleRenameCancel(element, true)"
|
||||||
>
|
>
|
||||||
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
|
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
|
||||||
<a-tooltip :content="element.name">
|
<a-tooltip :content="element.name">
|
||||||
|
@ -78,7 +79,7 @@
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<div class="node-extra">
|
<div class="node-extra">
|
||||||
<div class="flex flex-row items-center gap-[8px]">
|
<div class="flex flex-row items-center gap-[8px]">
|
||||||
<MsButton type="icon" class="!mr-0 p-[2px]">
|
<MsButton type="icon" class="drag-handle !mr-0 p-[2px]">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
type="icon-icon_drag"
|
type="icon-icon_drag"
|
||||||
size="16"
|
size="16"
|
||||||
|
@ -118,9 +119,9 @@
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 环境list-->
|
<!-- 环境组list-->
|
||||||
<div v-if="envList.length">
|
<div v-if="envList.length">
|
||||||
<VueDraggable v-model="envList" ghost-class="ghost">
|
<VueDraggable v-model="envList" ghost-class="ghost" handle=".drag-handle">
|
||||||
<div
|
<div
|
||||||
v-for="element in envList"
|
v-for="element in envList"
|
||||||
:key="element.id"
|
:key="element.id"
|
||||||
|
@ -132,7 +133,7 @@
|
||||||
:type="(showType as EnvAuthScopeEnum)"
|
:type="(showType as EnvAuthScopeEnum)"
|
||||||
v-bind="popVisible[element.id]"
|
v-bind="popVisible[element.id]"
|
||||||
@cancel="handleRenameCancel(element)"
|
@cancel="handleRenameCancel(element)"
|
||||||
@submit="handleRenameCancel(element, element.id)"
|
@submit="handleRenameCancel(element, true)"
|
||||||
>
|
>
|
||||||
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
|
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
|
||||||
<a-tooltip :content="element.name">
|
<a-tooltip :content="element.name">
|
||||||
|
@ -144,7 +145,7 @@
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<div class="node-extra">
|
<div class="node-extra">
|
||||||
<div class="flex flex-row items-center gap-[8px]">
|
<div class="flex flex-row items-center gap-[8px]">
|
||||||
<MsButton type="icon" class="!mr-0 p-[2px]">
|
<MsButton type="icon" class="drag-handle !mr-0 p-[2px]">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
type="icon-icon_drag"
|
type="icon-icon_drag"
|
||||||
size="16"
|
size="16"
|
||||||
|
@ -194,8 +195,10 @@
|
||||||
import EnvParamBox from './components/EnvParamBox.vue';
|
import EnvParamBox from './components/EnvParamBox.vue';
|
||||||
import RenamePop from './components/RenamePop.vue';
|
import RenamePop from './components/RenamePop.vue';
|
||||||
|
|
||||||
|
import { listEnv } from '@/api/modules/project-management/envManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useProjectEnvStore, { ALL_PARAM } from '@/store/modules/setting/useProjectEnvStore';
|
import { useAppStore } from '@/store';
|
||||||
|
import useProjectEnvStore, { ALL_PARAM, NEW_ENV_PARAM } from '@/store/modules/setting/useProjectEnvStore';
|
||||||
|
|
||||||
import { EnvListItem } from '@/models/projectManagement/environmental';
|
import { EnvListItem } from '@/models/projectManagement/environmental';
|
||||||
import { PopVisible } from '@/models/setting/usergroup';
|
import { PopVisible } from '@/models/setting/usergroup';
|
||||||
|
@ -210,6 +213,9 @@
|
||||||
|
|
||||||
const activeKey = computed(() => store.currentId); // 当前选中的id
|
const activeKey = computed(() => store.currentId); // 当前选中的id
|
||||||
|
|
||||||
|
const keyword = ref<string>(''); // 搜索关键字
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
// 气泡弹窗
|
// 气泡弹窗
|
||||||
const popVisible = ref<PopVisible>({});
|
const popVisible = ref<PopVisible>({});
|
||||||
|
|
||||||
|
@ -262,26 +268,33 @@
|
||||||
console.log(item, id, scopeType);
|
console.log(item, id, scopeType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCreateEnv = () => {
|
||||||
|
const tmpArr = envList.value;
|
||||||
|
tmpArr.unshift({
|
||||||
|
id: NEW_ENV_PARAM,
|
||||||
|
name: t('project.environmental.newEnv'),
|
||||||
|
});
|
||||||
|
store.setCurrentId(NEW_ENV_PARAM);
|
||||||
|
envList.value = tmpArr;
|
||||||
|
};
|
||||||
|
|
||||||
function changeShowType(value: string | number | boolean) {
|
function changeShowType(value: string | number | boolean) {
|
||||||
console.log(value);
|
console.log(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户组数据初始化
|
// 用户组数据初始化
|
||||||
const initData = async (id?: string, isSelect = true) => {
|
const initData = async (keywordStr = '') => {
|
||||||
const tmpArr: EnvListItem[] = [];
|
try {
|
||||||
for (let i = 0; i < 100; i++) {
|
envList.value = await listEnv({ projectId: appStore.currentProjectId, keyword: keywordStr });
|
||||||
tmpArr.push({
|
} catch (error) {
|
||||||
id: `${i + 1}`,
|
// eslint-disable-next-line no-console
|
||||||
name: `环境${i + 1}`,
|
console.log(error);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
envList.value = tmpArr;
|
|
||||||
console.log(id, isSelect);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRenameCancel = (element: EnvListItem, id?: string) => {
|
const handleRenameCancel = (element: EnvListItem, shouldSearch?: boolean) => {
|
||||||
if (id) {
|
if (shouldSearch) {
|
||||||
initData(id, true);
|
initData();
|
||||||
}
|
}
|
||||||
popVisible.value[element.id].visible = false;
|
popVisible.value[element.id].visible = false;
|
||||||
};
|
};
|
||||||
|
@ -291,22 +304,8 @@
|
||||||
store.setCurrentId(id);
|
store.setCurrentId(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
function enterData(eve: Event) {
|
function searchData() {
|
||||||
if (!(eve.target as HTMLInputElement).value) {
|
initData(keyword.value);
|
||||||
return;
|
|
||||||
}
|
|
||||||
const keyword = (eve.target as HTMLInputElement).value;
|
|
||||||
const tmpArr = envList.value.filter((ele) => ele.name.includes(keyword));
|
|
||||||
envList.value = tmpArr;
|
|
||||||
}
|
|
||||||
function searchData(value: string) {
|
|
||||||
if (!value) {
|
|
||||||
// initData('', false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const keyword = value;
|
|
||||||
const tmpArr = envList.value.filter((ele) => ele.name.includes(keyword));
|
|
||||||
envList.value = tmpArr;
|
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initData();
|
initData();
|
||||||
|
@ -330,14 +329,14 @@
|
||||||
border-radius: var(--border-radius-base);
|
border-radius: var(--border-radius-base);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
.node-extra {
|
.node-extra {
|
||||||
@apply relative hidden;
|
opacity: 0;
|
||||||
&:hover {
|
&:hover {
|
||||||
@apply block;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
.node-extra {
|
.node-extra {
|
||||||
@apply block;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:active {
|
:active {
|
||||||
|
@ -351,7 +350,7 @@
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
.env-row-extra {
|
.env-row-extra {
|
||||||
@apply block;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ export default {
|
||||||
'project.environmental.desc': '描述',
|
'project.environmental.desc': '描述',
|
||||||
'project.environmental.envName': '环境名称',
|
'project.environmental.envName': '环境名称',
|
||||||
'project.environmental.envParams': '环境变量',
|
'project.environmental.envParams': '环境变量',
|
||||||
|
'project.environmental.newEnv': '未命名环境',
|
||||||
'project.environmental.envNamePlaceholder': '请输入环境名称',
|
'project.environmental.envNamePlaceholder': '请输入环境名称',
|
||||||
'project.environmental.envNameRequired': '环境名称不能为空',
|
'project.environmental.envNameRequired': '环境名称不能为空',
|
||||||
'project.environmental.database': '数据库',
|
'project.environmental.database': '数据库',
|
||||||
|
|
Loading…
Reference in New Issue