新增环境配置

This commit is contained in:
opensnail 2025-01-12 17:41:16 +08:00
parent c56742f7d7
commit 538b54e6e7
4 changed files with 281 additions and 7 deletions

View File

@ -0,0 +1,119 @@
<script setup lang="ts">
const content = defineModel<{ key: string; value: string; type: string }[]>('value', {
required: true,
default: () => []
});
const path = defineModel<string>('path', {
required: true
});
const onCreate = () => {
return {
key: '',
value: '',
type: 'string'
};
};
const dynamicInputRule = [
{
trigger: ['input', 'blur'],
validator(_: unknown, value: string | number) {
if (!value && value !== 0) return new Error('不能为空');
return true;
}
}
];
const typeOptions = [
{
label: 'string',
value: 'string'
},
{
label: 'number',
value: 'number'
},
{
label: 'boolean',
value: 'boolean'
}
];
const boolenOptions = [
{
label: 'true',
value: 1
},
{
label: 'false',
value: 0
}
];
const handleUpdateType = (index: number) => {
if (content.value[index].type === 'string') {
content.value[index].value = '';
}
};
</script>
<template>
<NDynamicInput v-model:value="content" item-style="margin-bottom: 0;" :on-create="onCreate" #="{ index }">
<NGrid>
<NFormItemGi
:span="7"
ignore-path-change
:show-label="false"
:rule="dynamicInputRule"
:path="`${path}[${index}].key`"
>
<NInput v-model:value="content[index].key" placeholder="key" @keydown.enter.prevent />
</NFormItemGi>
<NGi :span="2" class="h-34px text-center lh-34px">=</NGi>
<NFormItemGi
:span="7"
ignore-path-change
:show-label="false"
:rule="dynamicInputRule"
:path="`${path}[${index}].value`"
>
<NInput
v-if="content[index].type === 'string'"
v-model:value="content[index].value as string"
placeholder="value"
@keydown.enter.prevent
/>
<NSelect
v-if="content[index].type === 'boolean'"
v-model:value="content[index].value as number"
class="w-full"
:options="boolenOptions"
placeholder="value"
@keydown.enter.prevent
/>
</NFormItemGi>
<NFormItemGi
:span="3"
class="ml-12px w-115px"
ignore-path-change
:show-label="false"
:path="`${path}[${index}].type`"
>
<div class="h-34px lh-34px">(</div>
<NSelect
v-model:value="content[index].type"
class="mx-3px"
:options="typeOptions"
placeholder="字段类型"
@keydown.enter.prevent
@update:value="handleUpdateType(index)"
/>
<div class="h-34px lh-34px">)</div>
</NFormItemGi>
</NGrid>
</NDynamicInput>
</template>
<style scoped></style>

View File

@ -0,0 +1,119 @@
<script setup lang="ts">
const content = defineModel<{ key: string; value: string; type: string }[]>('value', {
required: true,
default: () => []
});
const path = defineModel<string>('path', {
required: true
});
const onCreate = () => {
return {
key: '',
value: '',
type: 'string'
};
};
const dynamicInputRule = [
{
trigger: ['input', 'blur'],
validator(_: unknown, value: string | number) {
if (!value && value !== 0) return new Error('不能为空');
return true;
}
}
];
const typeOptions = [
{
label: 'string',
value: 'string'
},
{
label: 'number',
value: 'number'
},
{
label: 'boolean',
value: 'boolean'
}
];
const boolenOptions = [
{
label: 'true',
value: 1
},
{
label: 'false',
value: 0
}
];
const handleUpdateType = (index: number) => {
if (content.value[index].type === 'string') {
content.value[index].value = '';
}
};
</script>
<template>
<NDynamicInput v-model:value="content" item-style="margin-bottom: 0;" :on-create="onCreate" #="{ index }">
<NGrid>
<NFormItemGi
:span="7"
ignore-path-change
:show-label="false"
:rule="dynamicInputRule"
:path="`${path}[${index}].key`"
>
<NInput v-model:value="content[index].key" placeholder="key" @keydown.enter.prevent />
</NFormItemGi>
<NGi :span="2" class="h-34px text-center lh-34px">=</NGi>
<NFormItemGi
:span="7"
ignore-path-change
:show-label="false"
:rule="dynamicInputRule"
:path="`${path}[${index}].value`"
>
<NInput
v-if="content[index].type === 'string'"
v-model:value="content[index].value as string"
placeholder="value"
@keydown.enter.prevent
/>
<NSelect
v-if="content[index].type === 'boolean'"
v-model:value="content[index].value as number"
class="w-full"
:options="boolenOptions"
placeholder="value"
@keydown.enter.prevent
/>
</NFormItemGi>
<NFormItemGi
:span="3"
class="ml-12px w-115px"
ignore-path-change
:show-label="false"
:path="`${path}[${index}].type`"
>
<div class="h-34px lh-34px">(</div>
<NSelect
v-model:value="content[index].type"
class="mx-3px"
:options="typeOptions"
placeholder="字段类型"
@keydown.enter.prevent
@update:value="handleUpdateType(index)"
/>
<div class="h-34px lh-34px">)</div>
</NFormItemGi>
</NGrid>
</NDynamicInput>
</template>
<style scoped></style>

20
src/typings/api.d.ts vendored
View File

@ -1373,10 +1373,30 @@ declare namespace Api {
nanoCpus: number;
memory: number;
env: string;
envs: { key: string; value: string | number | boolean; type: string }[];
labels: string;
network: string;
}>;
type MountsConfig = CommonType.RecordNullable<{
/** volume/bind */
mountType: string;
sourceDir: string;
containerDir: string;
mode: string;
}>;
type EnvConfig = {
name: string;
value: string | number | boolean;
type: string;
};
type LabelsConfig = CommonType.RecordNullable<{
name: string;
value: string;
}>;
type AutoRemove = 0 | 1;
/** 0不重启 1一直重启 2失败后重启(默认重启3次) 3未手动停止则重启 */

View File

@ -3,13 +3,8 @@ import { computed, reactive, ref, watch } from 'vue';
import { useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
import { publishConfigAutoRemoveOptions, restartPolicyOptions } from '@/constants/business';
import {
fetchAddPublishConfig,
fetchEditPublishConfig,
fetchGetPartitionTableList,
fetchNetworkList
} from '@/service/api';
import { translateOptions2 } from '@/utils/common';
import { fetchAddPublishConfig, fetchEditPublishConfig, fetchNetworkList } from '@/service/api';
import { parseContent, translateOptions2 } from '@/utils/common';
defineOptions({
name: 'PublishOperateDrawer'
@ -61,6 +56,7 @@ type Model = Pick<
| 'nanoCpus'
| 'memory'
| 'env'
| 'envs'
| 'labels'
| 'network'
>;
@ -82,6 +78,7 @@ function createDefaultModel(): Model {
memory: 0,
network: 'none',
env: '',
envs: [],
labels: ''
};
}
@ -128,6 +125,15 @@ function closeDrawer() {
}
async function handleSubmit() {
formRef.value
?.validate(errors => {
if (!errors) {
model.env = JSON.stringify(parseContent(model.envs) || {});
close();
}
})
.catch(() => window.$message?.warning('请检查表单信息'));
await validate();
// request
if (props.operateType === 'add') {
@ -145,6 +151,7 @@ async function handleSubmit() {
memory,
network,
env,
envs,
labels
} = model;
const { error } = await fetchAddPublishConfig({
@ -161,6 +168,7 @@ async function handleSubmit() {
memory,
network,
env,
envs,
labels
});
if (error) return;
@ -180,6 +188,7 @@ async function handleSubmit() {
memory,
network,
env,
envs,
labels
} = model;
const { error } = await fetchEditPublishConfig({
@ -196,6 +205,7 @@ async function handleSubmit() {
memory,
network,
env,
envs,
labels
});
if (error) return;
@ -293,6 +303,12 @@ watch(visible, () => {
:options="translateOptions2(networkList)"
/>
</NFormItem>
<NFormItem :label="$t('page.docker.publishConfig.env')" path="envs">
<DynamicInput v-model:value="model.envs" path="envs" />
</NFormItem>
<NFormItem :label="$t('page.docker.publishConfig.labels')" path="labels">
<DynamicInput v-model:value="model.envs" path="labels" />
</NFormItem>
</NForm>
<template #footer>
<NSpace :size="16">