diff --git a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteCmsService.java b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteCmsService.java index 0d68a77d0..0fde0212b 100644 --- a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteCmsService.java +++ b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteCmsService.java @@ -158,4 +158,8 @@ public interface RemoteCmsService { @GetMapping("/doc/getJSONObject/{cmsDocId}") R selectCmsDocJSONObjectById(@PathVariable(value = "cmsDocId") Long cmsDocId , @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + @PutMapping("/project/changeOrgRole/user/{userId}/operate/{operate}") + R changeUserOrgRole(@PathVariable("userId") Long userId, @PathVariable("operate") int operate + , @RequestHeader(SecurityConstants.FROM_SOURCE) String source); } diff --git a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteDeptService.java b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteDeptService.java index 5e901c250..6d5a36bf8 100644 --- a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteDeptService.java +++ b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/RemoteDeptService.java @@ -85,7 +85,7 @@ public interface RemoteDeptService { * 根据组织id删除部门 * * @param deptId 部门id - * @param source 请求来源 + * @param source 请求来源 * @return 是否删除成功 */ @DeleteMapping("/dept/deleteDeptByDeptId") @@ -105,7 +105,7 @@ public interface RemoteDeptService { * 通过用户名查询用户下组织及组织对应角色列表 * * @param deptId 组织ID - * @param source 请求来源 + * @param source 请求来源 * @return 用户下组织及组织对应角色列表 */ @GetMapping("/SysUserDeptRole/userByDeptId/{deptId}/list") @@ -115,7 +115,7 @@ public interface RemoteDeptService { /** * 查询组织编号下拥有传入角色权限字符串的用户名 * - * @param deptId 组织编号 + * @param deptId 组织编号 * @param roleKeys 角色权限字符串 * @return 组织下拥有传入角色权限字符串的用户名列表 */ @@ -126,7 +126,7 @@ public interface RemoteDeptService { * 检查用户是否在指定部门下具有指定角色 * * @param currentDeptId 组织编号 - * @param roleKey 角色权限字符串 + * @param roleKey 角色权限字符串 * @return 组织下拥有传入角色权限字符串的用户名列表 */ @GetMapping("/SysUserDeptRole/checkUserInDeptHasRole") @@ -143,6 +143,17 @@ public interface RemoteDeptService { @GetMapping("/SysUserDeptRole/checkUserInDeptHasPerms") R checkUserInDeptHasPerms(@RequestParam("currentDeptId") Long currentDeptId, @RequestParam("userId") Long userId, @RequestParam("perms") String perms, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + /** + * 检查用户是否在指定部门或指定部门的父级部门下具有指定菜单权限 + * + * @param deptId 指定组织id + * @param userId 用户id + * @param perms 菜单权限 + * @return 用户是否在指定部门下具有菜单权限 是true 否false + */ + @GetMapping("/SysUserDeptRole/checkUserInDeptOrParentDeptHasPerms") + R checkUserInDeptOrParentDeptHasPerms(@RequestParam("deptId") Long deptId, @RequestParam("userId") Long userId, @RequestParam("perms") String perms, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + /** * 检查用户是否在指定部门下 * @@ -152,4 +163,7 @@ public interface RemoteDeptService { */ @GetMapping("/SysUserDeptRole/checkUserInDept") R checkUserInDept(@RequestParam("currentDeptId") Long currentDeptId, @RequestParam("userId") Long userId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + @GetMapping("/SysUserDeptRole/getSysUserDeptRoleByDeptIdAndUserId") + R getSysUserDeptRoleByDeptIdAndUserId(@RequestParam("deptId") Long deptId, @RequestParam("userId") Long userId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); } diff --git a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteCmsFallbackFactory.java b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteCmsFallbackFactory.java index aa9763708..19fc136ef 100644 --- a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteCmsFallbackFactory.java +++ b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteCmsFallbackFactory.java @@ -83,6 +83,11 @@ public class RemoteCmsFallbackFactory implements FallbackFactory selectCmsDocJSONObjectById(Long cmsDocId, String source) { return R.fail("获取文章JSON对象失败:" + throwable.getMessage()); } + + @Override + public R changeUserOrgRole(Long userId, int operate, String source) { + return R.fail("更新组织权限失败:" + throwable.getMessage()); + } }; } } diff --git a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteDeptFallbackFactory.java b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteDeptFallbackFactory.java index 91f4fdb34..65fc6775e 100644 --- a/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteDeptFallbackFactory.java +++ b/microservices-api/microservices-api-system/src/main/java/com/microservices/system/api/factory/RemoteDeptFallbackFactory.java @@ -83,10 +83,20 @@ public class RemoteDeptFallbackFactory implements FallbackFactory checkUserInDeptOrParentDeptHasPerms(Long deptId, Long userId, String perms, String source) { + return R.fail("检查用户是否在指定部门或指定部门的父级部门下具有指定菜单权限失败:" + throwable.getMessage()); + } + @Override public R checkUserInDept(Long currentDeptId, Long userId, String source) { return R.fail("检查用户是否在指定部门下失败:" + throwable.getMessage()); } + + @Override + public R getSysUserDeptRoleByDeptIdAndUserId(Long deptId, Long userId, String source) { + return R.fail("获取用户在指定部门下的角色失败:" + throwable.getMessage()); + } }; } } diff --git a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/UserConstants.java b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/UserConstants.java index f7a77171c..578b6f430 100644 --- a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/UserConstants.java +++ b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/UserConstants.java @@ -5,8 +5,7 @@ package com.microservices.common.core.constant; * * @author microservices */ -public class UserConstants -{ +public class UserConstants { /** * 平台内系统用户的唯一标志 */ @@ -28,55 +27,89 @@ public class UserConstants */ public static final String DEL_FLAG_FALSE = "0"; - /** 正常状态 */ + /** + * 正常状态 + */ public static final String NORMAL = "0"; - /** 异常状态 */ + /** + * 异常状态 + */ public static final String EXCEPTION = "1"; - /** 用户封禁状态 */ + /** + * 用户封禁状态 + */ public static final String USER_DISABLE = "1"; - /** 角色封禁状态 */ + /** + * 角色封禁状态 + */ public static final String ROLE_DISABLE = "1"; - /** 部门正常状态 */ + /** + * 部门正常状态 + */ public static final String DEPT_NORMAL = "0"; - /** 部门停用状态 */ + /** + * 部门停用状态 + */ public static final String DEPT_DISABLE = "1"; - /** 字典正常状态 */ + /** + * 字典正常状态 + */ public static final String DICT_NORMAL = "0"; - /** 是否为系统默认(是) */ + /** + * 是否为系统默认(是) + */ public static final String YES = "Y"; - /** 是否菜单外链(是) */ + /** + * 是否菜单外链(是) + */ public static final String YES_FRAME = "0"; - /** 是否菜单外链(否) */ + /** + * 是否菜单外链(否) + */ public static final String NO_FRAME = "1"; - /** 菜单类型(目录) */ + /** + * 菜单类型(目录) + */ public static final String TYPE_DIR = "M"; - /** 菜单类型(菜单) */ + /** + * 菜单类型(菜单) + */ public static final String TYPE_MENU = "C"; - /** 菜单类型(按钮) */ + /** + * 菜单类型(按钮) + */ public static final String TYPE_BUTTON = "F"; - /** Layout组件标识 */ + /** + * Layout组件标识 + */ public final static String LAYOUT = "Layout"; - /** ParentView组件标识 */ + /** + * ParentView组件标识 + */ public final static String PARENT_VIEW = "ParentView"; - /** InnerLink组件标识 */ + /** + * InnerLink组件标识 + */ public final static String INNER_LINK = "InnerLink"; - /** 校验是否唯一的返回标识 */ + /** + * 校验是否唯一的返回标识 + */ public final static boolean UNIQUE = true; public final static boolean NOT_UNIQUE = false; @@ -122,4 +155,20 @@ public class UserConstants * 项目管理-知识库管理权限 */ public static final String PMS_PERMS_DOCS_MANAGE = "pms:docs:manage"; + /** + * 文章管理-文章删除权限 + */ + public static final String CMS_PERMS_DOCS_DELETE = "cms:doc:remove"; + /** + * 文章管理-新增文章权限 + */ + public static final String CMS_PERMS_DOCS_ADD = "cms:doc:add"; + /** + * 文章管理-编辑文章权限 + */ + public static final String CMS_PERMS_DOCS_EDIT = "cms:doc:edit"; + /** + * 文章管理-审核文章权限 + */ + public static final String CMS_PERMS_DOCS_AUDIT = "cms:doc:audit"; } diff --git a/microservices-common/microservices-common-httpClient/src/main/java/com/microservices/common/httpClient/service/HttpAPIService.java b/microservices-common/microservices-common-httpClient/src/main/java/com/microservices/common/httpClient/service/HttpAPIService.java index 58a2e9503..21514172e 100644 --- a/microservices-common/microservices-common-httpClient/src/main/java/com/microservices/common/httpClient/service/HttpAPIService.java +++ b/microservices-common/microservices-common-httpClient/src/main/java/com/microservices/common/httpClient/service/HttpAPIService.java @@ -211,6 +211,17 @@ public class HttpAPIService { return doRequest(httpDelete, headers); } + /** + * 不带Header的get请求 + * + * @param url + * @return + * @throws Exception + */ + public JSONObject doGet(String url) throws Exception { + return doGet(url, null); + } + /** * 带Header的get请求 * diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/CmsDocController.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/CmsDocController.java index fba775ffe..82aa61d7d 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/CmsDocController.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/CmsDocController.java @@ -3,6 +3,7 @@ package com.microservices.cms.doc.controller; import com.alibaba.fastjson2.JSONObject; import com.microservices.cms.doc.domain.*; import com.microservices.cms.doc.service.ICmsDocService; +import com.microservices.common.core.constant.UserConstants; import com.microservices.common.core.domain.R; import com.microservices.common.core.web.controller.BaseController; import com.microservices.common.core.web.domain.AjaxResult; @@ -164,7 +165,7 @@ public class CmsDocController extends BaseController { /** * 新增文章信息 */ - @RequiresPermissions("cms:doc:add") + @RequiresPermissions(UserConstants.CMS_PERMS_DOCS_ADD) @Log(title = "文章信息", businessType = BusinessType.INSERT) @PostMapping("/dir/{dirId}") @ApiOperation("在栏目下创建文章") @@ -201,7 +202,7 @@ public class CmsDocController extends BaseController { /** * 删除文章 */ - @RequiresPermissions("cms:doc:remove") + @RequiresPermissions(UserConstants.CMS_PERMS_DOCS_DELETE) @Log(title = "文章信息", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") @ApiOperation("删除文章/栏目") @@ -212,7 +213,7 @@ public class CmsDocController extends BaseController { /** * 修改文章信息 */ - @RequiresPermissions("cms:doc:edit") + @RequiresPermissions(UserConstants.CMS_PERMS_DOCS_EDIT) @Log(title = "文章信息", businessType = BusinessType.UPDATE) @PutMapping("/{id}") @ApiOperation("更新文章") @@ -237,12 +238,12 @@ public class CmsDocController extends BaseController { /** * 审核文章信息 */ - @RequiresPermissions("cms:doc:audit") + @RequiresPermissions(UserConstants.CMS_PERMS_DOCS_AUDIT) @Log(title = "文章信息", businessType = BusinessType.UPDATE) @PutMapping("/{id}/audit") @ApiOperation("审核文章") public AjaxResult audit(@ApiParam(name = "id", value = "文章Id") @PathVariable Long id, - @ApiParam(name = "cmsDocAuditVo", value = "文章审核对象") @RequestBody CmsDocAuditVo cmsDocAuditVo) { + @ApiParam(name = "cmsDocAuditVo", value = "文章审核对象") @RequestBody CmsDocAuditVo cmsDocAuditVo) { return toAjax(cmsDocService.auditCmsDoc(id, cmsDocAuditVo)); } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/OpenController.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/OpenController.java index 423a042dd..9bcfd5e6d 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/OpenController.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/controller/OpenController.java @@ -5,12 +5,17 @@ import com.microservices.cms.doc.domain.*; import com.microservices.cms.doc.service.ICmsDocCommentService; import com.microservices.cms.doc.service.ICmsDocService; import com.microservices.cms.doc.service.ICmsWechatService; +import com.microservices.cms.search.dto.DocSearchResult; import com.microservices.common.core.web.controller.BaseController; import com.microservices.common.core.web.domain.AjaxResult; import com.microservices.common.core.web.domain.GenericsAjaxResult; import com.microservices.common.core.web.page.GenericsTableDataInfo; +import com.microservices.common.core.web.page.TableDataInfo; import com.microservices.common.log.annotation.Log; import com.microservices.common.log.enums.BusinessType; +import com.microservices.cms.search.dto.DocSearchRequest; +import com.microservices.cms.search.dto.DocSearchResponse; +import com.microservices.cms.search.service.IGlobalSearchService; import io.swagger.annotations.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -35,6 +40,22 @@ public class OpenController extends BaseController { @Autowired private ICmsWechatService cmsWechatService; + @Autowired + private IGlobalSearchService globalSearchService; + + /** + * 文章搜索接口 + * + * @return 搜索结果 + */ + @ApiOperation("文章搜索") + @PostMapping("/search") + public GenericsTableDataInfo docSearch(@RequestBody DocSearchRequest docSearchRequest) { + logger.info("文章搜索请求: keyword={}", docSearchRequest.getKeyword()); + DocSearchResponse response = globalSearchService.docSearch(docSearchRequest); + return new GenericsTableDataInfo<>(response.getResults(), response.getTotal()); + } + /** * 查询栏目列表 */ @@ -175,9 +196,9 @@ public class OpenController extends BaseController { @Log(title = "同步文章数据", businessType = BusinessType.UPDATE) public AjaxResult syncDocData( @ApiParam(name = "deptId", value = "组织Id", required = true) @PathVariable("deptId") Long deptId - ,@RequestBody() String bodyStr + , @RequestBody() String bodyStr , HttpServletRequest request) { - cmsDocService.syncDocData(deptId,bodyStr); + cmsDocService.syncDocData(deptId, bodyStr); return AjaxResult.success("同步消息发送成功"); } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDoc.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDoc.java index 5e4b59cdc..9739aada9 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDoc.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDoc.java @@ -3,6 +3,7 @@ package com.microservices.cms.doc.domain; import com.fasterxml.jackson.annotation.JsonFormat; import com.microservices.cms.utils.CmsConstants; import com.microservices.common.core.annotation.Excel; +import com.microservices.common.core.utils.bean.BeanUtils; import com.microservices.common.core.web.domain.BaseSortEntity; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -36,19 +37,27 @@ public class CmsDoc extends BaseSortEntity { @Excel(name = "文件名称") private String fileName; - /** 文件路径 */ + /** + * 文件路径 + */ @Excel(name = "文件路径") private String filePath; - /** 文件SHA */ + /** + * 文件SHA + */ @Excel(name = "文件SHA") private String fileSha; - /** 文件大小 */ + /** + * 文件大小 + */ @Excel(name = "文件大小") private Long fileSize; - /** 文件URL */ + /** + * 文件URL + */ @Excel(name = "文件URL") private String fileUrl; @@ -162,6 +171,11 @@ public class CmsDoc extends BaseSortEntity { */ private String keywords; + /** + * 备注 + */ + private String remark; + public CmsDir copyToCmsDir() { CmsDir cmsDir = new CmsDir(); cmsDir.setId(id); @@ -210,30 +224,12 @@ public class CmsDoc extends BaseSortEntity { } private CmsDocBaseDto getCmsDocBaseDto(CmsDocBaseDto cmsDocDto) { - cmsDocDto.setId(id); - cmsDocDto.setName(name); - cmsDocDto.setHeadImg(headImg); - cmsDocDto.setIsHomepage(isHomepage); - cmsDocDto.setSummary(summary); - cmsDocDto.setEditorType(editorType); - cmsDocDto.setDeptId(deptId); - + BeanUtils.copyProperties(this, cmsDocDto); if (visits == null) { cmsDocDto.setVisits(0L); } else { cmsDocDto.setVisits(visits); } - - cmsDocDto.setPublishTime(publishTime); - cmsDocDto.setPublishUser(publishUser); - cmsDocDto.setPublishUserUrl(publishUserUrl); - cmsDocDto.setPublishUserImage(publishUserImage); - cmsDocDto.setPublishUserNickname(publishUserNickname); - cmsDocDto.setAuditStatus(auditStatus); - cmsDocDto.setAuditType(auditType); - cmsDocDto.setCreateBy(createBy); - cmsDocDto.setKeywords(keywords); - return cmsDocDto; } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocAuditVo.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocAuditVo.java index d9b061992..f895f4675 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocAuditVo.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocAuditVo.java @@ -20,4 +20,10 @@ public class CmsDocAuditVo { */ @ApiModelProperty(value = "是否重新编辑: 0不允许重新编辑 1允许重新编辑") private Integer reedit; + + /** + * 备注 + */ + @ApiModelProperty(value = "审核备注") + private String remark; } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocBaseDto.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocBaseDto.java index 0c76dcb77..44e221ffb 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocBaseDto.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocBaseDto.java @@ -101,6 +101,10 @@ public class CmsDocBaseDto { */ @ApiModelProperty("关键词") private String keywords; + /** + * 备注 + */ + private String remark; public void setPublishTime(Date publishTime) { if (publishTime != null) { diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocWithScore.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocWithScore.java new file mode 100644 index 000000000..1b1690561 --- /dev/null +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/domain/CmsDocWithScore.java @@ -0,0 +1,23 @@ +package com.microservices.cms.doc.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * CmsDoc with full-text search score + * 用于全局搜索结果,包含全文搜索相关度评分 + * + * @author otto + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class CmsDocWithScore extends CmsDoc implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 全文搜索相关度评分(来自 MySQL MATCH...AGAINST) + */ + private Double searchScore; +} diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/mapper/CmsDocMapper.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/mapper/CmsDocMapper.java index aacb21b3e..39b05dfd6 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/mapper/CmsDocMapper.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/mapper/CmsDocMapper.java @@ -2,6 +2,7 @@ package com.microservices.cms.doc.mapper; import com.microservices.cms.doc.domain.CmsDoc; import com.microservices.cms.doc.domain.CmsDocSearchVo; +import com.microservices.cms.doc.domain.CmsDocWithScore; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -192,4 +193,41 @@ public interface CmsDocMapper { List selectCmsDocAndDirListByDept(Long deptId); void updateCmsDocShaByPathAndDeptId(@Param("sha") String sha, @Param("filePath") String filePath, @Param("deptId") Long deptId); + + /** + * 全局搜索 - 全文索引查询 + * + * @param keyword 搜索关键词 + * @param deptId 组织ID(可选) + * @param offset 偏移量 + * @param pageSize 每页数量 + * @return 搜索结果列表 + */ + List globalSearch(@Param("keyword") String keyword, @Param("deptId") Long deptId, + @Param("offset") int offset, @Param("pageSize") int pageSize); + + /** + * 全局搜索结果计数 + * + * @param keyword 搜索关键词 + * @param deptId 组织ID(可选) + * @return 结果数量 + */ + Long globalSearchCount(@Param("keyword") String keyword, @Param("deptId") Long deptId); + + /** + * 全局搜索 - 全文索引查询(含评分) + * + * @param keyword 搜索关键词 + * @param deptId 组织ID(可选) + * @param offset 偏移量 + * @param pageSize 每页数量 + * @return 搜索结果列表(含评分) + */ + List globalSearchWithScore( + @Param("keyword") String keyword, + @Param("deptId") Long deptId, + @Param("offset") int offset, + @Param("pageSize") int pageSize + ); } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsAsyncService.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsAsyncService.java index 8b65689fa..4261b6464 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsAsyncService.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsAsyncService.java @@ -99,4 +99,6 @@ public interface ICmsAsyncService { * @param cmsDoc 文章 */ void pushDocDataSearchEngine(CmsDoc cmsDoc); + + void clearTmpDoc(CmsProject cmsProject,List tmpDocList); } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsDocService.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsDocService.java index 1ea9e9833..a0f78e9c9 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsDocService.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/ICmsDocService.java @@ -294,4 +294,6 @@ public interface ICmsDocService { List selectCmsDocAndDirListByDept(Long deptId); void updateCmsDocShaByPathAndDeptId(String sha, String filePath, Long deptId); + + List getTmpDocList(CmsDoc cmsDoc); } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsAsyncServiceImpl.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsAsyncServiceImpl.java index d5643f8c8..f9c4d535b 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsAsyncServiceImpl.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsAsyncServiceImpl.java @@ -20,6 +20,8 @@ import com.microservices.cms.utils.CustomExecutorFactory; import com.microservices.common.core.constant.CacheConstants; import com.microservices.common.core.constant.Constants; import com.microservices.common.core.constant.SecurityConstants; +import com.microservices.common.core.enums.DocAndZoneOperation; +import com.microservices.common.core.enums.DocAuditStatus; import com.microservices.common.core.enums.SystemRole; import com.microservices.common.core.exception.ServiceException; import com.microservices.common.core.utils.DateUtils; @@ -618,11 +620,12 @@ public class CmsAsyncServiceImpl implements ICmsAsyncService { 100, "..."), tmpBranchName); } catch (ServiceException e) { //忽略重复创建PR异常 - if (!"请求GitLink失败(合并请求已存在)".equals(e.getMessage())) { + if (!e.getMessage().contains("合并请求已存在")) { throw new ServiceException(e.getMessage()); } } + cmsDocService.updateCmsCommonDatabase(cmsDoc, tmpBranchName); } @@ -1003,6 +1006,23 @@ public class CmsAsyncServiceImpl implements ICmsAsyncService { } } + @Override + public void clearTmpDoc(CmsProject cmsProject, List tmpDocList) { + CustomExecutorFactory.threadPoolExecutor.execute(() -> { + for (CmsDoc tmpDoc : tmpDocList) { + //拒绝GitLink合并请求 + String gitLinkPullRequestNumber = tmpDoc.getAuditPrNumber().split("-")[0]; + gitLinkRequestHelper.doPost( + CmsGitLinkRequestUrl.REFUSE_MERGE_PULL_REQUEST(cmsProject, gitLinkPullRequestNumber), null); + gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, tmpDoc.getAuditTmpBranchName()), null); + // 所有删除操作调整为将审核状态设置为已拒绝 + tmpDoc.setAuditStatus(DocAuditStatus.AUDIT_FAIL.getAuditCode()); + tmpDoc.setRemark("管理员删除"); + cmsDocMapper.updateCmsDoc(tmpDoc); + } + }); + } + private void moveCmsDocToNewCmsDir(CmsProject cmsProject, String oldDirName, String newDirName, String message) { CmsDocSearchVo cmsDocSearch = new CmsDocSearchVo(); cmsDocSearch.setIsDir(false); diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsDocServiceImpl.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsDocServiceImpl.java index c7662b826..8adf2ef20 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsDocServiceImpl.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/doc/service/impl/CmsDocServiceImpl.java @@ -15,6 +15,7 @@ import com.microservices.cms.utils.CmsGitLinkRequestUrl; import com.microservices.common.core.constant.CacheConstants; import com.microservices.common.core.constant.HttpStatus; import com.microservices.common.core.constant.SecurityConstants; +import com.microservices.common.core.constant.UserConstants; import com.microservices.common.core.enums.DocAndZoneOperation; import com.microservices.common.core.enums.DocAuditStatus; import com.microservices.common.core.enums.SystemRole; @@ -296,7 +297,7 @@ public class CmsDocServiceImpl implements ICmsDocService { @Override public void updateCmsDocShaByPathAndDeptId(String sha, String filePath, Long deptId) { - cmsDocMapper.updateCmsDocShaByPathAndDeptId(sha,filePath,deptId); + cmsDocMapper.updateCmsDocShaByPathAndDeptId(sha, filePath, deptId); } private List selectCmsDocListByDatabase(Long dirId, CmsDocSearchVo cmsDocSearchVo) { @@ -313,7 +314,8 @@ public class CmsDocServiceImpl implements ICmsDocService { /** * 设置文章默认头图为栏目头图 - * @param dirId 栏目id + * + * @param dirId 栏目id * @param cmsDocSearchVo 文章查询条件 * @return 文章列表 */ @@ -358,7 +360,7 @@ public class CmsDocServiceImpl implements ICmsDocService { checkCmsLockStatus(dirDoc.getDeptId()); CmsDoc cmsDoc = cmsDocInputDto.toCmsDoc(dirDoc); - if (isNoAuditRequired(dirDoc.getDeptId()) || isCurrentUserZoneAdmin(dirDoc.getDeptId())) { + if (isNoAuditRequired(dirDoc.getDeptId()) || hasDeptAdminPerms(dirDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT)) { //文章自动置为审核通过状态值 cmsDoc.setAuditStatus(DocAuditStatus.AUDIT_PASS.getAuditCode()); boolean success = insertCommonCmsDoc(cmsDoc, @@ -421,8 +423,15 @@ public class CmsDocServiceImpl implements ICmsDocService { @Transactional(rollbackFor = Exception.class) public boolean auditCmsDoc(Long docId, CmsDocAuditVo cmsDocAuditVo) { CmsDoc cmsDoc = cmsDocMapper.selectCmsDocById(docId); + if (cmsDoc == null) { + throw new ServiceException("该文章不存在"); + } checkCmsLockStatus(cmsDoc.getDeptId()); CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDoc.getDeptId()); + + // 设置审核备注 + cmsDoc.setRemark(cmsDocAuditVo.getRemark()); + if (cmsDocAuditVo.getPass() == 1) { //同意合并请求 JSONObject result = mergePullRequestByGitLink(cmsProject, cmsDoc); @@ -446,7 +455,9 @@ public class CmsDocServiceImpl implements ICmsDocService { } if (cmsDocAuditVo.getPass() == 0) { //拒绝GitLink合并请求 - JSONObject result = refuseMergePullRequestByGitLink(cmsDoc, cmsProject); + String gitLinkPullRequestNumber = cmsDoc.getAuditPrNumber().split("-")[0]; + JSONObject result = gitLinkRequestHelper.doPost( + CmsGitLinkRequestUrl.REFUSE_MERGE_PULL_REQUEST(cmsProject, gitLinkPullRequestNumber), null); if (result.containsKey(GitLinkConstants.STATUS_KEY)) { //2.若拒绝GitLink合并请求操作返回正确的状态值,更新数据库 if (result.getInteger(GitLinkConstants.STATUS_KEY).equals(1)) { @@ -494,7 +505,7 @@ public class CmsDocServiceImpl implements ICmsDocService { //删除待审核文章 cmsDocMapper.deleteCmsDocById(cmsDoc.getId()); //删除分支 - gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName())); + gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null); return; } } @@ -506,7 +517,7 @@ public class CmsDocServiceImpl implements ICmsDocService { int success = deleteCmsDocDatabaseById(ids); if (success == ids.length) { //删除临时分支 - gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName())); + gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null); } } @@ -526,7 +537,7 @@ public class CmsDocServiceImpl implements ICmsDocService { int success = cmsDocMapper.deleteCmsDocById(newDocId); if (success > 0) { //删除临时分支 - gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName())); + gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null); } } @@ -540,7 +551,7 @@ public class CmsDocServiceImpl implements ICmsDocService { int success = cmsDocMapper.updateCmsDoc(cmsDoc); if (success > 0) { //删除临时分支 - gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName())); + gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null); } // 推送文章地址到搜索引擎 @@ -559,12 +570,6 @@ public class CmsDocServiceImpl implements ICmsDocService { CmsGitLinkRequestUrl.MERGE_PULL_REQUEST(cmsProject, gitLinkPullRequestId), requestBody); } - private JSONObject refuseMergePullRequestByGitLink(CmsDoc cmsDoc, CmsProject cmsProject) { - //1.调用gitlink拒绝合并请求接口 - return gitLinkRequestHelper.doPost( - CmsGitLinkRequestUrl.REFUSE_MERGE_PULL_REQUEST(cmsProject, cmsDoc.getAuditPrNumber()), null); - } - public static String sha1(String data) { try { MessageDigest md = MessageDigest.getInstance("SHA1"); @@ -725,14 +730,14 @@ public class CmsDocServiceImpl implements ICmsDocService { } // 当用户更新栏目时,需检查新栏目下是否已存在相同文章名 - if(cmsDocDto.getDirId()!=null){ + if (cmsDocDto.getDirId() != null) { CmsDir cmsDir = selectCmsDirById(cmsDocDto.getDirId(), false); - if(cmsDir!=null&&!cmsDir.getName().equals(oldCmsDoc.getDirName())){ + if (cmsDir != null && !cmsDir.getName().equals(oldCmsDoc.getDirName())) { checkDocName(cmsDocDto.getName(), oldCmsDoc.getDeptId(), cmsDir.getName()); } } //用户为专区管理员或专区无审核机制时,直接更新文章及仓库主分支 - if (isCurrentUserZoneAdmin(oldCmsDoc.getDeptId()) || isNoAuditRequired(oldCmsDoc.getDeptId())) { + if (hasDeptAdminPerms(oldCmsDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT) || isNoAuditRequired(oldCmsDoc.getDeptId())) { //专区管理员重新编辑并提交审核未通过文章 或 重新编辑并提交待审核文章时专区不需审核机制 if (!oldCmsDoc.getAuditStatus().equals(DocAuditStatus.AUDIT_PASS.getAuditCode())) { //文章审核类型:update-原文章id 取出原文章id直接更新,删除待审核更新类型文章 @@ -764,7 +769,7 @@ public class CmsDocServiceImpl implements ICmsDocService { || DocAuditStatus.TO_BE_AUDIT.getAuditCode().equals(oldCmsDoc.getAuditStatus())) { oldCmsDoc.setAuditStatus(DocAuditStatus.TO_BE_AUDIT.getAuditCode()); newDocWithAudit = oldCmsDoc; - } else + } else { //更新已发布文章 if (oldCmsDoc.getAuditStatus().equals(DocAuditStatus.AUDIT_PASS.getAuditCode())) { //1.创建一条auditType="update-原文章id",audit_status为2,其余字段与待更新文章一致的新文章数据 @@ -772,6 +777,7 @@ public class CmsDocServiceImpl implements ICmsDocService { DocAndZoneOperation.OPERATION_UPDATE.getOperationCode() + "-" + id, DocAuditStatus.TO_BE_AUDIT.getAuditCode()); } + } cmsAsyncService.asyncUpdateBranchAndFileAndCreatePR(newDocWithAudit, cmsDocDto); return true; } @@ -825,7 +831,7 @@ public class CmsDocServiceImpl implements ICmsDocService { private void deleteTmpBranchIfBranchExist(CmsDoc cmsDoc) { CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDoc.getDeptId()); try { - gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName())); + gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null); } catch (ServiceException e) { //忽略分支不存在异常 if (!"分支不存在!".equals(e.getMessage())) { @@ -856,6 +862,10 @@ public class CmsDocServiceImpl implements ICmsDocService { } private CmsDoc insertDocWithAudit(CmsDoc oldCmsDoc, String auditType, String auditStatus) { + List tmpDocList = getTmpDocList(oldCmsDoc); + if (!tmpDocList.isEmpty()) { + throw new ServiceException("已存在待审核操作,请等待审核完成后再进行操作"); + } oldCmsDoc.setId(null); oldCmsDoc.setAuditType(auditType); oldCmsDoc.setAuditStatus(auditStatus); @@ -865,6 +875,10 @@ public class CmsDocServiceImpl implements ICmsDocService { } private CmsDoc insertDeletedDocWithAudit(CmsDoc oldCmsDoc, Long oldCmsDocId) { + List tmpDocList = getTmpDocList(oldCmsDoc); + if (!tmpDocList.isEmpty()) { + throw new ServiceException("已存在待审核操作,请等待审核完成后再进行操作"); + } oldCmsDoc.setId(null); oldCmsDoc.setAuditType(DocAndZoneOperation.OPERATION_DELETE.getOperationCode() + "-" + oldCmsDocId); oldCmsDoc.setAuditStatus(DocAuditStatus.TO_BE_AUDIT.getAuditCode()); @@ -1303,6 +1317,18 @@ public class CmsDocServiceImpl implements ICmsDocService { cmsAsyncService.updateCmsPublishDataByGitLink(cmsProject, cmsDoc, branchName); } + private Boolean hasDeptAdminPerms(Long deptId, String perms) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + Boolean hasPerms = FeignUtils.getReturnData( + remoteDeptService.checkUserInDeptOrParentDeptHasPerms(deptId, loginUser.getUserId(), perms, SecurityConstants.INNER) + ); + + if (hasPerms == null) { + hasPerms = false; + } + return hasPerms; + } + @Override public int deleteCmsDocById(Long id) { CmsDoc cmsDoc = cmsDocMapper.selectCmsDocById(id); @@ -1314,20 +1340,33 @@ public class CmsDocServiceImpl implements ICmsDocService { CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDoc.getDeptId()); //删除待审核、审核未通过文章——删除临时分支,拒绝合并请求 - if (DocAuditStatus.TO_BE_AUDIT.getAuditCode().equals(cmsDoc.getAuditStatus()) - || DocAuditStatus.AUDIT_FAIL.getAuditCode().equals(cmsDoc.getAuditStatus())) { - gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName())); - cmsDocMapper.deleteCmsDocById(id); - return 1; + if (DocAuditStatus.TO_BE_AUDIT.getAuditCode().equals(cmsDoc.getAuditStatus())) { + + //拒绝GitLink合并请求 + String gitLinkPullRequestNumber = cmsDoc.getAuditPrNumber().split("-")[0]; + gitLinkRequestHelper.doPost( + CmsGitLinkRequestUrl.REFUSE_MERGE_PULL_REQUEST(cmsProject, gitLinkPullRequestNumber), null); + gitLinkRequestHelper.doPost(CmsGitLinkRequestUrl.DELETE_BRANCH(cmsProject, cmsDoc.getAuditTmpBranchName()), null); + return cmsDocMapper.deleteCmsDocById(cmsDoc.getId()); } - if (isCurrentUserZoneAdmin(cmsDoc.getDeptId()) //当前用户为专区管理员 + if (DocAuditStatus.AUDIT_FAIL.getAuditCode().equals(cmsDoc.getAuditStatus())) { + return cmsDocMapper.deleteCmsDocById(cmsDoc.getId()); + } + // 判读当前用户是否拥有文章直接删除权限 + if (hasDeptAdminPerms(cmsDoc.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT) //当前用户为专区管理员 || isNoAuditRequired(cmsDoc.getDeptId()) //当前专区文章发布无需审核机制 ) { String branchName = CmsConstants.BRANCH_MASTER; boolean deleteResult = cmsAsyncService.deleteCmsDocForGitLink(cmsDoc, cmsProject, branchName); if (deleteResult) { - return deleteCmsDocDatabaseById(cmsDoc.getId()); + // 拒绝相关合并请求并清理所有临时分支,同时删除所有临时申请 + List tmpDocList = getTmpDocList(cmsDoc); + cmsAsyncService.clearTmpDoc(cmsProject, tmpDocList); + cmsDoc.setAuditStatus(DocAuditStatus.AUDIT_FAIL.getAuditCode()); + cmsDoc.setRemark("管理员删除"); + return cmsDocMapper.updateCmsDoc(cmsDoc); } + } else { //1.创建一条auditType="delete-原文章id",audit_status=2,其余字段与待删除文章一致的新文章数据 CmsDoc newDocWithAudit = insertDeletedDocWithAudit(cmsDoc, id); @@ -1337,6 +1376,18 @@ public class CmsDocServiceImpl implements ICmsDocService { throw new ServiceException("文件删除失败"); } + @Override + public List getTmpDocList(CmsDoc cmsDoc) { + CmsDocSearchVo cmsDocSearchVo = new CmsDocSearchVo(); + cmsDocSearchVo.setName(cmsDoc.getName()); + cmsDocSearchVo.setDeptId(cmsDoc.getDeptId()); + cmsDocSearchVo.setIsDir(false); + cmsDocSearchVo.setDirName(cmsDoc.getDirName()); + cmsDocSearchVo.setAuditStatus(DocAuditStatus.TO_BE_AUDIT.getAuditCode()); + // 拒绝相关合并请求并清理所有临时分支,同时删除所有临时申请 + return cmsDocMapper.selectCmsDocList(cmsDocSearchVo); + } + public int deleteCmsDocDatabaseById(Long id) { CmsDoc cmsDoc = cmsDocMapper.selectCmsDocById(id); if (cmsDoc != null && !cmsDoc.getIsDir()) { diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/controller/CmsProjectController.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/controller/CmsProjectController.java index 08ded4e6f..4b8ed5011 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/controller/CmsProjectController.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/controller/CmsProjectController.java @@ -49,6 +49,16 @@ public class CmsProjectController extends BaseController { return R.ok(changeRoleResult); } + @InnerAuth + @PutMapping("/changeOrgRole/user/{userId}/operate/{operate}") + @ApiOperation(value = "修改用户所在GItLink组织中的权限", hidden = true) + public R changeUserOrgRole(@PathVariable("userId") Long userId, @PathVariable("operate") Long operate + ) { + Boolean changeRoleResult = cmsProjectService.changeUserOrgRole(userId, operate); + return R.ok(changeRoleResult); + } + + /** * 查询专区对应项目列表 */ diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/domain/GitlinkOrganizationTeamVo.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/domain/GitlinkOrganizationTeamVo.java new file mode 100644 index 000000000..d27977c6b --- /dev/null +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/domain/GitlinkOrganizationTeamVo.java @@ -0,0 +1,21 @@ +package com.microservices.cms.project.domain; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author otto + */ +@Data +public class GitlinkOrganizationTeamVo implements Serializable { + @ApiModelProperty(value = "团队权限") + private String authorize; + @ApiModelProperty(value = "团队Id") + private Long id; + @ApiModelProperty(value = "团队名称") + private String name; + @ApiModelProperty(value = "团队昵称") + private String nickname; +} diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/mapper/CmsProjectMapper.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/mapper/CmsProjectMapper.java index 377b04816..a7c9495eb 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/mapper/CmsProjectMapper.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/mapper/CmsProjectMapper.java @@ -2,6 +2,7 @@ package com.microservices.cms.project.mapper; import com.microservices.cms.project.domain.CmsProject; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -64,4 +65,25 @@ public interface CmsProjectMapper { CmsProject selectCmsProjectByDeptId(Long deptId); CmsProject selectCmsProjectByIdentifier(String identifier); + + /** + * 全局搜索 - 全文索引查询 + * + * @param keyword 搜索关键词 + * @param deptId 组织ID(可选) + * @param offset 偏移量 + * @param pageSize 每页数量 + * @return 搜索结果列表 + */ + List globalSearch(@Param("keyword") String keyword, @Param("deptId") Long deptId, + @Param("offset") int offset, @Param("pageSize") int pageSize); + + /** + * 全局搜索结果计数 + * + * @param keyword 搜索关键词 + * @param deptId 组织ID(可选) + * @return 结果数量 + */ + Long globalSearchCount(@Param("keyword") String keyword, @Param("deptId") Long deptId); } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/ICmsProjectService.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/ICmsProjectService.java index ce095be0e..01088a77a 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/ICmsProjectService.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/ICmsProjectService.java @@ -82,4 +82,6 @@ public interface ICmsProjectService { boolean initZoneCmsProjectByDept(Long deptId); CmsProject selectCmsProjectByDeptIdAndNoException(Long deptId); + + Boolean changeUserOrgRole(Long userId, Long operate); } diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/impl/CmsProjectServiceImpl.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/impl/CmsProjectServiceImpl.java index 04d78d57d..c57be2569 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/impl/CmsProjectServiceImpl.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/project/service/impl/CmsProjectServiceImpl.java @@ -6,6 +6,7 @@ import com.microservices.cms.doc.domain.*; import com.microservices.cms.doc.service.ICmsAsyncService; import com.microservices.cms.doc.service.ICmsDocService; import com.microservices.cms.project.domain.CmsProject; +import com.microservices.cms.project.domain.GitlinkOrganizationTeamVo; import com.microservices.cms.project.mapper.CmsProjectMapper; import com.microservices.cms.project.service.ICmsProjectService; import com.microservices.cms.utils.CmsConstants; @@ -320,6 +321,40 @@ public class CmsProjectServiceImpl implements ICmsProjectService { return cmsProjectMapper.selectCmsProjectByDeptId(deptId); } + @Override + public Boolean changeUserOrgRole(Long userId, Long operate) { + Long gitlinkOrgId = getOrganizationId(); + SysUser sysUser = FeignUtils.getReturnData(remoteUserService.getSysUserByUserId(userId, SecurityConstants.INNER)); + if (sysUser == null) { + return false; + } + List gitlinkOrganizationTeamVoList = gitLinkRequestHelper.getAllDataByPage( + CmsGitLinkRequestUrl.TEAMS_BY_ORGANIZATION_URL(gitlinkOrgId), "teams", GitlinkOrganizationTeamVo.class + ); + GitlinkOrganizationTeamVo ownerTeam = gitlinkOrganizationTeamVoList.stream().filter(x -> "owner".equals(x.getAuthorize())).findFirst().orElse(null); + if (ownerTeam == null) { + return false; + } + if (operate == 1) { + JSONObject addUserToTeam = new JSONObject(); + addUserToTeam.put("username", sysUser.getUserName()); + gitLinkRequestHelper.doPost( + CmsGitLinkRequestUrl.ADD_USER_TO_ORGANIZATION_TEAM(gitLinkOrganization, ownerTeam.getId()), addUserToTeam); + } + if (operate == 3) { + try { + gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.DELETE_USER_FROM_ORGANIZATION_TEAM( + gitLinkOrganization, + ownerTeam.getId(), + sysUser.getUserName() + )); + } catch (Exception e) { + return false; + } + } + return false; + } + @Override public Boolean changeUserRole(Long userId, Long oldDeptId, Long newDeptId, Long oldRoleId, Long newRoleId) { SysUser sysUser = FeignUtils.getReturnData(remoteUserService.getSysUserByUserId(userId, SecurityConstants.INNER)); @@ -338,9 +373,10 @@ public class CmsProjectServiceImpl implements ICmsProjectService { try { gitLinkRequestHelper.doDelete(CmsGitLinkRequestUrl.REMOVE_USER_FROM_PROJECT(oldCmsProject), requestBody); } catch (ServiceException e) { - if (!e.getMessage().contains("用户为组织成员,请到组织下操作")) { - throw new ServiceException(e.getMessage()); - } + log.error("将用户从原项目中移除发生异常:{}", e.getMessage()); +// if (!e.getMessage().contains("用户为组织成员,请到组织下操作")||!e.getMessage().contains("还不是项目成员")) { +// throw new ServiceException(e.getMessage()); +// } } } //将用户加入新的项目 diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchRequest.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchRequest.java new file mode 100644 index 000000000..ec491aa4d --- /dev/null +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchRequest.java @@ -0,0 +1,43 @@ +package com.microservices.cms.search.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 文章搜索请求对象 + * + * @author microservices + */ +@Data +@ApiModel("文章搜索请求对象") +public class DocSearchRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 搜索关键词 + */ + @ApiModelProperty(value = "搜索关键词", required = true) + private String keyword; + + /** + * 专区ID + */ + @ApiModelProperty(value = "专区ID") + private Long zoneId; + + /** + * 页码 + */ + @ApiModelProperty(value = "页码") + private Integer pageNum = 1; + + /** + * 每页数量 + */ + @ApiModelProperty(value = "每页数量") + private Integer pageSize = 20; +} diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchResponse.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchResponse.java new file mode 100644 index 000000000..93ecf514c --- /dev/null +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchResponse.java @@ -0,0 +1,63 @@ +package com.microservices.cms.search.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * 全局搜索响应对象 + * + * @author microservices + */ +@Data +@ApiModel("文章搜索响应对象") +public class DocSearchResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 总结果数 + */ + @ApiModelProperty(value = "总结果数") + private Long total; + + /** + * 搜索结果列表 + */ + @ApiModelProperty(value = "搜索结果列表") + private List results; + + /** + * 各类型结果数量统计 + */ + @ApiModelProperty(value = "各类型结果数量统计") + private Map typeCounts; + + /** + * 搜索耗时(毫秒) + */ + @ApiModelProperty(value = "搜索耗时(毫秒)") + private Long searchTime; + + /** + * 搜索关键词 + */ + @ApiModelProperty(value = "搜索关键词") + private String keyword; + + /** + * 当前页码 + */ + @ApiModelProperty(value = "当前页码") + private Integer pageNum; + + /** + * 每页数量 + */ + @ApiModelProperty(value = "每页数量") + private Integer pageSize; +} diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchResult.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchResult.java new file mode 100644 index 000000000..e0b57bc3b --- /dev/null +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/dto/DocSearchResult.java @@ -0,0 +1,65 @@ +package com.microservices.cms.search.dto; + +import com.alibaba.fastjson2.JSONObject; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 文章搜索结果对象 + * + * @author microservices + */ +@Data +@ApiModel("文章搜索结果对象") +public class DocSearchResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ApiModelProperty(value = "ID") + private Long id; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题") + private String title; + + /** + * 内容摘要 + */ + @ApiModelProperty(value = "内容摘要") + private String content; + + /** + * 组织ID + */ + @ApiModelProperty(value = "组织ID") + private Long deptId; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建时间") + private Date createTime; + + /** + * 相关度评分 + */ + @ApiModelProperty(value = "相关度评分") + private Double score; + + /** + * 扩展数据(JSON格式) + */ + @ApiModelProperty(value = "扩展数据") + private JSONObject extendData; +} diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/service/IGlobalSearchService.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/service/IGlobalSearchService.java new file mode 100644 index 000000000..3231b5caa --- /dev/null +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/service/IGlobalSearchService.java @@ -0,0 +1,20 @@ +package com.microservices.cms.search.service; + +import com.microservices.cms.search.dto.DocSearchRequest; +import com.microservices.cms.search.dto.DocSearchResponse; + +/** + * 全局搜索服务接口 + * + * @author microservices + */ +public interface IGlobalSearchService { + + /** + * 全局搜索 + * + * @param request 搜索请求 + * @return 搜索响应 + */ + DocSearchResponse docSearch(DocSearchRequest request); +} diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/service/impl/GlobalSearchServiceImpl.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/service/impl/GlobalSearchServiceImpl.java new file mode 100644 index 000000000..b7b4e9e93 --- /dev/null +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/search/service/impl/GlobalSearchServiceImpl.java @@ -0,0 +1,215 @@ +package com.microservices.cms.search.service.impl; + +import com.alibaba.fastjson2.JSONObject; +import com.microservices.cms.doc.domain.CmsDoc; +import com.microservices.cms.doc.domain.CmsDocWithScore; +import com.microservices.cms.doc.mapper.CmsDocMapper; +import com.microservices.cms.doc.service.ICmsDocService; +import com.microservices.cms.search.service.IGlobalSearchService; +import com.microservices.common.core.utils.StringUtils; +import com.microservices.common.redis.service.RedisService; +import com.microservices.cms.search.dto.DocSearchRequest; +import com.microservices.cms.search.dto.DocSearchResponse; +import com.microservices.cms.search.dto.DocSearchResult; +import com.microservices.common.security.utils.SecurityUtils; +import com.microservices.system.api.model.LoginUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +/** + * 全局搜索服务实现 + * + * @author microservices + */ +@Service +public class GlobalSearchServiceImpl implements IGlobalSearchService { + + private static final Logger logger = LoggerFactory.getLogger(GlobalSearchServiceImpl.class); + + @Autowired + private CmsDocMapper cmsDocMapper; + @Autowired + private RedisService redisService; + @Autowired + private ICmsDocService cmsDocService; + + private static final String SEARCH_CACHE_PREFIX = "search:cache:"; + private static final Long CACHE_EXPIRE_SECONDS = 300L; // 5分钟 + + @Override + public DocSearchResponse docSearch(DocSearchRequest request) { + long startTime = System.currentTimeMillis(); + + // 参数校验 + if (StringUtils.isEmpty(request.getKeyword())) { + return buildEmptyResponse(request); + } + + // 1. 尝试从缓存获取(仅第一页) + if (request.getPageNum() == 1) { + String cacheKey = buildCacheKey(request); + + DocSearchResponse cached = redisService.getCacheObject(SEARCH_CACHE_PREFIX + cacheKey); + if (cached != null) { + cached.setSearchTime(System.currentTimeMillis() - startTime); + return cached; + } + } + + // 2. 并行搜索各类型 + List allResults = new ArrayList<>(); + Map typeCounts = new HashMap<>(); + + // 获取当前用户信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // 搜索CMS文章 + List docResults = searchDocs(request); + allResults.addAll(docResults); + typeCounts.put("doc", (long) docResults.size()); + + // 3. 按相关度评分排序 + allResults.sort((a, b) -> { + if (b.getScore() != null && a.getScore() != null) { + return b.getScore().compareTo(a.getScore()); + } + return 0; + }); + + // 4. 分页 + int total = allResults.size(); + int start = (request.getPageNum() - 1) * request.getPageSize(); + int end = Math.min(start + request.getPageSize(), total); + List pagedResults = start < total ? + allResults.subList(start, end) : new ArrayList<>(); + + // 5. 构建响应 + DocSearchResponse response = new DocSearchResponse(); + response.setTotal((long) total); + response.setResults(pagedResults); + response.setTypeCounts(typeCounts); + response.setKeyword(request.getKeyword()); + response.setPageNum(request.getPageNum()); + response.setPageSize(request.getPageSize()); + response.setSearchTime(System.currentTimeMillis() - startTime); + + // 6. 缓存结果(仅第一页) + if (request.getPageNum() == 1) { + String cacheKey = buildCacheKey(request); + redisService.setCacheObject(SEARCH_CACHE_PREFIX + cacheKey, response, CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS); + } + + // 7. 记录搜索日志 + recordSearchLog(request, response, loginUser); + + return response; + } + + /** + * 记录搜索日志 + */ + private void recordSearchLog(DocSearchRequest request, DocSearchResponse response, LoginUser loginUser) { + Long userId = loginUser != null ? loginUser.getUserId() : null; + String searchTypes = "文章"; + Long deptId = cmsDocService.getDeptIdByZoneId(request.getZoneId()); + logger.info("全局搜索 - 关键词: {}, 用户ID: {}, 耗时: {}ms, 结果数: {}, 类型: {}, 专区Id: {}, 组织ID: {}", + request.getKeyword(), + userId, + response.getSearchTime(), + response.getTotal(), + searchTypes, + request.getZoneId(), + deptId + ); + } + + /** + * 搜索CMS文章 + */ + private List searchDocs(DocSearchRequest request) { + List results = new ArrayList<>(); + try { + // 使用部门ID参数 + Long deptId = cmsDocService.getDeptIdByZoneId(request.getZoneId()); + + // 使用新的带评分的查询方法 + List docs = cmsDocMapper.globalSearchWithScore( + request.getKeyword(), + deptId, + (request.getPageNum() - 1) * request.getPageSize(), + request.getPageSize() + ); + + for (CmsDocWithScore doc : docs) { + DocSearchResult result = new DocSearchResult(); + result.setId(doc.getId()); + result.setTitle(highlightKeyword(doc.getName(), request.getKeyword())); + result.setContent(highlightKeyword(doc.getSummary(), request.getKeyword())); + result.setDeptId(doc.getDeptId()); + result.setCreateTime(doc.getCreateTime()); + + // 使用数据库返回的实际搜索评分 + Double score = doc.getSearchScore(); + if (score == null || score == 0.0) { + // 对于 LIKE 匹配(无全文评分),赋予最小评分 + score = 0.1; + } + result.setScore(score); + + JSONObject extendData = new JSONObject(); + extendData.put("visits", doc.getVisits()); + extendData.put("publishTime", doc.getPublishTime()); + result.setExtendData(extendData); + results.add(result); + } + } catch (Exception e) { + // 记录错误但继续处理其他类型 + System.err.println("搜索CMS文章失败: " + e.getMessage()); + } + return results; + } + + /** + * 构建缓存键 + */ + private String buildCacheKey(DocSearchRequest request) { + Long deptId = cmsDocService.getDeptIdByZoneId(request.getZoneId()); + StringBuilder key = new StringBuilder(request.getKeyword()); + key.append(":").append(String.join(",", "Doc")); + if (deptId != null) { + key.append(":dept=").append(deptId); + } + return key.toString(); + } + + /** + * 构建空响应 + */ + private DocSearchResponse buildEmptyResponse(DocSearchRequest request) { + DocSearchResponse response = new DocSearchResponse(); + response.setTotal(0L); + response.setResults(new ArrayList<>()); + response.setTypeCounts(new HashMap<>()); + response.setKeyword(request.getKeyword()); + response.setPageNum(request.getPageNum()); + response.setPageSize(request.getPageSize()); + response.setSearchTime(0L); + return response; + } + + /** + * 将文本中的关键词用 标签包裹(不区分大小写) + */ + private String highlightKeyword(String text, String keyword) { + if (StringUtils.isEmpty(text) || StringUtils.isEmpty(keyword)) { + return text; + } + return text.replaceAll("(?i)(" + Pattern.quote(keyword) + ")", "$1"); + } +} diff --git a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/utils/CmsGitLinkRequestUrl.java b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/utils/CmsGitLinkRequestUrl.java index 0fedd22aa..26e8beaa8 100644 --- a/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/utils/CmsGitLinkRequestUrl.java +++ b/microservices-modules/microservices-modules-cms/src/main/java/com/microservices/cms/utils/CmsGitLinkRequestUrl.java @@ -12,6 +12,17 @@ import java.util.Map; public class CmsGitLinkRequestUrl extends GitLinkRequestUrl { + public static GitLinkRequestUrl ADD_USER_TO_ORGANIZATION_TEAM(String orgIdentifier, Long teamId) { + return getAdminGitLinkRequestUrl(String.format("/api/organizations/%s/teams/%d/team_users.json", orgIdentifier, teamId)); + } + public static String TEAMS_BY_ORGANIZATION_URL(Long orgId) { + return String.format("/api/organizations/%s/teams.json", orgId); + } + + public static GitLinkRequestUrl DELETE_USER_FROM_ORGANIZATION_TEAM(String orgIdentifier, Long teamId, String username) { + return getAdminGitLinkRequestUrl(String.format("/api/organizations/%s/teams/%d/team_users/%s.json", orgIdentifier, teamId, username)); + } + /** * 创建项目 */ @@ -66,7 +77,7 @@ public class CmsGitLinkRequestUrl extends GitLinkRequestUrl { public static GitLinkRequestUrl DELETE_BRANCH(CmsProject cmsProject, String branchName) { return getGitLinkRequestUrl( - String.format("/api/v1/%s/%s/branches/%s.json", cmsProject.getUsername(), cmsProject.getIdentifier(), branchName) + String.format("/api/v1/%s/%s/branches/delete.json?branch_name=%s", cmsProject.getUsername(), cmsProject.getIdentifier(), branchName) ); } diff --git a/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsDocMapper.xml b/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsDocMapper.xml index c67f642be..86e7ba14c 100644 --- a/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsDocMapper.xml +++ b/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsDocMapper.xml @@ -37,6 +37,7 @@ + @@ -71,7 +72,8 @@ audit_type, audit_tmp_branch_name, keywords, - audit_pr_number + audit_pr_number, + remark from cms_doc @@ -103,7 +105,43 @@ cd.is_homepage, cd.editor_type, cd.keywords, - cd.is_dir + cd.is_dir, + cd.remark + from cms_doc cd + + + + select cd.id, + cd.create_by, + cd.create_time, + cd.update_by, + cd.update_time, + cd.name, + cd.file_name, + cd.file_path, + cd.file_sha, + cd.file_size, + cd.file_url, + cd.html_url, + cd.visits, + cd.sort, + cd.publish_time, + cd.publish_user, + cd.publish_user_image, + cd.publish_user_url, + cd.publish_user_nickname, + cd.summary, + cd.head_img, + cd.dir_name, + cd.dept_id, + cd.issue_id, + cd.is_homepage, + cd.editor_type, + cd.keywords, + cd.is_dir, + -- 计算全文搜索相关度评分 + MATCH(cd.name, cd.summary) AGAINST(#{keyword} IN NATURAL LANGUAGE MODE) AS search_score, + cd.remark from cms_doc cd @@ -141,7 +179,8 @@ cd.is_homepage, cd.editor_type, cd.keywords, - cd.is_dir + cd.is_dir, + cd.remark from cms_doc cd left join cms_doc dir on cd.dir_name = dir.name and cd.dept_id = dir.dept_id and dir.is_dir=1 @@ -458,6 +497,7 @@ audit_tmp_branch_name = #{auditTmpBranchName}, audit_pr_number = #{auditPrNumber}, keywords = #{keywords}, + remark = #{remark}, where id = #{id} @@ -494,4 +534,70 @@ #{id} + + + + + + + + + + + + + \ No newline at end of file diff --git a/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsProjectMapper.xml b/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsProjectMapper.xml index 1c99f7f0d..4684628ec 100644 --- a/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsProjectMapper.xml +++ b/microservices-modules/microservices-modules-cms/src/main/resources/mapper/cms/CmsProjectMapper.xml @@ -159,4 +159,38 @@ item="id" collection="array" open="(" separator="," close=")">#{id} + + + + + \ No newline at end of file diff --git a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/controller/SysUserDeptRoleController.java b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/controller/SysUserDeptRoleController.java index afc78e888..818101fac 100644 --- a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/controller/SysUserDeptRoleController.java +++ b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/controller/SysUserDeptRoleController.java @@ -289,6 +289,24 @@ public class SysUserDeptRoleController extends BaseController { return R.ok(userInDeptHasRole); } + /** + * 检查用户是否在指定部门或父级部门下具有指定菜单权限 + * + * @param deptId 组织id + * @param userId 用户id + * @param perms 菜单权限 + * @return 用户是否指定部门或父级部门下具有菜单权限 是true 否false + */ + @ApiOperation(value = "检查用户是否在指定部门或父级部门下具有指定菜单权限", hidden = true) + @InnerAuth + @GetMapping("/checkUserInDeptOrParentDeptHasPerms") + public R checkUserInDeptOrParentDeptHasPerms(@ApiParam(name = "deptId", value = "组织id", required = true) Long deptId, + @ApiParam(name = "userId", value = "用户id", required = true) Long userId, + @ApiParam(name = "perms", value = "菜单权限", required = true) String perms) { + Boolean userInDeptHasRole = sysUserDeptRoleService.checkUserInDeptOrParentDeptHasPerms(deptId, userId, perms); + return R.ok(userInDeptHasRole); + } + /** * 检查用户是否在指定部门下 * @@ -304,4 +322,12 @@ public class SysUserDeptRoleController extends BaseController { Boolean userInDept = sysUserDeptRoleService.checkUserInDept(currentDeptId, userId); return R.ok(userInDept); } + @ApiOperation(value = "用户是否在指定部门下", hidden = true) + @InnerAuth + @GetMapping("/getSysUserDeptRoleByDeptIdAndUserId") + public R getSysUserDeptRoleByDeptIdAndUserId(@ApiParam(name = "deptId", value = "组织id", required = true) Long deptId, + @ApiParam(name = "userId", value = "用户id", required = true) Long userId) { + SysUserDeptRole userIdentifier = sysUserDeptRoleService.getSysUserDeptRoleByDeptIdAndUserId(deptId, userId); + return R.ok(userIdentifier); + } } diff --git a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/mapper/SysUserDeptRoleMapper.java b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/mapper/SysUserDeptRoleMapper.java index 608d8b8cd..9f5e51322 100644 --- a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/mapper/SysUserDeptRoleMapper.java +++ b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/mapper/SysUserDeptRoleMapper.java @@ -151,4 +151,6 @@ public interface SysUserDeptRoleMapper { * @param state 状态 */ void updateUserIdentifyStateByUserId(@Param("userId") Long userId, @Param("state") String state); + + int selectUserInDeptOrParentDeptHasPermsCount(@Param("deptId") Long deptId, @Param("userId") Long userId, @Param("perms") String perms); } diff --git a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/ISysUserDeptRoleService.java b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/ISysUserDeptRoleService.java index f0720a45d..5b6aedd5b 100644 --- a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/ISysUserDeptRoleService.java +++ b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/ISysUserDeptRoleService.java @@ -160,4 +160,8 @@ public interface ISysUserDeptRoleService { * @param userId 用户Id */ void deleteSysUserDeptRoleByDeleteUser(@Param("userId") Long userId); + + Boolean checkUserInDeptOrParentDeptHasPerms(Long deptId, Long userId, String perms); + + SysUserDeptRole getSysUserDeptRoleByDeptIdAndUserId(Long deptId, Long userId); } diff --git a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/impl/SysUserDeptRoleServiceImpl.java b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/impl/SysUserDeptRoleServiceImpl.java index 0e56bf55a..074a42b8c 100644 --- a/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/impl/SysUserDeptRoleServiceImpl.java +++ b/microservices-modules/microservices-modules-system/src/main/java/com/microservices/system/service/impl/SysUserDeptRoleServiceImpl.java @@ -83,8 +83,8 @@ public class SysUserDeptRoleServiceImpl implements ISysUserDeptRoleService { * 查询用户与部门及部门内角色关联列表 * * @param userName 用户名 - * @param deptId 组织Id - * @param roleId 角色Id + * @param deptId 组织Id + * @param roleId 角色Id * @return 用户与部门及部门内角色关联 */ @Override @@ -124,7 +124,10 @@ public class SysUserDeptRoleServiceImpl implements ISysUserDeptRoleService { } for (Long userId : userIds) { SysUserDeptRole userIdentify = sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(userId, deptId); - updateUserGitLinkRole(userId, deptId, userIdentify.getRoleId(), null, OPERATE_REMOVE); + if (userIdentify != null) { + updateUserGitLinkRole(userId, deptId, userIdentify.getRoleId(), null, OPERATE_REMOVE); + } + } int success = deleteUserIdentityByDeptIdAndUserIds(sysDept, userIds); for (Long userId : userIds) { @@ -231,8 +234,13 @@ public class SysUserDeptRoleServiceImpl implements ISysUserDeptRoleService { if (secondaryDeptIds == null) { return; } - - if (!secondaryDeptIds.contains(dept.getDeptId())) { + SysDept parentDept = sysDeptMapper.selectDeptById(dept.getParentId()); + if (parentDept == null) { + return; + } + if (dept.getParentId() == 0L || (parentDept.getParentId() == 0L && dept.getDeptType() == CacheConstants.DEPT_TYPE_TSZQ)) { + remoteCmsService.changeUserOrgRole(userId, operate, SecurityConstants.INNER); + } else if (!secondaryDeptIds.contains(dept.getDeptId())) { if (secondaryDeptIds.contains(dept.getParentId())) { switch (dept.getDeptType()) { case CacheConstants.DEPT_TYPE_TSZQ: { @@ -568,6 +576,17 @@ public class SysUserDeptRoleServiceImpl implements ISysUserDeptRoleService { return false; } + @Override + public Boolean checkUserInDeptOrParentDeptHasPerms(Long deptId, Long userId, String perms) { + int hasPermsCount = sysUserDeptRoleMapper.selectUserInDeptOrParentDeptHasPermsCount(deptId, userId, perms); + return hasPermsCount > 0; + } + + @Override + public SysUserDeptRole getSysUserDeptRoleByDeptIdAndUserId(Long deptId, Long userId) { + return sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(userId, deptId); + } + @Override public Boolean checkUserInDept(Long currentDeptId, Long userId) { SysUserDeptRole sysUserDeptRole = sysUserDeptRoleMapper.selectSysUserDeptRoleByUserIdAndDeptId(userId, currentDeptId); diff --git a/microservices-modules/microservices-modules-system/src/main/resources/mapper/system/SysUserDeptRoleMapper.xml b/microservices-modules/microservices-modules-system/src/main/resources/mapper/system/SysUserDeptRoleMapper.xml index 29196a19f..f8b8d8937 100644 --- a/microservices-modules/microservices-modules-system/src/main/resources/mapper/system/SysUserDeptRoleMapper.xml +++ b/microservices-modules/microservices-modules-system/src/main/resources/mapper/system/SysUserDeptRoleMapper.xml @@ -234,6 +234,18 @@ and udr.dept_id = #{deptId} + insert into sys_user_dept_role diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/FrontController.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/FrontController.java index 5cb7c4ef3..3ff031eb0 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/FrontController.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/FrontController.java @@ -1,5 +1,6 @@ package com.microservices.zone.common.controller; +import com.alibaba.fastjson2.JSONObject; import com.microservices.common.core.web.controller.BaseController; import com.microservices.common.core.web.domain.AjaxResult; import com.microservices.common.core.web.domain.GenericsAjaxResult; @@ -10,16 +11,25 @@ import com.microservices.common.security.annotation.RequiresPermissions; import com.microservices.common.security.utils.SecurityUtils; import com.microservices.zone.detail.domain.vo.ZoneFrontRoleVo; import com.microservices.zone.detail.service.IZoneDetailService; +import com.microservices.zone.project.domain.ZoneProjectType; +import com.microservices.zone.project.domain.vo.*; +import com.microservices.zone.project.service.IZoneProjectService; +import com.microservices.zone.project.service.IZoneProjectTypeService; import com.microservices.zone.resource.domain.ZoneResource; import com.microservices.zone.resource.domain.vo.*; import com.microservices.zone.resource.service.IAiSkillParseService; import com.microservices.zone.resource.service.IZoneResourceService; import io.swagger.annotations.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.util.List; + /** * @author otto */ @@ -34,9 +44,15 @@ public class FrontController extends BaseController { @Autowired private IAiSkillParseService aiSkillParseService; + @Autowired + private IZoneProjectService zoneProjectService; + @Autowired private IZoneDetailService zoneDetailService; + @Autowired + private IZoneProjectTypeService zoneProjectTypeService; + /** * 查询我的资源列表 */ @@ -93,6 +109,72 @@ public class FrontController extends BaseController { return toAjax(zoneResourceService.deleteMyZoneResourceByIds(ids)); } + + /** + * 查询GitLink项目列表 + */ + @GetMapping("/zone/{zoneId}/myGitlinkProjectList") + @ApiOperation("查询专区下我的GitLink项目列表") + public GenericsTableDataInfo selectMyGitlinkProjectListByZone( + @ApiParam(name = "zoneId", value = "专区Id") @PathVariable Long zoneId + , MyGitLinkProjectSearchVo myGitLinkProjectSearchVo) { + return zoneProjectService.selectMyGitlinkProjectListByZone(zoneId, myGitLinkProjectSearchVo); + } + + /** + * 查询我的项目列表 + */ + @RequiresPermissions("zone:front:project:myList") + @GetMapping("/myProjectList") + @ApiOperation(value = "查询我的项目聚合列表") + public GenericsTableDataInfo myProjectList(ZoneProjectSearchVo zoneProjectSearchVo) { + zoneProjectSearchVo.setCreateBy(SecurityUtils.getUsername()); + return zoneProjectService.selectMyZoneProjectList(zoneProjectSearchVo); + } + + /** + * 查询我的项目详情 + */ + @RequiresPermissions("zone:front:project:query") + @GetMapping("/myProject/{id}") + @ApiOperation(value = "查询我的项目聚合详情") + public GenericsAjaxResult myProject(@PathVariable("id") Long id) { + return genericsSuccess(zoneProjectService.selectZoneProjectDataById(id)); + } + + /** + * 新增项目 + */ + @RequiresPermissions("zone:front:project:add") + @Log(title = "专区前台项目操作", businessType = BusinessType.INSERT) + @PostMapping("/addProject") + @ApiOperation(value = "新增项目聚合") + public AjaxResult addProject(@RequestBody @Validated List zoneProjectInputVoList) { + return success(zoneProjectService.insertBatchZoneProject(zoneProjectInputVoList)); + } + + /** + * 编辑项目 + */ + @RequiresPermissions("zone:front:project:edit") + @Log(title = "专区前台项目操作", businessType = BusinessType.UPDATE) + @PutMapping("/editProject/{projectId}") + @ApiOperation(value = "编辑项目聚合") + public AjaxResult editProject(@PathVariable("projectId") Long projectId,@RequestBody ZoneProjectFrontUpdateVo zoneProjectFrontUpdateVo) { + return success(zoneProjectService.updateMyZoneProject(projectId, zoneProjectFrontUpdateVo.toZoneProjectUpdateVo())); + } + + /** + * 删除项目 + */ + @RequiresPermissions("zone:front:project:remove") + @Log(title = "专区前台项目操作", businessType = BusinessType.DELETE) + @DeleteMapping("/removeProject/{ids}") + @ApiOperation(value = "删除项目聚合") + public AjaxResult removeProject(@PathVariable Long[] ids) { + return toAjax(zoneProjectService.deleteMyZoneProjectByIds(ids)); + } + /** * 检查当前登录用户在当前专区下角色 */ diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/OpenController.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/OpenController.java index 4a8ab83df..38421610c 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/OpenController.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/controller/OpenController.java @@ -32,7 +32,6 @@ import com.microservices.zone.project.domain.vo.ZoneProjectSearchVo; import com.microservices.zone.project.domain.vo.ZoneStatisticsVo; import com.microservices.zone.project.service.IZoneProjectService; import com.microservices.zone.project.service.IZoneProjectTypeService; -import com.microservices.zone.resource.domain.ZoneResource; import com.microservices.zone.resource.domain.ZoneResourceDomain; import com.microservices.zone.resource.domain.ZoneResourceType; import com.microservices.zone.resource.domain.vo.ZoneResourceDataVo; @@ -41,6 +40,10 @@ import com.microservices.zone.resource.enums.AiResourceType; import com.microservices.zone.resource.service.IZoneResourceDomainService; import com.microservices.zone.resource.service.IZoneResourceService; import com.microservices.zone.resource.service.IZoneResourceTypeService; +import com.microservices.zone.search.dto.GlobalSearchRequest; +import com.microservices.zone.search.dto.GlobalSearchResponse; +import com.microservices.zone.search.dto.GlobalSearchResult; +import com.microservices.zone.search.service.IGlobalSearchService; import com.microservices.zone.specialProject.domain.ZoneSpecialProject; import com.microservices.zone.specialProject.domain.ZoneSpecialProjectRelevancy; import com.microservices.zone.specialProject.domain.ZoneSpecialProjectReport; @@ -99,6 +102,9 @@ public class OpenController extends BaseController { @Autowired private IZoneVisitsService zoneVisitsService; + @Autowired + private IGlobalSearchService globalSearchService; + /** * 新增特色专区用户浏览 */ @@ -416,6 +422,19 @@ public class OpenController extends BaseController { return getGenericsDataTable(list); } + /** + * 全局搜索接口(POST方法) + * + * @return 搜索结果 + */ + @ApiOperation("全局搜索") + @PostMapping("/global") + public GenericsTableDataInfo globalSearch(@RequestBody GlobalSearchRequest globalSearchRequest) { + logger.info("全局搜索请求: keyword={}, types={}", globalSearchRequest.getKeyword(), globalSearchRequest.getTypes()); + GlobalSearchResponse response = globalSearchService.globalSearch(globalSearchRequest); + return new GenericsTableDataInfo<>(response.getResults(), response.getTotal()); + } + // ==================== AI资源广场 - 开放接口 ==================== /** diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/IZoneAsyncService.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/IZoneAsyncService.java index c88092603..935e011c8 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/IZoneAsyncService.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/IZoneAsyncService.java @@ -1,9 +1,12 @@ package com.microservices.zone.common.service; +import com.alibaba.fastjson2.JSONObject; import com.microservices.zone.detail.domain.ZoneDetail; import com.microservices.zone.project.domain.ZoneProject; import com.microservices.zone.resource.domain.ZoneResourceType; +import java.util.List; + /** * 特色专区异步Service接口 * @@ -51,4 +54,6 @@ public interface IZoneAsyncService { void setProjectGitlinkInfoCache(ZoneProject zoneProject); void clearZoneProjectSortByScoreCache(ZoneProject zoneProject); + + List getGitlinkProjectsDetail(List gitLinkProjectIdList); } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/impl/ZoneAsyncServiceImpl.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/impl/ZoneAsyncServiceImpl.java index d24539abc..dba37288d 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/impl/ZoneAsyncServiceImpl.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/common/service/impl/ZoneAsyncServiceImpl.java @@ -62,10 +62,7 @@ import org.springframework.transaction.annotation.Transactional; import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.stream.Collectors; /** @@ -522,6 +519,41 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService { }); } + @Override + public List getGitlinkProjectsDetail(List gitLinkProjectIdList) { + int queryCount = gitLinkProjectIdList.size() / 50 + 1; + CountDownLatch countDownLatch = new CountDownLatch(queryCount); + List gitLinkProjectList = new ArrayList<>(); + for (int i = 0; i < queryCount; i++) { + int finalI = i; + threadPoolExecutor.execute(() -> { + try { + int pageMaxCount = (finalI + 1) * 50; + if (pageMaxCount >= gitLinkProjectIdList.size()) { + pageMaxCount = gitLinkProjectIdList.size(); + } + List tmpIdList = gitLinkProjectIdList.subList(finalI * 50, pageMaxCount); + JSONObject result = gitLinkRequestHelper.doGet( + ZoneGitLinkRequestUrl.PROJECTS("?ids=" + String.join(ZoneConstants.ARRAY_SPLIT_SYMBOLS, tmpIdList)) + ); + + gitLinkProjectList.addAll(result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class)); + } catch (Exception e) { + logger.error("异步批量获取项目详细信息失败:{}", e.getMessage()); + } finally { + countDownLatch.countDown(); + } + }); + } + try { + countDownLatch.await(); + } catch (InterruptedException e) { + logger.error("根据gitlinkProjectId调用Gitlink接口批量获取项目详细信息失败:{}", e.getMessage()); + throw new ServiceException("获取平台项目详细信息失败"); + } + return gitLinkProjectList; + } + private Double calcProjectScore(ZoneProject zoneProject, String startDate, String endDate) { Double theWeekScore = forgeProjectStatisticsMapper .selectLastWeekScoreByProjectId(zoneProject.getGitlinkProjectId(), startDate, endDate); diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/ZoneDetail.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/ZoneDetail.java index 795a05090..7cd52081e 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/ZoneDetail.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/ZoneDetail.java @@ -190,6 +190,11 @@ public class ZoneDetail extends BaseEntity { @ApiModelProperty(value = "资源是否需要审核(0:不需要审核,1:需要审核)") private Integer resourceNeedAudit; + /** + * 项目是否需要审核(0:不需要,1:需要) + */ + @ApiModelProperty(value = "项目是否需要审核(0:不需要审核,1:需要审核)") + private Integer projectNeedAudit; /** * 资讯是否锁定中(0:未锁定,1:锁定) diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailDataVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailDataVo.java index 7a1fe28d2..8517331fb 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailDataVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailDataVo.java @@ -155,6 +155,12 @@ public class ZoneDetailDataVo extends BaseEntity { @ApiModelProperty(value = "资源是否需要审核(0:不需要审核,1:需要审核)") private Integer resourceNeedAudit; + /** + * 项目是否需要审核(0:不需要,1:需要) + */ + @ApiModelProperty(value = "项目是否需要审核(0:不需要审核,1:需要审核)") + private Integer projectNeedAudit; + /** * 资讯是否锁定中(0:未锁定,1:锁定) */ diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailUpdateVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailUpdateVo.java index a6554d6be..414d4f622 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailUpdateVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneDetailUpdateVo.java @@ -123,6 +123,12 @@ public class ZoneDetailUpdateVo { @ApiModelProperty(value = "资源是否需要审核(0:不需要审核,1:需要审核)") private Integer resourceNeedAudit; + /** + * 项目是否需要审核(0:不需要,1:需要) + */ + @ApiModelProperty(value = "项目是否需要审核(0:不需要审核,1:需要审核)") + private Integer projectNeedAudit; + /** * 资讯是否锁定中(0:未锁定,1:锁定) */ diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneFrontRoleVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneFrontRoleVo.java index 4e7ed58ed..c9fb9f985 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneFrontRoleVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/domain/vo/ZoneFrontRoleVo.java @@ -20,6 +20,12 @@ public class ZoneFrontRoleVo { @ApiModelProperty(value = "资讯管理访问地址") @JsonInclude(JsonInclude.Include.NON_EMPTY) private String docManageUrl; + @ApiModelProperty(value = "项目管理访问地址") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String projectManageUrl; + @ApiModelProperty(value = "用户访问组织Id") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Long deptId; } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/service/impl/ZoneDetailServiceImpl.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/service/impl/ZoneDetailServiceImpl.java index a84b8dc0d..5ba3e376b 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/service/impl/ZoneDetailServiceImpl.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/detail/service/impl/ZoneDetailServiceImpl.java @@ -24,6 +24,7 @@ import com.microservices.system.api.RemoteUserService; import com.microservices.system.api.domain.SysDept; import com.microservices.system.api.domain.SysDictData; import com.microservices.system.api.domain.SysUserDeptRole; +import com.microservices.system.api.model.LoginUser; import com.microservices.system.api.utils.FeignUtils; import com.microservices.zone.common.service.IZoneAsyncService; import com.microservices.zone.detail.domain.ZoneDetail; @@ -108,14 +109,16 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { private IZoneSpecialProjectService zoneSpecialProjectService; @Value("${zone.zoneAdminUrl}") private String zoneAdminUrl; - @Value("${zone.zoneConfigurationUrl}") - private String zoneConfigurationUrl; + @Value("${zone.zoneConfigurationPath:/zone/configuration}") + private String zoneConfigurationPath; @Value("${zone.adminUrl}") private String adminUrl; - @Value("${zone.resourceManageUrl}") - private String resourceManageUrl; - @Value("${zone.docManageUrl}") - private String docManageUrl; + @Value("${zone.resourceManagePath:/zone/resource/resource}") + private String resourceManagePath; + @Value("${zone.docManagePath:/zone/content/doc}") + private String docManagePath; + @Value("${zone.projectManagePath:/zone/project/list}") + private String projectManagePath; @Autowired private RedisService redisService; @@ -202,13 +205,13 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { Date[] lastWeek = getLastWeek(); //专区文章数统计 ZoneDetailDataVo articlesGroupByKey = zoneDetailMapper - .countArticlesGroupByKey(lastWeek[0],lastWeek[1],zoneDetail.getKey()) ; + .countArticlesGroupByKey(lastWeek[0], lastWeek[1], zoneDetail.getKey()); if (articlesGroupByKey != null) { zoneDetailDataVo.setWeekArticles(articlesGroupByKey.getWeekArticles()); } //专区浏览数据统计 ZoneDetailDataVo puVsGroupByKey = zoneDetailMapper - .countPUVsGroupByKey(lastWeek[0],lastWeek[1],zoneDetail.getKey()) ; + .countPUVsGroupByKey(lastWeek[0], lastWeek[1], zoneDetail.getKey()); if (puVsGroupByKey != null) { zoneDetailDataVo.setWeekPV(puVsGroupByKey.getWeekPV()); zoneDetailDataVo.setWeekUV(puVsGroupByKey.getWeekUV()); @@ -277,6 +280,16 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { throw new ServiceException("当前专区下存在待审核资源,需完成审核后才能将专区资源修改为不需要审核(专区名称[%s],待审核资源数量[%d])", oldZoneDetail.getName(), notAuditCount); } } + // 专区项目聚合审核设置由需要审核修改为不需要审核时,需检查当前专区下是否存在待审核项目聚合,如果存在,需要处理完成后再修改配置 + if (zoneDetail.getProjectNeedAudit() != null && (0 == zoneDetail.getProjectNeedAudit())) { + ZoneProjectSearchVo zoneProjectSearchVo = new ZoneProjectSearchVo(); + zoneProjectSearchVo.setZoneId(zoneDetail.getId()); + zoneProjectSearchVo.setAuditStatus(ZoneConstants.PROJECT_NOT_AUDIT); + Integer notAuditCount = zoneProjectMapper.selectZoneProjectListCount(zoneProjectSearchVo); + if (notAuditCount > 0) { + throw new ServiceException("当前专区下存在待审核项目聚合,需完成审核后才能将专区项目聚合修改为不需要审核(专区名称[%s],待审核项目聚合数量[%d])", oldZoneDetail.getName(), notAuditCount); + } + } // 专区资讯审核设置由需要审核修改为不需要审核时,需检查当前专区下是否存在待审核资讯,如果存在,需要处理完成后再修改配置 if (zoneDetail.getDocNeedAudit() != null && (0 == zoneDetail.getDocNeedAudit())) { Long notAuditCount = FeignUtils.getReturnData( @@ -505,14 +518,14 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { .filter(x -> zoneDetail.getDeptId().equals(x.getDeptId())) .findFirst().orElse(null); if (userIdentify != null) { - return genChangeCurrentUserIdentityUrl(userIdentify, gitLinkToken, zoneId, notMemberParentUserIdentify); + return genChangeCurrentUserIdentityUrl(userIdentify, zoneId, notMemberParentUserIdentify); } // 当不存在当前专区对应的管理权限时查找在父级组织中是否存在身份 userIdentify = userIdentifyList.stream() .filter(x -> deptAncestors.contains(String.valueOf(x.getDeptId()))) .findFirst().orElse(null); if (userIdentify != null) { - return genChangeCurrentUserIdentityUrl(userIdentify, gitLinkToken, zoneId, notMemberParentUserIdentify); + return genChangeCurrentUserIdentityUrl(userIdentify, zoneId, notMemberParentUserIdentify); } } return null; @@ -525,12 +538,11 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { * 参照需求 * * @param userIdentify - * @param gitLinkToken * @param zoneId * @param notMemberParentUserIdentify * @return */ - private String genChangeCurrentUserIdentityUrl(SysUserDeptRole userIdentify, String gitLinkToken, Long zoneId, SysUserDeptRole notMemberParentUserIdentify) { + private String genChangeCurrentUserIdentityUrl(SysUserDeptRole userIdentify, Long zoneId, SysUserDeptRole notMemberParentUserIdentify) { String roleKey = userIdentify.getSysRole().getRoleKey(); Long deptId = userIdentify.getDeptId(); if (SystemRole.ZONE_MEMBER.getRoleKey().equals(roleKey)) { @@ -541,10 +553,10 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { } if (SystemRole.ZONE_ADMIN.getRoleKey().equals(roleKey) || SystemRole.ZONE_OPERATOR.getRoleKey().equals(roleKey)) { - return zoneConfigurationUrl + "?changeCurrentUserIdentity=" + deptId; + return adminUrl + zoneConfigurationPath + "?changeCurrentUserIdentity=" + deptId; } if (SystemRole.PLATFORM_ADMIN.getRoleKey().equals(roleKey)) { - return zoneConfigurationUrl + "/" + zoneId + "?changeCurrentUserIdentity=" + deptId; + return adminUrl + zoneConfigurationPath + "/" + zoneId + "?changeCurrentUserIdentity=" + deptId; } return null; @@ -635,19 +647,56 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { public ZoneFrontRoleVo checkCurrentRoleInZone(Long zoneId) { ZoneFrontRoleVo zoneFrontRoleVo = new ZoneFrontRoleVo(); ZoneDetail zoneDetail = selectZoneDetailById(zoneId); - boolean isZoneAdmin = AuthUtil.hasUserIdentity(zoneDetail.getDeptId(), SystemRole.ZONE_ADMIN.getRoleKey()); - boolean isZoneOperator = AuthUtil.hasUserIdentity(zoneDetail.getDeptId(), SystemRole.ZONE_OPERATOR.getRoleKey()); - boolean isZoneMember = AuthUtil.hasUserIdentity(zoneDetail.getDeptId(), SystemRole.ZONE_MEMBER.getRoleKey()); - if (isZoneAdmin || isZoneOperator) { - zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MANAGER); - zoneFrontRoleVo.setResourceManageUrl(resourceManageUrl); - zoneFrontRoleVo.setDocManageUrl(docManageUrl); - } else if (isZoneMember) { - zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MEMBER); - } else { + LoginUser loginUser = SecurityUtils.getLoginUser(); + SysDept sysDept = FeignUtils.getReturnData(remoteDeptService.getDeptByDeptId(zoneDetail.getDeptId(), SecurityConstants.INNER)); + List userIdentifyList = FeignUtils.getReturnData( + remoteUserService.getSysUserDeptRoleListByUserName(loginUser.getUsername(), SecurityConstants.INNER) + ); + if (sysDept == null || userIdentifyList == null) { zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_NONE); + return zoneFrontRoleVo; + } else { + List deptIdList = Arrays.asList(sysDept.getAncestors().split(",")); + SysUserDeptRole parentDeptUserIdentify = userIdentifyList + .stream() + .filter(x -> deptIdList.contains(String.valueOf(x.getDeptId()))) + .filter(x -> !x.getSysRole().getRoleKey().equals(SystemRole.ZONE_MEMBER.getRoleKey())) + .findFirst().orElse(null); + SysUserDeptRole currentUserIdentify = userIdentifyList.stream().filter(x -> x.getDeptId().equals(zoneDetail.getDeptId())).findFirst().orElse(null); + String resourceManageUrl = adminUrl + resourceManagePath + "?changeCurrentUserIdentity="; + String docManageUrl = adminUrl + docManagePath + "?changeCurrentUserIdentity="; + String projectManageUrl = adminUrl + projectManagePath + "?changeCurrentUserIdentity="; + if (currentUserIdentify != null) { + if (currentUserIdentify.getSysRole().getRoleKey().equals(SystemRole.ZONE_MEMBER.getRoleKey())) { + if (parentDeptUserIdentify != null) { + zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MANAGER); + zoneFrontRoleVo.setResourceManageUrl(resourceManageUrl + parentDeptUserIdentify.getDeptId()); + zoneFrontRoleVo.setDocManageUrl(docManageUrl + parentDeptUserIdentify.getDeptId()); + zoneFrontRoleVo.setProjectManageUrl(projectManageUrl + parentDeptUserIdentify.getDeptId()); + zoneFrontRoleVo.setDeptId(parentDeptUserIdentify.getDeptId()); + } else { + zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MEMBER); + zoneFrontRoleVo.setDeptId(currentUserIdentify.getDeptId()); + } + } else { + zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MANAGER); + zoneFrontRoleVo.setResourceManageUrl(resourceManageUrl + currentUserIdentify.getDeptId()); + zoneFrontRoleVo.setDocManageUrl(docManageUrl + currentUserIdentify.getDeptId()); + zoneFrontRoleVo.setProjectManageUrl(projectManageUrl + currentUserIdentify.getDeptId()); + zoneFrontRoleVo.setDeptId(currentUserIdentify.getDeptId()); + } + return zoneFrontRoleVo; + } else if (parentDeptUserIdentify != null) { + zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_MANAGER); + zoneFrontRoleVo.setResourceManageUrl(resourceManageUrl + parentDeptUserIdentify.getDeptId()); + zoneFrontRoleVo.setDocManageUrl(docManageUrl + parentDeptUserIdentify.getDeptId()); + zoneFrontRoleVo.setProjectManageUrl(projectManageUrl + parentDeptUserIdentify.getDeptId()); + zoneFrontRoleVo.setDeptId(parentDeptUserIdentify.getDeptId()); + return zoneFrontRoleVo; + } } + zoneFrontRoleVo.setRole(ZoneConstants.FRONT_ROLE_NONE); return zoneFrontRoleVo; } @@ -678,14 +727,14 @@ public class ZoneDetailServiceImpl implements IZoneDetailService { } if (SystemRole.ZONE_ADMIN.getRoleKey().equals(roleKey) || SystemRole.ZONE_OPERATOR.getRoleKey().equals(roleKey)) { - return zoneConfigurationUrl; + return adminUrl + zoneConfigurationPath; } if (SystemRole.PLATFORM_ADMIN.getRoleKey().equals(roleKey)) { ZoneDetail zoneDetail = zoneDetailMapper.selectZoneDetailByDeptId(deptId); if (zoneDetail == null) { return zoneAdminUrl; } - return zoneConfigurationUrl + "/" + zoneDetail.getId(); + return adminUrl + zoneConfigurationPath + "/" + zoneDetail.getId(); } return adminUrl; diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/member/domain/ZoneMemberWithScore.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/member/domain/ZoneMemberWithScore.java new file mode 100644 index 000000000..85b642d4f --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/member/domain/ZoneMemberWithScore.java @@ -0,0 +1,24 @@ +package com.microservices.zone.member.domain; + +import com.microservices.zone.member.domain.ZoneMember; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * ZoneMember with full-text search score + * 用于全局搜索结果,包含全文搜索相关度评分 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ZoneMemberWithScore extends ZoneMember implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 全文搜索相关度评分(来自 MySQL MATCH...AGAINST) + */ + private Double searchScore; + + private String memberTypeName; +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/member/mapper/ZoneMemberMapper.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/member/mapper/ZoneMemberMapper.java index ed373f64f..9db2cab83 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/member/mapper/ZoneMemberMapper.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/member/mapper/ZoneMemberMapper.java @@ -154,4 +154,21 @@ public interface ZoneMemberMapper { * @return 会员组织Id列表 */ List checkUserIsMemberInDepts(@Param("userId") Long userId, @Param("deptIds") Long[] deptIds); + + /** + * 全局搜索 - 会员名称和用户名搜索(含评分) + * + * @param keyword 搜索关键词 + * @param zoneId 专区ID + * @param offset 偏移量 + * @param pageSize 每页数量 + * @return 搜索结果列表(含评分) + */ + List globalSearchWithScore( + @Param("keyword") String keyword, + @Param("zoneId") Long zoneId, + @Param("offset") int offset, + @Param("pageSize") int pageSize); + + Long globalSearchCount(@Param("keyword") String keyword, @Param("zoneId") Long zoneId); } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectController.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectController.java index 3ec4b74a1..f3af0daa7 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectController.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectController.java @@ -100,7 +100,7 @@ public class ZoneProjectController extends BaseController { @PostMapping @ApiOperation("批量新增项目聚合") public AjaxResult add(@RequestBody @Validated List zoneProjectInputVoList) { - return toAjax(zoneProjectService.insertBatchZoneProject(zoneProjectInputVoList)); + return success(zoneProjectService.insertBatchZoneProject(zoneProjectInputVoList)); } /** @@ -135,4 +135,15 @@ public class ZoneProjectController extends BaseController { public AjaxResult updateHomepageShow(@PathVariable Long id) { return toAjax(zoneProjectService.updateZoneProjectHomePageShow(id)); } + + /** + * 审核特色专区项目 + */ + @RequiresPermissions("zone:project:audit") + @Log(title = "审核特色专区项目", businessType = BusinessType.UPDATE) + @PutMapping("/audit") + @ApiOperation("审核特色专区项目") + public AjaxResult audit(@RequestBody @Validated ZoneProjectAuditVo zoneProjectAuditVo) { + return toAjax(zoneProjectService.auditZoneProject(zoneProjectAuditVo)); + } } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectTypeController.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectTypeController.java index 3d7ff90dc..475b60caf 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectTypeController.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/controller/ZoneProjectTypeController.java @@ -35,7 +35,6 @@ public class ZoneProjectTypeController extends BaseController { /** * 查询特色专区项目分类列表 */ - @RequiresPermissions("zone:projectType:list") @GetMapping("/list") @ApiOperation("查询特色专区项目分类列表") public GenericsTableDataInfo list(ZoneProjectType zoneProjectType) { diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProject.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProject.java index bfd1c3463..e185f422e 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProject.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProject.java @@ -1,11 +1,15 @@ package com.microservices.zone.project.domain; import com.microservices.common.core.annotation.Excel; +import com.microservices.common.core.utils.bean.BeanUtils; import com.microservices.common.core.web.domain.BaseEntity; import com.microservices.system.api.domain.SysDept; +import io.swagger.annotations.ApiModelProperty; import com.microservices.zone.project.domain.vo.ZoneProjectDataVo; import lombok.Data; +import java.util.Date; + /** * 特色专区项目聚合对象 zone_project * @@ -83,16 +87,18 @@ public class ZoneProject extends BaseEntity { */ private String isHomepage; + @ApiModelProperty(value = "审核状态(0:待审核,1:审核通过 2:审核不通过)") + private String auditStatus; + @ApiModelProperty(value = "审核时间") + private Date auditTime; + @ApiModelProperty(value = "审核人") + private String auditBy; + public ZoneProjectDataVo toZoneProjectDataVo() { ZoneProjectDataVo zoneProjectDataVo = new ZoneProjectDataVo(); - zoneProjectDataVo.setId(this.getId()); + BeanUtils.copyProperties(this, zoneProjectDataVo); zoneProjectDataVo.setDeptName(this.getDept().getDeptName()); zoneProjectDataVo.setProjectType(this.getZoneProjectType().getName()); - zoneProjectDataVo.setProjectTypeId(this.getProjectTypeId()); - zoneProjectDataVo.setIsHomepage(this.getIsHomepage()); - zoneProjectDataVo.setZoneId(this.getZoneId()); - zoneProjectDataVo.setSort(this.getSort()); - zoneProjectDataVo.setGitlinkProjectId(this.getGitlinkProjectId()); return zoneProjectDataVo; } } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProjectType.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProjectType.java index cc5d56dbb..c2cd0dbfe 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProjectType.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProjectType.java @@ -43,6 +43,18 @@ public class ZoneProjectType extends BaseEntity { @Excel(name = "排序") private Integer sort; + /** + * 类型详情JSON + */ + @Excel(name = "类型详情JSON") + private String detailJson; + + /** + * 分类下项目总数 + */ + @ApiModelProperty(value = "分类下项目总数") + private Integer projectCount; + /** * 删除标志(0代表存在 2代表删除) */ diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProjectWithScore.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProjectWithScore.java new file mode 100644 index 000000000..52a11e6c8 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/ZoneProjectWithScore.java @@ -0,0 +1,48 @@ +package com.microservices.zone.project.domain; + +import com.alibaba.fastjson2.JSONObject; +import com.microservices.zone.project.domain.ZoneProject; +import com.microservices.zone.project.domain.vo.ZoneProjectDataVo; +import com.microservices.zone.search.dto.GlobalSearchResult; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * ZoneProject with full-text search score + * 用于全局搜索结果,包含全文搜索相关度评分 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ZoneProjectWithScore extends ZoneProject implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 全文搜索相关度评分(来自 MySQL MATCH...AGAINST) + */ + private Double searchScore; + + public GlobalSearchResult toGlobalSearchResult(ZoneProjectDataVo zoneProjectDataVo) { + GlobalSearchResult result = new GlobalSearchResult(); + result.setType("zone_project"); + result.setId(this.getId()); + result.setTitle(this.getName()); + result.setContent(this.getFullName()); + result.setDeptId(this.getDeptId()); + result.setZoneId(this.getZoneId()); + result.setCreateTime(this.getCreateTime()); + + if (zoneProjectDataVo != null) { + result.setExtendData(zoneProjectDataVo.getProjectProperties()); + } + + // 使用数据库返回的实际搜索评分 + Double score = this.getSearchScore(); + if (score == null || score == 0.0) { + score = 0.1; // LIKE 匹配的最小评分 + } + result.setScore(score); + return result; + } +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/GitLinkProjectSearchVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/GitLinkProjectSearchVo.java index 6d4c81e55..c210c0599 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/GitLinkProjectSearchVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/GitLinkProjectSearchVo.java @@ -11,37 +11,15 @@ import lombok.Data; @Data @ApiModel("GitLink项目搜索对象") -public class GitLinkProjectSearchVo { +public class GitLinkProjectSearchVo extends MyGitLinkProjectSearchVo { @ApiModelProperty(value = "项目语言") private Long languageId; - @ApiModelProperty(value = "项目排序") - private String sortBy; - @ApiModelProperty(value = "搜索关键字") - private String search; - @ApiModelProperty(value = "页码") - private Long page; - @ApiModelProperty(value = "每页数量") - private Long limit; public String genQueryString() { - StringBuilder stringBuilder = new StringBuilder("?"); - if (page == null) { - page = 1L; - } - if (limit == null) { - limit = 15L; - } - stringBuilder.append("page=").append(page); - stringBuilder.append("&limit=").append(limit); + StringBuilder queryString = super.genBaseQueryString(); if (languageId != null) { - stringBuilder.append("&language_id=").append(languageId); + queryString.append("&language_id=").append(languageId); } - if (StringUtils.isNotEmpty(sortBy)) { - stringBuilder.append("&sort_by=").append(sortBy); - } - if (StringUtils.isNotEmpty(search)) { - stringBuilder.append("&search=").append(search); - } - return stringBuilder.toString(); + return queryString.toString(); } } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/MyGitLinkProjectSearchVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/MyGitLinkProjectSearchVo.java new file mode 100644 index 000000000..02056e6c7 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/MyGitLinkProjectSearchVo.java @@ -0,0 +1,48 @@ +package com.microservices.zone.project.domain.vo; + +import com.microservices.common.core.utils.StringUtils; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author otto + */ + +@Data +@ApiModel("GitLink项目搜索对象") +public class MyGitLinkProjectSearchVo { + @ApiModelProperty(value = "项目排序") + private String sortBy; + @ApiModelProperty(value = "搜索关键字") + private String search; + @ApiModelProperty(value = "页码") + private Long page; + @ApiModelProperty(value = "每页数量") + private Long limit; + + protected StringBuilder genBaseQueryString() { + StringBuilder stringBuilder = new StringBuilder("?"); + if (page == null) { + page = 1L; + } + if (limit == null) { + limit = 15L; + } + stringBuilder.append("page=").append(page); + stringBuilder.append("&limit=").append(limit); + if (StringUtils.isNotEmpty(sortBy)) { + stringBuilder.append("&sort_by=").append(sortBy); + } + if (StringUtils.isNotEmpty(search)) { + stringBuilder.append("&search=").append(search); + } + return stringBuilder; + } + + public String myProjectsQueryString() { + StringBuilder stringBuilder = genBaseQueryString(); + stringBuilder.append("&category=admin&is_public=public"); + return stringBuilder.toString(); + } +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectAuditVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectAuditVo.java new file mode 100644 index 000000000..519b89163 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectAuditVo.java @@ -0,0 +1,22 @@ +package com.microservices.zone.project.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +@ApiModel("项目审核对象") +public class ZoneProjectAuditVo { + @ApiModelProperty(value = "项目Id", required = true) + @NotNull + private Long id; + + @ApiModelProperty(value = "审核状态(1:审核通过 2:审核不通过)", required = true) + @NotNull + private String auditStatus; + + @ApiModelProperty(value = "备注") + private String remark; +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectDataVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectDataVo.java index 6f77549d7..ec248310d 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectDataVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectDataVo.java @@ -6,6 +6,8 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.Date; + /** * @author otto */ @@ -40,6 +42,15 @@ public class ZoneProjectDataVo implements Comparable { @Excel(name = "gitlink项目Id") private Long gitlinkProjectId; + @ApiModelProperty(value = "审核状态(0:待审核,1:审核通过 2:审核不通过)") + private String auditStatus; + @ApiModelProperty(value = "审核时间") + private Date auditTime; + @ApiModelProperty(value = "审核人") + private String auditBy; + @ApiModelProperty(value = "备注") + private String remark; + @Override public int compareTo(ZoneProjectDataVo zoneProjectDataVo) { // 重写Comparable接口的compareTo方法,根据年龄升序排列,降序修改相减顺序即可 diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectFrontUpdateVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectFrontUpdateVo.java new file mode 100644 index 000000000..e1c93b6bf --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectFrontUpdateVo.java @@ -0,0 +1,28 @@ +package com.microservices.zone.project.domain.vo; + +import com.microservices.common.core.utils.bean.BeanUtils; +import com.microservices.zone.project.domain.ZoneProject; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author otto + */ + +@Data +@ApiModel("项目聚合前台更新对象") +public class ZoneProjectFrontUpdateVo { + @ApiModelProperty(value = "聚合项目类型") + @NotNull + protected Long projectTypeId; + + + public ZoneProjectUpdateVo toZoneProjectUpdateVo() { + ZoneProjectUpdateVo zoneProjectUpdateVo = new ZoneProjectUpdateVo(); + BeanUtils.copyProperties(this, zoneProjectUpdateVo); + return zoneProjectUpdateVo; + } +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectInputVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectInputVo.java index e0977a679..faaa66f4a 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectInputVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectInputVo.java @@ -14,19 +14,16 @@ import javax.validation.constraints.NotNull; @Data @ApiModel("项目聚合输入对象") -public class ZoneProjectInputVo { +public class ZoneProjectInputVo { @ApiModelProperty(value = "gitlink项目Id", required = true) @NotNull - private Long gitlinkProjectId; + protected Long gitlinkProjectId; @ApiModelProperty(value = "聚合项目类型", required = true) @NotNull - private Long projectTypeId; + protected Long projectTypeId; @ApiModelProperty(value = "所属专区", required = true) @NotNull - private Long zoneId; - - @ApiModelProperty(value = "排序") - private Integer sort; + protected Long zoneId; public ZoneProject toZoneProject() { ZoneProject zoneProject = new ZoneProject(); diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectSearchVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectSearchVo.java index 3d1a7405b..292f5d5a8 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectSearchVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectSearchVo.java @@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotNull; + /** * @author otto */ @@ -11,6 +13,11 @@ import lombok.Data; @Data @ApiModel("项目聚合搜索对象") public class ZoneProjectSearchVo extends ZoneProjectOpenSearchVo { - @ApiModelProperty(value = "所属专区") + @ApiModelProperty(value = "所属专区", required = true) + @NotNull private Long zoneId; + @ApiModelProperty(value = "审核状态(0:待审核,1:审核通过 2:审核不通过)") + private String auditStatus; + @ApiModelProperty(value = "是否为我的项目", hidden = true) + private Boolean isMyProject; } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeInputVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeInputVo.java index 798b6c6d0..29fb4782e 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeInputVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeInputVo.java @@ -27,11 +27,15 @@ public class ZoneProjectTypeInputVo extends BaseEntity { @ApiModelProperty(value = "排序") private Integer sort; + @ApiModelProperty(value = "类型详情JSON") + private String detailJson; + public ZoneProjectType toZoneProjectType() { ZoneProjectType zoneProjectType = new ZoneProjectType(); zoneProjectType.setZoneId(zoneId); zoneProjectType.setName(name); zoneProjectType.setSort(sort); + zoneProjectType.setDetailJson(detailJson); return zoneProjectType; } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeUpdateVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeUpdateVo.java index 33c6722cb..86df214a2 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeUpdateVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectTypeUpdateVo.java @@ -27,10 +27,14 @@ public class ZoneProjectTypeUpdateVo extends BaseEntity { @ApiModelProperty(value = "顺序") private Integer order; + @ApiModelProperty(value = "类型详情JSON") + private String detailJson; + public ZoneProjectType toZoneProjectType() { ZoneProjectType zoneProjectType = new ZoneProjectType(); zoneProjectType.setId(id); zoneProjectType.setName(name); + zoneProjectType.setDetailJson(detailJson); return zoneProjectType; } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectUpdateVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectUpdateVo.java index 31eaa2814..e01e29333 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectUpdateVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/domain/vo/ZoneProjectUpdateVo.java @@ -13,18 +13,15 @@ import javax.validation.constraints.NotNull; @Data @ApiModel("项目聚合更新对象") -public class ZoneProjectUpdateVo { - @ApiModelProperty(value = "聚合项目类型") - @NotNull - private Long projectTypeId; - +public class ZoneProjectUpdateVo extends ZoneProjectFrontUpdateVo{ @ApiModelProperty(value = "顺序") private Integer order; public ZoneProject toZoneProject(Long id) { ZoneProject zoneProject = new ZoneProject(); zoneProject.setId(id); - zoneProject.setProjectTypeId(projectTypeId); + zoneProject.setProjectTypeId(super.projectTypeId); + zoneProject.setSort(order); return zoneProject; } } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/mapper/ZoneProjectMapper.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/mapper/ZoneProjectMapper.java index 91e1bae05..883654868 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/mapper/ZoneProjectMapper.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/mapper/ZoneProjectMapper.java @@ -155,4 +155,39 @@ public interface ZoneProjectMapper { * @return */ int deleteZoneProjectByZoneId(Long zoneId); + + /** + * 全局搜索结果计数 + * + * @param keyword 搜索关键词 + * @param zoneId 专区ID(可选) + * @return 结果数量 + */ + Long globalSearchCount(@Param("keyword") String keyword, @Param("zoneId") Long zoneId); + + /** + * 全局搜索 - 全文索引查询(含评分) + * + * @param keyword 搜索关键词 + * @param zoneId 专区ID + * @param offset 偏移量 + * @param pageSize 每页数量 + * @return 搜索结果列表(含评分) + */ + List globalSearchWithScore( + @Param("keyword") String keyword, + @Param("zoneId") Long zoneId, + @Param("offset") int offset, + @Param("pageSize") int pageSize); + + /** + * 获取专区下项目项目gitlink id列表 + * + * @param zoneId 专区id + * @param projectTypeId 专区类型id + * @return 项目gitlink id列表 + */ + List selectZoneProjectGitlinkIdList(@Param("zoneId") Long zoneId, @Param("projectTypeId") Long projectTypeId); + + List selectZoneProjectListFromGitlinkProjectIdList(@Param("zoneId") Long zoneId, @Param("gitlinkProjectIdList") List gitlinkProjectIdList); } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/IZoneProjectService.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/IZoneProjectService.java index 7dce19372..d1be2435a 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/IZoneProjectService.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/IZoneProjectService.java @@ -2,6 +2,7 @@ package com.microservices.zone.project.service; import com.alibaba.fastjson2.JSONObject; import com.microservices.common.core.web.page.GenericsTableDataInfo; +import com.microservices.zone.project.domain.ZoneProject; import com.microservices.zone.project.domain.vo.*; import java.util.List; @@ -112,4 +113,40 @@ public interface IZoneProjectService { Integer selectHomepageCount(Long zoneId); List selectZoneProjectByScoreList(ZoneProjectSearchVo zoneProjectSearchVo, boolean isOpen); + + /** + * 查询我的项目列表 + * + * @param zoneProjectSearchVo 查询条件 + * @return 项目列表 + */ + GenericsTableDataInfo selectMyZoneProjectList(ZoneProjectSearchVo zoneProjectSearchVo); + + /** + * 批量删除我的项目(校验创建者) + * + * @param ids 需要删除的项目主键集合 + * @return 结果 + */ + int deleteMyZoneProjectByIds(Long[] ids); + + /** + * 修改我的项目(校验创建者) + * + * @param id 项目主键 + * @param zoneProjectUpdateVo 更新数据 + * @return 结果 + */ + int updateMyZoneProject(Long id, ZoneProjectUpdateVo zoneProjectUpdateVo); + + /** + * 审核项目 + * + * @param zoneProjectAuditVo 审核数据 + * @return 结果 + */ + int auditZoneProject(ZoneProjectAuditVo zoneProjectAuditVo); + + GenericsTableDataInfo selectMyGitlinkProjectListByZone(Long zoneId, MyGitLinkProjectSearchVo myGitLinkProjectSearchVo); + List toZoneProjectDataVoList(List zoneProjectList); } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/impl/ZoneProjectServiceImpl.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/impl/ZoneProjectServiceImpl.java index 9dc5da87b..abf98b7d7 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/impl/ZoneProjectServiceImpl.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/project/service/impl/ZoneProjectServiceImpl.java @@ -1,5 +1,6 @@ package com.microservices.zone.project.service.impl; +import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.microservices.common.core.constant.CacheConstants; @@ -12,8 +13,10 @@ import com.microservices.common.core.web.page.GenericsTableDataInfo; import com.microservices.common.datascope.annotation.DataScope; import com.microservices.common.httpClient.util.GitLinkRequestHelper; import com.microservices.common.redis.service.RedisService; +import com.microservices.common.security.auth.AuthUtil; import com.microservices.common.security.utils.DictUtils; import com.microservices.common.security.utils.SecurityUtils; +import com.microservices.common.core.enums.SystemRole; import com.microservices.system.api.domain.SysDictData; import com.microservices.zone.common.service.IZoneAsyncService; import com.microservices.zone.detail.domain.ZoneDetail; @@ -113,23 +116,24 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { throw new ServiceException("查询项目列表时,请指定专区Id"); } zoneDetailService.selectZoneDetailById(zoneProjectSearchVo.getZoneId()); + if (isOpen) { + zoneProjectSearchVo.setAuditStatus(ZoneConstants.PROJECT_AUDIT_PASS); + } startPage(); zoneProjectSearchVo.setIsOpen(isOpen); List zoneProjectList = zoneProjectMapper.selectZoneProjectList(zoneProjectSearchVo); return PageUtils.toListPage(zoneProjectList, this::toZoneProjectDataVoList); } - private List toZoneProjectDataVoList(List zoneProjectList) { + @Override + public List toZoneProjectDataVoList(List zoneProjectList) { List zoneProjectDataVoList = new ArrayList<>(); // 原方案为遍历项目聚合再逐一从GitLink获取对应项目详情,此方案延时过高,调整为根据项目Id批量获取GitLink项目信息 List gitLinkProjectIdList = zoneProjectList .stream() .map(x -> String.valueOf(x.getGitlinkProjectId())) .collect(Collectors.toList()); - JSONObject result = gitLinkRequestHelper.doGet( - ZoneGitLinkRequestUrl.PROJECTS("?ids=" + String.join(ZoneConstants.ARRAY_SPLIT_SYMBOLS, gitLinkProjectIdList)) - ); - List gitLinkProjectList = result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class); + List gitLinkProjectList = zoneAsyncService.getGitlinkProjectsDetail(gitLinkProjectIdList); List resultGitLinkProjectIdList = gitLinkProjectList .stream() .map(x -> x.getString("id")) @@ -210,6 +214,24 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { } } + private static String extractFirstPathSegment(String url) { + if (url == null || url.isEmpty()) return null; + + // 找到协议后的第一个 '/' 的位置(路径开始) + int schemeSep = url.indexOf("://"); + if (schemeSep == -1) return null; + + int hostStart = schemeSep + 3; + int pathStart = url.indexOf('/', hostStart); + if (pathStart == -1) return null; // 没有路径 + + // 找到下一个 '/' 或结尾 + int pathEnd = url.indexOf('/', pathStart + 1); + if (pathEnd == -1) pathEnd = url.length(); + + return url.substring(pathStart + 1, pathEnd); + } + private ZoneProjectDataVo zoneProjectToZoneProjectDataVo(ZoneProject zoneProject, JSONObject gitLinkProject) { //每次从GitLink查询项目时自动更新项目名称和项目标识 updateProjectNameAndFullName(gitLinkProject, zoneProject); @@ -229,6 +251,11 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { projectKeyName.put("name", "项目名称"); projectPropertiesVo.put("fullName", author.getString("login") + "/" + gitLinkProject.getString("identifier")); projectKeyName.put("fullName", "项目完整地址"); + projectPropertiesVo.put("fromOwner", author.getString("login")); + } + String mirrorUrl = gitLinkProject.getString("mirror_url"); + if (StringUtils.isNotEmpty(mirrorUrl)) { + projectPropertiesVo.put("fromOwner", extractFirstPathSegment(mirrorUrl)); } String description = gitLinkProject.getString("description"); projectPropertiesVo.put("description", description); @@ -385,9 +412,20 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { public int insertZoneProject(ZoneProjectInputVo zoneProjectInputVo) { ZoneDetail zoneDetail = zoneDetailService.selectZoneDetailById(zoneProjectInputVo.getZoneId()); zoneProjectTypeService.selectZoneProjectTypeByIdAndZoneId(zoneProjectInputVo.getProjectTypeId(), zoneProjectInputVo.getZoneId()); + ZoneProject existingProject = zoneProjectMapper.selectZoneProjectByGitLinkProjectIdAndZoneId( + zoneProjectInputVo.getGitlinkProjectId(), zoneProjectInputVo.getZoneId()); + if (existingProject != null) { + if (existingProject.getAuditStatus().equals(ZoneConstants.PROJECT_NOT_AUDIT)) { + throw new ServiceException("该项目正处于于专区审核中,不可重复添加"); + } + throw new ServiceException("该项目已存在于专区中,不可重复添加"); + } JSONObject gitLinkProject = getGitLinkProjectById(zoneProjectInputVo.getGitlinkProjectId()); ZoneProject zoneProject = zoneProjectInputVo.toZoneProject(); zoneProject.setCreateTime(DateUtils.getNowDate()); + if (StringUtils.isEmpty(zoneProject.getCreateBy())) { + zoneProject.setCreateBy(SecurityUtils.getUsername()); + } zoneProject.setDeptId(zoneDetail.getDeptId()); zoneProject.setDeptId(zoneDetail.getDeptId()); JSONObject author = gitLinkProject.getJSONObject("author"); @@ -395,6 +433,12 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { zoneProject.setName(author.getString("name") + "/" + gitLinkProject.getString("name")); zoneProject.setFullName(author.getString("login") + "/" + gitLinkProject.getString("identifier")); } + // 专区开启项目审核后,专区会员和专区运营人员新增项目都需要审核 + if (projectNeedAudit(zoneDetail)) { + zoneProject.setAuditStatus(ZoneConstants.PROJECT_NOT_AUDIT); + } else { + zoneProject.setAuditStatus(ZoneConstants.PROJECT_AUDIT_PASS); + } //设置排序值为当前最大的排序值+1 Integer maxSort = zoneProjectMapper.selectMaxSortByZoneId(zoneProjectInputVo.getZoneId()); if (maxSort == null) { @@ -548,27 +592,10 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { JSONObject result = gitLinkRequestHelper.doGet( ZoneGitLinkRequestUrl.PROJECTS(gitLinkProjectSearchVo.genQueryString()) ); - List list = result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class); - if (list == null) { - throw new ServiceException("Gitlink项目列表获取失败"); - } ZoneProjectSearchVo zoneProjectSearchVo = new ZoneProjectSearchVo(); zoneProjectSearchVo.setZoneId(zoneId); List zoneProjectList = zoneProjectMapper.selectZoneProjectList(zoneProjectSearchVo); - List gitlinkProjectList = new ArrayList<>(); - for (JSONObject gitlinkProject : list) { - if (zoneId != null) { - boolean isChoose = zoneProjectList.stream().anyMatch(x -> x.getGitlinkProjectId().equals(gitlinkProject.getLong("id"))); - if (isChoose) { - gitlinkProject.put("isChoose", true); - } else { - gitlinkProject.put("isChoose", false); - } - } - gitlinkProjectList.add(gitlinkProject); - } - Long size = result.getLong(ZoneConstants.GITLINK_RESPONSE_TOTAL_COUNT_KEY); - return PageUtils.toPage(gitlinkProjectList, size); + return execGitlinkProjectsSearch(zoneId, result, ZoneConstants.GITLINK_RESPONSE_TOTAL_COUNT_KEY, zoneProjectList); } @Override @@ -582,7 +609,12 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { ZoneProject zoneProject = zoneProjectMapper .selectZoneProjectByGitLinkProjectIdAndZoneId(gitlinkProjectId, zoneId); if (zoneProject != null) { - throw new ServiceException("该GitLink项目已存在于专区中,不可重复添加(专区Id[" + zoneId + "],GitLink项目Id[" + gitlinkProjectId + "])"); + if (zoneProject.getAuditStatus().equals(ZoneConstants.PROJECT_NOT_AUDIT)) { + throw new ServiceException("该项目正处于于专区审核中,不可重复添加(专区Id[" + zoneId + "],项目Id[" + gitlinkProjectId + "])"); + } + throw new ServiceException("该项目已存在于专区中,不可重复添加(专区Id[" + zoneId + "],项目Id[" + gitlinkProjectId + "])"); +// logger.warn("该GitLink项目已存在于专区中,不可重复添加(专区Id[{}],GitLink项目Id[{}])", zoneId, gitlinkProjectId); +// break; } success += insertZoneProject(zoneProjectInputVo); } @@ -633,6 +665,55 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { return zoneProjectMapper.selectHomepageCount(zoneId); } + @Override + public GenericsTableDataInfo selectMyZoneProjectList(ZoneProjectSearchVo zoneProjectSearchVo) { + if (zoneProjectSearchVo == null || zoneProjectSearchVo.getZoneId() == null) { + throw new ServiceException("获取我的项目列表时必须传入专区Id"); + } + zoneDetailService.selectZoneDetailById(zoneProjectSearchVo.getZoneId()); + startPage(); + List zoneProjectList = zoneProjectMapper.selectZoneProjectList(zoneProjectSearchVo); + return PageUtils.toListPage(zoneProjectList, this::toZoneProjectDataVoList); + } + + @Override + public int deleteMyZoneProjectByIds(Long[] ids) { + for (Long id : ids) { + ZoneProject zoneProject = zoneProjectMapper.selectZoneProjectById(id); + if (zoneProject == null) { + throw new ServiceException("该项目不存在(项目Id[" + id + "])"); + } + if (!zoneProject.getCreateBy().equals(SecurityUtils.getUsername())) { + throw new ServiceException("仅允许删除自身创建的项目"); + } + } + int success = 0; + for (Long id : ids) { + success += deleteZoneProjectById(id); + } + return success; + } + + @Override + public int updateMyZoneProject(Long id, ZoneProjectUpdateVo zoneProjectUpdateVo) { + ZoneProject zoneProject = zoneProjectMapper.selectZoneProjectById(id); + if (zoneProject == null) { + throw new ServiceException("该项目不存在(项目Id[" + id + "])"); + } + if (!zoneProject.getCreateBy().equals(SecurityUtils.getUsername())) { + throw new ServiceException("仅允许编辑自身创建的项目"); + } + ZoneDetail zoneDetail = zoneDetailService.selectZoneDetailById(zoneProject.getZoneId()); + int result = updateZoneProject(id, zoneProjectUpdateVo); + if (projectNeedAudit(zoneDetail)) { + ZoneProject updateProject = new ZoneProject(); + updateProject.setId(id); + updateProject.setAuditStatus(ZoneConstants.PROJECT_NOT_AUDIT); + zoneProjectMapper.updateZoneProject(updateProject); + } + return result; + } + @Override public List selectZoneProjectByScoreList(ZoneProjectSearchVo zoneProjectSearchVo, boolean isOpen) { if (zoneProjectSearchVo.getProjectTypeId() == null) { @@ -680,4 +761,78 @@ public class ZoneProjectServiceImpl implements IZoneProjectService { } return zoneProjectJSONList; } + + private boolean projectNeedAudit(ZoneDetail zoneDetail) { + if (1 == zoneDetail.getProjectNeedAudit()) { + boolean isOperator = AuthUtil.hasUserIdentity(zoneDetail.getDeptId(), SystemRole.ZONE_OPERATOR.getRoleKey()); + boolean isMember = AuthUtil.hasUserIdentity(zoneDetail.getDeptId(), SystemRole.ZONE_MEMBER.getRoleKey()); + return isOperator || isMember; + } + return false; + } + + @Override + public int auditZoneProject(ZoneProjectAuditVo zoneProjectAuditVo) { + ZoneProject zoneProject = zoneProjectMapper.selectZoneProjectById(zoneProjectAuditVo.getId()); + if (zoneProject == null) { + throw new ServiceException("该项目不存在(项目Id[" + zoneProjectAuditVo.getId() + "])"); + } + zoneDetailService.checkZoneDataScope(zoneProject.getZoneId()); + if (!ZoneConstants.PROJECT_AUDIT_PASS.equals(zoneProjectAuditVo.getAuditStatus()) + && !ZoneConstants.PROJECT_AUDIT_FAILED.equals(zoneProjectAuditVo.getAuditStatus())) { + throw new ServiceException("审核状态仅允许设置为审核通过和审核不通过"); + } + if (!ZoneConstants.PROJECT_NOT_AUDIT.equals(zoneProject.getAuditStatus())) { + throw new ServiceException("该项目当前未处于待审核状态,不允许进行审核操作"); + } + zoneProject.setAuditTime(DateUtils.getNowDate()); + zoneProject.setAuditBy(SecurityUtils.getUsername()); + zoneProject.setAuditStatus(zoneProjectAuditVo.getAuditStatus()); + zoneProject.setRemark(zoneProjectAuditVo.getRemark()); + return zoneProjectMapper.updateZoneProject(zoneProject); + } + + @Override + public GenericsTableDataInfo selectMyGitlinkProjectListByZone(Long zoneId, MyGitLinkProjectSearchVo gitLinkProjectSearchVo) { + JSONObject result = gitLinkRequestHelper.doGet( + ZoneGitLinkRequestUrl.MY_OWNER_PROJECTS(SecurityUtils.getUsername(), gitLinkProjectSearchVo.myProjectsQueryString()) + ); + ZoneProjectSearchVo zoneProjectSearchVo = new ZoneProjectSearchVo(); + zoneProjectSearchVo.setZoneId(zoneId); + zoneProjectSearchVo.setIsMyProject(true); + List zoneProjectList = zoneProjectMapper.selectZoneProjectList(zoneProjectSearchVo); + return execGitlinkProjectsSearch(zoneId, result, ZoneConstants.GITLINK_RESPONSE_COUNT_KEY, zoneProjectList); + } + + private GenericsTableDataInfo execGitlinkProjectsSearch(Long zoneId, JSONObject result, String totalKey, List zoneProjectList) { + List list = result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class); + if (list == null) { + throw new ServiceException("Gitlink项目列表获取失败"); + } + + List gitlinkProjectList = new ArrayList<>(); + for (JSONObject gitlinkProject : list) { + if (zoneId != null) { + ZoneProject isChooseProject = zoneProjectList + .stream() + .filter(x -> x.getGitlinkProjectId().equals(gitlinkProject.getLong("id"))) + .findFirst() + .orElse(null); + if (isChooseProject == null) { + gitlinkProject.put("isChoose", false); + gitlinkProject.put("isAudited", false); + } else { + gitlinkProject.put("isChoose", true); + if (isChooseProject.getAuditStatus().equals(ZoneConstants.PROJECT_NOT_AUDIT)) { + gitlinkProject.put("isAudited", false); + } else { + gitlinkProject.put("isAudited", true); + } + } + } + gitlinkProjectList.add(gitlinkProject); + } + Long size = result.getLong(totalKey); + return PageUtils.toPage(gitlinkProjectList, size); + } } diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/ZoneResourceWithScore.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/ZoneResourceWithScore.java new file mode 100644 index 000000000..37c99dcd3 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/ZoneResourceWithScore.java @@ -0,0 +1,24 @@ +package com.microservices.zone.resource.domain; + +import com.microservices.zone.resource.domain.ZoneResource; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * ZoneResource with full-text search score + * 用于全局搜索结果,包含全文搜索相关度评分 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ZoneResourceWithScore extends ZoneResource implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 全文搜索相关度评分(来自 MySQL MATCH...AGAINST) + */ + private Double searchScore; + + private Long downloadCount; +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceDataVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceDataVo.java index a01d051ac..3b205b5a8 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceDataVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceDataVo.java @@ -75,6 +75,10 @@ public class ZoneResourceDataVo { private Date auditTime; @ApiModelProperty(value = "审核人") private String auditBy; + @ApiModelProperty(value = "拓展数据") + private String extendData; + @ApiModelProperty(value = "备注") + private String remark; @ApiModelProperty(value = "拓展数据(JSON格式)") private JSONObject extendData; diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceSearchVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceSearchVo.java index 0002f0390..e46f63d2c 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceSearchVo.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/domain/vo/ZoneResourceSearchVo.java @@ -5,6 +5,8 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotNull; + /** * @author otto */ @@ -12,7 +14,8 @@ import lombok.Data; @ApiModel("资源搜索对象") public class ZoneResourceSearchVo extends ZoneResourceOpenSearchVo { - @ApiModelProperty(value = "所属专区") + @ApiModelProperty(value = "所属专区",required = true) + @NotNull private Long zoneId; @ApiModelProperty(value = "审核状态(0:待审核,1:审核通过 2:审核不通过)") diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/mapper/ZoneResourceMapper.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/mapper/ZoneResourceMapper.java index c50137631..acd4327b1 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/mapper/ZoneResourceMapper.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/resource/mapper/ZoneResourceMapper.java @@ -96,6 +96,30 @@ public interface ZoneResourceMapper { */ void deleteZoneResourceByZoneId(Long zoneId); + /** + * 全局搜索结果计数 + * + * @param keyword 搜索关键词 + * @param zoneId 专区ID(可选) + * @return 结果数量 + */ + Long globalSearchCount(@Param("keyword") String keyword, @Param("zoneId") Long zoneId); + + /** + * 全局搜索 - 全文索引查询(含评分) + * + * @param keyword 搜索关键词 + * @param zoneId 专区ID + * @param offset 偏移量 + * @param pageSize 每页数量 + * @return 搜索结果列表(含评分) + */ + List globalSearchWithScore( + @Param("keyword") String keyword, + @Param("zoneId") Long zoneId, + @Param("offset") int offset, + @Param("pageSize") int pageSize); + /** * 通过名称查询Skill资源(resource_category='SKILL') * diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GitlinkSearchDataVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GitlinkSearchDataVo.java new file mode 100644 index 000000000..7f3178643 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GitlinkSearchDataVo.java @@ -0,0 +1,13 @@ +package com.microservices.zone.search.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class GitlinkSearchDataVo { + + private Long total=0L; + + private List gitlinkSearchVoList; +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GitlinkSearchVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GitlinkSearchVo.java new file mode 100644 index 000000000..ba2cdc38c --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GitlinkSearchVo.java @@ -0,0 +1,73 @@ +package com.microservices.zone.search.dto; + +import com.alibaba.fastjson2.JSONObject; +import com.microservices.common.core.utils.StringUtils; +import com.microservices.zone.project.domain.vo.ZoneProjectDataVo; +import com.microservices.zone.search.utils.SearchUtils; +import lombok.Data; + +import java.util.List; + +@Data +public class GitlinkSearchVo { + + private String id; + + private Long instanceId; + + private String title; + + private String content; + + private String userName; + + private Long type; + + private Long star; + + private Long fork; + + private Long watch; + + private String createTime; + + private String updateTime; + + private List topics; + + private Long praisesCount; + + private Long forkedCount; + + private Long watchersCount; + + private String url; + + private Double score; + + public GlobalSearchResult toGlobalSearchResult(ZoneProjectDataVo zoneProjectDataVo, String topic) { + GlobalSearchResult globalSearchResult = new GlobalSearchResult(); + globalSearchResult.setTitle(replaceHighlightGitlinkSearch(this.title)); + globalSearchResult.setContent(replaceHighlightGitlinkSearch(this.content)); + globalSearchResult.setScore(this.score); + globalSearchResult.setId(zoneProjectDataVo.getId()); + globalSearchResult.setType("zone_project"); + globalSearchResult.setDeptId(zoneProjectDataVo.getZoneId()); + globalSearchResult.setCreateTime(globalSearchResult.getCreateTime()); + globalSearchResult.setZoneId(zoneProjectDataVo.getZoneId()); + JSONObject extendData = zoneProjectDataVo.getProjectProperties(); + String topics = extendData.getString("topics"); + if (StringUtils.isNotEmpty(topics)) { + extendData.put("topics", SearchUtils.highlightKeyword(topics, topic)); + } + globalSearchResult.setExtendData(extendData); + return globalSearchResult; + } + + private String replaceHighlightGitlinkSearch(String text) { + if (StringUtils.isNotEmpty(text)) { + text = text.replace("", "").replace("", ""); + } + return text; + } +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchRequest.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchRequest.java new file mode 100644 index 000000000..f3037e824 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchRequest.java @@ -0,0 +1,72 @@ +package com.microservices.zone.search.dto; + +import com.alibaba.fastjson2.JSONObject; +import com.microservices.common.core.utils.StringUtils; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 全局搜索请求对象 + * + * @author microservices + */ +@Data +@ApiModel("全局搜索请求对象") +public class GlobalSearchRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 搜索关键词 + */ + @ApiModelProperty(value = "搜索关键词", required = true) + private String keyword; + + /** + * 搜索类型列表(zone_project, resource, member) + * 为空则搜索所有类型 + */ + @ApiModelProperty(value = "搜索类型列表") + private List types; + + /** + * 专区ID + */ + @ApiModelProperty(value = "专区ID") + private Long zoneId; + + /** + * 页码 + */ + @ApiModelProperty(value = "页码") + private Integer pageNum = 1; + + /** + * 每页数量 + */ + @ApiModelProperty(value = "每页数量") + private Integer pageSize = 20; + + + @ApiModelProperty(value = "额外搜索参数(项目类型:projectTypeId,topic)") + private JSONObject extraSearchParam; + + public String toProjectEsSearchString(String gitlinkSearchUrl, String gitlinkProjectIds, String topic) { + String esSearchString= gitlinkSearchUrl + + "/search" + + "?" + + "page=" + this.pageNum + + "&size=" + this.pageSize + + "&term=" + this.keyword + + "&type=" + 1 + + "&instanceIds=" + gitlinkProjectIds; + if(StringUtils.isNotEmpty(topic)){ + esSearchString+="&topic=" + topic; + } + return esSearchString; + } +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResponse.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResponse.java new file mode 100644 index 000000000..59550f99f --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResponse.java @@ -0,0 +1,63 @@ +package com.microservices.zone.search.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * 全局搜索响应对象 + * + * @author microservices + */ +@Data +@ApiModel("全局搜索响应对象") +public class GlobalSearchResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 总结果数 + */ + @ApiModelProperty(value = "总结果数") + private Long total; + + /** + * 搜索结果列表 + */ + @ApiModelProperty(value = "搜索结果列表") + private List results; + + /** + * 各类型结果数量统计 + */ + @ApiModelProperty(value = "各类型结果数量统计") + private Map typeCounts; + + /** + * 搜索耗时(毫秒) + */ + @ApiModelProperty(value = "搜索耗时(毫秒)") + private Long searchTime; + + /** + * 搜索关键词 + */ + @ApiModelProperty(value = "搜索关键词") + private String keyword; + + /** + * 当前页码 + */ + @ApiModelProperty(value = "当前页码") + private Integer pageNum; + + /** + * 每页数量 + */ + @ApiModelProperty(value = "每页数量") + private Integer pageSize; +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResult.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResult.java new file mode 100644 index 000000000..334af2cfe --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResult.java @@ -0,0 +1,77 @@ +package com.microservices.zone.search.dto; + +import com.alibaba.fastjson2.JSONObject; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 全局搜索结果对象 + * + * @author microservices + */ +@Data +@ApiModel("全局搜索结果对象") +public class GlobalSearchResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 结果类型(zone_project, resource, member) + */ + @ApiModelProperty(value = "结果类型") + private String type; + + /** + * ID + */ + @ApiModelProperty(value = "ID") + private Long id; + + /** + * 标题 + */ + @ApiModelProperty(value = "标题") + private String title; + + /** + * 内容摘要 + */ + @ApiModelProperty(value = "内容摘要") + private String content; + + /** + * 组织ID + */ + @ApiModelProperty(value = "组织ID") + private Long deptId; + + /** + * 专区ID + */ + @ApiModelProperty(value = "专区ID") + private Long zoneId; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建时间") + private Date createTime; + + /** + * 相关度评分 + */ + @ApiModelProperty(value = "相关度评分") + private Double score; + + /** + * 扩展数据(JSON格式) + */ + @ApiModelProperty(value = "扩展数据") + private JSONObject extendData; +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResultDataVo.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResultDataVo.java new file mode 100644 index 000000000..7fe4dabf0 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/dto/GlobalSearchResultDataVo.java @@ -0,0 +1,29 @@ +package com.microservices.zone.search.dto; + +import com.alibaba.fastjson2.JSONObject; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 全局搜索结果对象 + * + * @author microservices + */ +@Data +@ApiModel("全局搜索结果对象") +public class GlobalSearchResultDataVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "总数") + private Long total; + + @ApiModelProperty(value = "搜索结果") + private List globalSearchResultList; +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/service/IGlobalSearchService.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/service/IGlobalSearchService.java new file mode 100644 index 000000000..6b7162cd3 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/service/IGlobalSearchService.java @@ -0,0 +1,20 @@ +package com.microservices.zone.search.service; + +import com.microservices.zone.search.dto.GlobalSearchRequest; +import com.microservices.zone.search.dto.GlobalSearchResponse; + +/** + * 全局搜索服务接口 + * + * @author microservices + */ +public interface IGlobalSearchService { + + /** + * 全局搜索 + * + * @param request 搜索请求 + * @return 搜索响应 + */ + GlobalSearchResponse globalSearch(GlobalSearchRequest request); +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/service/impl/GlobalSearchServiceImpl.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/service/impl/GlobalSearchServiceImpl.java new file mode 100644 index 000000000..73bbaeae0 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/service/impl/GlobalSearchServiceImpl.java @@ -0,0 +1,432 @@ +package com.microservices.zone.search.service.impl; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.microservices.common.core.domain.R; +import com.microservices.common.core.exception.ServiceException; +import com.microservices.common.core.utils.StringUtils; +import com.microservices.common.httpClient.service.HttpAPIService; +import com.microservices.common.redis.service.RedisService; +import com.microservices.common.security.utils.SecurityUtils; +import com.microservices.system.api.RemoteFileService; +import com.microservices.system.api.domain.SysFileInfo; +import com.microservices.system.api.model.LoginUser; +import com.microservices.zone.project.domain.ZoneProject; +import com.microservices.zone.project.domain.ZoneProjectWithScore; +import com.microservices.zone.project.domain.vo.GitLinkProjectSearchVo; +import com.microservices.zone.project.domain.vo.ZoneProjectDataVo; +import com.microservices.zone.project.mapper.ZoneProjectMapper; +import com.microservices.zone.project.service.IZoneProjectService; +import com.microservices.zone.resource.domain.ZoneResourceWithScore; +import com.microservices.zone.resource.mapper.ZoneResourceMapper; +import com.microservices.zone.member.domain.ZoneMemberWithScore; +import com.microservices.zone.member.mapper.ZoneMemberMapper; +import com.microservices.zone.search.dto.*; +import com.microservices.zone.search.service.IGlobalSearchService; +import com.microservices.zone.search.utils.SearchUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.commons.config.DefaultsBindHandlerAdvisor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.regex.Pattern; + +/** + * 全局搜索服务实现 + * + * @author microservices + */ +@Service +public class GlobalSearchServiceImpl implements IGlobalSearchService { + + private static final Logger logger = LoggerFactory.getLogger(GlobalSearchServiceImpl.class); + + @Autowired + private ZoneProjectMapper zoneProjectMapper; + + @Autowired + private ZoneResourceMapper zoneResourceMapper; + + @Autowired + private ZoneMemberMapper zoneMemberMapper; + + @Autowired + private RemoteFileService remoteFileService; + + @Autowired + private RedisService redisService; + + @Autowired + private IZoneProjectService projectService; + @Autowired + private HttpAPIService httpAPIService; + + @Value("${http.gitLinkSearchUrl:}") + public String gitLinkSearchUrl; + + private static final String SEARCH_CACHE_PREFIX = "search:cache:"; + private static final long CACHE_EXPIRE_SECONDS = 300; // 5分钟 + @Autowired + private DefaultsBindHandlerAdvisor.MappingsProvider mappingsProvider; + + @Override + public GlobalSearchResponse globalSearch(GlobalSearchRequest request) { + long startTime = System.currentTimeMillis(); + + if (request.getZoneId() == null) { + throw new ServiceException("专区id不能为空"); + } + + // 2. 并行搜索各类型 + List allResults = new ArrayList<>(); + Map typeCounts = new HashMap<>(); + + // 获取当前用户信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // 确定要搜索的类型 + List searchTypes = request.getTypes(); + if (searchTypes == null || searchTypes.isEmpty()) { + searchTypes = Arrays.asList("zone_project", "resource", "member"); + } + Long searchTotal = 0L; + + // 搜索Zone项目 + if (searchTypes.contains("zone_project")) { + GlobalSearchResultDataVo resultDataVo = searchZoneProjects(request); + allResults.addAll(resultDataVo.getGlobalSearchResultList()); + typeCounts.put("zone_project", resultDataVo.getTotal()); + searchTotal += resultDataVo.getTotal(); + } + + // 搜索Zone资源 + if (searchTypes.contains("resource")) { + List resourceResults = searchResources(request); + allResults.addAll(resourceResults); + Long searchResourceCount = zoneResourceMapper.globalSearchCount(request.getKeyword(), request.getZoneId()); + typeCounts.put("resource", searchResourceCount); + searchTotal += searchResourceCount; + } + + // 搜索Zone会员 + if (searchTypes.contains("member")) { + List memberResults = searchZoneMembers(request); + allResults.addAll(memberResults); + Long searchMemberCount = zoneMemberMapper.globalSearchCount(request.getKeyword(), request.getZoneId()); + typeCounts.put("member", searchMemberCount); + searchTotal += searchMemberCount; + } + + // 3. 按相关度评分排序 + allResults.sort((a, b) -> { + if (b.getScore() != null && a.getScore() != null) { + return b.getScore().compareTo(a.getScore()); + } + return 0; + }); + + // 4. 分页 + int total = allResults.size(); + int start = (request.getPageNum() - 1) * request.getPageSize(); + int end = Math.min(start + request.getPageSize(), total); + List pagedResults = start < total ? + allResults.subList(start, end) : new ArrayList<>(); + + // 5. 构建响应 + GlobalSearchResponse response = new GlobalSearchResponse(); + response.setTotal(searchTotal); + response.setResults(pagedResults); + response.setTypeCounts(typeCounts); + response.setKeyword(request.getKeyword()); + response.setPageNum(request.getPageNum()); + response.setPageSize(request.getPageSize()); + response.setSearchTime(System.currentTimeMillis() - startTime); + + // 7. 异步记录搜索日志 + recordSearchLog(request, response, loginUser); + + return response; + } + + /** + * 异步记录搜索日志 + */ + @Async + public void recordSearchLog(GlobalSearchRequest request, GlobalSearchResponse response, LoginUser loginUser) { + try { + logger.info("全局搜索 - 关键词: {}, 用户ID: {}, 耗时: {}ms, 结果数: {}, 搜索类型: {}, 专区ID: {}", + request.getKeyword(), + loginUser != null ? loginUser.getUserId() : null, + response.getSearchTime(), + response.getTotal(), + request.getTypes() != null ? String.join(",", request.getTypes()) : null, + request.getZoneId() + ); + } catch (Exception e) { + logger.error("记录搜索日志失败: {}", e.getMessage()); + } + } + + /** + * 搜索Zone项目 + */ + private GlobalSearchResultDataVo searchZoneProjects(GlobalSearchRequest request) { + GlobalSearchResultDataVo globalSearchResultDataVo = new GlobalSearchResultDataVo(); + List results = new ArrayList<>(); + Long total = 0L; + try { + if (StringUtils.isNotEmpty(gitLinkSearchUrl)) { + Long projectTypeId = null; + String topic = null; + if (request.getExtraSearchParam() != null) { + projectTypeId = request.getExtraSearchParam().getLong("projectTypeId"); + topic = request.getExtraSearchParam().getString("topic"); + } + List gitlinkProjectIds = zoneProjectMapper.selectZoneProjectGitlinkIdList(request.getZoneId(), projectTypeId); + + JSONObject searchRes = httpAPIService.doGet(request.toProjectEsSearchString(gitLinkSearchUrl, String.join(",", gitlinkProjectIds), topic)); + GitlinkSearchDataVo gitlinkSearchDataVos = gitlinkSearchResToGitlinkSearchDataVo(searchRes); + total = gitlinkSearchDataVos.getTotal(); + if (gitlinkSearchDataVos.getTotal() > 0) { + List gitlinkSearchVoList = gitlinkSearchDataVos.getGitlinkSearchVoList(); + List gitlinkProjectIdList = gitlinkSearchVoList.stream().map(GitlinkSearchVo::getInstanceId).collect(Collectors.toList()); + List zoneProjectList = zoneProjectMapper.selectZoneProjectListFromGitlinkProjectIdList(request.getZoneId(), gitlinkProjectIdList); + List projectDataVoList = projectService.toZoneProjectDataVoList(zoneProjectList); + for (GitlinkSearchVo gitlinkSearchVo : gitlinkSearchVoList) { + ZoneProjectDataVo zoneProjectDataVo = projectDataVoList.stream().filter(x -> x.getGitlinkProjectId().equals(gitlinkSearchVo.getInstanceId())).findFirst().orElse(null); + if (zoneProjectDataVo != null) { + GlobalSearchResult result = gitlinkSearchVo.toGlobalSearchResult(zoneProjectDataVo, topic); + results.add(result); + } + } + } + } else { + List projects = zoneProjectMapper.globalSearchWithScore( + request.getKeyword(), + request.getZoneId(), + (request.getPageNum() - 1) * request.getPageSize(), + request.getPageSize() + ); + total = zoneProjectMapper.globalSearchCount(request.getKeyword(), request.getZoneId()); + List zoneProjectList = projects.stream().map(x -> (ZoneProject) x).collect(Collectors.toList()); + List projectDataVoList = projectService.toZoneProjectDataVoList(zoneProjectList); + + for (ZoneProjectWithScore project : projects) { + ZoneProjectDataVo zoneProjectDataVo = projectDataVoList.stream().filter(x -> x.getId().equals(project.getId())).findFirst().orElse(null); + GlobalSearchResult result = project.toGlobalSearchResult(zoneProjectDataVo); + result.setTitle(SearchUtils.highlightKeyword(result.getTitle(), request.getKeyword())); + result.setContent(SearchUtils.highlightKeyword(result.getContent(), request.getKeyword())); + results.add(result); + } + } + } catch (Exception e) { + System.err.println("搜索Zone项目失败: " + e.getMessage()); + } + globalSearchResultDataVo.setTotal(total); + globalSearchResultDataVo.setGlobalSearchResultList(results); + return globalSearchResultDataVo; + } + + private GitlinkSearchDataVo gitlinkSearchResToGitlinkSearchDataVo(JSONObject gitlinkSearchRes) { + + GitlinkSearchDataVo gitlinkSearchDataVo = new GitlinkSearchDataVo(); + List results = new ArrayList<>(); + if (gitlinkSearchRes != null && gitlinkSearchRes.getJSONObject("data") != null) { + JSONObject data = gitlinkSearchRes.getJSONObject("data"); + if (data.getLong("total") == null || data.getLong("total") == 0) { + gitlinkSearchDataVo.setGitlinkSearchVoList(results); + return gitlinkSearchDataVo; + } + gitlinkSearchDataVo.setTotal(data.getLong("total")); + JSONArray rows = data.getJSONArray("rows"); + for (int i = 0; i < rows.size(); i++) { + JSONObject row = rows.getJSONObject(i); + results.add(row.toJavaObject(GitlinkSearchVo.class)); + } + gitlinkSearchDataVo.setGitlinkSearchVoList(results); + } + + return gitlinkSearchDataVo; + } + + /** + * 搜索Zone资源 + */ + private List searchResources(GlobalSearchRequest request) { + List results = new ArrayList<>(); + try { + List resources = zoneResourceMapper.globalSearchWithScore( + request.getKeyword(), + request.getZoneId(), + (request.getPageNum() - 1) * request.getPageSize(), + request.getPageSize() + ); + + for (ZoneResourceWithScore resource : resources) { + GlobalSearchResult result = new GlobalSearchResult(); + result.setType("resource"); + result.setId(resource.getId()); + result.setTitle(SearchUtils.highlightKeyword(resource.getName(), request.getKeyword())); + result.setContent(SearchUtils.highlightKeyword(resource.getSummary(), request.getKeyword())); + result.setDeptId(resource.getDeptId()); + result.setZoneId(resource.getZoneId()); + result.setCreateTime(resource.getCreateTime()); + + // 使用数据库返回的实际搜索评分 + Double score = resource.getSearchScore(); + if (score == null || score == 0.0) { + score = 0.1; // LIKE 匹配的最小评分 + } + result.setScore(score); + + // 查询并过滤匹配的附件 + if (StringUtils.isNotEmpty(resource.getFileIds())) { + try { + JSONObject extendData = new JSONObject(); + extendData.put("downloadCount", resource.getDownloadCount()); + if (resource.getFileIds() != null) { + String[] fileIds = resource.getFileIds().split(","); + extendData.put("fileCount", fileIds.length); + } + + + R> fileResponse = remoteFileService.getFileList(resource.getFileIds()); + if (fileResponse != null && fileResponse.getCode() == 200 && fileResponse.getData() != null) { + List matchedFiles = fileResponse.getData().stream() + .filter(file -> StringUtils.isNotEmpty(file.getFileOriginName()) + && file.getFileOriginName().toLowerCase().contains(request.getKeyword().toLowerCase())) + .map(file -> { + JSONObject fileInfo = new JSONObject(); + fileInfo.put("fileId", file.getFileId()); + fileInfo.put("fileName", SearchUtils.highlightKeyword(file.getFileOriginName(), request.getKeyword())); + fileInfo.put("fileSize", file.getFileSizeInfo()); + return fileInfo; + }) + .collect(Collectors.toList()); + + if (!matchedFiles.isEmpty()) { + + extendData.put("matchedFiles", matchedFiles); + + } + } + result.setExtendData(extendData); + } catch (Exception e) { + logger.warn("查询附件信息失败: resourceId={}, error={}", resource.getId(), e.getMessage()); + } + } + + results.add(result); + } + } catch (Exception e) { + logger.error("搜索Zone资源失败: {}", e.getMessage()); + } + return results; + } + + /** + * 搜索Zone会员 + */ + private List searchZoneMembers(GlobalSearchRequest request) { + List results = new ArrayList<>(); + try { + List members = zoneMemberMapper.globalSearchWithScore( + request.getKeyword(), + request.getZoneId(), + (request.getPageNum() - 1) * request.getPageSize(), + request.getPageSize() + ); + + for (ZoneMemberWithScore member : members) { + GlobalSearchResult result = new GlobalSearchResult(); + result.setType("member"); + result.setId(member.getId()); + result.setTitle(SearchUtils.highlightKeyword(member.getName(), request.getKeyword())); + + // 构建内容:用户名 + 会员介绍 + StringBuilder content = new StringBuilder(); + if (member.getSysUser() != null && StringUtils.isNotEmpty(member.getSysUser().getUserName())) { + content.append("用户名: ").append(member.getSysUser().getUserName()); + } + if (StringUtils.isNotEmpty(member.getIntroduction())) { + if (content.length() > 0) { + content.append(" | "); + } + content.append(member.getIntroduction()); + } + result.setContent(SearchUtils.highlightKeyword(content.toString(), request.getKeyword())); + + result.setDeptId(member.getDeptId()); + result.setZoneId(member.getZoneId()); + result.setCreateTime(member.getCreateTime()); + + // 使用数据库返回的实际搜索评分 + Double score = member.getSearchScore(); + if (score == null || score == 0.0) { + score = 0.1; // LIKE 匹配(包括用户名匹配)的最小评分 + } + result.setScore(score); + + // 添加扩展数据 + if (StringUtils.isNotEmpty(member.getImageUrl()) || member.getMemberLevelId() != null) { + try { + JSONObject extendData = new JSONObject(); + if (StringUtils.isNotEmpty(member.getImageUrl())) { + extendData.put("imageUrl", member.getImageUrl()); + } + if (StringUtils.isNotEmpty(member.getMemberTypeName())) { + extendData.put("memberTypeName", member.getMemberTypeName()); + } + if (member.getSysUser() != null) { + extendData.put("username", member.getSysUser().getUserName()); + } + + + result.setExtendData(extendData); + } catch (Exception e) { + logger.warn("构建会员扩展数据失败: memberId={}, error={}", member.getId(), e.getMessage()); + } + } + + results.add(result); + } + } catch (Exception e) { + logger.error("搜索Zone会员失败: {}", e.getMessage()); + } + return results; + } + + /** + * 构建缓存键 + */ + private String buildCacheKey(GlobalSearchRequest request) { + StringBuilder key = new StringBuilder(request.getKeyword()); + if (request.getTypes() != null && !request.getTypes().isEmpty()) { + key.append(":").append(String.join(",", request.getTypes())); + } + if (request.getZoneId() != null) { + key.append(":zone=").append(request.getZoneId()); + } + return key.toString(); + } + + /** + * 构建空响应 + */ + private GlobalSearchResponse buildEmptyResponse(GlobalSearchRequest request) { + GlobalSearchResponse response = new GlobalSearchResponse(); + response.setTotal(0L); + response.setResults(new ArrayList<>()); + response.setTypeCounts(new HashMap<>()); + response.setKeyword(request.getKeyword()); + response.setPageNum(request.getPageNum()); + response.setPageSize(request.getPageSize()); + response.setSearchTime(0L); + return response; + } +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/utils/SearchUtils.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/utils/SearchUtils.java new file mode 100644 index 000000000..ff06049e0 --- /dev/null +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/search/utils/SearchUtils.java @@ -0,0 +1,19 @@ +package com.microservices.zone.search.utils; + +import com.microservices.common.core.utils.StringUtils; + +import java.util.regex.Pattern; + +public class SearchUtils { + + + /** + * 将文本中的关键词用 标签包裹(不区分大小写) + */ + public static String highlightKeyword(String text, String keyword) { + if (StringUtils.isEmpty(text) || StringUtils.isEmpty(keyword)) { + return text; + } + return text.replaceAll("(?i)(" + Pattern.quote(keyword) + ")", "$1"); + } +} diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneConstants.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneConstants.java index 68fd32470..abecf2b09 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneConstants.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneConstants.java @@ -28,6 +28,10 @@ public class ZoneConstants { * GitLink响应总数Key */ public final static String GITLINK_RESPONSE_TOTAL_COUNT_KEY = "total_count"; + /** + * GitLink响应总数Key + */ + public final static String GITLINK_RESPONSE_COUNT_KEY = "count"; /** * GitLink项目列表Key */ @@ -66,6 +70,19 @@ public class ZoneConstants { * 资源审核状态-待审核 */ public final static String RESOURCE_NOT_AUDIT = "0"; + + /** + * 项目审核状态-审核通过 + */ + public final static String PROJECT_AUDIT_PASS = "1"; + /** + * 项目审核状态-审核未通过 + */ + public final static String PROJECT_AUDIT_FAILED = "2"; + /** + * 项目审核状态-待审核 + */ + public final static String PROJECT_NOT_AUDIT = "0"; /** * 资源审核状态-已下架 */ diff --git a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneGitLinkRequestUrl.java b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneGitLinkRequestUrl.java index 382aad989..bd65e46cb 100644 --- a/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneGitLinkRequestUrl.java +++ b/microservices-modules/microservices-modules-zone/src/main/java/com/microservices/zone/utils/ZoneGitLinkRequestUrl.java @@ -22,6 +22,13 @@ public class ZoneGitLinkRequestUrl extends GitLinkRequestUrl { return getOpenGitLinkRequestUrl(String.format("/api/projects.json%s", query)); } + /** + * 搜索项目列表 + */ + public static GitLinkRequestUrl MY_OWNER_PROJECTS(String username,String query) { + return getOpenGitLinkRequestUrl(String.format("/api/users/%s/projects.json%s",username, query)); + } + /** * 获取项目贡献者 diff --git a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneDetailMapper.xml b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneDetailMapper.xml index c7cddd80d..b53997f14 100644 --- a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneDetailMapper.xml +++ b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneDetailMapper.xml @@ -44,6 +44,7 @@ + @@ -101,6 +102,7 @@ template, is_lock_cms, resource_need_audit, + project_need_audit, doc_need_audit, section_cms_show, section_project_show, @@ -159,6 +161,7 @@ z.template, z.is_lock_cms, z.resource_need_audit, + z.project_need_audit, z.doc_need_audit, z.section_cms_show, z.section_project_show, @@ -273,6 +276,7 @@ helper_show, doc_need_audit, resource_need_audit, + project_need_audit, is_lock_cms, section_cms_show, section_project_show, @@ -327,6 +331,7 @@ #{helperShow}, #{docNeedAudit}, #{resourceNeedAudit}, + #{projectNeedAudit}, #{isLockCms}, #{sectionCmsShow}, #{sectionProjectShow}, @@ -390,6 +395,7 @@ helper_title = #{helperTitle}, doc_need_audit = #{docNeedAudit}, resource_need_audit = #{resourceNeedAudit}, + project_need_audit = #{projectNeedAudit}, is_lock_cms = #{isLockCms}, section_cms_show = #{sectionCmsShow}, section_project_show = #{sectionProjectShow}, diff --git a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneMemberMapper.xml b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneMemberMapper.xml index 891a864e7..0c37dcecf 100644 --- a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneMemberMapper.xml +++ b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneMemberMapper.xml @@ -61,6 +61,12 @@ + + + + + select zm.id, zm.user_id, @@ -109,6 +115,54 @@ left join zone_member_type zmt on zmt.id = zm.member_type_id + + select zm.id, + zm.user_id, + zm.name, + zm.image_url, + zm.introduction, + zm.member_type_id, + zm.member_level_id, + zm.is_audit, + zm.is_homepage, + zm.dept_id, + zm.del_flag, + zm.create_by, + zm.create_time, + zm.update_by, + zm.update_time, + zm.zone_id, + zm.sort, + zm.remark, + zm.audit_time, + zml.name as levelName, + zml.sort as levelSort, + zmt.name as typeName, + zmt.sort as typeSort, + u.user_id as userId, + u.gitlink_user_id, + u.user_name, + u.nick_name, + u.email, + u.avatar, + u.phonenumber, + u.sex, + u.status, + u.del_flag as userDelFlag, + d.dept_id as deptId, + d.parent_id, + d.ancestors, + d.dept_name, + d.order_num, + d.leader, + d.status as dept_status, + MATCH(zm.name) AGAINST(#{keyword} IN BOOLEAN MODE) AS search_score + from zone_member as zm + left join sys_dept d on zm.dept_id = d.dept_id + left join sys_user u on u.user_id = zm.user_id + left join zone_member_level zml on zml.id = zm.member_level_id + left join zone_member_type zmt on zmt.id = zm.member_type_id + select id, user_id, @@ -363,4 +417,32 @@ from zone_member where zone_id = #{zoneId} + + + + \ No newline at end of file diff --git a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectMapper.xml b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectMapper.xml index b735f8d6e..86e8c6705 100644 --- a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectMapper.xml +++ b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectMapper.xml @@ -19,6 +19,10 @@ + + + + + + + + select id, name, @@ -56,7 +65,11 @@ create_time, update_by, is_homepage, - update_time + update_time, + audit_status, + audit_time, + audit_by, + remark from zone_project @@ -75,6 +88,9 @@ zp.update_time, zp.project_type_id, zp.is_homepage, + zp.audit_status, + zp.audit_time, + zp.audit_by, d.dept_id, d.parent_id, d.ancestors, @@ -84,7 +100,8 @@ d.status as dept_status, zpt.id, zpt.name as type_name, - zpt.dept_id as type_dept_id + zpt.dept_id as type_dept_id, + zp.remark from zone_project as zp left join sys_dept as d on zp.dept_id = d.dept_id left join zone_project_type as zpt on zp.project_type_id = zpt.id @@ -114,6 +131,22 @@ and zp.project_type_id = #{projectTypeId} and zp.zone_id = #{zoneId} + and zp.create_by = #{createBy} + + + and zp.audit_status != '2' + + + + + and zp.audit_status = #{auditStatus} + + + and zp.audit_status = '1' + + + + and zp.is_homepage = #{isHomepage} @@ -132,6 +165,21 @@ and zp.name like concat('%', #{name}, '%') and zp.project_type_id = #{projectTypeId} and zp.zone_id = #{zoneId} + + + and zp.audit_status != '2' + + + + + and zp.audit_status = #{auditStatus} + + + and zp.audit_status = '1' + + + + ${params.dataScope} @@ -140,6 +188,7 @@ where zp.zone_id = #{zoneId} and zp.gitlink_project_id = #{gitlinkProjectId} + and zp.audit_status != '2' + SELECT + zp.id, zp.name, zp.sort, zp.full_name, zp.gitlink_project_id, + zp.dept_id, zp.zone_id, zp.del_flag, zp.create_by, zp.create_time, + zp.update_by, zp.update_time, zp.project_type_id, zp.is_homepage, + zp.audit_status, zp.audit_time, zp.audit_by, + MATCH(zp.name) AGAINST(#{keyword} IN BOOLEAN MODE) AS search_score + FROM zone_project zp + WHERE zp.zone_id = #{zoneId} + AND zp.audit_status = '1' + AND ( + MATCH(zp.name) AGAINST(#{keyword} IN BOOLEAN MODE) + OR zp.name LIKE CONCAT('%', #{keyword}, '%') + ) + ORDER BY search_score DESC, zp.update_time DESC + LIMIT #{offset}, #{pageSize} + + + + + \ No newline at end of file diff --git a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectTypeMapper.xml b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectTypeMapper.xml index e14cedfc0..83ef2fd4e 100644 --- a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectTypeMapper.xml +++ b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneProjectTypeMapper.xml @@ -15,12 +15,15 @@ + + select id, name, sort, + detail_json, dept_id, zone_id, del_flag, @@ -35,13 +38,15 @@ select zpt.id, zpt.name, zpt.sort, + zpt.detail_json, zpt.dept_id, zpt.zone_id, zpt.del_flag, zpt.create_by, zpt.create_time, zpt.update_by, - zpt.update_time + zpt.update_time, + (select count(1) from zone_project where project_type_id=zpt.id) as projectCount from zone_project_type as zpt @@ -124,6 +129,7 @@ dept_id, zone_id, sort, + detail_json, del_flag, create_by, create_time, @@ -135,6 +141,7 @@ #{deptId}, #{zoneId}, #{sort}, + #{detailJson}, #{delFlag}, #{createBy}, #{createTime}, @@ -150,6 +157,7 @@ dept_id = #{deptId}, zone_id = #{zoneId}, sort = #{sort}, + detail_json = #{detailJson}, del_flag = #{delFlag}, create_by = #{createBy}, create_time = #{createTime}, diff --git a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneResourceMapper.xml b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneResourceMapper.xml index 21ff8b529..f86defd8f 100644 --- a/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneResourceMapper.xml +++ b/microservices-modules/microservices-modules-zone/src/main/resources/mapper/zone/ZoneResourceMapper.xml @@ -42,6 +42,12 @@ + + + + + select id, name, @@ -325,6 +331,53 @@ where zone_id = #{zoneId} + + + + +