fix 构建流程交互(采用步骤条)

This commit is contained in:
bwcx_jzy 2024-01-09 17:34:25 +08:00
parent 3c9b3809cf
commit 9fd41da9f9
No known key found for this signature in database
GPG Key ID: 5E48E9372088B9E5
7 changed files with 593 additions and 338 deletions

View File

@ -7,6 +7,7 @@
### 🐞 解决BUG、优化功能 ### 🐞 解决BUG、优化功能
1. 【server】优化 上传文件前解析文件信息采用全局 loading 1. 【server】优化 上传文件前解析文件信息采用全局 loading
2. 【server】优化 构建流程交互(采用步骤条)
------ ------

View File

@ -140,4 +140,18 @@ public class DockerInfoController extends BaseServerController {
dockerInfoService.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId); dockerInfoService.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId);
return JsonMessage.success("操作成功"); return JsonMessage.success("操作成功");
} }
/**
* 查询所有的 tag
*
* @return msg
*/
@GetMapping(value = "all-tag", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<List<String>> allTag(HttpServletRequest request) {
String workspaceId = dockerInfoService.getCheckUserWorkspace(request);
//
List<String> strings = dockerInfoService.allTag(workspaceId);
return JsonMessage.success("", strings);
}
} }

View File

@ -22,7 +22,9 @@
*/ */
package org.dromara.jpom.service.docker; package org.dromara.jpom.service.docker;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.sql.Condition; import cn.hutool.db.sql.Condition;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.model.docker.DockerInfoModel; import org.dromara.jpom.model.docker.DockerInfoModel;
@ -30,7 +32,11 @@ import org.dromara.jpom.service.h2db.BaseWorkspaceService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/** /**
@ -87,6 +93,26 @@ public class DockerInfoService extends BaseWorkspaceService<DockerInfoModel> {
return (int) super.count(sql, workspaceId, StrUtil.wrap(tag, StrUtil.COLON)); return (int) super.count(sql, workspaceId, StrUtil.wrap(tag, StrUtil.COLON));
} }
/**
* 根据 tag 查询 容器
*
* @param workspaceId 工作空间
* @return count
*/
public List<String> allTag(String workspaceId) {
String sql = StrUtil.format("SELECT tags FROM {} where workspaceId=?", super.getTableName());
List<Entity> query = super.query(sql, workspaceId);
if (CollUtil.isEmpty(query)) {
return new ArrayList<>();
}
return query.stream()
.map(entity -> entity.getStr("tags"))
.flatMap((Function<String, Stream<String>>) s -> StrUtil.splitTrim(s, StrUtil.COLON).stream())
.filter(StrUtil::isNotEmpty)
.distinct()
.collect(Collectors.toList());
}
/** /**
* 将节点信息同步到其他工作空间 * 将节点信息同步到其他工作空间
* *

View File

@ -1,5 +1,5 @@
import axios from "./config"; import axios from './config'
import { loadRouterBase } from "./config"; import { loadRouterBase } from './config'
/** /**
* *
@ -7,10 +7,10 @@ import { loadRouterBase } from "./config";
*/ */
export function dockerList(params) { export function dockerList(params) {
return axios({ return axios({
url: "/docker/list", url: '/docker/list',
method: "post", method: 'post',
data: params, data: params
}); })
} }
/** /**
@ -19,18 +19,18 @@ export function dockerList(params) {
*/ */
export function apiVersions() { export function apiVersions() {
return axios({ return axios({
url: "/docker/api-versions", url: '/docker/api-versions',
method: "get", method: 'get',
data: {}, data: {}
}); })
} }
export function editDocker(data) { export function editDocker(data) {
return axios({ return axios({
url: "/docker/edit", url: '/docker/edit',
method: "post", method: 'post',
data: data, data: data
}); })
} }
/** /**
@ -41,10 +41,10 @@ export function editDocker(data) {
*/ */
export function deleteDcoker(params) { export function deleteDcoker(params) {
return axios({ return axios({
url: "/docker/del", url: '/docker/del',
method: "get", method: 'get',
params, params
}); })
} }
/** /**
@ -53,13 +53,13 @@ export function deleteDcoker(params) {
*/ */
export function dockerContainerList(urlPrefix, params) { export function dockerContainerList(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/list", url: urlPrefix + '/container/list',
method: "post", method: 'post',
data: params, data: params,
headers: { headers: {
loading: "no", loading: 'no'
}, }
}); })
} }
/** /**
@ -68,13 +68,13 @@ export function dockerContainerList(urlPrefix, params) {
*/ */
export function dockerContainerListCompose(urlPrefix, params) { export function dockerContainerListCompose(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/list-compose", url: urlPrefix + '/container/list-compose',
method: "post", method: 'post',
data: params, data: params,
headers: { headers: {
loading: "no", loading: 'no'
}, }
}); })
} }
/** /**
@ -83,10 +83,10 @@ export function dockerContainerListCompose(urlPrefix, params) {
*/ */
export function dockerInfo(urlPrefix, params) { export function dockerInfo(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/info", url: urlPrefix + '/container/info',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -95,11 +95,11 @@ export function dockerInfo(urlPrefix, params) {
*/ */
export function dockerPrune(urlPrefix, params) { export function dockerPrune(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/prune", url: urlPrefix + '/container/prune',
method: "post", method: 'post',
data: params, data: params,
timeout: 0, timeout: 0
}); })
} }
/** /**
@ -108,10 +108,10 @@ export function dockerPrune(urlPrefix, params) {
*/ */
export function dockerContainerRemove(urlPrefix, params) { export function dockerContainerRemove(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/remove", url: urlPrefix + '/container/remove',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -120,10 +120,10 @@ export function dockerContainerRemove(urlPrefix, params) {
*/ */
export function dockerContainerRestart(urlPrefix, params) { export function dockerContainerRestart(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/restart", url: urlPrefix + '/container/restart',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -132,10 +132,10 @@ export function dockerContainerRestart(urlPrefix, params) {
*/ */
export function dockerContainerStart(urlPrefix, params) { export function dockerContainerStart(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/start", url: urlPrefix + '/container/start',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -144,10 +144,10 @@ export function dockerContainerStart(urlPrefix, params) {
*/ */
export function dockerContainerStop(urlPrefix, params) { export function dockerContainerStop(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/stop", url: urlPrefix + '/container/stop',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -156,14 +156,14 @@ export function dockerContainerStop(urlPrefix, params) {
*/ */
export function dockerContainerStats(urlPrefix, params) { export function dockerContainerStats(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/stats", url: urlPrefix + '/container/stats',
method: "get", method: 'get',
params: params, params: params,
headers: { headers: {
// tip: "no", // tip: "no",
loading: "no", loading: 'no'
}, }
}); })
} }
/** /**
@ -172,10 +172,10 @@ export function dockerContainerStats(urlPrefix, params) {
*/ */
export function dockerInspectContainer(urlPrefix, params) { export function dockerInspectContainer(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/inspect-container", url: urlPrefix + '/container/inspect-container',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -185,19 +185,19 @@ export function dockerInspectContainer(urlPrefix, params) {
*/ */
export function dockerUpdateContainer(urlPrefix, params) { export function dockerUpdateContainer(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/update-container", url: urlPrefix + '/container/update-container',
method: "post", method: 'post',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json'
}, },
data: params, data: params
}); })
} }
export function dockerContainerDownloaLog(urlPrefix, id) { export function dockerContainerDownloaLog(urlPrefix, id) {
return loadRouterBase(urlPrefix + "/container/download-log", { return loadRouterBase(urlPrefix + '/container/download-log', {
id: id, id: id
}); })
} }
/** /**
@ -206,10 +206,10 @@ export function dockerContainerDownloaLog(urlPrefix, id) {
*/ */
export function dockerImagesList(urlPrefix, params) { export function dockerImagesList(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/images/list", url: urlPrefix + '/images/list',
method: "post", method: 'post',
data: params, data: params
}); })
} }
/** /**
@ -218,10 +218,10 @@ export function dockerImagesList(urlPrefix, params) {
*/ */
export function dockerImageRemove(urlPrefix, params) { export function dockerImageRemove(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/images/remove", url: urlPrefix + '/images/remove',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -230,10 +230,10 @@ export function dockerImageRemove(urlPrefix, params) {
*/ */
export function dockerImageBatchRemove(urlPrefix, params) { export function dockerImageBatchRemove(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/images/batchRemove", url: urlPrefix + '/images/batchRemove',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -242,10 +242,10 @@ export function dockerImageBatchRemove(urlPrefix, params) {
*/ */
export function dockerImageInspect(urlPrefix, params) { export function dockerImageInspect(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/images/inspect", url: urlPrefix + '/images/inspect',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -254,13 +254,13 @@ export function dockerImageInspect(urlPrefix, params) {
*/ */
export function dockerImageCreateContainer(urlPrefix, params) { export function dockerImageCreateContainer(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/images/create-container", url: urlPrefix + '/images/create-container',
method: "post", method: 'post',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json'
}, },
data: params, data: params
}); })
} }
/** /**
@ -269,10 +269,10 @@ export function dockerImageCreateContainer(urlPrefix, params) {
*/ */
export function dockerImagePullImage(urlPrefix, params) { export function dockerImagePullImage(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/images/pull-image", url: urlPrefix + '/images/pull-image',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -280,7 +280,7 @@ export function dockerImagePullImage(urlPrefix, params) {
* @param {JSON} params * @param {JSON} params
*/ */
export function dockerImageSaveImage(urlPrefix, params) { export function dockerImageSaveImage(urlPrefix, params) {
return loadRouterBase(urlPrefix + "/images/save-image", params); return loadRouterBase(urlPrefix + '/images/save-image', params)
} }
/** /**
@ -293,15 +293,15 @@ export function dockerImageSaveImage(urlPrefix, params) {
*/ */
export function dockerImageLoadImage(baseUrl, formData) { export function dockerImageLoadImage(baseUrl, formData) {
return axios({ return axios({
url: baseUrl + "/images/load-image", url: baseUrl + '/images/load-image',
headers: { headers: {
"Content-Type": "multipart/form-data;charset=UTF-8", 'Content-Type': 'multipart/form-data;charset=UTF-8'
}, },
method: "post", method: 'post',
// 0 表示无超时时间 // 0 表示无超时时间
timeout: 0, timeout: 0,
data: formData, data: formData
}); })
} }
/** /**
@ -310,14 +310,14 @@ export function dockerImageLoadImage(baseUrl, formData) {
*/ */
export function dockerImagePullImageLog(urlPrefix, params) { export function dockerImagePullImageLog(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/images/pull-image-log", url: urlPrefix + '/images/pull-image-log',
method: "get", method: 'get',
params: params, params: params,
headers: { headers: {
// tip: "no", // tip: "no",
loading: "no", loading: 'no'
}, }
}); })
} }
/** /**
@ -326,10 +326,10 @@ export function dockerImagePullImageLog(urlPrefix, params) {
*/ */
export function dockerVolumesList(urlPrefix, params) { export function dockerVolumesList(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/volumes/list", url: urlPrefix + '/volumes/list',
method: "post", method: 'post',
data: params, data: params
}); })
} }
/** /**
@ -338,10 +338,10 @@ export function dockerVolumesList(urlPrefix, params) {
*/ */
export function dockerVolumesRemove(urlPrefix, params) { export function dockerVolumesRemove(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/volumes/remove", url: urlPrefix + '/volumes/remove',
method: "get", method: 'get',
params: params, params: params
}); })
} }
/** /**
@ -350,18 +350,26 @@ export function dockerVolumesRemove(urlPrefix, params) {
*/ */
export function dockerNetworksList(urlPrefix, params) { export function dockerNetworksList(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/networks/list", url: urlPrefix + '/networks/list',
method: "post", method: 'post',
data: params, data: params
}); })
} }
export function syncToWorkspace(params) { export function syncToWorkspace(params) {
return axios({ return axios({
url: "/docker/sync-to-workspace", url: '/docker/sync-to-workspace',
method: "get", method: 'get',
params: params, params: params
}); })
}
export function dockerAllTag(params) {
return axios({
url: '/docker/all-tag',
method: 'get',
params: params
})
} }
/** /**
@ -370,11 +378,11 @@ export function syncToWorkspace(params) {
*/ */
export function dockerContainerRebuildContainer(urlPrefix, params) { export function dockerContainerRebuildContainer(urlPrefix, params) {
return axios({ return axios({
url: urlPrefix + "/container/rebuild-container", url: urlPrefix + '/container/rebuild-container',
method: "post", method: 'post',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json'
}, },
data: params, data: params
}); })
} }

View File

@ -26,6 +26,7 @@ declare module 'vue' {
ADivider: typeof import('ant-design-vue/es')['Divider'] ADivider: typeof import('ant-design-vue/es')['Divider']
ADrawer: typeof import('ant-design-vue/es')['Drawer'] ADrawer: typeof import('ant-design-vue/es')['Drawer']
ADropdown: typeof import('ant-design-vue/es')['Dropdown'] ADropdown: typeof import('ant-design-vue/es')['Dropdown']
ADropdownButton: typeof import('ant-design-vue/es')['DropdownButton']
AEmpty: typeof import('ant-design-vue/es')['Empty'] AEmpty: typeof import('ant-design-vue/es')['Empty']
AForm: typeof import('ant-design-vue/es')['Form'] AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem'] AFormItem: typeof import('ant-design-vue/es')['FormItem']
@ -59,6 +60,7 @@ declare module 'vue' {
AreaChartOutlined: typeof import('@ant-design/icons-vue')['AreaChartOutlined'] AreaChartOutlined: typeof import('@ant-design/icons-vue')['AreaChartOutlined']
AResult: typeof import('ant-design-vue/es')['Result'] AResult: typeof import('ant-design-vue/es')['Result']
ARow: typeof import('ant-design-vue/es')['Row'] ARow: typeof import('ant-design-vue/es')['Row']
ArrowRightOutlined: typeof import('@ant-design/icons-vue')['ArrowRightOutlined']
ASelect: typeof import('ant-design-vue/es')['Select'] ASelect: typeof import('ant-design-vue/es')['Select']
ASelectOptGroup: typeof import('ant-design-vue/es')['SelectOptGroup'] ASelectOptGroup: typeof import('ant-design-vue/es')['SelectOptGroup']
ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
@ -87,6 +89,7 @@ declare module 'vue' {
BarsOutlined: typeof import('@ant-design/icons-vue')['BarsOutlined'] BarsOutlined: typeof import('@ant-design/icons-vue')['BarsOutlined']
BlockOutlined: typeof import('@ant-design/icons-vue')['BlockOutlined'] BlockOutlined: typeof import('@ant-design/icons-vue')['BlockOutlined']
CheckCircleFilled: typeof import('@ant-design/icons-vue')['CheckCircleFilled'] CheckCircleFilled: typeof import('@ant-design/icons-vue')['CheckCircleFilled']
CheckCircleOutlined: typeof import('@ant-design/icons-vue')['CheckCircleOutlined']
CheckOutlined: typeof import('@ant-design/icons-vue')['CheckOutlined'] CheckOutlined: typeof import('@ant-design/icons-vue')['CheckOutlined']
CloseOutlined: typeof import('@ant-design/icons-vue')['CloseOutlined'] CloseOutlined: typeof import('@ant-design/icons-vue')['CloseOutlined']
CloudDownloadOutlined: typeof import('@ant-design/icons-vue')['CloudDownloadOutlined'] CloudDownloadOutlined: typeof import('@ant-design/icons-vue')['CloudDownloadOutlined']
@ -125,10 +128,16 @@ declare module 'vue' {
LogoutOutlined: typeof import('@ant-design/icons-vue')['LogoutOutlined'] LogoutOutlined: typeof import('@ant-design/icons-vue')['LogoutOutlined']
LogView: typeof import('./../components/logView/index.vue')['default'] LogView: typeof import('./../components/logView/index.vue')['default']
MenuOutlined: typeof import('@ant-design/icons-vue')['MenuOutlined'] MenuOutlined: typeof import('@ant-design/icons-vue')['MenuOutlined']
MessageOutlined: typeof import('@ant-design/icons-vue')['MessageOutlined']
MinusCircleOutlined: typeof import('@ant-design/icons-vue')['MinusCircleOutlined'] MinusCircleOutlined: typeof import('@ant-design/icons-vue')['MinusCircleOutlined']
MoreOutlined: typeof import('@ant-design/icons-vue')['MoreOutlined']
PlayCircleOutlined: typeof import('@ant-design/icons-vue')['PlayCircleOutlined']
PlusOutlined: typeof import('@ant-design/icons-vue')['PlusOutlined'] PlusOutlined: typeof import('@ant-design/icons-vue')['PlusOutlined']
PlusSquareOutlined: typeof import('@ant-design/icons-vue')['PlusSquareOutlined']
ProfileOutlined: typeof import('@ant-design/icons-vue')['ProfileOutlined'] ProfileOutlined: typeof import('@ant-design/icons-vue')['ProfileOutlined']
PushpinOutlined: typeof import('@ant-design/icons-vue')['PushpinOutlined']
QuestionCircleOutlined: typeof import('@ant-design/icons-vue')['QuestionCircleOutlined'] QuestionCircleOutlined: typeof import('@ant-design/icons-vue')['QuestionCircleOutlined']
RedoOutlined: typeof import('@ant-design/icons-vue')['RedoOutlined']
ReloadOutlined: typeof import('@ant-design/icons-vue')['ReloadOutlined'] ReloadOutlined: typeof import('@ant-design/icons-vue')['ReloadOutlined']
RestOutlined: typeof import('@ant-design/icons-vue')['RestOutlined'] RestOutlined: typeof import('@ant-design/icons-vue')['RestOutlined']
RetweetOutlined: typeof import('@ant-design/icons-vue')['RetweetOutlined'] RetweetOutlined: typeof import('@ant-design/icons-vue')['RetweetOutlined']
@ -142,11 +151,13 @@ declare module 'vue' {
SortAscendingOutlined: typeof import('@ant-design/icons-vue')['SortAscendingOutlined'] SortAscendingOutlined: typeof import('@ant-design/icons-vue')['SortAscendingOutlined']
SortDescendingOutlined: typeof import('@ant-design/icons-vue')['SortDescendingOutlined'] SortDescendingOutlined: typeof import('@ant-design/icons-vue')['SortDescendingOutlined']
StopFilled: typeof import('@ant-design/icons-vue')['StopFilled'] StopFilled: typeof import('@ant-design/icons-vue')['StopFilled']
StopOutlined: typeof import('@ant-design/icons-vue')['StopOutlined']
SwapOutlined: typeof import('@ant-design/icons-vue')['SwapOutlined'] SwapOutlined: typeof import('@ant-design/icons-vue')['SwapOutlined']
SwitcherOutlined: typeof import('@ant-design/icons-vue')['SwitcherOutlined'] SwitcherOutlined: typeof import('@ant-design/icons-vue')['SwitcherOutlined']
SyncOutlined: typeof import('@ant-design/icons-vue')['SyncOutlined'] SyncOutlined: typeof import('@ant-design/icons-vue')['SyncOutlined']
TableOutlined: typeof import('@ant-design/icons-vue')['TableOutlined'] TableOutlined: typeof import('@ant-design/icons-vue')['TableOutlined']
TagOutlined: typeof import('@ant-design/icons-vue')['TagOutlined'] TagOutlined: typeof import('@ant-design/icons-vue')['TagOutlined']
TagsOutlined: typeof import('@ant-design/icons-vue')['TagsOutlined']
Terminal: typeof import('./../components/terminal/index.vue')['default'] Terminal: typeof import('./../components/terminal/index.vue')['default']
UnorderedListOutlined: typeof import('@ant-design/icons-vue')['UnorderedListOutlined'] UnorderedListOutlined: typeof import('@ant-design/icons-vue')['UnorderedListOutlined']
Upgrade: typeof import('./../components/upgrade/index.vue')['default'] Upgrade: typeof import('./../components/upgrade/index.vue')['default']

View File

@ -1,7 +1,90 @@
<template> <template>
<div> <div>
<a-spin tip="加载构建数据中" :spinning="loading"> <a-spin tip="加载构建数据中" :spinning="loading">
<a-card>
<template #title>
<a-steps v-model:current="stepsCurrent" size="small" :items="stepsItems"></a-steps>
</template>
<a-form ref="editBuildForm" :rules="rules" :model="temp" :label-col="{ span: 3 }" :wrapper-col="{ span: 20 }"> <a-form ref="editBuildForm" :rules="rules" :model="temp" :label-col="{ span: 3 }" :wrapper-col="{ span: 20 }">
<div v-show="stepsCurrent === 0">
<a-alert message="如何选择构建方式" type="info" show-icon>
<template #description>
<ul>
<li>
本地构建是指直接在服务端中的服务器执行构建命令
<ul>
<li>注意执行相关命令需要所在服务器中存在对应的环境</li>
<li>并且配置正确的环境变量</li>
<li>如果是在启动服务端后安装并配置的环境变量需要通过终端命令来重启服务端才能生效</li>
</ul>
</li>
<li>
容器构建是指使用 docker 容器执行构建,这样可以达到和宿主机环境隔离不用安装依赖环境
<ul>
<li>使用容器构建docker 容器所在的宿主机需要有公网,因为需要远程下载环境依赖的 sdk 和镜像</li>
</ul>
</li>
<li>创建后构建方式不支持修改</li>
<li style="color: red" v-if="this.getExtendPlugins.indexOf('inDocker') > -1">
容器安装的服务端不能使用本地构建因为本地构建依赖启动服务端本地的环境容器方式安装不便于管理本地依赖插件
</li>
</ul>
</template>
</a-alert>
<a-form-item :name="['buildMode']">
<template #label> 构建方式 </template>
<a-space>
<a-radio-group
:disabled="temp.id ? true : false"
v-model:value="temp.buildMode"
name="buildMode"
@change="changeBuildMode"
>
<a-radio
v-for="item in buildModeArray"
:disabled="item.disabled"
:key="item.value"
:value="item.value"
>{{ item.name }}</a-radio
>
</a-radio-group>
</a-space>
</a-form-item>
<template v-if="temp.buildMode === 1">
<a-form-item>
<template #help>
<a-button
type="link"
@click="
() => {
this.dockerListVisible = 1
}
"
>
查看当前可用容器
</a-button>
</template>
<template #label> 可用标签 </template>
<a-spin tip="加载容器可用标签中...." :spinning="dockerAllTagLoading">
<a-space v-if="dockerAllTagList && dockerAllTagList.length">
<a-tag v-for="(item, index) in dockerAllTagList" :key="index">{{ item }}</a-tag>
</a-space>
<span v-else>还没有容器或者未配置标签不可以使用容器构建奥</span>
</a-spin>
</a-form-item>
<a-alert message="容器构建注意" type="warning" show-icon>
<template #description>
<ul>
<li>实现您需要配置 docker 容器到服务端中来管理并且分配到当前工作空间中</li>
<li>为当前工作空间中的容器配置标签</li>
<li>需要将标签值配置到构建 DSL 中的 <b style="color: red">fromTag</b> 字段</li>
</ul>
</template>
</a-alert>
</template>
</div>
<div v-show="stepsCurrent === 1">
<a-form-item label="名称" name="name"> <a-form-item label="名称" name="name">
<a-row> <a-row>
<a-col :span="10"> <a-col :span="10">
@ -105,40 +188,9 @@
/> />
</a-form-item> </a-form-item>
</template> </template>
</div>
<a-collapse v-model:activeKey="collapseKey" expandIconPosition="right"> <div v-show="stepsCurrent === 2">
<a-collapse-panel key="0">
<template v-slot:header>
<a-form-item name="buildMode" no-style>
<a-space>
<a-tooltip>
方式
<template v-slot:title>
<ul>
<li>本地构建是指直接在服务端中的服务器执行构建命令</li>
<li>容器构建是指使用 docker 容器执行构建,这样可以达到和宿主机环境隔离不用安装依赖环境</li>
<li>使用容器构建docker 容器所在的宿主机需要有公网,因为需要远程下载环境依赖的 sdk 和镜像</li>
<li>创建后构建方式不支持修改</li>
<li v-if="this.getExtendPlugins.indexOf('inDocker') > -1">容器安装的服务端不能使用本地构建</li>
</ul>
</template>
<QuestionCircleOutlined v-if="!temp.id" />
</a-tooltip>
<a-radio-group :disabled="temp.id ? true : false" v-model:value="temp.buildMode" name="buildMode">
<a-radio
v-for="item in buildModeArray"
:disabled="item.disabled"
:key="item.value"
:value="item.value"
>{{ item.name }}</a-radio
>
</a-radio-group>
</a-space>
</a-form-item>
</template>
<div v-if="temp.buildMode === undefined" style="text-align: center">请选择构建方式</div>
<a-form-item v-if="temp.buildMode === 0" name="script"> <a-form-item v-if="temp.buildMode === 0" name="script">
<template v-slot:label> <template v-slot:label>
<a-tooltip> <a-tooltip>
@ -273,11 +325,12 @@
placeholder="构建产物目录,相对仓库的路径,如 java 项目的 target/xxx.jar vue 项目的 dist" placeholder="构建产物目录,相对仓库的路径,如 java 项目的 target/xxx.jar vue 项目的 dist"
/> />
</a-form-item> </a-form-item>
</a-collapse-panel> <div v-if="temp.buildMode === undefined">还没有选择构建方式</div>
<a-collapse-panel key="1"> </div>
<template v-slot:header>
<a-form-item name="releaseMethod" no-style> <div v-show="stepsCurrent === 3">
<a-space> <a-form-item name="releaseMethod">
<template #label>
<a-tooltip> <a-tooltip>
发布操作 发布操作
<template v-slot:title> <template v-slot:title>
@ -297,15 +350,13 @@
</template> </template>
<QuestionCircleOutlined v-if="!temp.id" /> <QuestionCircleOutlined v-if="!temp.id" />
</a-tooltip> </a-tooltip>
</template>
<a-space>
<a-radio-group v-model:value="temp.releaseMethod" name="releaseMethod"> <a-radio-group v-model:value="temp.releaseMethod" name="releaseMethod">
<a-radio v-for="(val, key) in releaseMethodMap" :key="key" :value="parseInt(key)">{{ <a-radio v-for="(val, key) in releaseMethodMap" :key="key" :value="parseInt(key)">{{ val }}</a-radio>
val
}}</a-radio>
</a-radio-group> </a-radio-group>
</a-space> </a-space>
</a-form-item> </a-form-item>
</template>
<div v-if="!temp.releaseMethod" style="text-align: center">请选择发布方式</div> <div v-if="!temp.releaseMethod" style="text-align: center">请选择发布方式</div>
<template v-else> <template v-else>
<template v-if="temp.releaseMethod === 0"> <template v-if="temp.releaseMethod === 0">
@ -715,11 +766,9 @@
</a-form-item> </a-form-item>
</template> </template>
</template> </template>
</a-collapse-panel> </div>
<a-collapse-panel key="2">
<template v-slot:header> <div v-show="stepsCurrent === 4">
<a-form-item label="" no-style>其他配置</a-form-item>
</template>
<a-form-item name="cacheBuild"> <a-form-item name="cacheBuild">
<template v-slot:label> <template v-slot:label>
<a-tooltip> <a-tooltip>
@ -1019,9 +1068,9 @@
placeholder="排除发布 ANT 表达式,多个使用逗号分隔" placeholder="排除发布 ANT 表达式,多个使用逗号分隔"
/> />
</a-form-item> </a-form-item>
</a-collapse-panel> </div>
</a-collapse>
</a-form> </a-form>
</a-card>
</a-spin> </a-spin>
<!-- 选择仓库 --> <!-- 选择仓库 -->
<a-drawer <a-drawer
@ -1153,6 +1202,22 @@
</a-space> </a-space>
</template> </template>
</a-drawer> </a-drawer>
<!-- 查看容器 -->
<a-drawer
destroyOnClose
:title="`查看容器`"
placement="right"
:open="dockerListVisible != 0"
width="70vw"
:zIndex="1009"
@close="
() => {
this.dockerListVisible = 0
}
"
>
<docker-list v-if="dockerListVisible" ref="dockerlist"></docker-list>
</a-drawer>
<!-- 查看命令示例 --> <!-- 查看命令示例 -->
<a-modal <a-modal
@ -1199,6 +1264,7 @@
import codeEditor from '@/components/codeEditor' import codeEditor from '@/components/codeEditor'
import repository from '@/pages/repository/list.vue' import repository from '@/pages/repository/list.vue'
import scriptPage from '@/pages/script/script-list.vue' import scriptPage from '@/pages/script/script-list.vue'
import DockerList from '@/pages/docker/list'
import CustomSelect from '@/components/customSelect' import CustomSelect from '@/components/customSelect'
import { dockerSwarmListAll, dockerSwarmServicesList } from '@/api/docker-swarm' import { dockerSwarmListAll, dockerSwarmServicesList } from '@/api/docker-swarm'
import { import {
@ -1215,15 +1281,17 @@ import { getNodeListAll, getProjectListAll } from '@/api/node'
// import { getScriptListAll } from "@/api/server-script"; // import { getScriptListAll } from "@/api/server-script";
import { getDishPatchListAll } from '@/api/dispatch' import { getDishPatchListAll } from '@/api/dispatch'
import { itemGroupBy, CRON_DATA_SOURCE, randomStr } from '@/utils/const' import { itemGroupBy, CRON_DATA_SOURCE, randomStr } from '@/utils/const'
import { mapState } from 'pinia'
import { useGuideStore } from '@/stores/guide' import { useGuideStore } from '@/stores/guide'
import { afterOptListSimple } from '@/api/dispatch' import { afterOptListSimple } from '@/api/dispatch'
import { dockerAllTag } from '@/api/docker-api'
export default { export default {
components: { components: {
CustomSelect, CustomSelect,
codeEditor, codeEditor,
repository, repository,
scriptPage scriptPage,
DockerList
}, },
data() { data() {
return { return {
@ -1318,9 +1386,49 @@ export default {
branchName: [{ required: true, message: '请选择分支', trigger: 'blur' }], branchName: [{ required: true, message: '请选择分支', trigger: 'blur' }],
script: [{ required: true, message: '请填写构建命令', trigger: 'blur' }], script: [{ required: true, message: '请填写构建命令', trigger: 'blur' }],
resultDirFile: [{ required: true, message: '请填写产物目录', trigger: 'blur' }], resultDirFile: [{ required: true, message: '请填写产物目录', trigger: 'blur' }],
releasePath: [{ required: true, message: '请填写发布目录', trigger: 'blur' }], // releasePath: [{ required: true, message: '', trigger: 'blur' }],
repositoryId: [{ required: true, message: '请填选择构建的仓库', trigger: 'blur' }] repositoryId: [{ required: true, message: '请填选择构建的仓库', trigger: 'blur' }]
}, },
rulesSteps: [
['buildMode'],
['name', 'branchName', 'repositoryId'],
['script', 'resultDirFile'],
['releaseMethod']
// name: [{ required: true, message: '', trigger: 'blur', stepsCurrent: 1 }],
// buildMode: [{ required: true, message: '', trigger: 'blur', stepsCurrent: 0 }],
// releaseMethod: [{ required: true, message: '', trigger: 'blur', stepsCurrent: 3 }],
// branchName: [{ required: true, message: '', trigger: 'blur', stepsCurrent: 1 }],
// script: [{ required: true, message: '', trigger: 'blur', stepsCurrent: 2 }],
// resultDirFile: [{ required: true, message: '', trigger: 'blur', stepsCurrent: 2 }],
// // releasePath: [{ required: true, message: '', trigger: 'blur' }],
// repositoryId: [{ required: true, message: '', trigger: 'blur', stepsCurrent: 1 }]
],
stepsCurrent: 0,
stepsItems: [
{
title: '构建方式'
},
{
title: '基础信息'
// status: 'process'
},
{
title: '构建流程'
// status: 'wait'
},
{
title: '发布操作'
// status: 'wait'
},
{
title: '其他配置'
// status: 'wait'
}
],
dslDefault: dslDefault:
'# 基础镜像 目前仅支持 ubuntu-latest\n' + '# 基础镜像 目前仅支持 ubuntu-latest\n' +
'runsOn: ubuntu-latest\n' + 'runsOn: ubuntu-latest\n' +
@ -1366,7 +1474,9 @@ export default {
'env:\n' + 'env:\n' +
' NODE_OPTIONS: --max-old-space-size=900', ' NODE_OPTIONS: --max-old-space-size=900',
loading: false, loading: false,
collapseKey: ['0', '1', '2'] dockerListVisible: 0,
dockerAllTagList: [],
dockerAllTagLoading: true
} }
}, },
computed: { computed: {
@ -1442,10 +1552,13 @@ export default {
this.$refs['editBuildForm']?.resetFields() this.$refs['editBuildForm']?.resetFields()
}, },
// //
handleEdit(record) { handleEdit(record, steps) {
this.$refs['editBuildForm']?.resetFields() this.$refs['editBuildForm']?.resetFields()
this.temp = Object.assign({}, record) this.temp = Object.assign({}, record)
this.temp.buildMode = this.temp.buildMode || 0 this.temp.buildMode = this.temp.buildMode || 0
if (this.temp.buildMode === 1) {
this.loadDockerAllTag()
}
// //
this.tempExtraData = JSON.parse(record.extraData) || {} this.tempExtraData = JSON.parse(record.extraData) || {}
if (typeof this.tempExtraData === 'string') { if (typeof this.tempExtraData === 'string') {
@ -1505,6 +1618,8 @@ export default {
} }
} }
}) })
//
this.stepsCurrent = steps === undefined ? 2 : steps
}, },
// // // //
// loadScriptListList() { // loadScriptListList() {
@ -1579,7 +1694,9 @@ export default {
// //
handleEditBuildOk(build) { handleEditBuildOk(build) {
// //
this.$refs['editBuildForm'].validate().then(() => { this.$refs['editBuildForm']
.validate()
.then(() => {
const tempExtraData = Object.assign({}, this.tempExtraData) const tempExtraData = Object.assign({}, this.tempExtraData)
// //
if (this.temp.releaseMethod === 2) { if (this.temp.releaseMethod === 2) {
@ -1617,6 +1734,25 @@ export default {
} }
}) })
}) })
.catch(({ errorFields }) => {
if (errorFields && errorFields[0]) {
const msg = errorFields[0].errors && errorFields[0].errors[0]
if (msg) {
$notification.warn({
message: msg
})
// console.log(error)
}
//
const filedName = errorFields[0].name && errorFields[0].name[0]
filedName &&
this.rulesSteps.forEach((item, index) => {
if (item.includes(filedName)) {
this.stepsCurrent = index
}
})
}
})
}, },
// //
changeRepositpry(noPullBranch) { changeRepositpry(noPullBranch) {
@ -1679,6 +1815,24 @@ export default {
this.groupList = res.data this.groupList = res.data
} }
}) })
},
changeBuildMode(e) {
if (e.target.value === 1) {
this.loadDockerAllTag()
}
},
// docker tag
loadDockerAllTag() {
this.dockerAllTagLoading = true
dockerAllTag()
.then((res) => {
if (res.code === 200) {
this.dockerAllTagList = res.data || []
}
})
.finally(() => {
this.dockerAllTagLoading = false
})
} }
}, },
emits: ['close', 'confirm'] emits: ['close', 'confirm']

View File

@ -201,8 +201,28 @@
</a-menu> </a-menu>
</template> </template>
</a-dropdown> </a-dropdown>
<a-dropdown>
<a-button size="small" type="primary" @click="handleEdit(item)">编辑</a-button> <a-button size="small" type="primary" @click="handleEdit(item)">编辑</a-button>
<template #overlay>
<a-menu>
<a-menu-item @click="handleEdit(item, 0)">
<a href="javascript:;">构建方式</a>
</a-menu-item>
<a-menu-item @click="handleEdit(item, 1)">
<a href="javascript:;">基础信息</a>
</a-menu-item>
<a-menu-item @click="handleEdit(item, 2)">
<a href="javascript:;">构建流程</a>
</a-menu-item>
<a-menu-item @click="handleEdit(item, 3)">
<a href="javascript:;">发布操作</a>
</a-menu-item>
<a-menu-item @click="handleEdit(item, 4)">
<a href="javascript:;">其他配置</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
<a-button size="small" @click="handleDelete(item)">删除</a-button> <a-button size="small" @click="handleDelete(item)">删除</a-button>
<a-tooltip <a-tooltip
placement="leftBottom" placement="leftBottom"
@ -363,7 +383,28 @@
</a-menu> </a-menu>
</template> </template>
</a-dropdown> </a-dropdown>
<a-dropdown>
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button> <a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
<template #overlay>
<a-menu>
<a-menu-item @click="handleEdit(record, 0)">
<a href="javascript:;">构建方式</a>
</a-menu-item>
<a-menu-item @click="handleEdit(record, 1)">
<a href="javascript:;">基础信息</a>
</a-menu-item>
<a-menu-item @click="handleEdit(record, 2)">
<a href="javascript:;">构建流程</a>
</a-menu-item>
<a-menu-item @click="handleEdit(record, 3)">
<a href="javascript:;">发布操作</a>
</a-menu-item>
<a-menu-item @click="handleEdit(record, 4)">
<a href="javascript:;">其他配置</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
<a-dropdown> <a-dropdown>
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()"> <a class="ant-dropdown-link" @click="(e) => e.preventDefault()">
更多 更多
@ -986,13 +1027,13 @@ export default {
delete temp.id delete temp.id
delete temp.triggerToken delete temp.triggerToken
temp.name = temp.name + '副本' temp.name = temp.name + '副本'
this.handleEdit(temp) this.handleEdit(temp, 1)
}, },
handleEdit(record) { handleEdit(record, steps) {
this.editBuildVisible = 2 this.editBuildVisible = 2
this.temp = { id: record.id, triggerToken: record.triggerToken } this.temp = { id: record.id, triggerToken: record.triggerToken }
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.editBuild.handleEdit({ ...record }) this.$refs.editBuild.handleEdit({ ...record }, steps)
}) })
}, },
handleDetails(record) { handleDetails(record) {