fix 部分列表新增排序功能(置顶、上移、下移) #I5KBN9

This commit is contained in:
bwcx_jzy 2022-08-08 10:31:51 +08:00
parent e92bc187ef
commit 33cdf7ae15
No known key found for this signature in database
GPG Key ID: 5E48E9372088B9E5
21 changed files with 613 additions and 310 deletions

View File

@ -8,6 +8,7 @@
2. 【server】账号新增状态字段,用于控制禁用账号
3. 【server】重置密码使用系统生成
4. 【server】构建 docker 镜像支持使用构建序号 ID 为 tag 版本号递增(感谢@Y.
5. 【server】部分列表新增排序功能(置顶、上移、下移)(感谢[@爱琳琳真是太好了](https://gitee.com/qiqi513_admin) [Gitee issues I5KBN9](https://gitee.com/dromara/Jpom/issues/I5KBN9)
### 🐞 解决BUG、优化功能

View File

@ -463,4 +463,28 @@ public class BuildInfoController extends BaseServerController {
return JsonMessage.getString(200, "清理成功");
}
/**
* 排序
*
* @param id 节点ID
* @param method 方法
* @param compareId 比较的ID
* @return msg
*/
@GetMapping(value = "/build/sort-item", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public JsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId) {
HttpServletRequest request = getRequest();
if (StrUtil.equalsIgnoreCase(method, "top")) {
buildInfoService.sortToTop(id, request);
} else if (StrUtil.equalsIgnoreCase(method, "up")) {
buildInfoService.sortMoveUp(id, compareId, request);
} else if (StrUtil.equalsIgnoreCase(method, "down")) {
buildInfoService.sortMoveDown(id, compareId, request);
} else {
return new JsonMessage<>(400, "不支持的方式" + method);
}
return new JsonMessage<>(200, "操作成功");
}
}

View File

@ -57,6 +57,7 @@ import io.jpom.system.JpomRuntimeException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -450,6 +451,30 @@ public class RepositoryController extends BaseServerController {
return JsonMessage.getString(200, "删除成功");
}
/**
* 排序
*
* @param id 节点ID
* @param method 方法
* @param compareId 比较的ID
* @return msg
*/
@GetMapping(value = "/build/repository/sort-item", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public JsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId) {
HttpServletRequest request = getRequest();
if (StrUtil.equalsIgnoreCase(method, "top")) {
repositoryService.sortToTop(id, request);
} else if (StrUtil.equalsIgnoreCase(method, "up")) {
repositoryService.sortMoveUp(id, compareId, request);
} else if (StrUtil.equalsIgnoreCase(method, "down")) {
repositoryService.sortMoveDown(id, compareId, request);
} else {
return new JsonMessage<>(400, "不支持的方式" + method);
}
return new JsonMessage<>(200, "操作成功");
}
/**
* Gitee 工具
*/

View File

@ -22,6 +22,7 @@
*/
package io.jpom.controller.node;
import cn.hutool.core.util.StrUtil;
import cn.jiangzeyin.common.JsonMessage;
import cn.jiangzeyin.common.validator.ValidatorItem;
import com.alibaba.fastjson.JSONArray;
@ -256,4 +257,28 @@ public class NodeEditController extends BaseServerController {
nodeService.syncToWorkspace(ids, nowWorkspaceId, workspaceId);
return JsonMessage.getString(200, "操作成功");
}
/**
* 排序
*
* @param id 节点ID
* @param method 方法
* @param compareId 比较的ID
* @return msg
*/
@GetMapping(value = "sort-item", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public JsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId) {
HttpServletRequest request = getRequest();
if (StrUtil.equalsIgnoreCase(method, "top")) {
nodeService.sortToTop(id, request);
} else if (StrUtil.equalsIgnoreCase(method, "up")) {
nodeService.sortMoveUp(id, compareId, request);
} else if (StrUtil.equalsIgnoreCase(method, "down")) {
nodeService.sortMoveDown(id, compareId, request);
} else {
return new JsonMessage<>(400, "不支持的方式" + method);
}
return new JsonMessage<>(200, "操作成功");
}
}

View File

@ -25,6 +25,7 @@ package io.jpom.controller.node;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.jiangzeyin.common.JsonMessage;
import cn.jiangzeyin.common.validator.ValidatorItem;
import io.jpom.common.BaseServerController;
import io.jpom.model.PageResultDto;
import io.jpom.model.data.NodeModel;
@ -41,6 +42,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
@ -54,80 +56,102 @@ import java.util.List;
@Feature(cls = ClassFeature.NODE)
public class NodeProjectInfoController extends BaseServerController {
private final ProjectInfoCacheService projectInfoCacheService;
private final ProjectInfoCacheService projectInfoCacheService;
public NodeProjectInfoController(ProjectInfoCacheService projectInfoCacheService) {
this.projectInfoCacheService = projectInfoCacheService;
}
public NodeProjectInfoController(ProjectInfoCacheService projectInfoCacheService) {
this.projectInfoCacheService = projectInfoCacheService;
}
/**
* @return json
* @author Hotstrip
* load node project list
* 加载节点项目列表
*/
@PostMapping(value = "node_project_list", produces = MediaType.APPLICATION_JSON_VALUE)
public String nodeProjectList() {
PageResultDto<ProjectInfoCacheModel> resultDto = projectInfoCacheService.listPageNode(getRequest());
return JsonMessage.getString(200, "success", resultDto);
}
/**
* @return json
* @author Hotstrip
* load node project list
* 加载节点项目列表
*/
@PostMapping(value = "node_project_list", produces = MediaType.APPLICATION_JSON_VALUE)
public String nodeProjectList() {
PageResultDto<ProjectInfoCacheModel> resultDto = projectInfoCacheService.listPageNode(getRequest());
return JsonMessage.getString(200, "success", resultDto);
}
/**
* load node project list
* 加载节点项目列表
*
* @return json
* @author Hotstrip
*/
@PostMapping(value = "project_list", produces = MediaType.APPLICATION_JSON_VALUE)
public String projectList() {
PageResultDto<ProjectInfoCacheModel> resultDto = projectInfoCacheService.listPage(getRequest());
return JsonMessage.getString(200, "success", resultDto);
}
/**
* load node project list
* 加载节点项目列表
*
* @return json
* @author Hotstrip
*/
@PostMapping(value = "project_list", produces = MediaType.APPLICATION_JSON_VALUE)
public String projectList() {
PageResultDto<ProjectInfoCacheModel> resultDto = projectInfoCacheService.listPage(getRequest());
return JsonMessage.getString(200, "success", resultDto);
}
/**
* load node project list
* 加载节点项目列表
*
* @return json
* @author Hotstrip
*/
@GetMapping(value = "project_list_all", produces = MediaType.APPLICATION_JSON_VALUE)
public String projectListAll() {
List<ProjectInfoCacheModel> projectInfoCacheModels = projectInfoCacheService.listByWorkspace(getRequest());
return JsonMessage.getString(200, "", projectInfoCacheModels);
}
/**
* load node project list
* 加载节点项目列表
*
* @return json
* @author Hotstrip
*/
@GetMapping(value = "project_list_all", produces = MediaType.APPLICATION_JSON_VALUE)
public String projectListAll() {
List<ProjectInfoCacheModel> projectInfoCacheModels = projectInfoCacheService.listByWorkspace(getRequest());
return JsonMessage.getString(200, "", projectInfoCacheModels);
}
/**
* 同步节点项目
*
* @return json
*/
@GetMapping(value = "sync_project", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(cls = ClassFeature.PROJECT, method = MethodFeature.DEL)
public String syncProject(String nodeId) {
NodeModel nodeModel = nodeService.getByKey(nodeId);
Assert.notNull(nodeModel, "对应的节点不存在");
int count = projectInfoCacheService.delCache(nodeId, getRequest());
String msg = projectInfoCacheService.syncExecuteNode(nodeModel);
return JsonMessage.getString(200, "主动清除:" + count + StrUtil.SPACE + msg);
}
/**
* 删除节点缓存的所有项目
*
* @return json
*/
@GetMapping(value = "clear_all_project", produces = MediaType.APPLICATION_JSON_VALUE)
@SystemPermission(superUser = true)
@Feature(cls = ClassFeature.PROJECT, method = MethodFeature.DEL)
public String clearAll() {
Entity where = Entity.create();
where.set("id", " <> id");
int del = projectInfoCacheService.del(where);
return JsonMessage.getString(200, "成功删除" + del + "条项目缓存");
}
/**
* 同步节点项目
*
* @return json
*/
@GetMapping(value = "sync_project", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(cls = ClassFeature.PROJECT, method = MethodFeature.DEL)
public String syncProject(String nodeId) {
NodeModel nodeModel = nodeService.getByKey(nodeId);
Assert.notNull(nodeModel, "对应的节点不存在");
int count = projectInfoCacheService.delCache(nodeId, getRequest());
String msg = projectInfoCacheService.syncExecuteNode(nodeModel);
return JsonMessage.getString(200, "主动清除:" + count + StrUtil.SPACE + msg);
}
/**
* 删除节点缓存的所有项目
*
* @return json
*/
@GetMapping(value = "clear_all_project", produces = MediaType.APPLICATION_JSON_VALUE)
@SystemPermission(superUser = true)
@Feature(cls = ClassFeature.PROJECT, method = MethodFeature.DEL)
public String clearAll() {
Entity where = Entity.create();
where.set("id", " <> id");
int del = projectInfoCacheService.del(where);
return JsonMessage.getString(200, "成功删除" + del + "条项目缓存");
}
/**
* 排序
*
* @param id 节点ID
* @param method 方法
* @param compareId 比较的ID
* @return msg
*/
@GetMapping(value = "project-sort-item", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public JsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId) {
HttpServletRequest request = getRequest();
if (StrUtil.equalsIgnoreCase(method, "top")) {
projectInfoCacheService.sortToTop(id, request);
} else if (StrUtil.equalsIgnoreCase(method, "up")) {
projectInfoCacheService.sortMoveUp(id, compareId, request);
} else if (StrUtil.equalsIgnoreCase(method, "down")) {
projectInfoCacheService.sortMoveDown(id, compareId, request);
} else {
return new JsonMessage<>(400, "不支持的方式" + method);
}
return new JsonMessage<>(200, "操作成功");
}
}

View File

@ -34,7 +34,7 @@ import lombok.EqualsAndHashCode;
public abstract class BaseGroupModel extends BaseWorkspaceModel {
/**
* 节点分组
* 分组
*/
private String group;

View File

@ -115,6 +115,10 @@ public class BuildInfoModel extends BaseGroupModel {
* 仓库代码最后一次变动信息IDgit commit hash, svn 最后的版本号
*/
private String repositoryLastCommitId;
/**
* 排序
*/
private Float sortValue;
@Tolerate
public BuildInfoModel() {

View File

@ -90,6 +90,10 @@ public class NodeModel extends BaseGroupModel {
* https 代理 类型
*/
private String httpProxyType;
/**
* 排序
*/
private Float sortValue;
public boolean isOpenStatus() {
return openStatus != null && openStatus == 1;

View File

@ -29,6 +29,8 @@ import io.jpom.model.BaseEnum;
import io.jpom.model.BaseWorkspaceModel;
import io.jpom.model.enums.GitProtocolEnum;
import io.jpom.service.h2db.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.HashMap;
import java.util.Map;
@ -38,6 +40,8 @@ import java.util.Map;
* 仓库地址实体类
*/
@TableName(value = "REPOSITORY", name = "仓库信息")
@Data
@EqualsAndHashCode(callSuper = true)
public class RepositoryModel extends BaseWorkspaceModel {
/**
* 名称
@ -75,29 +79,11 @@ public class RepositoryModel extends BaseWorkspaceModel {
*/
private String rsaPrv;
public String getName() {
return name;
}
/**
* 排序
*/
private Float sortValue;
public void setName(String name) {
this.name = name;
}
public String getGitUrl() {
return gitUrl;
}
public void setGitUrl(String gitUrl) {
this.gitUrl = gitUrl;
}
public Integer getRepoType() {
return repoType;
}
public void setRepoType(Integer repoType) {
this.repoType = repoType;
}
/**
* 返回协议类型如果为 null 会尝试识别 http
@ -119,44 +105,6 @@ public class RepositoryModel extends BaseWorkspaceModel {
return null;
}
public void setProtocol(Integer protocol) {
this.protocol = protocol;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Deprecated
public String getRsaPub() {
return rsaPub;
}
@Deprecated
public void setRsaPub(String rsaPub) {
this.rsaPub = rsaPub;
}
public String getRsaPrv() {
return rsaPrv;
}
public void setRsaPrv(String rsaPrv) {
this.rsaPrv = rsaPrv;
}
/**
* 转换为 map
*

View File

@ -24,177 +24,71 @@ package io.jpom.model.node;
import io.jpom.model.BaseNodeModel;
import io.jpom.service.h2db.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author bwcx_jzy
* @since 2021/12/5
*/
@TableName(value = "PROJECT_INFO", name = "项目信息")
@Data
@EqualsAndHashCode(callSuper = true)
public class ProjectInfoCacheModel extends BaseNodeModel {
private String projectId;
private String projectId;
private String name;
private String name;
private String mainClass;
private String lib;
/**
* 白名单目录
*/
private String whitelistDirectory;
/**
* 日志目录
*/
private String logPath;
/**
* jvm 参数
*/
private String jvm;
/**
* java main 方法参数
*/
private String args;
private String mainClass;
private String lib;
/**
* 白名单目录
*/
private String whitelistDirectory;
/**
* 日志目录
*/
private String logPath;
/**
* jvm 参数
*/
private String jvm;
/**
* java main 方法参数
*/
private String args;
private String javaCopyItemList;
/**
* WebHooks
*/
private String token;
private String javaCopyItemList;
/**
* WebHooks
*/
private String token;
private String jdkId;
private String jdkId;
private String runMode;
/**
* 节点分发项目不允许在项目管理中编辑
*/
private Integer outGivingProject;
/**
* -Djava.ext.dirs=lib -cp conf:run.jar
* 填写lib:conf
*/
private String javaExtDirsCp;
private String runMode;
/**
* 节点分发项目不允许在项目管理中编辑
*/
private Integer outGivingProject;
/**
* -Djava.ext.dirs=lib -cp conf:run.jar
* 填写lib:conf
*/
private String javaExtDirsCp;
/**
* 排序
*/
private Float sortValue;
@Override
public String dataId() {
return getProjectId();
}
@Override
public String dataId() {
return getProjectId();
}
@Override
public void dataId(String id) {
setProjectId(id);
}
public String getProjectId() {
return projectId;
}
public void setProjectId(String projectId) {
this.projectId = projectId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMainClass() {
return mainClass;
}
public void setMainClass(String mainClass) {
this.mainClass = mainClass;
}
public String getLib() {
return lib;
}
public void setLib(String lib) {
this.lib = lib;
}
public String getWhitelistDirectory() {
return whitelistDirectory;
}
public void setWhitelistDirectory(String whitelistDirectory) {
this.whitelistDirectory = whitelistDirectory;
}
public String getLogPath() {
return logPath;
}
public void setLogPath(String logPath) {
this.logPath = logPath;
}
public String getJvm() {
return jvm;
}
public void setJvm(String jvm) {
this.jvm = jvm;
}
public String getArgs() {
return args;
}
public void setArgs(String args) {
this.args = args;
}
public String getJavaCopyItemList() {
return javaCopyItemList;
}
public void setJavaCopyItemList(String javaCopyItemList) {
this.javaCopyItemList = javaCopyItemList;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getJdkId() {
return jdkId;
}
public void setJdkId(String jdkId) {
this.jdkId = jdkId;
}
public String getRunMode() {
return runMode;
}
public void setRunMode(String runMode) {
this.runMode = runMode;
}
public Integer getOutGivingProject() {
return outGivingProject;
}
public void setOutGivingProject(Integer outGivingProject) {
this.outGivingProject = outGivingProject;
}
public String getJavaExtDirsCp() {
return javaExtDirsCp;
}
public void setJavaExtDirsCp(String javaExtDirsCp) {
this.javaExtDirsCp = javaExtDirsCp;
}
@Override
public void dataId(String id) {
setProjectId(id);
}
}

View File

@ -72,12 +72,6 @@ public abstract class BaseDbCommonService<T> {
*/
protected final String key;
public BaseDbCommonService(String tableName, String key, Class<T> tClass) {
this.tableName = this.covetTableName(tableName, tClass);
this.tClass = tClass;
this.key = key;
}
@SuppressWarnings("unchecked")
public BaseDbCommonService(String tableName, String key) {
this.tClass = (Class<T>) TypeUtil.getTypeArgument(this.getClass());

View File

@ -22,9 +22,14 @@
*/
package io.jpom.service.h2db;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.sql.Direction;
import cn.hutool.db.sql.Order;
import cn.hutool.extra.servlet.ServletUtil;
import cn.jiangzeyin.common.spring.SpringUtil;
import io.jpom.common.BaseServerController;
@ -40,7 +45,9 @@ import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* 工作空间 通用 service
@ -49,6 +56,23 @@ import java.util.function.Consumer;
* @since 2021/8/13
*/
public abstract class BaseWorkspaceService<T extends BaseWorkspaceModel> extends BaseDbService<T> {
/**
* 是否可以进行排序
*/
private final boolean canSort;
/**
* 有排序字段的默认排序规则
*/
private static final Order[] SORT_DEFAULT_ORDERS = new Order[]{
new Order("sortValue", Direction.DESC),
new Order("createTimeMillis", Direction.DESC),
new Order("modifyTimeMillis", Direction.DESC)
};
public BaseWorkspaceService() {
super();
this.canSort = ReflectUtil.hasField(this.tClass, "sortValue");
}
/**
* 根据工作空间查询
@ -239,4 +263,80 @@ public abstract class BaseWorkspaceService<T extends BaseWorkspaceModel> extends
String workspaceId = this.getCheckUserWorkspace(request);
return super.updateById(info, entity -> entity.set("workspaceId", workspaceId));
}
// 排序相关方法 ---------
@Override
protected Order[] defaultOrders() {
if (canSort) {
return SORT_DEFAULT_ORDERS;
}
return super.defaultOrders();
}
/**
* 置顶
*
* @param id 数据ID
* @param request 请求
*/
public void sortToTop(String id, HttpServletRequest request) {
Assert.state(canSort, "当前数据不支持排序");
String workspaceId = this.getCheckUserWorkspace(request);
String maxSql = "select max(sortValue) as sortValue from " + this.tableName + " where workspaceId=?";
List<Entity> query = this.query(maxSql, workspaceId);
float maxSortValue = Opt.ofEmptyAble(query)
.map(CollUtil::getFirst)
.map(entity -> entity.getFloat("sortValue"))
.orElse(1f);
//
String updateSql = "update " + this.tableName + " set sortValue=? where id=? and workspaceId=?";
this.execute(updateSql, maxSortValue + 0.0001f, id, workspaceId);
}
/**
* 向上移
*
* @param id 数据ID
* @param beforeId 前面一个数据的ID
* @param request 请求
*/
public void sortMoveUp(String id, String beforeId, HttpServletRequest request) {
this.sortMove(id, beforeId, request, true);
}
/**
* 向下移
*
* @param id 数据ID
* @param afterId 后面一个数据的ID
* @param request 请求
*/
public void sortMoveDown(String id, String afterId, HttpServletRequest request) {
this.sortMove(id, afterId, request, false);
}
/**
* 移动排序方法
*
* @param id 数据ID
* @param compareId 比较的数据ID
* @param request 请求
* @param up true 上移
*/
private void sortMove(String id, String compareId, HttpServletRequest request, boolean up) {
Assert.state(canSort, "当前数据不支持排序");
Assert.hasText(id, "数据id 不存在");
Assert.hasText(compareId, "比较 id 不存在");
String workspaceId = this.getCheckUserWorkspace(request);
String sql = "select sortValue as sortValue from " + this.tableName + " where id=? and workspaceId=?";
List<Entity> query = this.query(sql, compareId, workspaceId);
float compareSortValue = Opt.ofEmptyAble(query)
.map(CollUtil::getFirst)
.map(entity -> entity.getFloat("sortValue"))
.orElse(1f);
String updateSql = "update " + this.tableName + " set sortValue=? where id=? and workspaceId=?";
this.execute(updateSql, up ? compareSortValue + 0.0001f : compareSortValue - 0.0001f, id, workspaceId);
}
}

View File

@ -137,3 +137,9 @@ ALTER TABLE BUILD_INFO
ALTER TABLE BUILD_INFO
ADD IF NOT EXISTS repositoryLastCommitId varchar(255) comment '仓库代码最后一次变动信息IDgit 为 commit hash, svn 最后的版本号)';
ALTER TABLE BUILD_INFO
ADD IF NOT EXISTS `sortValue` REAL comment '排序值';
ALTER TABLE REPOSITORY
ADD IF NOT EXISTS `sortValue` REAL comment '排序值';

View File

@ -114,6 +114,12 @@ ALTER TABLE COMMAND_INFO
ALTER TABLE SERVER_SCRIPT_INFO
ADD IF NOT EXISTS triggerToken VARCHAR(200) comment '触发器token';
ALTER TABLE NODE_INFO
ADD IF NOT EXISTS `sortValue` REAL comment '排序值';
ALTER TABLE PROJECT_INFO
ADD IF NOT EXISTS `sortValue` REAL comment '排序值';

View File

@ -248,6 +248,14 @@ export function deleteBuildHistory(logId) {
});
}
export function sortItem(params) {
return axios({
url: "/build/sort-item",
method: "get",
params: params,
});
}
export const statusMap = {
1: "构建中",
2: "构建完成",

View File

@ -104,6 +104,15 @@ export function syncToWorkspace(params) {
});
}
//
export function sortItem(params) {
return axios({
url: "/node/sort-item",
method: "get",
params: params,
});
}
// 删除节点项目缓存
export function delAllProjectCache() {
return axios({
@ -113,6 +122,15 @@ export function delAllProjectCache() {
});
}
// 项目排序
export function sortItemProject(params) {
return axios({
url: "/node/project-sort-item",
method: "get",
params: params,
});
}
/**
* 编辑 node
* @param {

View File

@ -91,3 +91,11 @@ export function authorizeRepos(param) {
params: param,
});
}
export function sortItem(params) {
return axios({
url: "/build/repository/sort-item",
method: "get",
params: params,
});
}

View File

@ -63,7 +63,7 @@
<!-- <a-icon type="edit" theme="twoTone" /> -->
<a-button type="link" style="padding: 0px" size="small">{{ text }}</a-button>
</a-tooltip>
<a-tooltip slot="branchName" slot-scope="text" placement="topLeft" :title="text">
<a-tooltip slot="branchName" slot-scope="text, record" placement="topLeft" :title="`分支名称:${text},上次构建基于 commitId${record.repositoryLastCommitId}`">
<span>{{ text }}</span>
</a-tooltip>
<!-- <a-tooltip slot="resultDirFile" slot-scope="text" placement="topLeft" :title="text">
@ -99,7 +99,7 @@
<a-tooltip slot="modifyUser" slot-scope="text" placement="topLeft" :title="text">
<span>{{ text }}</span>
</a-tooltip>
<template slot="operation" slot-scope="text, record">
<template slot="operation" slot-scope="text, record, index">
<a-space>
<a-button size="small" type="danger" v-if="record.status === 1 || record.status === 4" @click="handleStopBuild(record)">停止 </a-button>
<a-button size="small" type="primary" v-else @click="handleConfirmStartBuild(record)">构建</a-button>
@ -130,6 +130,18 @@
<a-button size="small" type="danger" :disabled="!record.sourceDirExist" @click="handleClear(record)">清除代码 </a-button>
</a-tooltip>
</a-menu-item>
<a-menu-divider />
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'top')">置顶</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'up')">上移</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) === listQuery.total" @click="sortItemHander(record, index, 'down')">
下移
</a-button>
</a-menu-item>
</a-menu>
</a-dropdown>
</a-space>
@ -928,6 +940,7 @@ import {
startBuild,
statusMap,
stopBuild,
sortItem,
} from "@/api/build-info";
import { afterOptList, afterOptListSimple, getDishPatchListAll } from "@/api/dispatch";
import { getNodeListAll, getProjectListAll } from "@/api/node";
@ -1605,6 +1618,43 @@ export default {
this.swarmServiceListOptions = [];
}
},
//
sortItemHander(record, index, method) {
const msgData = {
top: "确定要将此数据置顶吗?",
up: "确定要将此数上移吗?",
down: "确定要将此数据下移吗?",
};
let msg = msgData[method] || "确定要操作吗?";
if (!record.sortValue) {
msg += " 当前数据为默认状态,操后上移或者下移可能不会达到预期排序,还需要对相关数据都操作后才能达到预期排序";
}
// console.log(this.list, index, this.list[method === "top" ? index : method === "up" ? index - 1 : index + 1]);
const compareId = this.list[method === "top" ? index : method === "up" ? index - 1 : index + 1].id;
this.$confirm({
title: "系统提示",
content: msg,
okText: "确认",
cancelText: "取消",
onOk: () => {
//
sortItem({
id: record.id,
method: method,
compareId: compareId,
}).then((res) => {
if (res.code == 200) {
this.$notification.success({
message: res.msg,
});
this.loadData();
return false;
}
});
},
});
},
},
};
</script>

View File

@ -86,7 +86,7 @@
<!-- <a-tooltip slot="cycle" slot-scope="text" placement="topLeft" :title="nodeMonitorCycle[text]">
<span>{{ nodeMonitorCycle[text] }}</span>
</a-tooltip> -->
<template slot="operation" slot-scope="text, record">
<template slot="operation" slot-scope="text, record, index">
<a-tooltip title="我在这里" :visible="showOptVisible[record.id]">
<a-space>
<a-button size="small" v-if="record.unLockType" type="primary" @click="unlock(record)"><a-icon type="unlock" />解锁</a-button>
@ -105,19 +105,31 @@
</a>
<a-menu slot="overlay">
<a-menu-item>
<a-button type="primary" @click="handleEdit(record)">编辑</a-button>
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
</a-menu-item>
<a-menu-item>
<a-tooltip placement="leftBottom" title="删除会检查数据关联性,并且节点不存在项目或者脚本">
<a-button type="danger" @click="handleDelete(record)">删除</a-button>
<a-button size="small" type="danger" @click="handleDelete(record)">删除</a-button>
</a-tooltip>
</a-menu-item>
<a-menu-item>
<a-tooltip placement="leftBottom" title="解绑会检查数据关联性,同时将自动删除节点项目和脚本缓存信息,一般用于服务器无法连接且已经确定不再使用">
<a-button type="danger" @click="handleUnbind(record)">解绑</a-button>
<a-button size="small" type="danger" @click="handleUnbind(record)">解绑</a-button>
</a-tooltip>
</a-menu-item>
<a-menu-divider />
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'top')">置顶</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'up')">上移</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) === listQuery.total" @click="sortItemHander(record, index, 'down')">
下移
</a-button>
</a-menu-item>
</a-menu>
</a-dropdown>
</a-space>
@ -490,6 +502,7 @@ import {
syncToWorkspace,
unbind,
unLockWorkspace,
sortItem,
} from "@/api/node";
import { getSshListAll } from "@/api/ssh";
import { syncScript } from "@/api/node-other";
@ -988,6 +1001,43 @@ export default {
}
});
},
//
sortItemHander(record, index, method) {
const msgData = {
top: "确定要将此数据置顶吗?",
up: "确定要将此数上移吗?",
down: "确定要将此数据下移吗?",
};
let msg = msgData[method] || "确定要操作吗?";
if (!record.sortValue) {
msg += " 当前数据为默认状态,操后上移或者下移可能不会达到预期排序,还需要对相关数据都操作后才能达到预期排序";
}
// console.log(this.list, index, this.list[method === "top" ? index : method === "up" ? index - 1 : index + 1]);
const compareId = this.list[method === "top" ? index : method === "up" ? index - 1 : index + 1].id;
this.$confirm({
title: "系统提示",
content: msg,
okText: "确认",
cancelText: "取消",
onOk: () => {
//
sortItem({
id: record.id,
method: method,
compareId: compareId,
}).then((res) => {
if (res.code == 200) {
this.$notification.success({
message: res.msg,
});
this.loadData();
return false;
}
});
},
});
},
},
};
</script>

View File

@ -61,6 +61,7 @@
<ul>
<li>项目是存储在节点中的创建需要到节点管理里面去操作</li>
<li>状态数据是异步获取有一定时间延迟</li>
<li>在单页列表里面 file 类型项目将自动排序到最后</li>
</ul>
</div>
</template>
@ -92,10 +93,29 @@
<a-tooltip slot="port" slot-scope="text, record" placement="topLeft" :title="`进程号:${record.pid}, 端口号:${record.port}`">
<span v-if="record.pid">{{ record.port }}/{{ record.pid }}</span>
</a-tooltip>
<template slot="operation" slot-scope="text, record">
<template slot="operation" slot-scope="text, record, index">
<a-space>
<a-button size="small" type="primary" @click="handleFile(record)">文件</a-button>
<a-button size="small" type="primary" @click="handleConsole(record)" v-show="noFileModes.includes(record.runMode)">控制台</a-button>
<a-dropdown>
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()">
更多
<a-icon type="down" />
</a>
<a-menu slot="overlay">
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'top')">置顶</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'up')">上移</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) === listQuery.total" @click="sortItemHander(record, index, 'down')">
下移
</a-button>
</a-menu-item>
</a-menu>
</a-dropdown>
</a-space>
</template>
</a-table>
@ -127,12 +147,12 @@
</div>
</template>
<script>
import {delAllProjectCache, getNodeListAll, getProjectList} from "@/api/node";
import {getRuningProjectInfo, noFileModes, restartProject, runModeList, startProject, stopProject} from "@/api/node-project";
import { delAllProjectCache, getNodeListAll, getProjectList, sortItemProject } from "@/api/node";
import { getRuningProjectInfo, noFileModes, restartProject, runModeList, startProject, stopProject } from "@/api/node-project";
import File from "@/pages/node/node-layout/project/project-file";
import Console from "../node/node-layout/project/project-console";
import {itemGroupBy, parseTime} from "@/utils/time";
import {CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY} from "@/utils/const";
import { itemGroupBy, parseTime } from "@/utils/time";
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY } from "@/utils/const";
import FileRead from "@/pages/node/node-layout/project/project-file-read";
export default {
@ -186,7 +206,7 @@ export default {
},
{ title: "运行状态", dataIndex: "status", width: 100, ellipsis: true, scopedSlots: { customRender: "status" } },
{ title: "端口/PID", dataIndex: "port", width: 100, ellipsis: true, scopedSlots: { customRender: "port" } },
{ title: "操作", dataIndex: "operation", align: "center", scopedSlots: { customRender: "operation" }, width: 140 },
{ title: "操作", dataIndex: "operation", align: "center", scopedSlots: { customRender: "operation" }, width: "180px" },
],
};
},
@ -490,6 +510,44 @@ export default {
},
});
},
//
sortItemHander(record, index, method) {
const msgData = {
top: "确定要将此数据置顶吗?",
up: "确定要将此数上移吗?",
down: "确定要将此数据下移吗?",
};
let msg = msgData[method] || "确定要操作吗?";
if (!record.sortValue) {
msg += " 当前数据为默认状态,操后上移或者下移可能不会达到预期排序,还需要对相关数据都操作后才能达到预期排序";
}
// console.log(this.list, index, this.list[method === "top" ? index : method === "up" ? index - 1 : index + 1]);
const compareId = this.projList[method === "top" ? index : method === "up" ? index - 1 : index + 1].id;
this.$confirm({
title: "系统提示",
content: msg,
okText: "确认",
cancelText: "取消",
onOk: () => {
//
sortItemProject({
id: record.id,
method: method,
compareId: compareId,
}).then((res) => {
if (res.code == 200) {
this.$notification.success({
message: res.msg,
});
this.getNodeProjectData();
return false;
}
});
},
});
// console.log(record, index, method);
},
},
};
</script>

View File

@ -47,10 +47,29 @@
<!-- if no protocol value, get a default value from gitUrl -->
<span v-else>{{ record.gitUrl.indexOf("http") > -1 ? "HTTP(S)" : "SSH" }}</span>
</template>
<template slot="operation" slot-scope="text, record">
<template slot="operation" slot-scope="text, record, index">
<a-space>
<a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button>
<a-button type="danger" size="small" @click="handleDelete(record)">删除</a-button>
<a-dropdown>
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()">
更多
<a-icon type="down" />
</a>
<a-menu slot="overlay">
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'top')">置顶</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) <= 1" @click="sortItemHander(record, index, 'up')">上移</a-button>
</a-menu-item>
<a-menu-item>
<a-button size="small" type="primary" :disabled="(listQuery.page - 1) * listQuery.limit + (index + 1) === listQuery.total" @click="sortItemHander(record, index, 'down')">
下移
</a-button>
</a-menu-item>
</a-menu>
</a-dropdown>
</a-space>
</template>
</a-table>
@ -219,9 +238,9 @@
</div>
</template>
<script>
import {authorizeRepos, deleteRepository, editRepository, getRepositoryList, restHideField} from "@/api/repository";
import {parseTime} from "@/utils/time";
import {CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY} from "@/utils/const";
import { authorizeRepos, deleteRepository, editRepository, getRepositoryList, restHideField, sortItem } from "@/api/repository";
import { parseTime } from "@/utils/time";
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY } from "@/utils/const";
export default {
components: {},
@ -281,7 +300,7 @@ export default {
title: "操作",
dataIndex: "operation",
align: "center",
width: 120,
width: "180px",
scopedSlots: { customRender: "operation" },
},
],
@ -489,6 +508,43 @@ export default {
this.importTypePlaceholder = "请输入私人令牌";
}
},
//
sortItemHander(record, index, method) {
const msgData = {
top: "确定要将此数据置顶吗?",
up: "确定要将此数上移吗?",
down: "确定要将此数据下移吗?",
};
let msg = msgData[method] || "确定要操作吗?";
if (!record.sortValue) {
msg += " 当前数据为默认状态,操后上移或者下移可能不会达到预期排序,还需要对相关数据都操作后才能达到预期排序";
}
// console.log(this.list, index, this.list[method === "top" ? index : method === "up" ? index - 1 : index + 1]);
const compareId = this.list[method === "top" ? index : method === "up" ? index - 1 : index + 1].id;
this.$confirm({
title: "系统提示",
content: msg,
okText: "确认",
cancelText: "取消",
onOk: () => {
//
sortItem({
id: record.id,
method: method,
compareId: compareId,
}).then((res) => {
if (res.code == 200) {
this.$notification.success({
message: res.msg,
});
this.loadData();
return false;
}
});
},
});
},
},
};
</script>