mirror of
https://github.com/vran-dev/databasir.git
synced 2025-08-08 21:55:35 +08:00
feature: support search group & project in global system (#178)
* feat: add global search api * featï: add global search menu
This commit is contained in:
@@ -182,4 +182,8 @@ public interface Routes {
|
||||
String GET_SQL_MOCK_DATA = BASE + "/groups/{groupId}/projects/{projectId}/mock_data/sql";
|
||||
|
||||
}
|
||||
|
||||
interface Search {
|
||||
String SEARCH = BASE + "/search";
|
||||
}
|
||||
}
|
27
api/src/main/java/com/databasir/api/SearchController.java
Normal file
27
api/src/main/java/com/databasir/api/SearchController.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.databasir.api;
|
||||
|
||||
import com.databasir.common.JsonData;
|
||||
import com.databasir.core.domain.search.SearchService;
|
||||
import com.databasir.core.domain.search.data.SearchResponse;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Validated
|
||||
@Tag(name = "SearchController", description = "全局搜索 API")
|
||||
public class SearchController {
|
||||
|
||||
private final SearchService searchService;
|
||||
|
||||
@GetMapping(Routes.Search.SEARCH)
|
||||
@Operation(summary = "搜索")
|
||||
public JsonData<SearchResponse> search(@RequestParam(name = "query") String keyword) {
|
||||
return JsonData.ok(searchService.search(keyword));
|
||||
}
|
||||
}
|
@@ -1 +0,0 @@
|
||||
.left-menu:not(.el-menu--collapse){height:100vh}.databasir-nav{left:0;bottom:0}.databasir-main-header,.databasir-nav{position:fixed;transform:scale(1);top:0}.databasir-main-header{display:flex;justify-content:space-between;align-items:center;right:0;left:50px;padding:30px;margin-left:33px;background:#fff;z-index:100;border-color:#eee;border-width:0 0 1px 0;border-style:solid}.databasir{display:block}.databasir-main{position:relative;margin-left:60px;margin-top:80px;--el-main-padding:0px 20px 20px 20px}.databasir-main-expand{margin-left:50px}.databasir-main-content{max-width:95%;--el-main-padding:0px 20px 20px 20px}.h2{font-size:24px;color:#606266;margin-top:13px;margin-bottom:13px}.h2,.h3{font-family:Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Arial,sans-serif}.h3{font-size:20px;color:#909399;margin-top:18px;margin-bottom:18px}
|
1
api/src/main/resources/static/css/app.ee11d130.css
Normal file
1
api/src/main/resources/static/css/app.ee11d130.css
Normal file
@@ -0,0 +1 @@
|
||||
.left-menu:not(.el-menu--collapse){height:100vh}.search-item{padding:10px;width:99%;margin-bottom:12px;margin-right:12px;display:flex;justify-content:space-between;border-radius:8px}.search-item:hover{background-color:#f0f2f5}.search-item .jump{margin-right:8px}.search-container{max-height:420px;overflow-y:auto;overflow-x:hidden}.databasir-nav{left:0;bottom:0}.databasir-main-header,.databasir-nav{position:fixed;transform:scale(1);top:0}.databasir-main-header{display:flex;justify-content:space-between;align-items:center;right:0;left:50px;padding:30px;margin-left:33px;background:#fff;z-index:100;border-color:#eee;border-width:0 0 1px 0;border-style:solid}.databasir{display:block}.databasir-main{position:relative;margin-left:60px;margin-top:80px;--el-main-padding:0px 20px 20px 20px}.databasir-main-expand{margin-left:50px}.databasir-main-content{max-width:95%;--el-main-padding:0px 20px 20px 20px}.h2{font-size:24px;color:#606266;margin-top:13px;margin-bottom:13px}.h2,.h3{font-family:Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Arial,sans-serif}.h3{font-size:20px;color:#909399;margin-top:18px;margin-bottom:18px}
|
@@ -1 +1 @@
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir</title><script defer="defer" type="module" src="/js/chunk-vendors.9effab81.js"></script><script defer="defer" type="module" src="/js/app.1aa391ea.js"></script><link href="/css/chunk-vendors.81898547.css" rel="stylesheet"><link href="/css/app.15b40a89.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.fb0c8458.js" nomodule></script><script defer="defer" src="/js/app-legacy.18135b1d.js" nomodule></script></head><body><noscript><strong>We're sorry but databasir doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir</title><script defer="defer" type="module" src="/js/chunk-vendors.4f3fe369.js"></script><script defer="defer" type="module" src="/js/app.7ac511a9.js"></script><link href="/css/chunk-vendors.81898547.css" rel="stylesheet"><link href="/css/app.ee11d130.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.572a3b83.js" nomodule></script><script defer="defer" src="/js/app-legacy.94b013ac.js" nomodule></script></head><body><noscript><strong>We're sorry but databasir doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
api/src/main/resources/static/js/480-legacy.e63a01f3.js
Normal file
2
api/src/main/resources/static/js/480-legacy.e63a01f3.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
api/src/main/resources/static/js/725-legacy.47994393.js
Normal file
2
api/src/main/resources/static/js/725-legacy.47994393.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
api/src/main/resources/static/js/918-legacy.d3d8cbff.js
Normal file
2
api/src/main/resources/static/js/918-legacy.d3d8cbff.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
api/src/main/resources/static/js/app-legacy.94b013ac.js
Normal file
2
api/src/main/resources/static/js/app-legacy.94b013ac.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
api/src/main/resources/static/js/app.7ac511a9.js
Normal file
2
api/src/main/resources/static/js/app.7ac511a9.js
Normal file
File diff suppressed because one or more lines are too long
1
api/src/main/resources/static/js/app.7ac511a9.js.map
Normal file
1
api/src/main/resources/static/js/app.7ac511a9.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
|
||||
package com.databasir.core.domain.search;
|
||||
|
||||
import com.databasir.core.domain.search.converter.SearchResponseConverter;
|
||||
import com.databasir.core.domain.search.data.SearchResponse;
|
||||
import com.databasir.dao.impl.GroupDao;
|
||||
import com.databasir.dao.impl.ProjectDao;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SearchService {
|
||||
|
||||
private final ProjectDao projectDao;
|
||||
|
||||
private final GroupDao groupDao;
|
||||
|
||||
private final SearchResponseConverter searchResponseConverter;
|
||||
|
||||
public SearchResponse search(String query) {
|
||||
var groupPojoList = groupDao.selectByName(query);
|
||||
var groupResults = searchResponseConverter.toGroupResults(groupPojoList);
|
||||
var projectList = projectDao.selectByProjectNameOrDatabaseOrSchemaOrGroup(query);
|
||||
var projectResults = searchResponseConverter.toProjectResults(projectList);
|
||||
|
||||
// build response
|
||||
SearchResponse response = new SearchResponse();
|
||||
response.setGroups(groupResults);
|
||||
response.setProjects(projectResults);
|
||||
// TODO support Table search
|
||||
return response;
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package com.databasir.core.domain.search.converter;
|
||||
|
||||
import com.databasir.core.domain.search.data.SearchResponse;
|
||||
import com.databasir.dao.tables.pojos.GroupPojo;
|
||||
import com.databasir.dao.value.ProjectQueryPojo;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface SearchResponseConverter {
|
||||
|
||||
List<SearchResponse.GroupSearchResult> toGroupResults(List<GroupPojo> groups);
|
||||
|
||||
List<SearchResponse.ProjectSearchResult> toProjectResults(List<ProjectQueryPojo> projects);
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package com.databasir.core.domain.search.data;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class SearchResponse {
|
||||
|
||||
@Builder.Default
|
||||
private List<GroupSearchResult> groups = Collections.emptyList();
|
||||
|
||||
@Builder.Default
|
||||
private List<ProjectSearchResult> projects = Collections.emptyList();
|
||||
|
||||
@Data
|
||||
public static class GroupSearchResult {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ProjectSearchResult {
|
||||
|
||||
private Integer projectId;
|
||||
|
||||
private Integer groupId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private String projectName;
|
||||
|
||||
private String projectDescription;
|
||||
|
||||
private String databaseName;
|
||||
|
||||
private String schemaName;
|
||||
|
||||
}
|
||||
}
|
@@ -69,4 +69,12 @@ public class GroupDao extends BaseDao<GroupPojo> {
|
||||
.where(GROUP.ID.in(ids))
|
||||
.fetchInto(GroupPojo.class);
|
||||
}
|
||||
|
||||
public List<GroupPojo> selectByName(String nameContains) {
|
||||
return getDslContext()
|
||||
.select(GROUP.fields()).from(GROUP)
|
||||
.where(GROUP.NAME.contains(nameContains))
|
||||
.and(GROUP.DELETED.eq(false))
|
||||
.fetchInto(GroupPojo.class);
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ package com.databasir.dao.impl;
|
||||
|
||||
import com.databasir.dao.tables.pojos.ProjectPojo;
|
||||
import com.databasir.dao.value.GroupProjectCountPojo;
|
||||
import com.databasir.dao.value.ProjectQueryPojo;
|
||||
import lombok.Getter;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.DSLContext;
|
||||
@@ -19,8 +20,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.databasir.dao.Tables.DATA_SOURCE;
|
||||
import static com.databasir.dao.Tables.PROJECT;
|
||||
import static com.databasir.dao.Tables.*;
|
||||
|
||||
@Repository
|
||||
public class ProjectDao extends BaseDao<ProjectPojo> {
|
||||
@@ -126,4 +126,28 @@ public class ProjectDao extends BaseDao<ProjectPojo> {
|
||||
.where(PROJECT.ID.in(projectIds))
|
||||
.fetchMap(PROJECT.ID, PROJECT.GROUP_ID);
|
||||
}
|
||||
|
||||
public List<ProjectQueryPojo> selectByProjectNameOrDatabaseOrSchemaOrGroup(String query) {
|
||||
return getDslContext()
|
||||
.select(
|
||||
PROJECT.ID.as("project_id"),
|
||||
PROJECT.NAME.as("project_name"),
|
||||
PROJECT.DESCRIPTION.as("project_description"),
|
||||
DATA_SOURCE.DATABASE_NAME,
|
||||
DATA_SOURCE.SCHEMA_NAME,
|
||||
GROUP.NAME.as("group_name"),
|
||||
GROUP.ID.as("group_id")
|
||||
)
|
||||
.from(PROJECT)
|
||||
.leftJoin(DATA_SOURCE).on(DATA_SOURCE.PROJECT_ID.eq(PROJECT.ID))
|
||||
.leftJoin(GROUP).on(GROUP.ID.eq(PROJECT.GROUP_ID))
|
||||
.where(PROJECT.DELETED.eq(false)
|
||||
.and(GROUP.DELETED.eq(false))
|
||||
.and(PROJECT.NAME.contains(query)
|
||||
.or(DATA_SOURCE.DATABASE_NAME.contains(query))
|
||||
.or(DATA_SOURCE.SCHEMA_NAME.contains(query))
|
||||
.or(GROUP.NAME.contains(query)))
|
||||
)
|
||||
.fetchInto(ProjectQueryPojo.class);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,21 @@
|
||||
package com.databasir.dao.value;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ProjectQueryPojo {
|
||||
|
||||
private Integer projectId;
|
||||
|
||||
private Integer groupId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private String projectName;
|
||||
|
||||
private String projectDescription;
|
||||
|
||||
private String databaseName;
|
||||
|
||||
private String schemaName;
|
||||
}
|
Submodule databasir-frontend updated: b027e13326...f616e30e5b
Reference in New Issue
Block a user