✨ 路径标签.
This commit is contained in:
@@ -3,7 +3,7 @@ package com.orion.ops.module.asset.controller;
|
|||||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
||||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkWrapperVO;
|
||||||
import com.orion.ops.module.asset.service.PathBookmarkService;
|
import com.orion.ops.module.asset.service.PathBookmarkService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
@@ -13,7 +13,6 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路径标签 api
|
* 路径标签 api
|
||||||
@@ -48,8 +47,8 @@ public class PathBookmarkController {
|
|||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "查询全部路径标签")
|
@Operation(summary = "查询全部路径标签")
|
||||||
public List<PathBookmarkVO> getPathBookmarkList() {
|
public PathBookmarkWrapperVO getPathBookmarkList() {
|
||||||
return pathBookmarkService.getPathBookmarkList();
|
return pathBookmarkService.getPathBookmark();
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
### 创建路径标签分组
|
||||||
|
POST {{baseUrl}}/asset/path-bookmark-group/create
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### 更新路径标签分组
|
||||||
|
PUT {{baseUrl}}/asset/path-bookmark-group/update
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "",
|
||||||
|
"name": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### 查询全部路径标签分组
|
||||||
|
GET {{baseUrl}}/asset/path-bookmark-group/list
|
||||||
|
Authorization: {{token}}
|
||||||
|
|
||||||
|
|
||||||
|
### 删除路径标签分组
|
||||||
|
DELETE {{baseUrl}}/asset/path-bookmark-group/delete?id=1
|
||||||
|
Authorization: {{token}}
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.orion.ops.module.asset.controller;
|
||||||
|
|
||||||
|
import com.orion.ops.framework.common.validator.group.Id;
|
||||||
|
import com.orion.ops.framework.log.core.annotation.IgnoreLog;
|
||||||
|
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
|
||||||
|
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupDeleteRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||||
|
import com.orion.ops.module.asset.service.PathBookmarkGroupService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 api
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
@Tag(name = "asset - 路径标签分组服务")
|
||||||
|
@Slf4j
|
||||||
|
@Validated
|
||||||
|
@RestWrapper
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/asset/path-bookmark-group")
|
||||||
|
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||||
|
public class PathBookmarkGroupController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PathBookmarkGroupService pathBookmarkGroupService;
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@Operation(summary = "创建路径标签分组")
|
||||||
|
public Long createPathBookmarkGroup(@Validated @RequestBody PathBookmarkGroupCreateRequest request) {
|
||||||
|
return pathBookmarkGroupService.createPathBookmarkGroup(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "更新路径标签分组")
|
||||||
|
public Integer updatePathBookmarkGroup(@Validated @RequestBody PathBookmarkGroupUpdateRequest request) {
|
||||||
|
return pathBookmarkGroupService.updatePathBookmarkGroupById(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
|
@GetMapping("/list")
|
||||||
|
@Operation(summary = "查询全部路径标签分组")
|
||||||
|
public List<PathBookmarkGroupVO> getPathBookmarkGroupList() {
|
||||||
|
return pathBookmarkGroupService.getPathBookmarkGroupList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@Operation(summary = "删除路径标签分组")
|
||||||
|
public Integer deletePathBookmarkGroup(@Validated(Id.class) @RequestBody PathBookmarkGroupDeleteRequest request) {
|
||||||
|
return pathBookmarkGroupService.deletePathBookmarkGroup(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.orion.ops.module.asset.convert;
|
package com.orion.ops.module.asset.convert;
|
||||||
|
|
||||||
import com.orion.ops.module.asset.entity.domain.CommandSnippetGroupDO;
|
|
||||||
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupCreateRequest;
|
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupCreateRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupUpdateRequest;
|
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupUpdateRequest;
|
||||||
import com.orion.ops.module.asset.entity.vo.CommandSnippetGroupVO;
|
import com.orion.ops.module.asset.entity.vo.CommandSnippetGroupVO;
|
||||||
@@ -10,8 +9,6 @@ import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
|
|||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 命令片段分组 内部对象转换器
|
* 命令片段分组 内部对象转换器
|
||||||
*
|
*
|
||||||
@@ -30,6 +27,4 @@ public interface CommandSnippetGroupConvert {
|
|||||||
|
|
||||||
CommandSnippetGroupVO to(DataGroupDTO domain);
|
CommandSnippetGroupVO to(DataGroupDTO domain);
|
||||||
|
|
||||||
List<CommandSnippetGroupVO> to(List<CommandSnippetGroupDO> list);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.orion.ops.module.asset.convert;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||||
|
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||||
|
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||||
|
import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 内部对象转换器
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface PathBookmarkGroupConvert {
|
||||||
|
|
||||||
|
PathBookmarkGroupConvert MAPPER = Mappers.getMapper(PathBookmarkGroupConvert.class);
|
||||||
|
|
||||||
|
DataGroupCreateDTO to(PathBookmarkGroupCreateRequest request);
|
||||||
|
|
||||||
|
DataGroupRenameDTO to(PathBookmarkGroupUpdateRequest request);
|
||||||
|
|
||||||
|
PathBookmarkGroupVO to(DataGroupDTO domain);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package com.orion.ops.module.asset.entity.domain;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import com.orion.ops.framework.mybatis.core.domain.BaseDO;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 命令片段分组 实体对象
|
|
||||||
*
|
|
||||||
* @author Jiahang Li
|
|
||||||
* @version 1.0.0
|
|
||||||
* @since 2024-1-24 12:28
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@TableName(value = "command_snippet_group", autoResultMap = true)
|
|
||||||
@Schema(name = "CommandSnippetGroupDO", description = "命令片段分组 实体对象")
|
|
||||||
public class CommandSnippetGroupDO extends BaseDO {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Schema(description = "id")
|
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Schema(description = "用户id")
|
|
||||||
@TableField("user_id")
|
|
||||||
private Long userId;
|
|
||||||
|
|
||||||
@Schema(description = "分组名称")
|
|
||||||
@TableField("name")
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.orion.ops.module.asset.entity.request.path;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 创建请求对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PathBookmarkGroupCreateRequest", description = "路径标签分组 创建请求对象")
|
||||||
|
public class PathBookmarkGroupCreateRequest implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 64)
|
||||||
|
@Schema(description = "分组名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.orion.ops.module.asset.entity.request.path;
|
||||||
|
|
||||||
|
import com.orion.ops.framework.common.validator.group.Id;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 删除请求对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PathBookmarkGroupDeleteRequest", description = "路径标签分组 删除请求对象")
|
||||||
|
public class PathBookmarkGroupDeleteRequest implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotNull(groups = Id.class)
|
||||||
|
@Schema(description = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Schema(description = "是否删除组内数据")
|
||||||
|
private Boolean deleteItem;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.orion.ops.module.asset.entity.request.path;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 更新请求对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PathBookmarkGroupUpdateRequest", description = "路径标签分组 更新请求对象")
|
||||||
|
public class PathBookmarkGroupUpdateRequest implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Schema(description = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 64)
|
||||||
|
@Schema(description = "分组名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.orion.ops.module.asset.entity.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 视图响应对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PathBookmarkGroupVO", description = "路径标签分组 视图响应对象")
|
||||||
|
public class PathBookmarkGroupVO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "分组名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "路径标签列表")
|
||||||
|
private List<PathBookmarkVO> items;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -30,6 +30,9 @@ public class PathBookmarkVO implements Serializable {
|
|||||||
@Schema(description = "用户id")
|
@Schema(description = "用户id")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "分组id")
|
||||||
|
private Long groupId;
|
||||||
|
|
||||||
@Schema(description = "名称")
|
@Schema(description = "名称")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.orion.ops.module.asset.entity.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签组合 视图响应对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/1/24 17:30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PathBookmarkWrapperVO", description = "路径标签组合 视图响应对象")
|
||||||
|
public class PathBookmarkWrapperVO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "分组")
|
||||||
|
private List<PathBookmarkGroupVO> groups;
|
||||||
|
|
||||||
|
@Schema(description = "未分组的路径标签")
|
||||||
|
private List<PathBookmarkVO> ungroupedItems;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.orion.ops.module.asset.service;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupDeleteRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 服务类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
public interface PathBookmarkGroupService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建路径标签分组
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return id
|
||||||
|
*/
|
||||||
|
Long createPathBookmarkGroup(PathBookmarkGroupCreateRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新路径标签分组
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return effect
|
||||||
|
*/
|
||||||
|
Integer updatePathBookmarkGroupById(PathBookmarkGroupUpdateRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询全部路径标签分组
|
||||||
|
*
|
||||||
|
* @return rows
|
||||||
|
*/
|
||||||
|
List<PathBookmarkGroupVO> getPathBookmarkGroupList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除路径标签分组
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return effect
|
||||||
|
*/
|
||||||
|
Integer deletePathBookmarkGroup(PathBookmarkGroupDeleteRequest request);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.orion.ops.module.asset.service;
|
|||||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
||||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
||||||
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkWrapperVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -31,6 +32,13 @@ public interface PathBookmarkService {
|
|||||||
*/
|
*/
|
||||||
Integer updatePathBookmarkById(PathBookmarkUpdateRequest request);
|
Integer updatePathBookmarkById(PathBookmarkUpdateRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询路径标签
|
||||||
|
*
|
||||||
|
* @return rows
|
||||||
|
*/
|
||||||
|
PathBookmarkWrapperVO getPathBookmark();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询全部路径标签
|
* 查询全部路径标签
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.orion.ops.module.asset.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.orion.lang.utils.Booleans;
|
||||||
|
import com.orion.ops.framework.common.constant.Const;
|
||||||
|
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||||
|
import com.orion.ops.framework.common.utils.Valid;
|
||||||
|
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||||
|
import com.orion.ops.module.asset.convert.PathBookmarkGroupConvert;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupDeleteRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||||
|
import com.orion.ops.module.asset.service.PathBookmarkGroupService;
|
||||||
|
import com.orion.ops.module.asset.service.PathBookmarkService;
|
||||||
|
import com.orion.ops.module.infra.api.DataGroupApi;
|
||||||
|
import com.orion.ops.module.infra.api.DataGroupUserApi;
|
||||||
|
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||||
|
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||||
|
import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
|
||||||
|
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签分组 服务实现类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024-1-24 12:28
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class PathBookmarkGroupServiceImpl implements PathBookmarkGroupService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DataGroupApi dataGroupApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DataGroupUserApi dataGroupUserApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PathBookmarkService pathBookmarkService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createPathBookmarkGroup(PathBookmarkGroupCreateRequest request) {
|
||||||
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
|
log.info("PathBookmarkGroupService-createPathBookmarkGroup request: {}", JSON.toJSONString(request));
|
||||||
|
// 创建
|
||||||
|
DataGroupCreateDTO create = PathBookmarkGroupConvert.MAPPER.to(request);
|
||||||
|
create.setParentId(Const.ROOT_PARENT_ID);
|
||||||
|
return dataGroupUserApi.createDataGroup(DataGroupTypeEnum.PATH_BOOKMARK, userId, create);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer updatePathBookmarkGroupById(PathBookmarkGroupUpdateRequest request) {
|
||||||
|
Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING);
|
||||||
|
log.info("PathBookmarkGroupService-updatePathBookmarkGroupById id: {}, request: {}", id, JSON.toJSONString(request));
|
||||||
|
// 重命名
|
||||||
|
DataGroupRenameDTO rename = PathBookmarkGroupConvert.MAPPER.to(request);
|
||||||
|
return dataGroupApi.renameDataGroup(rename);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PathBookmarkGroupVO> getPathBookmarkGroupList() {
|
||||||
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
|
// 查询分组
|
||||||
|
return dataGroupUserApi.getDataGroupList(DataGroupTypeEnum.PATH_BOOKMARK, userId)
|
||||||
|
.stream()
|
||||||
|
.sorted(Comparator.comparing(DataGroupDTO::getSort))
|
||||||
|
.map(PathBookmarkGroupConvert.MAPPER::to)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Integer deletePathBookmarkGroup(PathBookmarkGroupDeleteRequest request) {
|
||||||
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
|
Long id = request.getId();
|
||||||
|
log.info("PathBookmarkGroupService-deletePathBookmarkGroupById id: {}", id);
|
||||||
|
// 删除分组
|
||||||
|
Integer effect = dataGroupApi.deleteDataGroupById(id);
|
||||||
|
if (Booleans.isTrue(request.getDeleteItem())) {
|
||||||
|
// 删除组内数据
|
||||||
|
effect += pathBookmarkService.deleteByGroupId(userId, id);
|
||||||
|
} else {
|
||||||
|
// 移动到根节点
|
||||||
|
effect += pathBookmarkService.setGroupNull(userId, id);
|
||||||
|
}
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,7 +16,10 @@ import com.orion.ops.module.asset.entity.domain.PathBookmarkDO;
|
|||||||
import com.orion.ops.module.asset.entity.dto.PathBookmarkCacheDTO;
|
import com.orion.ops.module.asset.entity.dto.PathBookmarkCacheDTO;
|
||||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
||||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
||||||
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
||||||
|
import com.orion.ops.module.asset.entity.vo.PathBookmarkWrapperVO;
|
||||||
|
import com.orion.ops.module.asset.service.PathBookmarkGroupService;
|
||||||
import com.orion.ops.module.asset.service.PathBookmarkService;
|
import com.orion.ops.module.asset.service.PathBookmarkService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -24,6 +27,8 @@ import org.springframework.stereotype.Service;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,6 +45,9 @@ public class PathBookmarkServiceImpl implements PathBookmarkService {
|
|||||||
@Resource
|
@Resource
|
||||||
private PathBookmarkDAO pathBookmarkDAO;
|
private PathBookmarkDAO pathBookmarkDAO;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PathBookmarkGroupService pathBookmarkGroupService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createPathBookmark(PathBookmarkCreateRequest request) {
|
public Long createPathBookmark(PathBookmarkCreateRequest request) {
|
||||||
Long userId = SecurityUtils.getLoginUserId();
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
@@ -83,6 +91,31 @@ public class PathBookmarkServiceImpl implements PathBookmarkService {
|
|||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PathBookmarkWrapperVO getPathBookmark() {
|
||||||
|
// 查询分组
|
||||||
|
List<PathBookmarkGroupVO> groups = pathBookmarkGroupService.getPathBookmarkGroupList();
|
||||||
|
// 查询命令片段
|
||||||
|
List<PathBookmarkVO> items = this.getPathBookmarkList();
|
||||||
|
// 设置组内数据
|
||||||
|
Map<Long, PathBookmarkGroupVO> groupMap = groups.stream()
|
||||||
|
.collect(Collectors.toMap(PathBookmarkGroupVO::getId, Function.identity()));
|
||||||
|
groupMap.forEach((groupId, group) -> {
|
||||||
|
List<PathBookmarkVO> groupedItems = items.stream()
|
||||||
|
.filter(s -> groupId.equals(s.getGroupId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
group.setItems(groupedItems);
|
||||||
|
});
|
||||||
|
// 未分组数据
|
||||||
|
List<PathBookmarkVO> ungroupedItems = items.stream()
|
||||||
|
.filter(s -> s.getGroupId() == null)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return PathBookmarkWrapperVO.builder()
|
||||||
|
.groups(groups)
|
||||||
|
.ungroupedItems(ungroupedItems)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PathBookmarkVO> getPathBookmarkList() {
|
public List<PathBookmarkVO> getPathBookmarkList() {
|
||||||
Long userId = SecurityUtils.getLoginUserId();
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
|
|||||||
54
orion-ops-ui/src/api/asset/path-bookmark-group.ts
Normal file
54
orion-ops-ui/src/api/asset/path-bookmark-group.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import type { PathBookmarkQueryResponse } from './path-bookmark';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径书签分组创建请求
|
||||||
|
*/
|
||||||
|
export interface PathBookmarkGroupCreateRequest {
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径书签分组更新请求
|
||||||
|
*/
|
||||||
|
export interface PathBookmarkGroupUpdateRequest extends PathBookmarkGroupCreateRequest {
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径书签分组查询响应
|
||||||
|
*/
|
||||||
|
export interface PathBookmarkGroupQueryResponse {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
items: Array<PathBookmarkQueryResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建路径书签分组
|
||||||
|
*/
|
||||||
|
export function createPathBookmarkGroup(request: PathBookmarkGroupCreateRequest) {
|
||||||
|
return axios.post('/asset/path-bookmark-group/create', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新路径书签分组
|
||||||
|
*/
|
||||||
|
export function updatePathBookmarkGroup(request: PathBookmarkGroupUpdateRequest) {
|
||||||
|
return axios.put('/asset/path-bookmark-group/update', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询全部路径书签分组
|
||||||
|
*/
|
||||||
|
export function getPathBookmarkGroupList() {
|
||||||
|
return axios.get<Array<PathBookmarkGroupQueryResponse>>('/asset/path-bookmark-group/list');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除路径书签分组
|
||||||
|
*/
|
||||||
|
export function deletePathBookmarkGroup(id: number) {
|
||||||
|
return axios.delete('/asset/path-bookmark-group/delete', { params: { id } });
|
||||||
|
}
|
||||||
|
|
||||||
69
orion-ops-ui/src/api/asset/path-bookmark.ts
Normal file
69
orion-ops-ui/src/api/asset/path-bookmark.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { PathBookmarkGroupQueryResponse } from '@/api/asset/path-bookmark-group';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签创建请求
|
||||||
|
*/
|
||||||
|
export interface PathBookmarkCreateRequest {
|
||||||
|
groupId?: number;
|
||||||
|
name?: string;
|
||||||
|
path?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签更新请求
|
||||||
|
*/
|
||||||
|
export interface PathBookmarkUpdateRequest extends PathBookmarkCreateRequest {
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签查询响应
|
||||||
|
*/
|
||||||
|
export interface PathBookmarkQueryResponse extends PathBookmarkQueryResponseExtra {
|
||||||
|
id: number;
|
||||||
|
groupId: number;
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PathBookmarkQueryResponseExtra {
|
||||||
|
visible: boolean;
|
||||||
|
expand?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径标签查询响应
|
||||||
|
*/
|
||||||
|
export interface PathBookmarkWrapperResponse {
|
||||||
|
groups: Array<PathBookmarkGroupQueryResponse>;
|
||||||
|
ungroupedItems: Array<PathBookmarkQueryResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建路径标签
|
||||||
|
*/
|
||||||
|
export function createPathBookmark(request: PathBookmarkCreateRequest) {
|
||||||
|
return axios.post('/asset/path-bookmark/create', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新路径标签
|
||||||
|
*/
|
||||||
|
export function updatePathBookmark(request: PathBookmarkUpdateRequest) {
|
||||||
|
return axios.put('/asset/path-bookmark/update', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询路径标签
|
||||||
|
*/
|
||||||
|
export function getPathBookmarkList() {
|
||||||
|
return axios.get<PathBookmarkWrapperResponse>('/asset/path-bookmark/list');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除路径标签
|
||||||
|
*/
|
||||||
|
export function deletePathBookmark(id: number) {
|
||||||
|
return axios.delete('/asset/path-bookmark/delete', { params: { id } });
|
||||||
|
}
|
||||||
@@ -14,12 +14,13 @@ import { getMenuList } from '@/api/system/menu';
|
|||||||
import { getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data';
|
import { getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data';
|
||||||
import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group';
|
import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group';
|
||||||
import { getExecJobList } from '@/api/exec/exec-job';
|
import { getExecJobList } from '@/api/exec/exec-job';
|
||||||
|
import { getPathBookmarkGroupList } from '@/api/asset/path-bookmark-group';
|
||||||
|
|
||||||
export type CacheType = 'users' | 'menus' | 'roles'
|
export type CacheType = 'users' | 'menus' | 'roles'
|
||||||
| 'hosts' | 'hostGroups' | 'hostKeys' | 'hostIdentities'
|
| 'hosts' | 'hostGroups' | 'hostKeys' | 'hostIdentities'
|
||||||
| 'dictKeys'
|
| 'dictKeys'
|
||||||
| 'authorizedHostKeys' | 'authorizedHostIdentities'
|
| 'authorizedHostKeys' | 'authorizedHostIdentities'
|
||||||
| 'commandSnippetGroups'
|
| 'commandSnippetGroups' | 'pathBookmarkGroups'
|
||||||
| 'execJob'
|
| 'execJob'
|
||||||
| string
|
| string
|
||||||
|
|
||||||
@@ -120,6 +121,11 @@ export default defineStore('cache', {
|
|||||||
return await this.load('commandSnippetGroups', getCommandSnippetGroupList, force);
|
return await this.load('commandSnippetGroups', getCommandSnippetGroupList, force);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 获取路径书签分组
|
||||||
|
async loadPathBookmarkGroups(force = false) {
|
||||||
|
return await this.load('pathBookmarkGroups', getPathBookmarkGroupList, force);
|
||||||
|
},
|
||||||
|
|
||||||
// 获取执行计划列表
|
// 获取执行计划列表
|
||||||
async loadExecJobs(force = false) {
|
async loadExecJobs(force = false) {
|
||||||
return await this.load('execJob', getExecJobList, force);
|
return await this.load('execJob', getExecJobList, force);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type {
|
|||||||
TerminalShortcutSetting,
|
TerminalShortcutSetting,
|
||||||
TerminalState
|
TerminalState
|
||||||
} from './types';
|
} from './types';
|
||||||
import type { ISshSession, PanelSessionTabType, TerminalPanelTabItem } from '@/views/host/terminal/types/terminal.type';
|
import type { ISftpSession, ISshSession, PanelSessionTabType, TerminalPanelTabItem } from '@/views/host/terminal/types/terminal.type';
|
||||||
import type { AuthorizedHostQueryResponse } from '@/api/asset/asset-authorized-data';
|
import type { AuthorizedHostQueryResponse } from '@/api/asset/asset-authorized-data';
|
||||||
import { getCurrentAuthorizedHost } from '@/api/asset/asset-authorized-data';
|
import { getCurrentAuthorizedHost } from '@/api/asset/asset-authorized-data';
|
||||||
import type { HostQueryResponse } from '@/api/asset/host';
|
import type { HostQueryResponse } from '@/api/asset/host';
|
||||||
@@ -226,6 +226,19 @@ export default defineStore('terminal', {
|
|||||||
return this.sessionManager.getSession<ISshSession>(sessionTab.sessionId);
|
return this.sessionManager.getSession<ISshSession>(sessionTab.sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 获取当前 sftp 会话
|
||||||
|
getCurrentSftpSession() {
|
||||||
|
// 获取面板会话
|
||||||
|
const sessionTab = this.panelManager
|
||||||
|
.getCurrentPanel()
|
||||||
|
.getCurrentTab();
|
||||||
|
if (!sessionTab || sessionTab.type !== PanelSessionType.SFTP.type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 获取会话
|
||||||
|
return this.sessionManager.getSession<ISftpSession>(sessionTab.sessionId);
|
||||||
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<a-spin class="full form-container" :loading="loading">
|
<a-spin class="full form-container" :loading="loading">
|
||||||
<a-form :model="formModel"
|
<a-form :model="formModel"
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
label-align="left"
|
label-align="right"
|
||||||
:auto-label-width="true"
|
:auto-label-width="true"
|
||||||
:rules="formRules">
|
:rules="formRules">
|
||||||
<!-- 名称 -->
|
<!-- 名称 -->
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
allow-clear />
|
allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 分组 -->
|
<!-- 分组 -->
|
||||||
<a-form-item field="groupId" label="命令分组">
|
<a-form-item field="groupId" label="分组">
|
||||||
<command-snippet-group-select v-model="formModel.groupId" />
|
<command-snippet-group-select v-model="formModel.groupId" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 代码片段 -->
|
<!-- 代码片段 -->
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
<!-- 表头 -->
|
<!-- 表头 -->
|
||||||
<template #title>
|
<template #title>
|
||||||
<span class="snippet-drawer-title usn">
|
<span class="snippet-drawer-title usn">
|
||||||
<icon-code />
|
|
||||||
命令片段
|
命令片段
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -32,21 +31,21 @@
|
|||||||
<!-- 搜索框 -->
|
<!-- 搜索框 -->
|
||||||
<a-input-search class="snippet-header-input"
|
<a-input-search class="snippet-header-input"
|
||||||
v-model="filterValue"
|
v-model="filterValue"
|
||||||
placeholder="名称"
|
placeholder="名称/命令"
|
||||||
allow-clear
|
allow-clear
|
||||||
@search="filterSnippet"
|
@search="filterSnippet"
|
||||||
@keyup.enter="filterSnippet" />
|
@keyup.enter="filterSnippet" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 加载中 -->
|
<!-- 加载中 -->
|
||||||
<a-skeleton v-if="loading"
|
<a-skeleton v-if="loading"
|
||||||
style="padding: 0 12px"
|
class="loading-skeleton"
|
||||||
:animation="true">
|
:animation="true">
|
||||||
<a-skeleton-line :rows="4"
|
<a-skeleton-line :rows="4"
|
||||||
:line-height="66"
|
:line-height="66"
|
||||||
:line-spacing="12" />
|
:line-spacing="12" />
|
||||||
</a-skeleton>
|
</a-skeleton>
|
||||||
<!-- 无数据 -->
|
<!-- 无数据 -->
|
||||||
<a-empty v-else-if="!snippet || (snippet.groups.length === 0 && snippet.ungroupedItems.length === 0)"
|
<a-empty v-else-if="!snippetValue || (snippetValue.groups.length === 0 && snippetValue.ungroupedItems.length === 0)"
|
||||||
style="padding: 28px 0">
|
style="padding: 28px 0">
|
||||||
<span>暂无数据</span><br>
|
<span>暂无数据</span><br>
|
||||||
<span>点击上方 '<icon-plus />' 添加一条数据吧~</span>
|
<span>点击上方 '<icon-plus />' 添加一条数据吧~</span>
|
||||||
@@ -54,10 +53,10 @@
|
|||||||
<!-- 命令片段 -->
|
<!-- 命令片段 -->
|
||||||
<div v-else class="snippet-list-container">
|
<div v-else class="snippet-list-container">
|
||||||
<!-- 命令片段组 -->
|
<!-- 命令片段组 -->
|
||||||
<command-snippet-list-group :snippet="snippet" />
|
<command-snippet-list-group :value="snippetValue" />
|
||||||
<!-- 未分组命令片段 -->
|
<!-- 未分组命令片段 -->
|
||||||
<div class="ungrouped-snippet-container">
|
<div class="ungrouped-snippet-container">
|
||||||
<template v-for="item in snippet.ungroupedItems">
|
<template v-for="item in snippetValue.ungroupedItems">
|
||||||
<command-snippet-list-item v-if="item.visible"
|
<command-snippet-list-item v-if="item.visible"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:item="item" />
|
:item="item" />
|
||||||
@@ -97,7 +96,7 @@
|
|||||||
|
|
||||||
const formDrawer = ref();
|
const formDrawer = ref();
|
||||||
const filterValue = ref<string>();
|
const filterValue = ref<string>();
|
||||||
const snippet = ref<CommandSnippetWrapperResponse>();
|
const snippetValue = ref<CommandSnippetWrapperResponse>();
|
||||||
|
|
||||||
// 打开
|
// 打开
|
||||||
const open = async () => {
|
const open = async () => {
|
||||||
@@ -110,14 +109,14 @@
|
|||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
const fetchData = async (force: boolean = false) => {
|
const fetchData = async (force: boolean = false) => {
|
||||||
if (snippet.value && !force) {
|
if (snippetValue.value && !force) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
// 查询
|
// 查询
|
||||||
const { data } = await getCommandSnippetList();
|
const { data } = await getCommandSnippetList();
|
||||||
snippet.value = data;
|
snippetValue.value = data;
|
||||||
// 设置状态
|
// 设置状态
|
||||||
filterSnippet();
|
filterSnippet();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -128,14 +127,14 @@
|
|||||||
|
|
||||||
// 过滤
|
// 过滤
|
||||||
const filterSnippet = () => {
|
const filterSnippet = () => {
|
||||||
snippet.value?.groups.forEach(g => {
|
snippetValue.value?.groups.forEach(g => {
|
||||||
g.items?.forEach(s => {
|
g.items?.forEach(s => {
|
||||||
s.visible = !filterValue.value
|
s.visible = !filterValue.value
|
||||||
|| s.name.toLowerCase().includes(filterValue.value.toLowerCase())
|
|| s.name.toLowerCase().includes(filterValue.value.toLowerCase())
|
||||||
|| s.command.toLowerCase().includes(filterValue.value.toLowerCase());
|
|| s.command.toLowerCase().includes(filterValue.value.toLowerCase());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
snippet.value?.ungroupedItems.forEach(s => {
|
snippetValue.value?.ungroupedItems.forEach(s => {
|
||||||
s.visible = !filterValue.value
|
s.visible = !filterValue.value
|
||||||
|| s.name.toLowerCase().includes(filterValue.value.toLowerCase())
|
|| s.name.toLowerCase().includes(filterValue.value.toLowerCase())
|
||||||
|| s.command.toLowerCase().includes(filterValue.value.toLowerCase());
|
|| s.command.toLowerCase().includes(filterValue.value.toLowerCase());
|
||||||
@@ -166,17 +165,17 @@
|
|||||||
|
|
||||||
// 暴露 删除
|
// 暴露 删除
|
||||||
provide(removeSnippetKey, async (id: number) => {
|
provide(removeSnippetKey, async (id: number) => {
|
||||||
if (!snippet.value) {
|
if (!snippetValue.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 删除
|
// 删除
|
||||||
await deleteCommandSnippet(id);
|
await deleteCommandSnippet(id);
|
||||||
// 查找并且删除未分组的数据
|
// 查找并且删除未分组的数据
|
||||||
if (findAndSplice(id, snippet.value.ungroupedItems)) {
|
if (findAndSplice(id, snippetValue.value.ungroupedItems)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 查找并且删除分组内数据
|
// 查找并且删除分组内数据
|
||||||
for (let group of snippet.value.groups) {
|
for (let group of snippetValue.value.groups) {
|
||||||
if (findAndSplice(id, group.items)) {
|
if (findAndSplice(id, group.items)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -186,14 +185,14 @@
|
|||||||
// 添加回调
|
// 添加回调
|
||||||
const onAdded = async (item: CommandSnippetQueryResponse) => {
|
const onAdded = async (item: CommandSnippetQueryResponse) => {
|
||||||
if (item.groupId) {
|
if (item.groupId) {
|
||||||
let group = snippet.value?.groups.find(g => g.id === item.groupId);
|
let group = snippetValue.value?.groups.find(g => g.id === item.groupId);
|
||||||
if (group) {
|
if (group) {
|
||||||
group?.items.push(item);
|
group?.items.push(item);
|
||||||
} else {
|
} else {
|
||||||
const cacheGroups = await cacheStore.loadCommandSnippetGroups();
|
const cacheGroups = await cacheStore.loadCommandSnippetGroups();
|
||||||
const findGroup = cacheGroups.find(s => s.id === item.groupId);
|
const findGroup = cacheGroups.find(s => s.id === item.groupId);
|
||||||
if (findGroup) {
|
if (findGroup) {
|
||||||
snippet.value?.groups.push({
|
snippetValue.value?.groups.push({
|
||||||
id: item.groupId,
|
id: item.groupId,
|
||||||
name: findGroup.name,
|
name: findGroup.name,
|
||||||
items: [item]
|
items: [item]
|
||||||
@@ -201,7 +200,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snippet.value?.ungroupedItems.push(item);
|
snippetValue.value?.ungroupedItems.push(item);
|
||||||
}
|
}
|
||||||
// 重置过滤
|
// 重置过滤
|
||||||
filterSnippet();
|
filterSnippet();
|
||||||
@@ -209,16 +208,16 @@
|
|||||||
|
|
||||||
// 修改回调
|
// 修改回调
|
||||||
const onUpdated = async (item: CommandSnippetQueryResponse) => {
|
const onUpdated = async (item: CommandSnippetQueryResponse) => {
|
||||||
if (!snippet.value) {
|
if (!snippetValue.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 查找原始数据
|
// 查找原始数据
|
||||||
let originItem;
|
let originItem;
|
||||||
const findInUngrouped = snippet.value.ungroupedItems.find(s => s.id === item.id);
|
const findInUngrouped = snippetValue.value.ungroupedItems.find(s => s.id === item.id);
|
||||||
if (findInUngrouped) {
|
if (findInUngrouped) {
|
||||||
originItem = findInUngrouped;
|
originItem = findInUngrouped;
|
||||||
} else {
|
} else {
|
||||||
for (let group of snippet.value.groups) {
|
for (let group of snippetValue.value.groups) {
|
||||||
const find = group.items.find(s => s.id === item.id);
|
const find = group.items.find(s => s.id === item.id);
|
||||||
if (find) {
|
if (find) {
|
||||||
originItem = find;
|
originItem = find;
|
||||||
@@ -230,12 +229,12 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 检查分组是否存在
|
// 检查分组是否存在
|
||||||
const findGroup = snippet.value.groups.find(s => s.id === item.groupId);
|
const findGroup = snippetValue.value.groups.find(s => s.id === item.groupId);
|
||||||
if (!findGroup) {
|
if (!findGroup) {
|
||||||
const cacheGroups = await cacheStore.loadCommandSnippetGroups();
|
const cacheGroups = await cacheStore.loadCommandSnippetGroups();
|
||||||
const cacheGroup = cacheGroups.find(s => s.id === item.groupId);
|
const cacheGroup = cacheGroups.find(s => s.id === item.groupId);
|
||||||
if (cacheGroup) {
|
if (cacheGroup) {
|
||||||
snippet.value.groups.push({
|
snippetValue.value.groups.push({
|
||||||
id: item.groupId,
|
id: item.groupId,
|
||||||
name: cacheGroup.name,
|
name: cacheGroup.name,
|
||||||
items: []
|
items: []
|
||||||
@@ -251,22 +250,22 @@
|
|||||||
if (item.groupId !== originGroupId) {
|
if (item.groupId !== originGroupId) {
|
||||||
// 从原始分组移除
|
// 从原始分组移除
|
||||||
if (originGroupId) {
|
if (originGroupId) {
|
||||||
const findGroup = snippet.value.groups.find(s => s.id === originGroupId);
|
const findGroup = snippetValue.value.groups.find(s => s.id === originGroupId);
|
||||||
if (findGroup) {
|
if (findGroup) {
|
||||||
findAndSplice(item.id, findGroup.items);
|
findAndSplice(item.id, findGroup.items);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 从未分组数据中移除
|
// 从未分组数据中移除
|
||||||
findAndSplice(item.id, snippet.value.ungroupedItems);
|
findAndSplice(item.id, snippetValue.value.ungroupedItems);
|
||||||
}
|
}
|
||||||
// 添加到新分组
|
// 添加到新分组
|
||||||
if (item.groupId) {
|
if (item.groupId) {
|
||||||
const findGroup = snippet.value.groups.find(s => s.id === item.groupId);
|
const findGroup = snippetValue.value.groups.find(s => s.id === item.groupId);
|
||||||
if (findGroup) {
|
if (findGroup) {
|
||||||
findGroup.items.push(item);
|
findGroup.items.push(item);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snippet.value.ungroupedItems.push(originItem);
|
snippetValue.value.ungroupedItems.push(originItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 重置过滤
|
// 重置过滤
|
||||||
@@ -283,7 +282,7 @@
|
|||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.snippet-drawer-title {
|
.snippet-drawer-title {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.snippet-container {
|
.snippet-container {
|
||||||
@@ -320,4 +319,12 @@
|
|||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading-skeleton {
|
||||||
|
padding: 0 12px;
|
||||||
|
|
||||||
|
:deep(.arco-skeleton-line-row) {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-collapse :bordered="false">
|
<a-collapse :bordered="false">
|
||||||
<template v-for="group in snippet.groups">
|
<template v-for="group in value.groups">
|
||||||
<a-collapse-item v-if="calcTotal(group) > 0"
|
<a-collapse-item v-if="calcTotal(group) > 0"
|
||||||
:key="group.id"
|
:key="group.id"
|
||||||
:header="group.name">
|
:header="group.name">
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'commandSnippetGroup'
|
name: 'commandSnippetListGroup'
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
import CommandSnippetListItem from './command-snippet-list-item.vue';
|
import CommandSnippetListItem from './command-snippet-list-item.vue';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
snippet: CommandSnippetWrapperResponse;
|
value: CommandSnippetWrapperResponse;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 计算总量
|
// 计算总量
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'commandSnippetItem'
|
name: 'commandSnippetListItem'
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<a-drawer v-model:visible="visible"
|
||||||
|
:width="388"
|
||||||
|
:title="title"
|
||||||
|
:mask-closable="false"
|
||||||
|
:unmount-on-close="true"
|
||||||
|
:ok-button-props="{ disabled: loading }"
|
||||||
|
:cancel-button-props="{ disabled: loading }"
|
||||||
|
:on-before-ok="handlerOk"
|
||||||
|
@cancel="handleClose">
|
||||||
|
<a-spin class="full form-container" :loading="loading">
|
||||||
|
<a-form :model="formModel"
|
||||||
|
ref="formRef"
|
||||||
|
label-align="right"
|
||||||
|
:auto-label-width="true"
|
||||||
|
:rules="formRules">
|
||||||
|
<!-- 名称 -->
|
||||||
|
<a-form-item field="name" label="名称">
|
||||||
|
<a-input v-model="formModel.name"
|
||||||
|
placeholder="请输入名称"
|
||||||
|
allow-clear />
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 分组 -->
|
||||||
|
<a-form-item field="groupId" label="分组">
|
||||||
|
<path-bookmark-group-select v-model="formModel.groupId" />
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 文件路径 -->
|
||||||
|
<a-form-item field="path" label="路径">
|
||||||
|
<a-textarea v-model="formModel.path"
|
||||||
|
placeholder="文件路径"
|
||||||
|
:auto-size="{ minRows: 8, maxRows: 8 }"
|
||||||
|
allow-clear />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-spin>
|
||||||
|
</a-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'pathBookmarkFormDrawer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { PathBookmarkUpdateRequest } from '@/api/asset/path-bookmark';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import { createPathBookmark, updatePathBookmark } from '@/api/asset/path-bookmark';
|
||||||
|
import formRules from '../types/form.rules';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import PathBookmarkGroupSelect from './path-bookmark-group-select.vue';
|
||||||
|
|
||||||
|
const { visible, setVisible } = useVisible();
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
|
|
||||||
|
const title = ref<string>();
|
||||||
|
const isAddHandle = ref<boolean>(true);
|
||||||
|
|
||||||
|
const defaultForm = (): PathBookmarkUpdateRequest => {
|
||||||
|
return {
|
||||||
|
id: undefined,
|
||||||
|
groupId: undefined,
|
||||||
|
name: undefined,
|
||||||
|
path: undefined,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const formRef = ref<any>();
|
||||||
|
const formModel = ref<PathBookmarkUpdateRequest>({});
|
||||||
|
|
||||||
|
const emits = defineEmits(['added', 'updated']);
|
||||||
|
|
||||||
|
// 打开新增
|
||||||
|
const openAdd = () => {
|
||||||
|
title.value = '添加路径标签';
|
||||||
|
isAddHandle.value = true;
|
||||||
|
renderForm({ ...defaultForm() });
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开修改
|
||||||
|
const openUpdate = (record: any) => {
|
||||||
|
title.value = '修改路径标签';
|
||||||
|
isAddHandle.value = false;
|
||||||
|
renderForm({ ...defaultForm(), ...record });
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染表单
|
||||||
|
const renderForm = (record: any) => {
|
||||||
|
formModel.value = Object.assign({}, record);
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ openAdd, openUpdate });
|
||||||
|
|
||||||
|
// 确定
|
||||||
|
const handlerOk = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
// 验证参数
|
||||||
|
const error = await formRef.value.validate();
|
||||||
|
if (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isAddHandle.value) {
|
||||||
|
// 新增
|
||||||
|
const { data: id } = await createPathBookmark(formModel.value);
|
||||||
|
formModel.value.id = id;
|
||||||
|
Message.success('创建成功');
|
||||||
|
emits('added', formModel.value);
|
||||||
|
} else {
|
||||||
|
// 修改
|
||||||
|
await updatePathBookmark(formModel.value);
|
||||||
|
Message.success('修改成功');
|
||||||
|
emits('updated', formModel.value);
|
||||||
|
}
|
||||||
|
// 清空
|
||||||
|
handlerClear();
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭
|
||||||
|
const handleClose = () => {
|
||||||
|
handlerClear();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清空
|
||||||
|
const handlerClear = () => {
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.form-container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<a-select v-model:model-value="value"
|
||||||
|
placeholder="请选择路径分组"
|
||||||
|
:options="optionData"
|
||||||
|
:loading="loading"
|
||||||
|
:allow-create="true"
|
||||||
|
allow-clear />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'pathBookmarkGroupSelect'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { SelectOptionData } from '@arco-design/web-vue';
|
||||||
|
import type { PathBookmarkGroupQueryResponse } from '@/api/asset/path-bookmark-group';
|
||||||
|
import { ref, computed, onBeforeMount } from 'vue';
|
||||||
|
import { useCacheStore } from '@/store';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import { createPathBookmarkGroup } from '@/api/asset/path-bookmark-group';
|
||||||
|
|
||||||
|
const props = defineProps<Partial<{
|
||||||
|
modelValue: number;
|
||||||
|
}>>();
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:modelValue']);
|
||||||
|
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
|
const cacheStore = useCacheStore();
|
||||||
|
|
||||||
|
const value = computed<number | string>({
|
||||||
|
get() {
|
||||||
|
return props.modelValue as number;
|
||||||
|
},
|
||||||
|
async set(e) {
|
||||||
|
const val = await checkCreateGroup(e);
|
||||||
|
emits('update:modelValue', val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const optionData = ref<SelectOptionData[]>([]);
|
||||||
|
|
||||||
|
// 检查是否可以创建分组
|
||||||
|
const checkCreateGroup = async (val: string | number): Promise<number> => {
|
||||||
|
// 清空
|
||||||
|
if (!val) {
|
||||||
|
return undefined as unknown as number;
|
||||||
|
}
|
||||||
|
// 为 number 代表为 id 已存在
|
||||||
|
if (typeof val === 'number') {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
// 已存在则跳过
|
||||||
|
const find = optionData.value.find((o) => o.label === val);
|
||||||
|
if (find) {
|
||||||
|
return find.value as number;
|
||||||
|
}
|
||||||
|
// 不存在则创建
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
return await doCreateGroup(val);
|
||||||
|
} catch (e) {
|
||||||
|
return undefined as unknown as number;
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建分组
|
||||||
|
const doCreateGroup = async (name: string) => {
|
||||||
|
const { data: id } = await createPathBookmarkGroup({
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
// 插入缓存
|
||||||
|
const groups = await cacheStore.loadPathBookmarkGroups();
|
||||||
|
groups && groups.push({ id, name } as PathBookmarkGroupQueryResponse);
|
||||||
|
// 插入 options
|
||||||
|
optionData.value.push({
|
||||||
|
label: name,
|
||||||
|
value: id,
|
||||||
|
});
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化选项
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const tags = await cacheStore.loadPathBookmarkGroups();
|
||||||
|
optionData.value = tags.map(s => {
|
||||||
|
return {
|
||||||
|
label: s.name,
|
||||||
|
value: s.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,330 @@
|
|||||||
|
<template>
|
||||||
|
<a-drawer v-model:visible="visible"
|
||||||
|
:width="388"
|
||||||
|
:footer="false"
|
||||||
|
@close="onClose">
|
||||||
|
<!-- 表头 -->
|
||||||
|
<template #title>
|
||||||
|
<span class="path-drawer-title usn">
|
||||||
|
路径书签
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<!-- 路径容器 -->
|
||||||
|
<div class="path-container">
|
||||||
|
<!-- 路径头部 -->
|
||||||
|
<div class="path-header">
|
||||||
|
<!-- 左侧按钮 -->
|
||||||
|
<a-space size="small">
|
||||||
|
<!-- 创建路径 -->
|
||||||
|
<span class="click-icon-wrapper path-header-icon"
|
||||||
|
title="创建路径"
|
||||||
|
@click="openAdd">
|
||||||
|
<icon-plus />
|
||||||
|
</span>
|
||||||
|
<!-- 刷新 -->
|
||||||
|
<span class="click-icon-wrapper path-header-icon"
|
||||||
|
title="刷新"
|
||||||
|
@click="fetchData(true)">
|
||||||
|
<icon-refresh />
|
||||||
|
</span>
|
||||||
|
</a-space>
|
||||||
|
<!-- 搜索框 -->
|
||||||
|
<a-input-search class="path-header-input"
|
||||||
|
v-model="filterValue"
|
||||||
|
placeholder="名称/路径"
|
||||||
|
allow-clear
|
||||||
|
@search="filterPath"
|
||||||
|
@keyup.enter="filterPath" />
|
||||||
|
</div>
|
||||||
|
<!-- 加载中 -->
|
||||||
|
<a-skeleton v-if="loading"
|
||||||
|
class="loading-skeleton"
|
||||||
|
:animation="true">
|
||||||
|
<a-skeleton-line :rows="4"
|
||||||
|
:line-height="66"
|
||||||
|
:line-spacing="12" />
|
||||||
|
</a-skeleton>
|
||||||
|
<!-- 无数据 -->
|
||||||
|
<a-empty v-else-if="!pathBookmarkData || (pathBookmarkData.groups.length === 0 && pathBookmarkData.ungroupedItems.length === 0)"
|
||||||
|
style="padding: 28px 0">
|
||||||
|
<span>暂无数据</span><br>
|
||||||
|
<span>点击上方 '<icon-plus />' 添加一条数据吧~</span>
|
||||||
|
</a-empty>
|
||||||
|
<!-- 路径书签 -->
|
||||||
|
<div v-else class="path-list-container">
|
||||||
|
<!-- 路径书签组 -->
|
||||||
|
<path-bookmark-list-group :value="pathBookmarkData" />
|
||||||
|
<!-- 未分组路径书签 -->
|
||||||
|
<div class="ungrouped-path-container">
|
||||||
|
<template v-for="item in pathBookmarkData.ungroupedItems">
|
||||||
|
<path-bookmark-list-item v-if="item.visible"
|
||||||
|
:key="item.id"
|
||||||
|
:item="item" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 路径编辑抽屉 -->
|
||||||
|
<path-bookmark-form-drawer ref="formDrawer"
|
||||||
|
@added="onAdded"
|
||||||
|
@updated="onUpdated" />
|
||||||
|
</a-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'pathBookmarkListDrawer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { PathBookmarkWrapperResponse, PathBookmarkQueryResponse } from '@/api/asset/path-bookmark';
|
||||||
|
import { ref, provide } from 'vue';
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import { deletePathBookmark, getPathBookmarkList } from '@/api/asset/path-bookmark';
|
||||||
|
import { useCacheStore, useTerminalStore } from '@/store';
|
||||||
|
import { openUpdatePathKey, removePathKey } from '../types/const';
|
||||||
|
import PathBookmarkListItem from './path-bookmark-list-item.vue';
|
||||||
|
import PathBookmarkListGroup from './path-bookmark-list-group.vue';
|
||||||
|
import PathBookmarkFormDrawer from './path-bookmark-form-drawer.vue';
|
||||||
|
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
|
const { visible, setVisible } = useVisible();
|
||||||
|
const { getCurrentSshSession } = useTerminalStore();
|
||||||
|
const cacheStore = useCacheStore();
|
||||||
|
|
||||||
|
const formDrawer = ref();
|
||||||
|
const filterValue = ref<string>();
|
||||||
|
const pathBookmarkData = ref<PathBookmarkWrapperResponse>();
|
||||||
|
|
||||||
|
// 打开
|
||||||
|
const open = async () => {
|
||||||
|
setVisible(true);
|
||||||
|
// 加载数据
|
||||||
|
await fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
|
||||||
|
// 加载数据
|
||||||
|
const fetchData = async (force: boolean = false) => {
|
||||||
|
if (pathBookmarkData.value && !force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
// 查询
|
||||||
|
const { data } = await getPathBookmarkList();
|
||||||
|
pathBookmarkData.value = data;
|
||||||
|
// 设置状态
|
||||||
|
filterPath();
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 过滤
|
||||||
|
const filterPath = () => {
|
||||||
|
pathBookmarkData.value?.groups.forEach(g => {
|
||||||
|
g.items?.forEach(s => {
|
||||||
|
s.visible = !filterValue.value
|
||||||
|
|| s.name.toLowerCase().includes(filterValue.value.toLowerCase())
|
||||||
|
|| s.path.toLowerCase().includes(filterValue.value.toLowerCase());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
pathBookmarkData.value?.ungroupedItems.forEach(s => {
|
||||||
|
s.visible = !filterValue.value
|
||||||
|
|| s.name.toLowerCase().includes(filterValue.value.toLowerCase())
|
||||||
|
|| s.path.toLowerCase().includes(filterValue.value.toLowerCase());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新建
|
||||||
|
const openAdd = () => {
|
||||||
|
formDrawer.value.openAdd();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查找并且删除
|
||||||
|
const findAndSplice = (id: number, items: Array<PathBookmarkQueryResponse>) => {
|
||||||
|
if (items) {
|
||||||
|
const index = items.findIndex(s => s.id === id);
|
||||||
|
if (index !== -1) {
|
||||||
|
items.splice(index, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暴露 修改抽屉
|
||||||
|
provide(openUpdatePathKey, (e: PathBookmarkQueryResponse) => {
|
||||||
|
formDrawer.value.openUpdate(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 暴露 删除
|
||||||
|
provide(removePathKey, async (id: number) => {
|
||||||
|
if (!pathBookmarkData.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 删除
|
||||||
|
await deletePathBookmark(id);
|
||||||
|
// 查找并且删除未分组的数据
|
||||||
|
if (findAndSplice(id, pathBookmarkData.value.ungroupedItems)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 查找并且删除分组内数据
|
||||||
|
for (let group of pathBookmarkData.value.groups) {
|
||||||
|
if (findAndSplice(id, group.items)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加回调
|
||||||
|
const onAdded = async (item: PathBookmarkQueryResponse) => {
|
||||||
|
if (item.groupId) {
|
||||||
|
let group = pathBookmarkData.value?.groups.find(g => g.id === item.groupId);
|
||||||
|
if (group) {
|
||||||
|
group?.items.push(item);
|
||||||
|
} else {
|
||||||
|
const cacheGroups = await cacheStore.loadPathBookmarkGroups();
|
||||||
|
const findGroup = cacheGroups.find(s => s.id === item.groupId);
|
||||||
|
if (findGroup) {
|
||||||
|
pathBookmarkData.value?.groups.push({
|
||||||
|
id: item.groupId,
|
||||||
|
name: findGroup.name,
|
||||||
|
items: [item]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pathBookmarkData.value?.ungroupedItems.push(item);
|
||||||
|
}
|
||||||
|
// 重置过滤
|
||||||
|
filterPath();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 修改回调
|
||||||
|
const onUpdated = async (item: PathBookmarkQueryResponse) => {
|
||||||
|
if (!pathBookmarkData.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 查找原始数据
|
||||||
|
let originItem;
|
||||||
|
const findInUngrouped = pathBookmarkData.value.ungroupedItems.find(s => s.id === item.id);
|
||||||
|
if (findInUngrouped) {
|
||||||
|
originItem = findInUngrouped;
|
||||||
|
} else {
|
||||||
|
for (let group of pathBookmarkData.value.groups) {
|
||||||
|
const find = group.items.find(s => s.id === item.id);
|
||||||
|
if (find) {
|
||||||
|
originItem = find;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!originItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 检查分组是否存在
|
||||||
|
const findGroup = pathBookmarkData.value.groups.find(s => s.id === item.groupId);
|
||||||
|
if (!findGroup) {
|
||||||
|
const cacheGroups = await cacheStore.loadPathBookmarkGroups();
|
||||||
|
const cacheGroup = cacheGroups.find(s => s.id === item.groupId);
|
||||||
|
if (cacheGroup) {
|
||||||
|
pathBookmarkData.value.groups.push({
|
||||||
|
id: item.groupId,
|
||||||
|
name: cacheGroup.name,
|
||||||
|
items: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 设置数据
|
||||||
|
const originGroupId = originItem.groupId;
|
||||||
|
originItem.groupId = item.groupId;
|
||||||
|
originItem.name = item.name;
|
||||||
|
originItem.path = item.path;
|
||||||
|
// 移动分组
|
||||||
|
if (item.groupId !== originGroupId) {
|
||||||
|
// 从原始分组移除
|
||||||
|
if (originGroupId) {
|
||||||
|
const findGroup = pathBookmarkData.value.groups.find(s => s.id === originGroupId);
|
||||||
|
if (findGroup) {
|
||||||
|
findAndSplice(item.id, findGroup.items);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 从未分组数据中移除
|
||||||
|
findAndSplice(item.id, pathBookmarkData.value.ungroupedItems);
|
||||||
|
}
|
||||||
|
// 添加到新分组
|
||||||
|
if (item.groupId) {
|
||||||
|
const findGroup = pathBookmarkData.value.groups.find(s => s.id === item.groupId);
|
||||||
|
if (findGroup) {
|
||||||
|
findGroup.items.push(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pathBookmarkData.value.ungroupedItems.push(originItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 重置过滤
|
||||||
|
filterPath();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭回调
|
||||||
|
const onClose = () => {
|
||||||
|
// 聚焦终端
|
||||||
|
getCurrentSshSession()?.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.path-drawer-title {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-container {
|
||||||
|
position: relative;
|
||||||
|
background: var(--color-bg-2);
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.path-header {
|
||||||
|
padding: 12px;
|
||||||
|
height: 56px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
&-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-input {
|
||||||
|
width: 248px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-list-container {
|
||||||
|
position: relative;
|
||||||
|
height: calc(100% - 56px);
|
||||||
|
overflow: auto;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-skeleton {
|
||||||
|
padding: 0 12px;
|
||||||
|
|
||||||
|
:deep(.arco-skeleton-line-row) {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<a-collapse :bordered="false">
|
||||||
|
<template v-for="group in value.groups">
|
||||||
|
<a-collapse-item v-if="calcTotal(group) > 0"
|
||||||
|
:key="group.id"
|
||||||
|
:header="group.name">
|
||||||
|
<!-- 总量 -->
|
||||||
|
<template #extra>
|
||||||
|
{{ calcTotal(group) }} 条
|
||||||
|
</template>
|
||||||
|
<!-- 路径 -->
|
||||||
|
<template v-for="item in group.items">
|
||||||
|
<path-bookmark-list-item v-if="item.visible"
|
||||||
|
:key="item.id"
|
||||||
|
:item="item" />
|
||||||
|
</template>
|
||||||
|
</a-collapse-item>
|
||||||
|
</template>
|
||||||
|
</a-collapse>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'pathBookmarkListGroup'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { PathBookmarkGroupQueryResponse } from '@/api/asset/path-bookmark-group';
|
||||||
|
import type { PathBookmarkWrapperResponse } from '@/api/asset/path-bookmark';
|
||||||
|
import PathBookmarkListItem from './path-bookmark-list-item.vue';
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
value: PathBookmarkWrapperResponse;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 计算总量
|
||||||
|
const calcTotal = (group: PathBookmarkGroupQueryResponse) => {
|
||||||
|
return group.items.filter(s => s.visible).length;
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
:deep(.arco-collapse-item) {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-extra {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
background-color: unset;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content-box {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
<template>
|
||||||
|
<a-dropdown class="terminal-context-menu"
|
||||||
|
:popup-max-height="false"
|
||||||
|
trigger="contextMenu"
|
||||||
|
position="bl"
|
||||||
|
alignPoint>
|
||||||
|
<!-- 路径 -->
|
||||||
|
<div class="path-item-wrapper"
|
||||||
|
:class="[!!item.expand ? 'path-item-wrapper-expand' : '']"
|
||||||
|
@click="clickItem">
|
||||||
|
<div class="path-item">
|
||||||
|
<div class="path-item-title">
|
||||||
|
<!-- 名称 -->
|
||||||
|
<span class="path-item-title-name">
|
||||||
|
{{ item.name }}
|
||||||
|
</span>
|
||||||
|
<!-- 操作 -->
|
||||||
|
<div class="path-item-title-actions">
|
||||||
|
<a-space>
|
||||||
|
<!-- 进入 -->
|
||||||
|
<a-tag class="pointer usn"
|
||||||
|
size="small"
|
||||||
|
:checkable="true"
|
||||||
|
:checked="true"
|
||||||
|
@click.stop="changePath">
|
||||||
|
<template #icon>
|
||||||
|
<icon-link />
|
||||||
|
</template>
|
||||||
|
进入
|
||||||
|
</a-tag>
|
||||||
|
<!-- 粘贴 -->
|
||||||
|
<a-tag class="pointer usn"
|
||||||
|
size="small"
|
||||||
|
:checkable="true"
|
||||||
|
:checked="true"
|
||||||
|
@click.stop.prevent="paste">
|
||||||
|
<template #icon>
|
||||||
|
<icon-paste />
|
||||||
|
</template>
|
||||||
|
粘贴
|
||||||
|
</a-tag>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 路径 -->
|
||||||
|
<span class="path-item-value" @click="clickPath">
|
||||||
|
{{ item.path }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 右键菜单 -->
|
||||||
|
<template #content>
|
||||||
|
<!-- 进入父目录 -->
|
||||||
|
<a-doption @click="changePath">
|
||||||
|
<div class="terminal-context-menu-icon">
|
||||||
|
<icon-link />
|
||||||
|
</div>
|
||||||
|
<div>进入父目录</div>
|
||||||
|
</a-doption>
|
||||||
|
<!-- 复制 -->
|
||||||
|
<a-doption @click="copyPath">
|
||||||
|
<div class="terminal-context-menu-icon">
|
||||||
|
<icon-copy />
|
||||||
|
</div>
|
||||||
|
<div>复制</div>
|
||||||
|
</a-doption>
|
||||||
|
<!-- 粘贴 -->
|
||||||
|
<a-doption @click="paste">
|
||||||
|
<div class="terminal-context-menu-icon">
|
||||||
|
<icon-paste />
|
||||||
|
</div>
|
||||||
|
<div>粘贴</div>
|
||||||
|
</a-doption>
|
||||||
|
<!-- 修改 -->
|
||||||
|
<a-doption @click="openUpdatePath(item)">
|
||||||
|
<div class="terminal-context-menu-icon">
|
||||||
|
<icon-edit />
|
||||||
|
</div>
|
||||||
|
<div>修改</div>
|
||||||
|
</a-doption>
|
||||||
|
<!-- 删除 -->
|
||||||
|
<a-doption @click="removePath(item.id)">
|
||||||
|
<div class="terminal-context-menu-icon">
|
||||||
|
<icon-delete />
|
||||||
|
</div>
|
||||||
|
<div>删除</div>
|
||||||
|
</a-doption>
|
||||||
|
<!-- 展开 -->
|
||||||
|
<a-doption v-if="!item.expand"
|
||||||
|
@click="() => item.expand = true">
|
||||||
|
<div class="terminal-context-menu-icon">
|
||||||
|
<icon-expand />
|
||||||
|
</div>
|
||||||
|
<div>展开</div>
|
||||||
|
</a-doption>
|
||||||
|
<!-- 收起 -->
|
||||||
|
<a-doption v-else
|
||||||
|
@click="() => item.expand = false">
|
||||||
|
<div class="terminal-context-menu-icon">
|
||||||
|
<icon-shrink />
|
||||||
|
</div>
|
||||||
|
<div>收起</div>
|
||||||
|
</a-doption>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'pathBookmarkListItem'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { PathBookmarkQueryResponse } from '@/api/asset/path-bookmark';
|
||||||
|
import { useTerminalStore } from '@/store';
|
||||||
|
import { useDebounceFn } from '@vueuse/core';
|
||||||
|
import { copy } from '@/hooks/copy';
|
||||||
|
import { inject } from 'vue';
|
||||||
|
import { openUpdatePathKey, removePathKey } from '../types/const';
|
||||||
|
import { getParentPath } from '@/utils/file';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: PathBookmarkQueryResponse;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { getAndCheckCurrentSshSession } = useTerminalStore();
|
||||||
|
|
||||||
|
let clickCount = 0;
|
||||||
|
|
||||||
|
// 修改
|
||||||
|
const openUpdatePath = inject(openUpdatePathKey) as (item: PathBookmarkQueryResponse) => void;
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const removePath = inject(removePathKey) as (id: number) => void;
|
||||||
|
|
||||||
|
// 点击路径
|
||||||
|
const clickItem = () => {
|
||||||
|
if (++clickCount == 2) {
|
||||||
|
clickCount = 0;
|
||||||
|
changePath();
|
||||||
|
} else {
|
||||||
|
expandItem();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 展开
|
||||||
|
const expandItem = useDebounceFn(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
// 为 0 则代表为双击
|
||||||
|
if (clickCount !== 0) {
|
||||||
|
props.item.expand = !props.item.expand;
|
||||||
|
clickCount = 0;
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击路径
|
||||||
|
const clickPath = (e: Event) => {
|
||||||
|
if (props.item.expand) {
|
||||||
|
// 获取选中的文本
|
||||||
|
const selectedText = window.getSelection()?.toString();
|
||||||
|
if (selectedText) {
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 复制路径
|
||||||
|
const copyPath = () => {
|
||||||
|
copy(props.item.path, '已复制');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 粘贴
|
||||||
|
const paste = () => {
|
||||||
|
write(props.item.path);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 进入父目录
|
||||||
|
const changePath = () => {
|
||||||
|
const parentPath = getParentPath(props.item.path);
|
||||||
|
write( parentPath+ '\r\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 写入路径
|
||||||
|
const write = (command: string) => {
|
||||||
|
const handler = getAndCheckCurrentSshSession()?.handler;
|
||||||
|
if (handler && handler.enabledStatus('checkAppendMissing')) {
|
||||||
|
handler.checkAppendMissing(command);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@transform-x: 8px;
|
||||||
|
@drawer-width: 388px;
|
||||||
|
@item-wrapper-p-y: 4px;
|
||||||
|
@item-wrapper-p-x: 12px;
|
||||||
|
@item-p: 8px;
|
||||||
|
@item-width: @drawer-width - @item-wrapper-p-x * 2;
|
||||||
|
@item-width-transform: @item-width + @transform-x;
|
||||||
|
@item-inline-width: @item-width - @item-p * 2;
|
||||||
|
@item-actions-width: 124px;
|
||||||
|
|
||||||
|
.path-item-wrapper {
|
||||||
|
padding: @item-wrapper-p-y 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&-expand {
|
||||||
|
|
||||||
|
.path-item {
|
||||||
|
width: @item-width-transform !important;
|
||||||
|
background: var(--color-fill-3) !important;
|
||||||
|
|
||||||
|
.path-item-value {
|
||||||
|
color: var(--color-text-1);
|
||||||
|
text-overflow: unset;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
user-select: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: @item-p;
|
||||||
|
background: var(--color-fill-2);
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
width: @item-width;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
width: @item-width-transform;
|
||||||
|
background: var(--color-fill-3);
|
||||||
|
|
||||||
|
.path-item-title {
|
||||||
|
&-name {
|
||||||
|
width: calc(@item-inline-width - @item-actions-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-actions {
|
||||||
|
width: @item-actions-width;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
color: var(--color-text-1);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
width: @item-inline-width;
|
||||||
|
height: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&-name {
|
||||||
|
width: @item-inline-width;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-actions {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-value {
|
||||||
|
color: var(--color-text-2);
|
||||||
|
font-size: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: @item-inline-width;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
5
orion-ops-ui/src/views/host/path-bookmark/types/const.ts
Normal file
5
orion-ops-ui/src/views/host/path-bookmark/types/const.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// 打开 updatePath key
|
||||||
|
export const openUpdatePathKey = Symbol();
|
||||||
|
|
||||||
|
// 删除 path key
|
||||||
|
export const removePathKey = Symbol();
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import type { FieldRule } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
export const groupId = [{
|
||||||
|
message: '请选择分组'
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
export const name = [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入名称'
|
||||||
|
}, {
|
||||||
|
maxLength: 64,
|
||||||
|
message: '名称长度不能大于64位'
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
export const path = [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入路径'
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
groupId,
|
||||||
|
name,
|
||||||
|
path,
|
||||||
|
} as Record<string, FieldRule | FieldRule[]>;
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
position="left" />
|
position="left" />
|
||||||
<!-- 命令片段列表抽屉 -->
|
<!-- 命令片段列表抽屉 -->
|
||||||
<command-snippet-list-drawer ref="snippetRef" />
|
<command-snippet-list-drawer ref="snippetRef" />
|
||||||
|
<!-- 路径书签列表抽屉 -->
|
||||||
|
<path-bookmark-list-drawer ref="pathRef" />
|
||||||
<!-- 传输列表 -->
|
<!-- 传输列表 -->
|
||||||
<transfer-drawer ref="transferRef" />
|
<transfer-drawer ref="transferRef" />
|
||||||
</div>
|
</div>
|
||||||
@@ -27,19 +29,25 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import IconActions from './icon-actions.vue';
|
import IconActions from './icon-actions.vue';
|
||||||
import CommandSnippetListDrawer from '../../../command-snippet/components/command-snippet-list-drawer.vue';
|
import CommandSnippetListDrawer from '../../../command-snippet/components/command-snippet-list-drawer.vue';
|
||||||
|
import PathBookmarkListDrawer from '../../../path-bookmark/components/path-bookmark-list-drawer.vue';
|
||||||
import TransferDrawer from '@/views/host/terminal/components/transfer/transfer-drawer.vue';
|
import TransferDrawer from '@/views/host/terminal/components/transfer/transfer-drawer.vue';
|
||||||
|
|
||||||
const { getAndCheckCurrentSshSession } = useTerminalStore();
|
const { getAndCheckCurrentSshSession } = useTerminalStore();
|
||||||
|
|
||||||
const snippetRef = ref();
|
const snippetRef = ref();
|
||||||
|
const pathRef = ref();
|
||||||
const transferRef = ref();
|
const transferRef = ref();
|
||||||
|
|
||||||
// 顶部操作
|
// 顶部操作
|
||||||
const topActions = [
|
const topActions = [
|
||||||
{
|
{
|
||||||
icon: 'icon-code',
|
icon: 'icon-code-block',
|
||||||
content: '打开命令片段',
|
content: '打开命令片段',
|
||||||
click: () => snippetRef.value.open()
|
click: () => snippetRef.value.open()
|
||||||
|
}, {
|
||||||
|
icon: 'icon-bookmark',
|
||||||
|
content: '打开路径书签',
|
||||||
|
click: () => pathRef.value.open()
|
||||||
}, {
|
}, {
|
||||||
icon: 'icon-swap',
|
icon: 'icon-swap',
|
||||||
content: '文件传输列表',
|
content: '文件传输列表',
|
||||||
|
|||||||
Reference in New Issue
Block a user