mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-11-30 10:58:14 +08:00
fix 构建详情页面布局(构建触发器、查看构建历史)
This commit is contained in:
parent
3a3547966d
commit
fecb477caf
@ -1,6 +1,6 @@
|
|||||||
# 🚀 版本日志
|
# 🚀 版本日志
|
||||||
|
|
||||||
### 2.10.38.5
|
### 2.10.38.5-beta
|
||||||
|
|
||||||
### 🐣 新增功能
|
### 🐣 新增功能
|
||||||
|
|
||||||
@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
1. 【server】优化 证书管理支持使用文件管理部署
|
1. 【server】优化 证书管理支持使用文件管理部署
|
||||||
2. 【server】优化 节点管理中项目管理和脚本管理菜单合并为一个菜单
|
2. 【server】优化 节点管理中项目管理和脚本管理菜单合并为一个菜单
|
||||||
|
3. 【server】修复 节点分发构建确认弹窗筛选项目不生效问题
|
||||||
|
4. 【server】修复 无法使用添加构建功能
|
||||||
|
5. 【server】修复 资产管理 ssh 分组不生效问题(感谢@A)
|
||||||
|
6. 【server】优化 构建详情页面布局(构建触发器、查看构建历史)
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
|
@ -141,11 +141,11 @@ public class BuildInfoController extends BaseServerController {
|
|||||||
*
|
*
|
||||||
* @return json
|
* @return json
|
||||||
*/
|
*/
|
||||||
@GetMapping(value = "/build/list_all", produces = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(value = "/build/get", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@Feature(method = MethodFeature.LIST)
|
@Feature(method = MethodFeature.LIST)
|
||||||
public JsonMessage<List<BuildInfoModel>> getBuildListAll(HttpServletRequest request) {
|
public JsonMessage<BuildInfoModel> getBuildListAll(String id, HttpServletRequest request) {
|
||||||
// load list with page
|
// load list with page
|
||||||
List<BuildInfoModel> modelList = buildInfoService.listByWorkspace(request);
|
BuildInfoModel modelList = buildInfoService.getByKey(id, request);
|
||||||
return JsonMessage.success("", modelList);
|
return JsonMessage.success("", modelList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ public class BuildInfoController extends BaseServerController {
|
|||||||
@RequestMapping(value = "/build/branch-list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(value = "/build/branch-list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@Feature(method = MethodFeature.LIST)
|
@Feature(method = MethodFeature.LIST)
|
||||||
public JsonMessage<JSONObject> branchList(
|
public JsonMessage<JSONObject> branchList(
|
||||||
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "仓库ID不能为空") String repositoryId) throws Exception {
|
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "仓库ID不能为空") String repositoryId) throws Exception {
|
||||||
// 根据 repositoryId 查询仓库信息
|
// 根据 repositoryId 查询仓库信息
|
||||||
RepositoryModel repositoryModel = repositoryService.getByKey(repositoryId, false);
|
RepositoryModel repositoryModel = repositoryService.getByKey(repositoryId, false);
|
||||||
Assert.notNull(repositoryModel, "无效的仓库信息");
|
Assert.notNull(repositoryModel, "无效的仓库信息");
|
||||||
|
@ -141,7 +141,8 @@ public class MachineSshController extends BaseGroupNameController {
|
|||||||
String charset,
|
String charset,
|
||||||
String id,
|
String id,
|
||||||
Integer timeout,
|
Integer timeout,
|
||||||
String allowEditSuffix) {
|
String allowEditSuffix,
|
||||||
|
String groupName) {
|
||||||
boolean add = StrUtil.isEmpty(id);
|
boolean add = StrUtil.isEmpty(id);
|
||||||
if (add) {
|
if (add) {
|
||||||
// 优先判断参数 如果是 password 在修改时可以不填写
|
// 优先判断参数 如果是 password 在修改时可以不填写
|
||||||
@ -156,6 +157,7 @@ public class MachineSshController extends BaseGroupNameController {
|
|||||||
}
|
}
|
||||||
MachineSshModel sshModel = new MachineSshModel();
|
MachineSshModel sshModel = new MachineSshModel();
|
||||||
sshModel.setId(id);
|
sshModel.setId(id);
|
||||||
|
sshModel.setGroupName(groupName);
|
||||||
sshModel.setHost(host);
|
sshModel.setHost(host);
|
||||||
// 如果密码传递不为空就设置值 因为上面已经判断了只有修改的情况下 password 才可能为空
|
// 如果密码传递不为空就设置值 因为上面已经判断了只有修改的情况下 password 才可能为空
|
||||||
if (StrUtil.isNotEmpty(password)) {
|
if (StrUtil.isNotEmpty(password)) {
|
||||||
@ -256,10 +258,10 @@ public class MachineSshController extends BaseGroupNameController {
|
|||||||
@PostMapping(value = "save-workspace-config", produces = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(value = "save-workspace-config", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@Feature(method = MethodFeature.EDIT)
|
@Feature(method = MethodFeature.EDIT)
|
||||||
public JsonMessage<String> saveWorkspaceConfig(
|
public JsonMessage<String> saveWorkspaceConfig(
|
||||||
String fileDirs,
|
String fileDirs,
|
||||||
@ValidatorItem String id,
|
@ValidatorItem String id,
|
||||||
String notAllowedCommand,
|
String notAllowedCommand,
|
||||||
String allowEditSuffix) {
|
String allowEditSuffix) {
|
||||||
SshModel sshModel = new SshModel(id);
|
SshModel sshModel = new SshModel(id);
|
||||||
// 目录
|
// 目录
|
||||||
if (StrUtil.isEmpty(fileDirs)) {
|
if (StrUtil.isEmpty(fileDirs)) {
|
||||||
@ -364,21 +366,21 @@ public class MachineSshController extends BaseGroupNameController {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
listPage.getResult()
|
listPage.getResult()
|
||||||
.stream()
|
.stream()
|
||||||
.map((Function<MachineSshModel, List<Object>>) machineSshModel -> CollUtil.newArrayList(
|
.map((Function<MachineSshModel, List<Object>>) machineSshModel -> CollUtil.newArrayList(
|
||||||
machineSshModel.getName(),
|
machineSshModel.getName(),
|
||||||
machineSshModel.getGroupName(),
|
machineSshModel.getGroupName(),
|
||||||
machineSshModel.getHost(),
|
machineSshModel.getHost(),
|
||||||
machineSshModel.getPort(),
|
machineSshModel.getPort(),
|
||||||
machineSshModel.getUser(),
|
machineSshModel.getUser(),
|
||||||
machineSshModel.getPassword(),
|
machineSshModel.getPassword(),
|
||||||
machineSshModel.getCharset(),
|
machineSshModel.getCharset(),
|
||||||
machineSshModel.getConnectType(),
|
machineSshModel.getConnectType(),
|
||||||
machineSshModel.getPrivateKey(),
|
machineSshModel.getPrivateKey(),
|
||||||
machineSshModel.getTimeout()
|
machineSshModel.getTimeout()
|
||||||
))
|
))
|
||||||
.map(objects -> objects.stream().map(StrUtil::toStringOrNull).toArray(String[]::new))
|
.map(objects -> objects.stream().map(StrUtil::toStringOrNull).toArray(String[]::new))
|
||||||
.forEach(writer::writeLine);
|
.forEach(writer::writeLine);
|
||||||
if (ObjectUtil.equal(listPage.getPage(), listPage.getTotalPage())) {
|
if (ObjectUtil.equal(listPage.getPage(), listPage.getTotalPage())) {
|
||||||
// 最后一页
|
// 最后一页
|
||||||
break;
|
break;
|
||||||
|
@ -67,10 +67,7 @@ import java.security.KeyStore;
|
|||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.util.Enumeration;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author bwcx_jzy
|
* @author bwcx_jzy
|
||||||
@ -372,7 +369,8 @@ public class CertificateInfoController extends BaseServerController {
|
|||||||
String absolutePath = FileUtil.file(tempSave, model.getSerialNumberStr() + ".zip").getAbsolutePath();
|
String absolutePath = FileUtil.file(tempSave, model.getSerialNumberStr() + ".zip").getAbsolutePath();
|
||||||
File zip = ZipUtil.zip(file.getAbsolutePath(), absolutePath, false);
|
File zip = ZipUtil.zip(file.getAbsolutePath(), absolutePath, false);
|
||||||
// 添加到文件中心
|
// 添加到文件中心
|
||||||
String fileId = fileStorageService.addFile(zip, 3, certificateInfoService.getCheckUserWorkspace(request), model.getSerialNumberStr() + model.getDescription(), null, 1);
|
String description = model.getSerialNumberStr() + Optional.ofNullable(model.getDescription()).map(s -> "," + s).orElse(StrUtil.EMPTY);
|
||||||
|
String fileId = fileStorageService.addFile(zip, 3, certificateInfoService.getCheckUserWorkspace(request), description, null, 1);
|
||||||
String releasePath = FileUtil.normalize(releasePathParent + StrUtil.SLASH + releasePathSecondary);
|
String releasePath = FileUtil.normalize(releasePathParent + StrUtil.SLASH + releasePathSecondary);
|
||||||
// 创建发布任务
|
// 创建发布任务
|
||||||
Map<String, String> env = new HashMap<>();
|
Map<String, String> env = new HashMap<>();
|
||||||
|
155
web-vue/src/pages/build/details.vue
Normal file
155
web-vue/src/pages/build/details.vue
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-descriptions bordered>
|
||||||
|
<a-descriptions-item label="构建名称"> {{ data.name }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="最新构建ID">
|
||||||
|
<a-tag color="#108ee9">#{{ data.buildId }}</a-tag>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="分组"> {{ data.group }} </a-descriptions-item>
|
||||||
|
<a-descriptions-item label="分组/标签"> {{ data.branchName }} </a-descriptions-item>
|
||||||
|
<a-descriptions-item label="构建方式">
|
||||||
|
<template v-if="data.bubuildMode === 1">
|
||||||
|
<a-icon type="cloud" />
|
||||||
|
容器构建
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a-icon type="code" />
|
||||||
|
本地构建
|
||||||
|
</template>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="产物目录"> {{ data.resultDirFile }} </a-descriptions-item>
|
||||||
|
<a-descriptions-item label="构建状态">
|
||||||
|
<a-tag :color="statusColor[data.status]">{{ statusMap[data.status] || "未知" }}</a-tag>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="发布方式">{{ releaseMethodMap[data.releaseMethod] }} </a-descriptions-item>
|
||||||
|
<a-descriptions-item label="定时构建"> {{ data.autoBuildCron }} </a-descriptions-item>
|
||||||
|
<a-descriptions-item label="创建时间"> {{ parseTime(data.createTimeMillis) }} </a-descriptions-item>
|
||||||
|
<a-descriptions-item label="最后修改时间"> {{ parseTime(data.modifyTimeMillis) }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="最后修改人">{{ data.modifyUser }}</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
|
||||||
|
<a-row type="flex" justify="center">
|
||||||
|
<a-divider v-if="listQuery.total > 1" dashed>构建历史</a-divider>
|
||||||
|
<a-timeline mode="alternate" style="width: 100%">
|
||||||
|
<a-timeline-item v-for="item in this.historyList" :key="item.id" :color="statusColor[item.status]">
|
||||||
|
<template slot="dot"> #{{ item.buildNumberId }}</template>
|
||||||
|
<a-space direction="vertical" :size="1">
|
||||||
|
<div v-if="item.buildRemark">构建备注:{{ item.buildRemark }}</div>
|
||||||
|
<div>
|
||||||
|
状态:<a-tag :color="statusColor[item.status]">{{ statusMap[item.status] || "未知" }}</a-tag>
|
||||||
|
</div>
|
||||||
|
<div>时间:{{ parseTime(item.startTime) }} ~ {{ parseTime(item.endTime) }}</div>
|
||||||
|
<div>触发类型:{{ triggerBuildTypeMap[item.triggerBuildType] || "未知" }}</div>
|
||||||
|
<div>占用空间:{{ renderSize(item.resultFileSize) }}(产物)/{{ renderSize(item.buildLogFileSize) }}(日志)</div>
|
||||||
|
|
||||||
|
<div>构建耗时:{{ formatDuration((item.endTime || 0) - (item.startTime || 0), "", 2) }}</div>
|
||||||
|
<div>
|
||||||
|
发布方式:
|
||||||
|
<a-tag> {{ releaseMethodMap[item.releaseMethod] || "未知" }}</a-tag>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
操作:
|
||||||
|
<a-space>
|
||||||
|
<a-tooltip title="下载构建日志,如果按钮不可用表示日志文件不存在,一般是构建历史相关文件被删除">
|
||||||
|
<a-button size="small" icon="download" type="primary" :disabled="!item.hasLog" @click="handleDownload(item)">日志</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
|
||||||
|
<a-tooltip title="下载构建产物,如果按钮不可用表示产物文件不存在,一般是构建没有产生对应的文件或者构建历史相关文件被删除">
|
||||||
|
<a-button size="small" icon="download" type="primary" :disabled="!item.hasFile" @click="handleFile(item)"> 产物 </a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</a-space>
|
||||||
|
</a-timeline-item>
|
||||||
|
</a-timeline>
|
||||||
|
<a-divider v-if="listQuery.total / listQuery.limit > 1" dashed />
|
||||||
|
<a-col>
|
||||||
|
<a-pagination
|
||||||
|
v-model="listQuery.page"
|
||||||
|
:showTotal="
|
||||||
|
(total) => {
|
||||||
|
return PAGE_DEFAULT_SHOW_TOTAL(total, listQuery);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:showSizeChanger="true"
|
||||||
|
:pageSizeOptions="PAGE_DEFAULT_SIZW_OPTIONS"
|
||||||
|
:pageSize="listQuery.limit"
|
||||||
|
:total="listQuery.total"
|
||||||
|
:hideOnSinglePage="true"
|
||||||
|
@showSizeChange="
|
||||||
|
(current, size) => {
|
||||||
|
this.listQuery.limit = size;
|
||||||
|
this.listHistory();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@change="this.listHistory"
|
||||||
|
show-less-items
|
||||||
|
/>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getBuildGet, releaseMethodMap, statusMap, geteBuildHistory, statusColor, triggerBuildTypeMap, downloadBuildFile, downloadBuildLog } from "@/api/build-info";
|
||||||
|
import { parseTime, PAGE_DEFAULT_LIST_QUERY, PAGE_DEFAULT_SIZW_OPTIONS, PAGE_DEFAULT_SHOW_TOTAL, renderSize, formatDuration } from "@/utils/const";
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
PAGE_DEFAULT_SIZW_OPTIONS,
|
||||||
|
triggerBuildTypeMap,
|
||||||
|
releaseMethodMap,
|
||||||
|
statusColor,
|
||||||
|
statusMap,
|
||||||
|
data: {},
|
||||||
|
listQuery: Object.assign({ buildDataId: this.id }, PAGE_DEFAULT_LIST_QUERY),
|
||||||
|
historyList: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getData();
|
||||||
|
this.listHistory();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
parseTime,
|
||||||
|
formatDuration,
|
||||||
|
PAGE_DEFAULT_SHOW_TOTAL,
|
||||||
|
renderSize,
|
||||||
|
// 获取构建数据
|
||||||
|
getData() {
|
||||||
|
// 构建基础信息
|
||||||
|
getBuildGet({
|
||||||
|
id: this.id,
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.data) {
|
||||||
|
this.data = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
listHistory() {
|
||||||
|
// 构建历史
|
||||||
|
geteBuildHistory(this.listQuery).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.historyList = res.data.result;
|
||||||
|
this.listQuery.total = res.data.total;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 下载构建日志
|
||||||
|
handleDownload(record) {
|
||||||
|
window.open(downloadBuildLog(record.id), "_blank");
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下载构建产物
|
||||||
|
handleFile(record) {
|
||||||
|
window.open(downloadBuildFile(record.id), "_blank");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
1187
web-vue/src/pages/build/edit.vue
Normal file
1187
web-vue/src/pages/build/edit.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div class="full-content">
|
||||||
<!-- <div ref="filter" class="filter">
|
|
||||||
|
|
||||||
<a-button type="primary" @click="handleFilter">刷新</a-button>
|
|
||||||
</div> -->
|
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table :data-source="list" size="middle" :columns="columns" :pagination="pagination" bordered rowKey="id" @change="change" :row-selection="rowSelection">
|
<a-table :data-source="list" size="middle" :columns="columns" :pagination="pagination" bordered rowKey="id" @change="change" :row-selection="rowSelection">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-select show-search option-filter-prop="children" v-model="listQuery.buildDataId" allowClear placeholder="请选择构建名称" class="search-input-item">
|
|
||||||
<a-select-option v-for="build in buildList" :key="build.id" :title="build.name">{{ build.name }}</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-select show-search option-filter-prop="children" v-model="listQuery.status" allowClear placeholder="请选择状态" class="search-input-item">
|
<a-select show-search option-filter-prop="children" v-model="listQuery.status" allowClear placeholder="请选择状态" class="search-input-item">
|
||||||
<a-select-option v-for="(val, key) in statusMap" :key="key">{{ val }}</a-select-option>
|
<a-select-option v-for="(val, key) in statusMap" :key="key">{{ val }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@ -52,9 +45,6 @@
|
|||||||
<span>{{ triggerBuildTypeMap[text] }}</span>
|
<span>{{ triggerBuildTypeMap[text] }}</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
|
||||||
<a-tooltip slot="startTime" slot-scope="text, record" :title="`开始时间:${parseTime(record.startTime)},${record.endTime ? '结束时间:' + parseTime(record.endTime) : ''}`">
|
|
||||||
<span>{{ parseTime(record.startTime) }}</span>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip slot="resultFileSize" slot-scope="text, record" :title="`产物文件大小:${renderSize(record.resultFileSize)}, 日志文件: ${renderSize(record.buildLogFileSize)}`">
|
<a-tooltip slot="resultFileSize" slot-scope="text, record" :title="`产物文件大小:${renderSize(record.resultFileSize)}, 日志文件: ${renderSize(record.buildLogFileSize)}`">
|
||||||
<span>{{ renderSize(record.resultFileSize) }}</span>
|
<span>{{ renderSize(record.resultFileSize) }}</span>
|
||||||
<!-- <div>{{ parseTime(record.endTime) }}</div> -->
|
<!-- <div>{{ parseTime(record.endTime) }}</div> -->
|
||||||
@ -107,7 +97,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import BuildLog from "./log";
|
import BuildLog from "./log";
|
||||||
import { deleteBuildHistory, downloadBuildFile, downloadBuildLog, getBuildListAll, geteBuildHistory, releaseMethodMap, rollback, statusMap, triggerBuildTypeMap } from "@/api/build-info";
|
import { deleteBuildHistory, downloadBuildFile, downloadBuildLog, geteBuildHistory, releaseMethodMap, rollback, statusMap, triggerBuildTypeMap } from "@/api/build-info";
|
||||||
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, formatDuration, parseTime, renderSize } from "@/utils/const";
|
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, formatDuration, parseTime, renderSize } from "@/utils/const";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -120,7 +110,7 @@ export default {
|
|||||||
triggerBuildTypeMap: triggerBuildTypeMap,
|
triggerBuildTypeMap: triggerBuildTypeMap,
|
||||||
loading: false,
|
loading: false,
|
||||||
list: [],
|
list: [],
|
||||||
buildList: [],
|
|
||||||
total: 0,
|
total: 0,
|
||||||
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
||||||
statusMap: statusMap,
|
statusMap: statusMap,
|
||||||
@ -139,16 +129,23 @@ export default {
|
|||||||
title: "开始时间",
|
title: "开始时间",
|
||||||
dataIndex: "startTime",
|
dataIndex: "startTime",
|
||||||
sorter: true,
|
sorter: true,
|
||||||
scopedSlots: { customRender: "startTime" },
|
customRender: (text) => parseTime(text),
|
||||||
width: "170px",
|
width: "170px",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "耗时",
|
title: "耗时",
|
||||||
dataIndex: "endTime",
|
dataIndex: "endTime",
|
||||||
sorter: true,
|
// sorter: true,
|
||||||
scopedSlots: { customRender: "endTime" },
|
scopedSlots: { customRender: "endTime" },
|
||||||
width: "120px",
|
width: "120px",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "数据更新时间",
|
||||||
|
dataIndex: "modifyTimeMillis",
|
||||||
|
sorter: true,
|
||||||
|
customRender: (text) => parseTime(text),
|
||||||
|
width: "170px",
|
||||||
|
},
|
||||||
{ title: "发布方式", dataIndex: "releaseMethod", width: "100px", ellipsis: true, scopedSlots: { customRender: "releaseMethod" } },
|
{ title: "发布方式", dataIndex: "releaseMethod", width: "100px", ellipsis: true, scopedSlots: { customRender: "releaseMethod" } },
|
||||||
{ title: "构建人", dataIndex: "modifyUser", width: "130px", ellipsis: true, scopedSlots: { customRender: "modifyUser" } },
|
{ title: "构建人", dataIndex: "modifyUser", width: "130px", ellipsis: true, scopedSlots: { customRender: "modifyUser" } },
|
||||||
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: "200px", align: "center", fixed: "right" },
|
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: "200px", align: "center", fixed: "right" },
|
||||||
@ -167,21 +164,14 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.loadBuildList();
|
// this.loadBuildList();
|
||||||
this.loadData();
|
this.loadData();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
parseTime,
|
parseTime,
|
||||||
renderSize,
|
renderSize,
|
||||||
formatDuration,
|
formatDuration,
|
||||||
// 加载构建列表
|
|
||||||
loadBuildList() {
|
|
||||||
getBuildListAll().then((res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.buildList = res.data;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
loadData(pointerEvent) {
|
loadData(pointerEvent) {
|
||||||
this.listQuery.page = pointerEvent?.altKey || pointerEvent?.ctrlKey ? 1 : this.listQuery.page;
|
this.listQuery.page = pointerEvent?.altKey || pointerEvent?.ctrlKey ? 1 : this.listQuery.page;
|
||||||
|
File diff suppressed because it is too large
Load Diff
236
web-vue/src/pages/build/trigger.vue
Normal file
236
web-vue/src/pages/build/trigger.vue
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-if="this.triggerToken || this.triggerVisible">
|
||||||
|
<a-form-model ref="editTriggerForm" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
|
<a-tabs default-active-key="1" type="card">
|
||||||
|
<template slot="tabBarExtraContent">
|
||||||
|
<a-tooltip title="重置触发器 token 信息,重置后之前的触发器 token 将失效">
|
||||||
|
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<a-tab-pane key="1" tab="执行构建">
|
||||||
|
<a-space style="display: block" direction="vertical" align="baseline">
|
||||||
|
<a-alert message="温馨提示" type="warning">
|
||||||
|
<template slot="description">
|
||||||
|
<ul>
|
||||||
|
<li>单个触发器地址中:第一个随机字符串为构建ID,第二个随机字符串为 token</li>
|
||||||
|
<li>重置为重新生成触发地址,重置成功后之前的触发器地址将失效,构建触发器绑定到生成触发器到操作人上,如果将对应的账号删除触发器将失效</li>
|
||||||
|
<li>批量构建参数 BODY json: [ { "id":"1", "token":"a", "delay":"0" } ]</li>
|
||||||
|
<li>批量构建参数还支持指定参数,delay(延迟执行构建,单位秒) branchName(分支名)、branchTagName(标签)、script(构建脚本)、resultDirFile(构建产物)、webhook(通知 webhook)</li>
|
||||||
|
<li>
|
||||||
|
批量构建全部参数举例 BODY json: [ { "id":"1", "token":"a", "delay":"0","branchName":"test","branchTagName":"1.*","script":"mvn clean
|
||||||
|
package","resultDirFile":"/target/","webhook":"http://test.com/webhook" } ]
|
||||||
|
</li>
|
||||||
|
<li>批量构建传入其他参数将同步执行修改</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert
|
||||||
|
v-clipboard:copy="temp.triggerBuildUrl"
|
||||||
|
v-clipboard:success="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.success({ message: '复制成功' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
v-clipboard:error="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.error({ message: '复制失败' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
type="info"
|
||||||
|
:message="`单个触发器地址(点击可以复制)`"
|
||||||
|
>
|
||||||
|
<template slot="description">
|
||||||
|
<a-tag>GET</a-tag> <span>{{ temp.triggerBuildUrl }} </span>
|
||||||
|
<a-icon type="copy" />
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert
|
||||||
|
v-clipboard:copy="temp.batchTriggerBuildUrl"
|
||||||
|
v-clipboard:success="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.success({ message: '复制成功' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
v-clipboard:error="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.error({ message: '复制失败' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
type="info"
|
||||||
|
:message="`批量触发器地址(点击可以复制)`"
|
||||||
|
>
|
||||||
|
<template slot="description">
|
||||||
|
<a-tag>POST</a-tag> <span>{{ temp.batchTriggerBuildUrl }} </span>
|
||||||
|
<a-icon type="copy" />
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
</a-space>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="2" tab="查看当前状态">
|
||||||
|
<a-space style="display: block" direction="vertical" align="baseline">
|
||||||
|
<a-alert message="温馨提示" type="warning">
|
||||||
|
<template slot="description">
|
||||||
|
<ul>
|
||||||
|
<li>批量构建参数 BODY json: [ { "id":"1", "token":"a" } ]</li>
|
||||||
|
<li>参数中的 id 、token 和触发构建一致</li>
|
||||||
|
<li>
|
||||||
|
<a-tag>No(0, "未构建")</a-tag>, <a-tag>Ing(1, "构建中")</a-tag>, <a-tag>Success(2, "构建结束")</a-tag>, <a-tag>Error(3, "构建失败")</a-tag>, <a-tag>PubIng(4, "发布中")</a-tag>,
|
||||||
|
<a-tag>PubSuccess(5, "发布成功")</a-tag>, <a-tag>PubError(6, "发布失败")</a-tag>, <a-tag>Cancel(7, "取消构建")</a-tag>,
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert
|
||||||
|
v-clipboard:copy="temp.batchBuildStatusUrl2"
|
||||||
|
v-clipboard:success="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.success({ message: '复制成功' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
v-clipboard:error="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.error({ message: '复制失败' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
type="info"
|
||||||
|
:message="`获取单个构建状态地址(点击可以复制)`"
|
||||||
|
>
|
||||||
|
<template slot="description">
|
||||||
|
<a-tag>GET</a-tag> <span>{{ temp.batchBuildStatusUrl2 }} </span>
|
||||||
|
<a-icon type="copy" />
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert
|
||||||
|
v-clipboard:copy="temp.batchBuildStatusUrl"
|
||||||
|
v-clipboard:success="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.success({ message: '复制成功' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
v-clipboard:error="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.error({ message: '复制失败' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
type="info"
|
||||||
|
:message="`批量获取构建状态地址(点击可以复制)`"
|
||||||
|
>
|
||||||
|
<template slot="description">
|
||||||
|
<a-tag>POST</a-tag> <span>{{ temp.batchBuildStatusUrl }} </span>
|
||||||
|
<a-icon type="copy" />
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
</a-space>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="3" tab="查看构建日志">
|
||||||
|
<a-space style="display: block" direction="vertical" align="baseline">
|
||||||
|
<a-alert message="温馨提示" type="warning">
|
||||||
|
<template slot="description">
|
||||||
|
<ul>
|
||||||
|
<li>参数中的 id 、token 和触发构建一致、buildNumId 构建序号id</li>
|
||||||
|
<li>构建序号id需要跟进实际情况替换</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert
|
||||||
|
v-clipboard:copy="temp.buildLogUrl"
|
||||||
|
v-clipboard:success="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.success({ message: '复制成功' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
v-clipboard:error="
|
||||||
|
() => {
|
||||||
|
tempVue.prototype.$notification.error({ message: '复制失败' });
|
||||||
|
}
|
||||||
|
"
|
||||||
|
type="info"
|
||||||
|
:message="`获取单个构建日志地址(点击可以复制)`"
|
||||||
|
>
|
||||||
|
<template slot="description">
|
||||||
|
<a-tag>GET</a-tag> <span>{{ temp.buildLogUrl }} </span>
|
||||||
|
<a-icon type="copy" />
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
</a-space>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-form-model>
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<a-result title="当前构建还没有生成触发器">
|
||||||
|
<template #extra>
|
||||||
|
<a-button key="console" type="primary" @click="handleTrigger"> 现成生成 </a-button>
|
||||||
|
</template>
|
||||||
|
</a-result>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Vue from "vue";
|
||||||
|
import { getTriggerUrl } from "@/api/build-info";
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
triggerToken: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
temp: {},
|
||||||
|
tempVue: null,
|
||||||
|
triggerVisible: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.triggerToken) {
|
||||||
|
this.handleTrigger();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 触发器
|
||||||
|
handleTrigger() {
|
||||||
|
this.temp = {};
|
||||||
|
this.tempVue = Vue;
|
||||||
|
getTriggerUrl({
|
||||||
|
id: this.id,
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.fillTriggerResult(res);
|
||||||
|
this.triggerVisible = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 重置触发器
|
||||||
|
resetTrigger() {
|
||||||
|
getTriggerUrl({
|
||||||
|
id: this.id,
|
||||||
|
rest: "rest",
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg,
|
||||||
|
});
|
||||||
|
this.fillTriggerResult(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fillTriggerResult(res) {
|
||||||
|
this.temp.triggerBuildUrl = `${location.protocol}//${location.host}${res.data.triggerBuildUrl}`;
|
||||||
|
this.temp.batchTriggerBuildUrl = `${location.protocol}//${location.host}${res.data.batchTriggerBuildUrl}`;
|
||||||
|
this.temp.batchBuildStatusUrl = `${location.protocol}//${location.host}${res.data.batchBuildStatusUrl}`;
|
||||||
|
this.temp.buildLogUrl = `${location.protocol}//${location.host}${res.data.buildLogUrl}`;
|
||||||
|
// this.temp.id = res.data.id;
|
||||||
|
// this.temp.token = res.data.token;
|
||||||
|
this.temp.batchBuildStatusUrl2 = `${this.temp.batchBuildStatusUrl}?id=${res.data.id}&token=${res.data.token}`;
|
||||||
|
this.temp.buildLogUrl = `${this.temp.buildLogUrl}?id=${res.data.id}&token=${res.data.token}&buildNumId=0`;
|
||||||
|
this.temp = { ...this.temp };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
@ -19,6 +19,8 @@
|
|||||||
<template slot="title">
|
<template slot="title">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input v-model="listQuery['%name%']" @pressEnter="loadData" placeholder="文件名称" class="search-input-item" />
|
<a-input v-model="listQuery['%name%']" @pressEnter="loadData" placeholder="文件名称" class="search-input-item" />
|
||||||
|
<a-input v-model="listQuery['%aliasCode%']" @pressEnter="loadData" placeholder="别名码" class="search-input-item" />
|
||||||
|
<a-input v-model="listQuery['extName']" @pressEnter="loadData" placeholder="后缀,精准搜索" class="search-input-item" />
|
||||||
<a-input v-model="listQuery['id']" @pressEnter="loadData" placeholder="文件id,精准搜索" class="search-input-item" />
|
<a-input v-model="listQuery['id']" @pressEnter="loadData" placeholder="文件id,精准搜索" class="search-input-item" />
|
||||||
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
||||||
<a-button type="primary" :loading="loading" @click="loadData">搜索</a-button>
|
<a-button type="primary" :loading="loading" @click="loadData">搜索</a-button>
|
||||||
|
@ -70,7 +70,12 @@
|
|||||||
size="middle"
|
size="middle"
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="changePage"
|
@change="
|
||||||
|
(pagination, filters, sorter) => {
|
||||||
|
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter });
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
>
|
>
|
||||||
<a-tooltip slot="url" slot-scope="text, record" placement="topLeft" :title="text">
|
<a-tooltip slot="url" slot-scope="text, record" placement="topLeft" :title="text">
|
||||||
@ -573,7 +578,7 @@ export default {
|
|||||||
renderSize,
|
renderSize,
|
||||||
PAGE_DEFAULT_SHOW_TOTAL,
|
PAGE_DEFAULT_SHOW_TOTAL,
|
||||||
parseTime,
|
parseTime,
|
||||||
|
CHANGE_PAGE,
|
||||||
introGuideList() {
|
introGuideList() {
|
||||||
this.$store.dispatch("tryOpenGuide", {
|
this.$store.dispatch("tryOpenGuide", {
|
||||||
key: "node-list-manage",
|
key: "node-list-manage",
|
||||||
@ -771,11 +776,7 @@ export default {
|
|||||||
query: query,
|
query: query,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 分页、排序、筛选变化时触发
|
|
||||||
changePage(pagination, filters, sorter) {
|
|
||||||
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter });
|
|
||||||
this.loadData();
|
|
||||||
},
|
|
||||||
// 加载工作空间数据
|
// 加载工作空间数据
|
||||||
loadWorkSpaceListAll() {
|
loadWorkSpaceListAll() {
|
||||||
getWorkSpaceListAll().then((res) => {
|
getWorkSpaceListAll().then((res) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user