1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-03-14 01:34:47 +08:00

feat: 运行环境支持增加挂载 (#6662)

Refs https://github.com/1Panel-dev/1Panel/issues/5837
This commit is contained in:
zhengkunwang 2024-10-09 17:26:57 +08:00 committed by GitHub
parent e359e1c544
commit 958993f81f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 373 additions and 350 deletions

View File

@ -30,12 +30,17 @@ type NodeConfig struct {
Port int `json:"port"`
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
}
type Environment struct {
Key string `json:"key"`
Value string `json:"value"`
}
type Volume struct {
Source string `json:"source"`
Target string `json:"target"`
}
type ExposedPort struct {
HostPort int `json:"hostPort"`

View File

@ -27,6 +27,7 @@ type RuntimeDTO struct {
Path string `json:"path"`
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
Environments []request.Environment `json:"environments"`
Volumes []request.Volume `json:"volumes"`
}
type PackageScripts struct {

View File

@ -387,6 +387,32 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
if err != nil {
return nil, err
}
volumes, err := getDockerComposeVolumes(composeByte)
if err != nil {
return nil, err
}
defaultVolumes := make(map[string]string)
switch runtime.Type {
case constant.RuntimeNode:
defaultVolumes = constant.RuntimeDefaultVolumes
case constant.RuntimeJava:
defaultVolumes = constant.RuntimeDefaultVolumes
case constant.RuntimeGo:
defaultVolumes = constant.GoDefaultVolumes
}
for _, volume := range volumes {
exist := false
for key, value := range defaultVolumes {
if key == volume.Source && value == volume.Target {
exist = true
break
}
}
if !exist {
res.Volumes = append(res.Volumes, volume)
}
}
}
return &res, nil
@ -461,6 +487,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
Install: true,
ExposedPorts: req.ExposedPorts,
Environments: req.Environments,
Volumes: req.Volumes,
},
}
composeContent, envContent, _, err := handleParams(create, projectDir)

View File

@ -474,9 +474,27 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
for _, e := range create.Environments {
environments = append(environments, fmt.Sprintf("%s:%s", e.Key, e.Value))
}
delete(serviceValue, "environment")
if len(environments) > 0 {
serviceValue["environment"] = environments
}
var volumes []interface{}
defaultVolumes := make(map[string]string)
switch create.Type {
case constant.RuntimeNode:
defaultVolumes = constant.RuntimeDefaultVolumes
case constant.RuntimeJava:
defaultVolumes = constant.RuntimeDefaultVolumes
case constant.RuntimeGo:
defaultVolumes = constant.GoDefaultVolumes
}
for k, v := range defaultVolumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", k, v))
}
for _, volume := range create.Volumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", volume.Source, volume.Target))
}
serviceValue["volumes"] = volumes
break
}
for k := range env {
@ -648,3 +666,30 @@ func getDockerComposeEnvironments(yml []byte) ([]request.Environment, error) {
}
return res, nil
}
func getDockerComposeVolumes(yml []byte) ([]request.Volume, error) {
var (
composeProject docker.ComposeProject
err error
)
err = yaml.Unmarshal(yml, &composeProject)
if err != nil {
return nil, err
}
var res []request.Volume
for _, service := range composeProject.Services {
for _, volume := range service.Volumes {
envArray := strings.Split(volume, ":")
source := envArray[0]
target := ""
if len(envArray) > 1 {
target = envArray[1]
}
res = append(res, request.Volume{
Source: source,
Target: target,
})
}
}
return res, nil
}

View File

@ -34,3 +34,16 @@ const (
RuntimeNpm = "npm"
RuntimeYarn = "yarn"
)
var GoDefaultVolumes = map[string]string{
"${CODE_DIR}": "/app",
"./run.sh": "/run.sh",
"./.env": "/.env",
"./mod": "/go/pkg/mod",
}
var RuntimeDefaultVolumes = map[string]string{
"./run.sh": "/run.sh",
"./.env": "/.env",
"./mod": "/go/pkg/mod",
}

View File

@ -55,6 +55,7 @@ type ComposeProject struct {
type Service struct {
Image string `yaml:"image"`
Environment []string `yaml:"environment"`
Volumes []string `json:"volumes"`
}
func replaceEnvVariables(input string, envVars map[string]string) string {

View File

@ -234,11 +234,13 @@ func (l *Location) AddSubFilter(subFilters map[string]string) {
}
l.UpdateDirective("proxy_set_header", []string{"Accept-Encoding", `""`})
l.UpdateDirective("sub_filter_once", []string{"off"})
l.UpdateDirective("sub_filter_types", []string{"*"})
}
func (l *Location) RemoveSubFilter() {
l.RemoveDirective("sub_filter", []string{})
l.RemoveDirective("proxy_set_header", []string{"Accept-Encoding", `""`})
l.RemoveDirective("sub_filter_once", []string{"off"})
l.RemoveDirective("sub_filter_types", []string{"*"})
l.Replaces = nil
}

View File

@ -40,6 +40,7 @@ export namespace Runtime {
path?: string;
exposedPorts?: ExposedPort[];
environments?: Environment[];
volumes?: Volume[];
}
export interface RuntimeCreate {
@ -58,6 +59,7 @@ export namespace Runtime {
port?: number;
exposedPorts?: ExposedPort[];
environments?: Environment[];
volumes?: Volume[];
}
export interface ExposedPort {
@ -69,6 +71,10 @@ export namespace Runtime {
key: string;
value: string;
}
export interface Volume {
source: string;
target: string;
}
export interface RuntimeUpdate {
name: string;

View File

@ -1,37 +1,22 @@
<template>
<div v-loading="loading">
<el-drawer
v-model="drawerVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
size="30%"
>
<template #header>
<DrawerHeader :header="$t('terminal.groupChange')" :back="handleClose" />
</template>
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form @submit.prevent ref="hostInfoRef" label-position="top" :model="dialogData" :rules="rules">
<el-form-item :label="$t('commons.table.group')" prop="group">
<el-select filterable v-model="dialogData.groupID" clearable style="width: 100%">
<div v-for="item in groupList" :key="item.id">
<el-option :label="item.name" :value="item.id" />
</div>
</el-select>
</el-form-item>
</el-form>
</el-col>
</el-row>
<DrawerPro v-model="drawerVisible" :header="$t('terminal.groupChange')" :back="handleClose" size="small">
<el-form @submit.prevent ref="hostInfoRef" label-position="top" :model="dialogData" :rules="rules">
<el-form-item :label="$t('commons.table.group')" prop="group">
<el-select filterable v-model="dialogData.groupID" clearable style="width: 100%">
<div v-for="item in groupList" :key="item.id">
<el-option :label="item.name" :value="item.id" />
</div>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="onSubmit(hostInfoRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="onSubmit(hostInfoRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
</div>
</template>
@ -40,7 +25,6 @@ import { ref, reactive } from 'vue';
import type { ElForm } from 'element-plus';
import { Rules } from '@/global/form-rules';
import { GetGroupList } from '@/api/modules/group';
import DrawerHeader from '@/components/drawer-header/index.vue';
const loading = ref();
interface DialogProps {

View File

@ -62,7 +62,7 @@
</template>
<template #main>
<div>
<MainDiv :heightDiff="mode === 'upgrade' ? 280 : 380">
<MainDiv :heightDiff="mode === 'upgrade' ? 320 : 350">
<el-alert
type="info"
:title="$t('app.upgradeHelper')"

View File

@ -1,52 +1,37 @@
<template>
<div>
<el-drawer
v-model="deleteVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
size="30%"
>
<template #header>
<DrawerHeader :header="$t('container.imageDelete')" :back="handleClose" />
</template>
<DrawerPro v-model="deleteVisible" :header="$t('container.imageDelete')" :back="handleClose" size="small">
<el-form @submit.prevent :model="form" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('container.tag')" prop="tagName">
<div style="width: 100%">
<el-checkbox
v-model="deleteAll"
:indeterminate="isIndeterminate"
@change="handleCheckAllChange"
>
{{ $t('container.removeAll') }}
</el-checkbox>
</div>
<el-checkbox-group v-model="form.deleteTags" @change="handleCheckedChange">
<div>
<el-checkbox
style="width: 100%"
v-for="item in form.tags"
:key="item"
:value="item"
:label="item"
/>
</div>
</el-checkbox-group>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('container.tag')" prop="tagName">
<div style="width: 100%">
<el-checkbox
v-model="deleteAll"
:indeterminate="isIndeterminate"
@change="handleCheckAllChange"
>
{{ $t('container.removeAll') }}
</el-checkbox>
</div>
<el-checkbox-group v-model="form.deleteTags" @change="handleCheckedChange">
<div>
<el-checkbox
style="width: 100%"
v-for="item in form.tags"
:key="item"
:value="item"
:label="item"
/>
</div>
</el-checkbox-group>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="deleteVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" :disabled="form.deleteTags.length === 0" @click="batchDelete()">
{{ $t('commons.button.delete') }}
</el-button>
</span>
<el-button @click="deleteVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" :disabled="form.deleteTags.length === 0" @click="batchDelete()">
{{ $t('commons.button.delete') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
<OpDialog ref="opRef" @search="onSearch" @cancel="handleClose" />
</div>
@ -55,7 +40,6 @@
import { reactive, ref } from 'vue';
import { ElForm } from 'element-plus';
import { imageRemove } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
import i18n from '@/lang';
const deleteVisible = ref(false);

View File

@ -1,55 +1,39 @@
<template>
<el-drawer
v-model="drawerVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
size="30%"
>
<template #header>
<DrawerHeader :header="$t('container.exportImage')" :back="handleClose" />
</template>
<DrawerPro v-model="drawerVisible" :header="$t('terminal.exportImage')" :back="handleClose" size="small">
<el-form v-loading="loading" label-position="top" ref="formRef" :model="form" label-width="80px">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('container.tag')" :rules="Rules.requiredSelect" prop="tagName">
<el-select filterable v-model="form.tagName">
<el-option
:disabled="item.indexOf(':<none>') !== -1"
v-for="item in form.tags"
:key="item"
:value="item"
:label="item"
/>
</el-select>
</el-form-item>
<el-form-item :label="$t('container.path')" :rules="Rules.requiredInput" prop="path">
<el-input v-model="form.path">
<template #prepend>
<FileList @choose="loadSaveDir" :dir="true"></FileList>
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('container.fileName')" :rules="Rules.requiredInput" prop="name">
<el-input v-model="form.name">
<template #append>.tar</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('container.tag')" :rules="Rules.requiredSelect" prop="tagName">
<el-select filterable v-model="form.tagName">
<el-option
:disabled="item.indexOf(':<none>') !== -1"
v-for="item in form.tags"
:key="item"
:value="item"
:label="item"
/>
</el-select>
</el-form-item>
<el-form-item :label="$t('container.path')" :rules="Rules.requiredInput" prop="path">
<el-input v-model="form.path">
<template #prepend>
<FileList @choose="loadSaveDir" :dir="true"></FileList>
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('container.fileName')" :rules="Rules.requiredInput" prop="name">
<el-input v-model="form.name">
<template #append>.tar</template>
</el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="drawerVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSubmit(formRef)">
{{ $t('container.export') }}
</el-button>
</span>
<el-button :disabled="loading" @click="drawerVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSubmit(formRef)">
{{ $t('container.export') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
</template>
<script lang="ts" setup>
@ -60,7 +44,6 @@ import i18n from '@/lang';
import { ElForm } from 'element-plus';
import { imageSave } from '@/api/modules/container';
import { Container } from '@/api/interface/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { MsgSuccess } from '@/utils/message';
const loading = ref(false);

View File

@ -1,16 +1,6 @@
<template>
<div>
<el-drawer
v-model="drawerVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="handleClose"
size="30%"
>
<template #header>
<DrawerHeader header="IPv6" :back="handleClose" />
</template>
<DrawerPro v-model="drawerVisible" header="IPv6" :back="handleClose" size="small">
<el-alert class="common-prompt" :closable="false" type="warning">
<template #default>
<span class="input-help">
@ -28,37 +18,31 @@
</el-alert>
<el-form :model="form" ref="formRef" :rules="rules" v-loading="loading" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item prop="fixedCidrV6" :label="$t('container.subnet')">
<el-input v-model="form.fixedCidrV6" />
<span class="input-help">{{ $t('container.ipv6CidrHelper') }}</span>
</el-form-item>
<el-form-item>
<el-checkbox v-model="showMore" :label="$t('app.advanced')" />
</el-form-item>
<div v-if="showMore">
<el-form-item prop="ip6Tables" label="ip6tables">
<el-switch v-model="form.ip6Tables"></el-switch>
<span class="input-help">{{ $t('container.ipv6TablesHelper') }}</span>
</el-form-item>
<el-form-item prop="experimental" label="experimental">
<el-switch v-model="form.experimental"></el-switch>
<span class="input-help">{{ $t('container.experimentalHelper') }}</span>
</el-form-item>
</div>
</el-col>
</el-row>
<el-form-item prop="fixedCidrV6" :label="$t('container.subnet')">
<el-input v-model="form.fixedCidrV6" />
<span class="input-help">{{ $t('container.ipv6CidrHelper') }}</span>
</el-form-item>
<el-form-item>
<el-checkbox v-model="showMore" :label="$t('app.advanced')" />
</el-form-item>
<div v-if="showMore">
<el-form-item prop="ip6Tables" label="ip6tables">
<el-switch v-model="form.ip6Tables"></el-switch>
<span class="input-help">{{ $t('container.ipv6TablesHelper') }}</span>
</el-form-item>
<el-form-item prop="experimental" label="experimental">
<el-switch v-model="form.experimental"></el-switch>
<span class="input-help">{{ $t('container.experimentalHelper') }}</span>
</el-form-item>
</div>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmitSave"></ConfirmDialog>
</div>
@ -69,7 +53,6 @@ import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { updateIpv6Option } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { checkIpV6 } from '@/utils/util';
const loading = ref();

View File

@ -1,16 +1,6 @@
<template>
<div>
<el-drawer
v-model="drawerVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="handleClose"
size="30%"
>
<template #header>
<DrawerHeader :header="$t('container.cutLog')" :back="handleClose" />
</template>
<DrawerPro v-model="drawerVisible" :header="$t('container.cutLog')" :back="handleClose" size="small">
<el-alert class="common-prompt" :closable="false" type="warning">
<template #default>
<ul style="margin-left: -20px">
@ -21,36 +11,29 @@
</template>
</el-alert>
<el-form :model="form" ref="formRef" :rules="rules" v-loading="loading" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item prop="logMaxSize" :label="$t('container.maxSize')">
<el-input v-model.number="form.logMaxSize">
<template #append>
<el-select v-model="form.sizeUnit" style="width: 70px">
<el-option label="Byte" value="b"></el-option>
<el-option label="KB" value="k"></el-option>
<el-option label="MB" value="m"></el-option>
<el-option label="GB" value="g"></el-option>
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item prop="logMaxFile" :label="$t('container.maxFile')">
<el-input v-model.number="form.logMaxFile" />
</el-form-item>
</el-col>
</el-row>
<el-form-item prop="logMaxSize" :label="$t('container.maxSize')">
<el-input v-model.number="form.logMaxSize">
<template #append>
<el-select v-model="form.sizeUnit" style="width: 70px">
<el-option label="Byte" value="b"></el-option>
<el-option label="KB" value="k"></el-option>
<el-option label="MB" value="m"></el-option>
<el-option label="GB" value="g"></el-option>
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item prop="logMaxFile" :label="$t('container.maxFile')">
<el-input v-model.number="form.logMaxFile" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmitSave"></ConfirmDialog>
</div>
</template>
@ -61,7 +44,6 @@ import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { updateLogOption } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
const loading = ref();
const drawerVisible = ref();

View File

@ -1,15 +1,6 @@
<template>
<div>
<el-drawer
v-model="drawerVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
size="30%"
>
<template #header>
<DrawerHeader :header="$t('container.mirrors')" :back="handleClose" />
</template>
<DrawerPro v-model="drawerVisible" :header="$t('container.mirrors')" :back="handleClose" size="small">
<el-form
ref="formRef"
label-position="top"
@ -18,28 +9,22 @@
:rules="rules"
v-loading="loading"
>
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('container.mirrors')" prop="mirrors">
<el-input
type="textarea"
:placeholder="$t('container.mirrorHelper')"
:rows="5"
v-model="form.mirrors"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('container.mirrors')" prop="mirrors">
<el-input
type="textarea"
:placeholder="$t('container.mirrorHelper')"
:rows="5"
v-model="form.mirrors"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit" />
</div>
@ -50,7 +35,6 @@ import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { updateDaemonJson } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { FormInstance } from 'element-plus';
import { emptyLineFilter } from '@/utils/util';

View File

@ -1,15 +1,6 @@
<template>
<div>
<el-drawer
v-model="drawerVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
size="30%"
>
<template #header>
<DrawerHeader :header="$t('container.registries')" :back="handleClose" />
</template>
<DrawerPro v-model="drawerVisible" :header="$t('container.registries')" :back="handleClose" size="small">
<el-form
ref="formRef"
label-position="top"
@ -18,29 +9,22 @@
@submit.prevent
v-loading="loading"
>
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('container.registries')" prop="registries">
<el-input
type="textarea"
:placeholder="$t('container.registrieHelper')"
:rows="5"
v-model="form.registries"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('container.registries')" prop="registries">
<el-input
type="textarea"
:placeholder="$t('container.registrieHelper')"
:rows="5"
v-model="form.registries"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit" />
</div>
</template>
@ -50,7 +34,6 @@ import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { updateDaemonJson } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { FormInstance } from 'element-plus';
import { emptyLineFilter } from '@/utils/util';

View File

@ -1,15 +1,6 @@
<template>
<div>
<el-drawer
v-model="drawerVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
size="30%"
>
<template #header>
<DrawerHeader :header="$t('container.sockPath')" :back="handleClose" />
</template>
<DrawerPro v-model="drawerVisible" :header="$t('container.sockPath')" :back="handleClose" size="small">
<el-form
ref="formRef"
label-position="top"
@ -18,29 +9,23 @@
@submit.prevent
v-loading="loading"
>
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('container.sockPath')" prop="dockerSockPath">
<el-input v-model="form.dockerSockPath">
<template #prepend>unix://</template>
<template #append>
<FileList @choose="loadBuildDir"></FileList>
</template>
</el-input>
<span class="input-help">{{ $t('container.sockPathHelper1') }}</span>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('container.sockPath')" prop="dockerSockPath">
<el-input v-model="form.dockerSockPath">
<template #prepend>unix://</template>
<template #append>
<FileList @choose="loadBuildDir"></FileList>
</template>
</el-input>
<span class="input-help">{{ $t('container.sockPathHelper1') }}</span>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSubmit(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSubmit(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
</div>
</template>
<script lang="ts" setup>
@ -48,7 +33,6 @@ import { reactive, ref } from 'vue';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { updateSetting } from '@/api/modules/setting';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { ElMessageBox, FormInstance } from 'element-plus';
const emit = defineEmits<{ (e: 'search'): void }>();

View File

@ -1,40 +1,31 @@
<template>
<div>
<el-drawer
<DrawerPro
v-model="changeVisible"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
width="30%"
:header="$t('database.permission')"
:resource="form.name"
:back="handleClose"
size="small"
>
<template #header>
<DrawerHeader :header="$t('database.permission')" :resource="form.name" :back="handleClose" />
</template>
<el-form v-loading="loading" :model="form" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('database.userBind')">
<el-tag>
{{ form.username }}
</el-tag>
</el-form-item>
<el-form-item :label="$t('database.permission')" prop="superUser">
<el-checkbox v-model="form.superUser">{{ $t('database.pgSuperUser') }}</el-checkbox>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('database.userBind')">
<el-tag>
{{ form.username }}
</el-tag>
</el-form-item>
<el-form-item :label="$t('database.permission')" prop="superUser">
<el-checkbox v-model="form.superUser">{{ $t('database.pgSuperUser') }}</el-checkbox>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="changeVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSubmit()">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
<el-button :disabled="loading" @click="changeVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSubmit()">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</el-drawer>
</DrawerPro>
</div>
</template>
<script lang="ts" setup>
@ -42,7 +33,6 @@ import { reactive, ref } from 'vue';
import i18n from '@/lang';
import { ElForm } from 'element-plus';
import { changePrivileges } from '@/api/modules/database';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { MsgSuccess } from '@/utils/message';
const loading = ref();

View File

@ -1,29 +1,32 @@
<template>
<el-row :gutter="20">
<el-col :span="4">
<el-button @click="addEnv">{{ $t('commons.button.add') }}{{ $t('runtime.environment') }}</el-button>
</el-col>
</el-row>
<div class="mt-1.5">
<el-row :gutter="20" v-for="(env, index) in environments" :key="index">
<el-col :span="7">
<el-form-item :prop="`environments.${index}.key`" :rules="rules.value">
<el-input v-model="env.key" :placeholder="$t('runtime.envKey')" />
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :prop="`environments.${index}.value`" :rules="rules.value">
<el-input v-model="env.value" :placeholder="$t('runtime.envValue')" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item>
<el-button type="primary" @click="removeEnv(index)" link>
{{ $t('commons.button.delete') }}
</el-button>
</el-form-item>
</el-col>
</el-row>
<el-text>{{ $t('runtime.environment') }}</el-text>
<div class="mt-1.5">
<el-row :gutter="20" v-for="(env, index) in environments" :key="index">
<el-col :span="7">
<el-form-item :prop="`environments.${index}.key`" :rules="rules.value">
<el-input v-model="env.key" :placeholder="$t('runtime.envKey')" />
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :prop="`environments.${index}.value`" :rules="rules.value">
<el-input v-model="env.value" :placeholder="$t('runtime.envValue')" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item>
<el-button type="primary" @click="removeEnv(index)" link>
{{ $t('commons.button.delete') }}
</el-button>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="4">
<el-button @click="addEnv">{{ $t('commons.button.add') }}{{ $t('runtime.environment') }}</el-button>
</el-col>
</el-row>
</div>
</div>
</template>

View File

@ -79,6 +79,7 @@
</el-row>
<PortConfig :params="runtime.params" :exposedPorts="runtime.exposedPorts" :rules="rules" />
<Environment :environments="runtime.environments" />
<Volumes :volumes="runtime.volumes" />
<el-form-item :label="$t('app.containerName')" prop="params.CONTAINER_NAME">
<el-input v-model.trim="runtime.params['CONTAINER_NAME']"></el-input>
</el-form-item>
@ -105,6 +106,7 @@ import { FormInstance } from 'element-plus';
import { reactive, ref, watch } from 'vue';
import PortConfig from '@/views/website/runtime/port/index.vue';
import Environment from '@/views/website/runtime/environment/index.vue';
import Volumes from '@/views/website/runtime/volume/index.vue';
interface OperateRrops {
id?: number;
@ -139,6 +141,7 @@ const initData = (type: string) => ({
port: 8080,
exposedPorts: [],
environments: [],
volumes: [],
});
let runtime = reactive<Runtime.RuntimeCreate>(initData('go'));
const rules = ref<any>({
@ -307,6 +310,7 @@ const getRuntime = async (id: number) => {
});
runtime.exposedPorts = data.exposedPorts || [];
runtime.environments = data.environments || [];
runtime.volumes = data.volumes || [];
editParams.value = data.appParams;
searchApp(data.appID);
open.value = true;

View File

@ -0,0 +1,60 @@
<template>
<div class="mt-1.5">
<el-text>{{ $t('container.mount') }}</el-text>
<div class="mt-1.5">
<el-row :gutter="20" v-for="(volume, index) in volumes" :key="index">
<el-col :span="7">
<el-form-item :prop="`volumes.${index}.source`" :rules="rules.value">
<el-input v-model="volume.source" :placeholder="$t('container.hostOption')" />
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item :prop="`volumes.${index}.target`" :rules="rules.value">
<el-input v-model="volume.target" :placeholder="$t('container.containerDir')" />
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item>
<el-button type="primary" @click="removeEnv(index)" link>
{{ $t('commons.button.delete') }}
</el-button>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="4">
<el-button @click="addEnv">{{ $t('commons.button.add') }}{{ $t('container.mount') }}</el-button>
</el-col>
</el-row>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, reactive } from 'vue';
import { FormRules } from 'element-plus';
import { Rules } from '@/global/form-rules';
import { Runtime } from '@/api/interface/runtime';
const props = defineProps({
volumes: {
type: Array<Runtime.Volume>,
required: true,
},
});
const rules = reactive<FormRules>({
value: [Rules.requiredInput],
});
const addEnv = () => {
props.volumes.push({
source: '',
target: '',
});
};
const removeEnv = (index: number) => {
props.volumes.splice(index, 1);
};
</script>

View File

@ -97,7 +97,6 @@
</template>
<script lang="ts" setup>
import DrawerHeader from '@/components/drawer-header/index.vue';
import { OperateProxyConfig } from '@/api/modules/website';
import { checkNumberRange, Rules } from '@/global/form-rules';
import i18n from '@/lang';