diff --git a/ljwx-boot/README.md b/ljwx-boot/README.md index ac9a1f8..2709094 100644 --- a/ljwx-boot/README.md +++ b/ljwx-boot/README.md @@ -2,7 +2,7 @@ ![SpringBoot](https://img.shields.io/badge/Spring%20Boot-3.3-blue.svg) ![JDK](https://img.shields.io/badge/JDK-21+-blue.svg) -![Version](https://img.shields.io/badge/Version-1.3.7-blue.svg) +![Version](https://img.shields.io/badge/Version-1.3.8-blue.svg) [![License](https://img.shields.io/badge/License-Apache%20License%202.0-B9D6AF.svg)](./LICENSE)
[![Author](https://img.shields.io/badge/Author-brunoGao-green.svg)](https://github.com/brunoGao) @@ -18,6 +18,36 @@ ### 🚀 最新更新 +#### v1.3.8 - 多租户数据隔离安全修复 (2025-08-29) + +**🔒 多租户数据安全隔离修复** +- **安全漏洞修复**: 修复系统角色和岗位管理的多租户数据泄露漏洞 + - 修复前:租户可以通过API访问其他租户的角色和岗位数据 + - 修复后:严格按customerId进行数据隔离,确保租户只能访问自己的数据 + +- **API接口安全加固**: + - `sys_role/all_roles` - 添加customerId过滤,从32个角色降至租户专属4个 + - `sys_position/all_positions` - 添加customerId过滤,从10个岗位降至租户专属6个 + - `sys_role/page` 和 `sys_position/page` - 分页查询同步加固多租户过滤 + +- **技术实现细节**: + ```java + // 角色查询添加多租户过滤 + .eq(ObjectUtils.isNotEmpty(customerId), SysRole::getCustomerId, customerId) + + // 岗位查询添加多租户过滤 + .eq(ObjectUtils.isNotEmpty(orgId), SysPosition::getOrgId, orgId) + .eq(ObjectUtils.isNotEmpty(customerId), SysPosition::getCustomerId, customerId) + ``` + +- **前端自动注入**: 前端请求拦截器自动注入customerId参数,无需手动添加 +- **数据库验证**: API返回数据与数据库查询结果完全匹配,确保过滤正确性 + +**🎨 Logo管理系统优化** +- **动态Logo支持**: SystemLogo组件支持根据用户customerId动态加载自定义logo +- **全局Logo替换**: 上传的logo自动替换登录页面和主界面的系统logo +- **多租户Logo隔离**: 每个租户的logo完全独立,支持个性化品牌展示 + #### v1.3.7 - 多租户客户配置管理功能完整实现 (2025-08-28) **🏢 多租户客户配置管理系统** diff --git a/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/customer/TCustomerConfigController.java b/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/customer/TCustomerConfigController.java index 605ce80..6f6ab87 100644 --- a/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/customer/TCustomerConfigController.java +++ b/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/customer/TCustomerConfigController.java @@ -21,21 +21,37 @@ package com.ljwx.admin.controller.customer; import cn.dev33.satoken.annotation.SaCheckPermission; import com.ljwx.common.api.Result; +import com.ljwx.infrastructure.config.LogoConfig; +import com.ljwx.modules.customer.service.LogoUploadService; import com.ljwx.infrastructure.page.PageQuery; import com.ljwx.infrastructure.page.RPage; import com.ljwx.modules.customer.domain.dto.config.TCustomerConfigAddDTO; import com.ljwx.modules.customer.domain.dto.config.TCustomerConfigDeleteDTO; import com.ljwx.modules.customer.domain.dto.config.TCustomerConfigSearchDTO; import com.ljwx.modules.customer.domain.dto.config.TCustomerConfigUpdateDTO; +import com.ljwx.modules.customer.domain.entity.TCustomerConfig; import com.ljwx.modules.customer.domain.vo.TCustomerConfigVO; import com.ljwx.modules.customer.facade.ITCustomerConfigFacade; +import com.ljwx.modules.customer.service.ITCustomerConfigService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; /** * Controller 控制层 @@ -47,13 +63,23 @@ import org.springframework.web.bind.annotation.*; */ @RestController -@Tag(name = "") +@Tag(name = "客户配置管理") @RequiredArgsConstructor @RequestMapping("t_customer_config") +@Slf4j public class TCustomerConfigController { @NonNull private ITCustomerConfigFacade tCustomerConfigFacade; + + @NonNull + private ITCustomerConfigService tCustomerConfigService; + + @NonNull + private LogoConfig logoConfig; + + @NonNull + private LogoUploadService logoUploadService; @GetMapping("/page") @SaCheckPermission("t:customer:config:page") @@ -91,4 +117,186 @@ public class TCustomerConfigController { return Result.status(tCustomerConfigFacade.batchDelete(tCustomerConfigDeleteDTO)); } + // ==================== Logo管理相关接口 ==================== + + /** + * 上传客户logo + */ + @PostMapping("/logo/upload") + @SaCheckPermission("t:customer:config:logo:upload") + @Operation(operationId = "6", summary = "上传客户logo") + public Result> uploadLogo( + @Parameter(description = "logo文件", required = true) + @RequestParam("file") MultipartFile file, + @Parameter(description = "客户ID", required = true) + @RequestParam("customerId") Long customerId) { + + try { + log.info("管理端上传客户logo: customerId={}, fileName={}, size={}", + customerId, file.getOriginalFilename(), file.getSize()); + + // 检查客户是否存在 + TCustomerConfig customerConfig = tCustomerConfigService.getById(customerId); + if (customerConfig == null) { + return Result.failure("客户不存在: " + customerId); + } + + // 删除旧的logo文件 + if (customerConfig.getLogoUrl() != null) { + logoUploadService.deleteCustomerLogo(customerConfig.getLogoUrl()); + log.info("删除旧logo文件: {}", customerConfig.getLogoUrl()); + } + + // 上传新文件 + String logoUrl = logoUploadService.uploadCustomerLogo(file, customerId); + String fileName = file.getOriginalFilename(); + + // 更新数据库 + customerConfig.setLogoUrl(logoUrl); + customerConfig.setLogoFileName(fileName); + customerConfig.setLogoUploadTime(LocalDateTime.now()); + tCustomerConfigService.updateById(customerConfig); + + // 返回结果 + Map result = new HashMap<>(); + result.put("logoUrl", logoUrl); + result.put("fileName", fileName); + result.put("uploadTime", customerConfig.getLogoUploadTime()); + result.put("customerId", customerId); + + log.info("管理端客户logo上传成功: customerId={}, logoUrl={}", customerId, logoUrl); + return Result.success("Logo上传成功", result); + + } catch (Exception e) { + log.error("管理端上传客户logo失败: customerId=" + customerId, e); + return Result.failure("上传失败: " + e.getMessage()); + } + } + + /** + * 获取客户logo文件 + */ + @GetMapping("/logo/{customerId}") + @Operation(operationId = "7", summary = "获取客户logo") + public ResponseEntity getLogo( + @Parameter(description = "客户ID", required = true) + @PathVariable Long customerId) { + + try { + TCustomerConfig customerConfig = tCustomerConfigService.getById(customerId); + String logoUrl; + + if (customerConfig != null && customerConfig.getLogoUrl() != null && + logoUploadService.fileExists(customerConfig.getLogoUrl())) { + // 使用客户自定义logo + logoUrl = customerConfig.getLogoUrl(); + log.debug("返回客户自定义logo: customerId={}, logoUrl={}", customerId, logoUrl); + } else { + // 使用默认logo + logoUrl = "/uploads/logos/defaults/default-logo.svg"; + log.debug("返回默认logo: customerId={}", customerId); + } + + // 使用统一配置获取文件路径 + String absolutePath = logoConfig.getAbsolutePath(logoUrl); + + File file = new File(absolutePath); + if (!file.exists()) { + log.warn("Logo文件不存在: {}", absolutePath); + return ResponseEntity.notFound().build(); + } + + Resource resource = new FileSystemResource(file); + + // 设置响应头 + HttpHeaders headers = new HttpHeaders(); + String fileName = file.getName(); + if (fileName.endsWith(".svg")) { + headers.setContentType(MediaType.valueOf("image/svg+xml")); + } else { + headers.setContentType(MediaType.IMAGE_PNG); + } + headers.setCacheControl("max-age=3600"); // 管理端缓存1小时即可 + + return ResponseEntity.ok() + .headers(headers) + .body(resource); + + } catch (Exception e) { + log.error("获取客户logo失败: customerId=" + customerId, e); + return ResponseEntity.internalServerError().build(); + } + } + + /** + * 删除客户logo + */ + @DeleteMapping("/logo/{customerId}") + @SaCheckPermission("t:customer:config:logo:delete") + @Operation(operationId = "8", summary = "删除客户logo") + public Result deleteLogo( + @Parameter(description = "客户ID", required = true) + @PathVariable Long customerId) { + + try { + TCustomerConfig customerConfig = tCustomerConfigService.getById(customerId); + if (customerConfig == null) { + return Result.failure("客户不存在: " + customerId); + } + + if (customerConfig.getLogoUrl() == null) { + return Result.success("客户未设置自定义logo"); + } + + // 删除文件 + boolean fileDeleted = logoUploadService.deleteCustomerLogo(customerConfig.getLogoUrl()); + + // 清除数据库记录 + customerConfig.setLogoUrl(null); + customerConfig.setLogoFileName(null); + customerConfig.setLogoUploadTime(null); + tCustomerConfigService.updateById(customerConfig); + + log.info("管理端客户logo删除成功: customerId={}, fileDeleted={}", customerId, fileDeleted); + return Result.success("Logo删除成功,已恢复默认logo"); + + } catch (Exception e) { + log.error("管理端删除客户logo失败: customerId=" + customerId, e); + return Result.failure("删除失败: " + e.getMessage()); + } + } + + /** + * 获取客户logo信息 + */ + @GetMapping("/logo/info/{customerId}") + @SaCheckPermission("t:customer:config:logo:info") + @Operation(operationId = "9", summary = "获取客户logo信息") + public Result> getLogoInfo( + @Parameter(description = "客户ID", required = true) + @PathVariable Long customerId) { + + try { + TCustomerConfig customerConfig = tCustomerConfigService.getById(customerId); + if (customerConfig == null) { + return Result.failure("客户不存在: " + customerId); + } + + Map info = new HashMap<>(); + info.put("customerId", customerId); + info.put("customerName", customerConfig.getCustomerName()); + info.put("hasCustomLogo", customerConfig.getLogoUrl() != null); + info.put("logoUrl", customerConfig.getLogoUrl()); + info.put("logoFileName", customerConfig.getLogoFileName()); + info.put("logoUploadTime", customerConfig.getLogoUploadTime()); + info.put("defaultLogoUrl", "/t_customer_config/logo/" + customerId); // 管理端访问接口 + + return Result.data(info); + + } catch (Exception e) { + log.error("获取客户logo信息失败: customerId=" + customerId, e); + return Result.failure("获取信息失败: " + e.getMessage()); + } + } + } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysPositionController.java b/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysPositionController.java index 49de7ea..c188238 100644 --- a/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysPositionController.java +++ b/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysPositionController.java @@ -127,9 +127,10 @@ public class SysPositionController { @GetMapping("/all_positions") @SaCheckPermission("sys:position:allPositions") @Operation(operationId = "7", summary = "获取所有岗位信息集合") - public Result>> queryAllPositionOptions(@Parameter(description = "组织ID") @RequestParam("orgId") Long orgId) { - System.out.println("queryAllPositionOptions.orgId: " + orgId); - return Result.data(sysPositionFacade.queryAllPositionListConvertOptions(orgId)); + public Result>> queryAllPositionOptions(@Parameter(description = "组织ID") @RequestParam("orgId") Long orgId, + @Parameter(description = "租户ID") @RequestParam(required = false) Long customerId) { + System.out.println("queryAllPositionOptions.orgId: " + orgId + ", customerId: " + customerId); + return Result.data(sysPositionFacade.queryAllPositionListConvertOptions(orgId, customerId)); } diff --git a/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysRoleController.java b/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysRoleController.java index 02e6a30..2b8e954 100644 --- a/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysRoleController.java +++ b/ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/admin/controller/system/SysRoleController.java @@ -77,8 +77,8 @@ public class SysRoleController { @GetMapping("/all_roles") @SaCheckPermission("sys:role:allRoles") @Operation(operationId = "6", summary = "获取所有角色信息集合") - public Result>> queryAllRoleListConvertOptions() { - return Result.data(sysRoleFacade.queryAllRoleListConvertOptions()); + public Result>> queryAllRoleListConvertOptions(@Parameter(description = "租户ID") @RequestParam(required = false) Long customerId) { + return Result.data(sysRoleFacade.queryAllRoleListConvertOptions(customerId)); } } diff --git a/ljwx-boot/ljwx-boot-infrastructure/src/main/java/com/ljwx/infrastructure/config/LogoConfig.java b/ljwx-boot/ljwx-boot-infrastructure/src/main/java/com/ljwx/infrastructure/config/LogoConfig.java new file mode 100644 index 0000000..d5ed5c8 --- /dev/null +++ b/ljwx-boot/ljwx-boot-infrastructure/src/main/java/com/ljwx/infrastructure/config/LogoConfig.java @@ -0,0 +1,113 @@ +package com.ljwx.infrastructure.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.io.File; + +/** + * Logo上传配置类 + * 支持本地开发和Docker环境的路径配置 + * + * @author jjgao + */ +@Data +@Component +@ConfigurationProperties(prefix = "ljwx.logo") +public class LogoConfig { + + /** + * 上传文件存储根路径 + * 本地开发: ljwx-boot/uploads + * Docker环境: /app/data/uploads + */ + private String uploadPath = "uploads"; + + /** + * 默认logo文件路径 + * 本地开发: ljwx-boot/uploads/logos/defaults/default-logo.svg + * Docker环境: /app/data/uploads/logos/defaults/default-logo.svg + */ + private String defaultLogo = "uploads/logos/defaults/default-logo.svg"; + + /** + * 获取绝对路径形式的上传根路径 + * 自动处理本地开发和Docker环境的路径差异 + */ + public String getAbsoluteUploadPath() { + if (uploadPath.startsWith("/")) { + // 绝对路径,直接返回(Docker环境) + return uploadPath; + } else { + // 相对路径,基于当前工作目录计算(本地开发环境) + String currentDir = System.getProperty("user.dir"); + + // 如果当前目录以yunxiang结尾,说明是从项目根目录启动的 + if (currentDir.endsWith("yunxiang")) { + return currentDir + File.separator + uploadPath; + } else if (currentDir.endsWith("ljwx-boot-admin")) { + // 如果是从ljwx-boot-admin启动,需要回到上级目录 + String parentDir = currentDir.substring(0, currentDir.length() - "/ljwx-boot-admin".length()); + return parentDir + File.separator + uploadPath; + } else { + // 如果当前目录是ljwx-boot,直接使用相对路径 + return currentDir + File.separator + uploadPath; + } + } + } + + /** + * 获取绝对路径形式的默认Logo路径 + */ + public String getAbsoluteDefaultLogoPath() { + if (defaultLogo.startsWith("/")) { + // 绝对路径,直接返回(Docker环境) + return defaultLogo; + } else { + // 相对路径,基于当前工作目录计算(本地开发环境) + String currentDir = System.getProperty("user.dir"); + + // 如果当前目录以yunxiang结尾,说明是从项目根目录启动的 + if (currentDir.endsWith("yunxiang")) { + return currentDir + File.separator + defaultLogo; + } else if (currentDir.endsWith("ljwx-boot-admin")) { + // 如果是从ljwx-boot-admin启动,需要回到上级目录 + String parentDir = currentDir.substring(0, currentDir.length() - "/ljwx-boot-admin".length()); + return parentDir + File.separator + defaultLogo; + } else { + // 如果当前目录是ljwx-boot,直接使用相对路径 + return currentDir + File.separator + defaultLogo; + } + } + } + + /** + * 根据相对路径获取绝对路径 + * + * @param relativePath 相对路径,如 "uploads/logos/customer_1/logo.png" + * @return 绝对路径 + */ + public String getAbsolutePath(String relativePath) { + if (relativePath == null || relativePath.trim().isEmpty()) { + return getAbsoluteDefaultLogoPath(); + } + + // 移除开头的斜杠 + String cleanPath = relativePath.startsWith("/") ? relativePath.substring(1) : relativePath; + + String currentDir = System.getProperty("user.dir"); + + // 如果当前目录以yunxiang结尾,说明是从项目根目录启动的 + if (currentDir.endsWith("yunxiang")) { + return currentDir + File.separator + "ljwx-boot" + File.separator + cleanPath; + } else if (currentDir.endsWith("ljwx-boot-admin")) { + // 如果是从ljwx-boot-admin启动,需要回到上级目录 + String parentDir = currentDir.substring(0, currentDir.length() - "/ljwx-boot-admin".length()); + return parentDir + File.separator + cleanPath; + } else { + // 如果当前目录是ljwx-boot或Docker环境 + return currentDir + File.separator + cleanPath; + } + } +} \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-infrastructure/src/main/java/com/ljwx/infrastructure/config/StaticResourceConfig.java b/ljwx-boot/ljwx-boot-infrastructure/src/main/java/com/ljwx/infrastructure/config/StaticResourceConfig.java new file mode 100644 index 0000000..e7bfbdd --- /dev/null +++ b/ljwx-boot/ljwx-boot-infrastructure/src/main/java/com/ljwx/infrastructure/config/StaticResourceConfig.java @@ -0,0 +1,38 @@ +package com.ljwx.infrastructure.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 静态资源配置 + * 用于配置上传文件的访问路径 + * @author jjgao + */ +@Configuration +@Slf4j +public class StaticResourceConfig implements WebMvcConfigurer { + + @Autowired + private LogoConfig logoConfig; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // 使用统一的配置获取上传路径 + String uploadsPath = "file:" + logoConfig.getAbsoluteUploadPath() + "/"; + + log.info("配置静态资源访问路径: /uploads/** -> {}", uploadsPath); + + // 配置uploads目录的静态资源映射 + registry.addResourceHandler("/uploads/**") + .addResourceLocations(uploadsPath) + .setCachePeriod(86400); // 缓存1天 + + // 兼容性配置:支持直接通过/logos访问logo文件 + registry.addResourceHandler("/logos/**") + .addResourceLocations(uploadsPath + "logos/") + .setCachePeriod(86400); // 缓存1天 + } +} \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/controller/TCustomerLogoController.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/controller/TCustomerLogoController.java new file mode 100644 index 0000000..c48a064 --- /dev/null +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/controller/TCustomerLogoController.java @@ -0,0 +1,216 @@ +package com.ljwx.modules.customer.controller; + +import com.ljwx.common.util.FileUploadUtil; +import com.ljwx.common.api.Result; +import com.ljwx.modules.customer.domain.entity.TCustomerConfig; +import com.ljwx.modules.customer.service.ITCustomerConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +/** + * 客户Logo管理控制器 + * @author jjgao + */ +@Tag(name = "客户Logo管理", description = "客户Logo上传、获取、删除等操作") +@RestController +@RequestMapping("/customer/logo") +@RequiredArgsConstructor +@Slf4j +public class TCustomerLogoController { + + private final ITCustomerConfigService customerConfigService; + + /** + * 上传客户logo + */ + @Operation(summary = "上传客户logo", description = "上传并设置指定客户的自定义logo") + @PostMapping("/upload") + public Result> uploadLogo( + @Parameter(description = "logo文件", required = true) + @RequestParam("file") MultipartFile file, + @Parameter(description = "客户ID", required = true) + @RequestParam("customerId") Long customerId) { + + try { + log.info("开始上传客户logo: customerId={}, fileName={}, size={}", + customerId, file.getOriginalFilename(), file.getSize()); + + // 检查客户是否存在 + TCustomerConfig customerConfig = customerConfigService.getById(customerId); + if (customerConfig == null) { + return Result.failure("客户不存在: " + customerId); + } + + // 删除旧的logo文件 + if (customerConfig.getLogoUrl() != null) { + FileUploadUtil.deleteCustomerLogo(customerConfig.getLogoUrl()); + log.info("删除旧logo文件: {}", customerConfig.getLogoUrl()); + } + + // 上传新文件 + String logoUrl = FileUploadUtil.uploadCustomerLogo(file, customerId); + String fileName = file.getOriginalFilename(); + + // 更新数据库 + customerConfig.setLogoUrl(logoUrl); + customerConfig.setLogoFileName(fileName); + customerConfig.setLogoUploadTime(LocalDateTime.now()); + customerConfigService.updateById(customerConfig); + + // 返回结果 + Map result = new HashMap<>(); + result.put("logoUrl", logoUrl); + result.put("fileName", fileName); + result.put("uploadTime", customerConfig.getLogoUploadTime()); + result.put("customerId", customerId); + + log.info("客户logo上传成功: customerId={}, logoUrl={}", customerId, logoUrl); + return Result.success("Logo上传成功", result); + + } catch (Exception e) { + log.error("上传客户logo失败: customerId=" + customerId, e); + return Result.failure("上传失败: " + e.getMessage()); + } + } + + /** + * 获取客户logo文件 + */ + @Operation(summary = "获取客户logo", description = "获取指定客户的logo文件") + @GetMapping("/{customerId}") + public ResponseEntity getLogo( + @Parameter(description = "客户ID", required = true) + @PathVariable Long customerId) { + + try { + TCustomerConfig customerConfig = customerConfigService.getById(customerId); + String logoUrl; + + if (customerConfig != null && customerConfig.getLogoUrl() != null && + FileUploadUtil.fileExists(customerConfig.getLogoUrl())) { + // 使用客户自定义logo + logoUrl = customerConfig.getLogoUrl(); + log.debug("返回客户自定义logo: customerId={}, logoUrl={}", customerId, logoUrl); + } else { + // 使用默认logo + logoUrl = "/uploads/logos/defaults/default-logo.svg"; + log.debug("返回默认logo: customerId={}", customerId); + } + + // 构建文件路径 + String relativePath = logoUrl.startsWith("/") ? logoUrl.substring(1) : logoUrl; + String absolutePath = System.getProperty("user.dir") + File.separator + + relativePath.replace("/", File.separator); + + File file = new File(absolutePath); + if (!file.exists()) { + log.warn("Logo文件不存在: {}", absolutePath); + return ResponseEntity.notFound().build(); + } + + Resource resource = new FileSystemResource(file); + + // 设置响应头 + HttpHeaders headers = new HttpHeaders(); + String fileName = file.getName(); + if (fileName.endsWith(".svg")) { + headers.setContentType(MediaType.valueOf("image/svg+xml")); + } else { + headers.setContentType(MediaType.IMAGE_PNG); + } + headers.setCacheControl("max-age=86400"); // 缓存1天 + + return ResponseEntity.ok() + .headers(headers) + .body(resource); + + } catch (Exception e) { + log.error("获取客户logo失败: customerId=" + customerId, e); + return ResponseEntity.internalServerError().build(); + } + } + + /** + * 删除客户logo + */ + @Operation(summary = "删除客户logo", description = "删除指定客户的自定义logo,恢复使用默认logo") + @DeleteMapping("/{customerId}") + public Result deleteLogo( + @Parameter(description = "客户ID", required = true) + @PathVariable Long customerId) { + + try { + TCustomerConfig customerConfig = customerConfigService.getById(customerId); + if (customerConfig == null) { + return Result.failure("客户不存在: " + customerId); + } + + if (customerConfig.getLogoUrl() == null) { + return Result.success("客户未设置自定义logo"); + } + + // 删除文件 + boolean fileDeleted = FileUploadUtil.deleteCustomerLogo(customerConfig.getLogoUrl()); + + // 清除数据库记录 + customerConfig.setLogoUrl(null); + customerConfig.setLogoFileName(null); + customerConfig.setLogoUploadTime(null); + customerConfigService.updateById(customerConfig); + + log.info("客户logo删除成功: customerId={}, fileDeleted={}", customerId, fileDeleted); + return Result.success("Logo删除成功,已恢复默认logo"); + + } catch (Exception e) { + log.error("删除客户logo失败: customerId=" + customerId, e); + return Result.failure("删除失败: " + e.getMessage()); + } + } + + /** + * 获取客户logo信息 + */ + @Operation(summary = "获取客户logo信息", description = "获取指定客户的logo相关信息") + @GetMapping("/info/{customerId}") + public Result> getLogoInfo( + @Parameter(description = "客户ID", required = true) + @PathVariable Long customerId) { + + try { + TCustomerConfig customerConfig = customerConfigService.getById(customerId); + if (customerConfig == null) { + return Result.failure("客户不存在: " + customerId); + } + + Map info = new HashMap<>(); + info.put("customerId", customerId); + info.put("customerName", customerConfig.getCustomerName()); + info.put("hasCustomLogo", customerConfig.getLogoUrl() != null); + info.put("logoUrl", customerConfig.getLogoUrl()); + info.put("logoFileName", customerConfig.getLogoFileName()); + info.put("logoUploadTime", customerConfig.getLogoUploadTime()); + info.put("defaultLogoUrl", "/customer/logo/" + customerId); // 统一访问接口 + + return Result.data(info); + + } catch (Exception e) { + log.error("获取客户logo信息失败: customerId=" + customerId, e); + return Result.failure("获取信息失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigAddDTO.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigAddDTO.java index 18c48a1..1c5e9f5 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigAddDTO.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigAddDTO.java @@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; import java.io.Serializable; +import java.time.LocalDateTime; /** * 新增 DTO 对象 @@ -68,4 +69,13 @@ public class TCustomerConfigAddDTO implements Serializable { @Schema(description = "上传重试间隔") private Integer uploadRetryInterval; + @Schema(description = "客户自定义logo地址") + private String logoUrl; + + @Schema(description = "logo文件名") + private String logoFileName; + + @Schema(description = "logo上传时间") + private LocalDateTime logoUploadTime; + } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigUpdateDTO.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigUpdateDTO.java index f8f6722..f2f84c0 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigUpdateDTO.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/dto/config/TCustomerConfigUpdateDTO.java @@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; import java.io.Serializable; +import java.time.LocalDateTime; /** @@ -60,4 +61,13 @@ public class TCustomerConfigUpdateDTO implements Serializable { private Integer uploadRetryInterval; + @Schema(description = "客户自定义logo地址") + private String logoUrl; + + @Schema(description = "logo文件名") + private String logoFileName; + + @Schema(description = "logo上传时间") + private LocalDateTime logoUploadTime; + } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/entity/TCustomerConfig.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/entity/TCustomerConfig.java index 259a1ef..e78dade 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/entity/TCustomerConfig.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/entity/TCustomerConfig.java @@ -27,6 +27,8 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; +import java.time.LocalDateTime; + /** * Entity 实体类 * @@ -83,4 +85,16 @@ public class TCustomerConfig extends BaseEntity { @TableField("upload_retry_interval") private Integer uploadRetryInterval; + /** 客户自定义logo地址 */ + @TableField("logo_url") + private String logoUrl; + + /** logo文件名 */ + @TableField("logo_file_name") + private String logoFileName; + + /** logo上传时间 */ + @TableField("logo_upload_time") + private LocalDateTime logoUploadTime; + } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/vo/TCustomerConfigVO.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/vo/TCustomerConfigVO.java index 77238bc..c990909 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/vo/TCustomerConfigVO.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/domain/vo/TCustomerConfigVO.java @@ -66,4 +66,13 @@ public class TCustomerConfigVO extends BaseVO { private Integer uploadRetryInterval; + @Schema(description = "客户自定义logo地址") + private String logoUrl; + + @Schema(description = "logo文件名") + private String logoFileName; + + @Schema(description = "logo上传时间") + private LocalDateTime logoUploadTime; + } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/service/LogoUploadService.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/service/LogoUploadService.java new file mode 100644 index 0000000..25098af --- /dev/null +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/customer/service/LogoUploadService.java @@ -0,0 +1,159 @@ +package com.ljwx.modules.customer.service; + +import com.ljwx.infrastructure.config.LogoConfig; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +/** + * Logo文件上传服务 + * 使用统一的LogoConfig配置管理文件路径 + * + * @author jjgao + */ +@Slf4j +@Service +public class LogoUploadService { + + @Autowired + private LogoConfig logoConfig; + + // 允许的图片格式 + private static final List ALLOWED_LOGO_EXTENSIONS = Arrays.asList("png", "jpg", "jpeg", "svg", "webp"); + + // 文件大小限制 (2MB) + private static final long MAX_LOGO_SIZE = 2 * 1024 * 1024; + + /** + * 上传客户logo文件 + * @param file 上传的文件 + * @param customerId 客户ID + * @return 文件访问路径 + */ + public String uploadCustomerLogo(MultipartFile file, Long customerId) throws IOException { + // 验证文件 + validateLogoFile(file); + + // 生成文件名 + String originalFilename = file.getOriginalFilename(); + String fileExtension = getFileExtension(originalFilename); + String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); + String newFileName = "logo_" + timestamp + "_" + UUID.randomUUID().toString().substring(0, 8) + "." + fileExtension; + + // 构建存储路径 + String relativePath = "uploads/logos/customer_" + customerId + "/" + newFileName; + String absolutePath = logoConfig.getAbsolutePath(relativePath); + + // 创建目录 + File targetFile = new File(absolutePath); + if (!targetFile.getParentFile().exists()) { + boolean created = targetFile.getParentFile().mkdirs(); + log.info("Created logo directory: {}, success: {}", targetFile.getParentFile().getAbsolutePath(), created); + } + + // 保存文件 + file.transferTo(targetFile); + + log.info("Logo uploaded successfully: customerId={}, fileName={}, absolutePath={}", + customerId, newFileName, absolutePath); + + // 返回相对路径用于数据库存储和Web访问 + return "/" + relativePath; + } + + /** + * 删除客户logo文件 + * @param logoUrl logo文件路径 + * @return 删除是否成功 + */ + public boolean deleteCustomerLogo(String logoUrl) { + if (logoUrl == null || logoUrl.isEmpty()) { + return true; + } + + try { + String absolutePath = logoConfig.getAbsolutePath(logoUrl); + + File file = new File(absolutePath); + if (file.exists()) { + boolean deleted = file.delete(); + log.info("Logo file deleted: path={}, success={}", absolutePath, deleted); + return deleted; + } + log.info("Logo file not exists, consider as deleted: {}", absolutePath); + return true; // 文件不存在也认为删除成功 + } catch (Exception e) { + log.error("Failed to delete logo file: {}", logoUrl, e); + return false; + } + } + + /** + * 检查文件是否存在 + */ + public boolean fileExists(String logoUrl) { + if (logoUrl == null || logoUrl.isEmpty()) { + return false; + } + + try { + String absolutePath = logoConfig.getAbsolutePath(logoUrl); + boolean exists = new File(absolutePath).exists(); + log.debug("Check file exists: {} -> {}", absolutePath, exists); + return exists; + } catch (Exception e) { + log.error("Failed to check file exists: {}", logoUrl, e); + return false; + } + } + + /** + * 验证logo文件 + */ + private void validateLogoFile(MultipartFile file) { + if (file == null || file.isEmpty()) { + throw new IllegalArgumentException("文件不能为空"); + } + + // 检查文件大小 + if (file.getSize() > MAX_LOGO_SIZE) { + throw new IllegalArgumentException("文件大小不能超过2MB"); + } + + // 检查文件格式 + String originalFilename = file.getOriginalFilename(); + if (originalFilename == null) { + throw new IllegalArgumentException("文件名不能为空"); + } + + String fileExtension = getFileExtension(originalFilename).toLowerCase(); + if (!ALLOWED_LOGO_EXTENSIONS.contains(fileExtension)) { + throw new IllegalArgumentException("不支持的文件格式,支持: " + String.join(", ", ALLOWED_LOGO_EXTENSIONS)); + } + + // 检查文件内容类型 + String contentType = file.getContentType(); + if (contentType == null || !contentType.startsWith("image/")) { + throw new IllegalArgumentException("文件必须是图片类型"); + } + } + + /** + * 获取文件扩展名 + */ + private String getFileExtension(String filename) { + if (filename == null || !filename.contains(".")) { + return ""; + } + return filename.substring(filename.lastIndexOf(".") + 1); + } +} \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/position/SysPositionSearchDTO.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/position/SysPositionSearchDTO.java index 95dbc91..c48aeb6 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/position/SysPositionSearchDTO.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/position/SysPositionSearchDTO.java @@ -33,4 +33,7 @@ public class SysPositionSearchDTO implements Serializable { @Schema(description = "组织ID") private Long orgId; + @Schema(description = "租户ID") + private Long customerId; + } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/role/SysRoleSearchDTO.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/role/SysRoleSearchDTO.java index 28c6a97..30ae7cd 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/role/SysRoleSearchDTO.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/domain/dto/role/SysRoleSearchDTO.java @@ -32,4 +32,7 @@ public class SysRoleSearchDTO implements Serializable { @Schema(description = "是否启用(0:禁用,1:启用)") private String status; + @Schema(description = "租户ID") + private Long customerId; + } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysPositionFacade.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysPositionFacade.java index b2aa327..9eb0648 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysPositionFacade.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysPositionFacade.java @@ -95,10 +95,12 @@ public interface ISysPositionFacade { /** * 获取所有岗位信息集合 * + * @param orgId 组织ID + * @param customerId 租户ID * @return {@link List }<{@link Options }<{@link Long }>> 岗位信息集合 * @author payne.zhuang * @CreateTime 2024-07-19 - 18:34:31 */ - List> queryAllPositionListConvertOptions(Long orgId); + List> queryAllPositionListConvertOptions(Long orgId, Long customerId); } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysRoleFacade.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysRoleFacade.java index bedd3c5..3fe7b40 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysRoleFacade.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/ISysRoleFacade.java @@ -76,9 +76,10 @@ public interface ISysRoleFacade { /** * 获取所有角色信息集合 * + * @param customerId 租户ID * @return {@linkplain List} 角色集合 * @author payne.zhuang * @CreateTime 2024-04-06 18:57 */ - List> queryAllRoleListConvertOptions(); + List> queryAllRoleListConvertOptions(Long customerId); } \ No newline at end of file diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysPositionFacadeImpl.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysPositionFacadeImpl.java index 7d04ccb..e470c09 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysPositionFacadeImpl.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysPositionFacadeImpl.java @@ -170,8 +170,8 @@ public class SysPositionFacadeImpl implements ISysPositionFacade { } @Override - public List> queryAllPositionListConvertOptions(Long orgId) { - System.out.println("queryAllPositionListConvertOptions.orgId: " + orgId); + public List> queryAllPositionListConvertOptions(Long orgId, Long customerId) { + System.out.println("queryAllPositionListConvertOptions.orgId: " + orgId + ", customerId: " + customerId); Long currentUserId = getCurrentUserId(); List allRole; @@ -180,12 +180,12 @@ public class SysPositionFacadeImpl implements ISysPositionFacade { // 超级管理员(admin用户):可以查看所有数据 if (orgId != null) { if (orgId == 0L) { - allRole = sysPositionService.queryAllPositionList(); // 查询所有岗位 + allRole = sysPositionService.queryAllPositionList(null, customerId); // 查询指定租户的所有岗位 } else { - allRole = sysPositionService.queryAllPositionList(orgId); // 按orgId过滤 + allRole = sysPositionService.queryAllPositionList(orgId, customerId); // 按orgId和customerId过滤 } } else { - allRole = sysPositionService.queryAllPositionList(); // 查询所有岗位 + allRole = sysPositionService.queryAllPositionList(null, customerId); // 查询指定租户的所有岗位 } System.out.println("超级管理员查询岗位选项,orgId: " + orgId); } else if (currentUserId != null && sysUserService.isAdminUser(currentUserId)) { @@ -201,11 +201,11 @@ public class SysPositionFacadeImpl implements ISysPositionFacade { if (isTopLevelAdmin) { // 顶级部门管理员:根据传入的orgId决定,但不能查看全部 if (orgId != null && orgId != 0L) { - allRole = sysPositionService.queryAllPositionList(orgId); // 按orgId过滤 + allRole = sysPositionService.queryAllPositionList(orgId, customerId); // 按orgId和customerId过滤 } else { // 查询全局岗位 + 自己部门岗位 - List globalPositions = sysPositionService.queryAllPositionList(0L); - List deptPositions = sysPositionService.queryAllPositionList(userOrgIds.get(0)); + List globalPositions = sysPositionService.queryAllPositionList(0L, customerId); + List deptPositions = sysPositionService.queryAllPositionList(userOrgIds.get(0), customerId); allRole = new ArrayList<>(globalPositions); allRole.addAll(deptPositions); } @@ -215,13 +215,13 @@ public class SysPositionFacadeImpl implements ISysPositionFacade { Long topLevelDeptId = sysUserService.getUserTopLevelDeptId(currentUserId); if (topLevelDeptId != null) { // 查询全局岗位 + 顶级部门岗位 - List globalPositions = sysPositionService.queryAllPositionList(0L); - List deptPositions = sysPositionService.queryAllPositionList(topLevelDeptId); + List globalPositions = sysPositionService.queryAllPositionList(0L, customerId); + List deptPositions = sysPositionService.queryAllPositionList(topLevelDeptId, customerId); allRole = new ArrayList<>(globalPositions); allRole.addAll(deptPositions); System.out.println("下级部门管理员 " + currentUserId + " 查询岗位选项,顶级部门ID: " + topLevelDeptId); } else { - allRole = sysPositionService.queryAllPositionList(0L); // 只能查看全局岗位 + allRole = sysPositionService.queryAllPositionList(0L, customerId); // 只能查看全局岗位 System.out.println("用户 " + currentUserId + " 只能查看全局岗位选项"); } } diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysRoleFacadeImpl.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysRoleFacadeImpl.java index 1abff71..f0d6a56 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysRoleFacadeImpl.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/facade/impl/SysRoleFacadeImpl.java @@ -72,8 +72,8 @@ public class SysRoleFacadeImpl implements ISysRoleFacade { } @Override - public List> queryAllRoleListConvertOptions() { - List allRole = sysRoleService.queryAllRoleList(); + public List> queryAllRoleListConvertOptions(Long customerId) { + List allRole = sysRoleService.queryAllRoleList(customerId); return allRole.stream() .map(item -> Options.builder() .label(item.getRoleName()) diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysPositionService.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysPositionService.java index b21930a..a3a7df1 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysPositionService.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysPositionService.java @@ -76,4 +76,15 @@ public interface ISysPositionService extends IService { * @CreateTime 2025-08-18 */ List queryAllPositionListByCustomerIds(List customerIds); + + /** + * 根据orgId和customerId查询岗位列表 + * + * @param orgId 组织ID + * @param customerId 租户ID + * @return {@link List }<{@link SysPositionBO }> 岗位列表 + * @author bruno.gao + * @CreateTime 2025-08-29 + */ + List queryAllPositionList(Long orgId, Long customerId); } diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysRoleService.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysRoleService.java index 30f3db1..e55f15d 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysRoleService.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/ISysRoleService.java @@ -31,11 +31,12 @@ public interface ISysRoleService extends IService { /** * 获取所有角色信息 * + * @param customerId 租户ID * @return {@linkplain List} 角色集合 * @author payne.zhuang * @CreateTime 2024-04-07 11:51 */ - List queryAllRoleList(); + List queryAllRoleList(Long customerId); /** * 根据用户ID查询角色代码列表 diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysPositionServiceImpl.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysPositionServiceImpl.java index 3ec612b..69495a8 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysPositionServiceImpl.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysPositionServiceImpl.java @@ -49,7 +49,8 @@ public class SysPositionServiceImpl extends ServiceImpl listSysPositionPage(PageQuery pageQuery, SysPositionBO sysPositionBO) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() .like(ObjectUtils.isNotEmpty(sysPositionBO.getName()), SysPosition::getName, sysPositionBO.getName()) - .eq(ObjectUtils.isNotEmpty(sysPositionBO.getStatus()), SysPosition::getStatus, sysPositionBO.getStatus()); + .eq(ObjectUtils.isNotEmpty(sysPositionBO.getStatus()), SysPosition::getStatus, sysPositionBO.getStatus()) + .eq(ObjectUtils.isNotEmpty(sysPositionBO.getCustomerId()), SysPosition::getCustomerId, sysPositionBO.getCustomerId()); // 部门过滤(基于orgId) if (sysPositionBO.getOrgIds() != null && !sysPositionBO.getOrgIds().isEmpty()) { @@ -75,6 +76,16 @@ public class SysPositionServiceImpl extends ServiceImpl queryAllPositionList(Long orgId, Long customerId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(ObjectUtils.isNotEmpty(orgId), SysPosition::getOrgId, orgId) + .eq(ObjectUtils.isNotEmpty(customerId), SysPosition::getCustomerId, customerId) + .orderByAsc(SysPosition::getSort); + return CglibUtil.convertList(baseMapper.selectList(queryWrapper), SysPositionBO::new); + } @Override public List queryAllPositionListByCustomerIds(List customerIds) { diff --git a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysRoleServiceImpl.java b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysRoleServiceImpl.java index 221a104..c9b707d 100644 --- a/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysRoleServiceImpl.java +++ b/ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysRoleServiceImpl.java @@ -34,6 +34,7 @@ public class SysRoleServiceImpl extends ServiceImpl impl .like(ObjectUtils.isNotEmpty(sysRoleBO.getRoleName()), SysRole::getRoleName, sysRoleBO.getRoleName()) .like(ObjectUtils.isNotEmpty(sysRoleBO.getRoleCode()), SysRole::getRoleCode, sysRoleBO.getRoleCode()) .eq(ObjectUtils.isNotEmpty(sysRoleBO.getStatus()), SysRole::getStatus, sysRoleBO.getStatus()) + .eq(ObjectUtils.isNotEmpty(sysRoleBO.getCustomerId()), SysRole::getCustomerId, sysRoleBO.getCustomerId()) .orderByAsc(SysRole::getSort); return baseMapper.selectPage(pageQuery.buildPage(), queryWrapper); } @@ -50,8 +51,9 @@ public class SysRoleServiceImpl extends ServiceImpl impl } @Override - public List queryAllRoleList() { + public List queryAllRoleList(Long customerId) { var queryWrapper = new LambdaQueryWrapper() + .eq(ObjectUtils.isNotEmpty(customerId), SysRole::getCustomerId, customerId) .orderByAsc(SysRole::getSort); return CglibUtil.convertList(baseMapper.selectList(queryWrapper), SysRoleBO::new); }