diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCandidateMaterialService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCandidateMaterialService.java index f52cbd4c..b6f11ac0 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCandidateMaterialService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCandidateMaterialService.java @@ -1,7 +1,7 @@ package org.dromara.aihr.service; import lombok.RequiredArgsConstructor; -import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.common.core.exception.ServiceException; import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.service.ISysOssService; @@ -192,7 +192,7 @@ public class AihrCandidateMaterialService { } private String tenantId() { - String tenantId = LoginHelper.getTenantId(); + String tenantId = TenantHelper.getTenantId(); return clean(tenantId, TENANT_ID); } diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java index 6d85f7db..a46f6f0a 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.aihr.domain.AihrCaseDto.CurateRequest; import org.dromara.aihr.domain.AihrCaseDto.CurateResponse; import org.dromara.aihr.domain.AihrCaseDto.DetailResponse; @@ -300,7 +301,7 @@ public class AihrCaseService { } private String tenantId() { - return firstNonBlank(LoginHelper.getTenantId(), "000000"); + return firstNonBlank(TenantHelper.getTenantId(), "000000"); } private Optional organizeWithModel(CaseState state) { diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrDashboardService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrDashboardService.java index a6908648..e3113de4 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrDashboardService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrDashboardService.java @@ -9,7 +9,7 @@ import org.dromara.aihr.domain.AihrDashboardDto.PipelineSummaryResponse; import org.dromara.aihr.domain.AihrDashboardDto.RiskResponse; import org.dromara.aihr.domain.AihrDashboardDto.StageResponse; import org.dromara.aihr.domain.AihrDashboardDto.TrainingRecordResponse; -import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.beans.factory.annotation.Value; @@ -253,7 +253,7 @@ public class AihrDashboardService { } private String tenantId() { - String tenantId = LoginHelper.getTenantId(); + String tenantId = TenantHelper.getTenantId(); return tenantId == null || tenantId.isBlank() ? TENANT_ID : tenantId; } diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java index 06fc9acc..78a85836 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.aihr.domain.AihrInterviewDto.AnswerRequest; import org.dromara.aihr.domain.AihrInterviewDto.AnswerResponse; import org.dromara.aihr.domain.AihrInterviewDto.CandidateLinkRequest; @@ -310,7 +310,7 @@ public class AihrInterviewService { } private String tenantId() { - return firstNonBlank(LoginHelper.getTenantId(), "000000"); + return firstNonBlank(TenantHelper.getTenantId(), "000000"); } private void saveResult(String sessionId, InterviewSession session, ScoreResult score) { diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrOrgSyncService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrOrgSyncService.java index d95a54e2..bb7ea317 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrOrgSyncService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrOrgSyncService.java @@ -9,7 +9,7 @@ import org.dromara.aihr.domain.AihrOrgSyncDto.OrgProjectOption; import org.dromara.aihr.domain.AihrOrgSyncDto.OrgSnapshotResponse; import org.dromara.aihr.domain.AihrOrgSyncDto.SyncRequest; import org.dromara.aihr.domain.AihrOrgSyncDto.SyncResponse; -import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -763,7 +763,7 @@ public class AihrOrgSyncService { } private String tenantId() { - String tenantId = LoginHelper.getTenantId(); + String tenantId = TenantHelper.getTenantId(); return clean(tenantId).isBlank() ? TENANT_ID : tenantId.trim(); } } diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java index e689d0b9..b8afaa4c 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java @@ -47,7 +47,7 @@ import org.dromara.aihr.domain.AihrPracticeDto.TeamMemberResponse; import org.dromara.aihr.service.AihrPracticeLlmService.PracticeTurn; import org.dromara.aihr.service.AihrPracticeLlmService.DailyDrillAssessment; import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.tenant.helper.TenantHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataAccessException; @@ -3957,7 +3957,7 @@ public class AihrPracticeSeedService { } private String tenantId() { - return firstNonBlank(LoginHelper.getTenantId(), TENANT_ID); + return firstNonBlank(TenantHelper.getTenantId(), TENANT_ID); } private String firstNonBlank(String first, String second) { diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrTenantContextContractTest.java b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrTenantContextContractTest.java new file mode 100644 index 00000000..6f6d3c50 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrTenantContextContractTest.java @@ -0,0 +1,36 @@ +package org.dromara.aihr.service; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@Tag("dev") +class AihrTenantContextContractTest { + + @Test + void businessServicesUseDynamicTenantContext() throws Exception { + Path moduleRoot = Path.of("src/main/java/org/dromara/aihr/service"); + if (!Files.exists(moduleRoot)) { + moduleRoot = Path.of("ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service"); + } + + for (String service : List.of( + "AihrCandidateMaterialService.java", + "AihrCaseService.java", + "AihrDashboardService.java", + "AihrInterviewService.java", + "AihrOrgSyncService.java", + "AihrPracticeSeedService.java" + )) { + String source = Files.readString(moduleRoot.resolve(service)); + assertTrue(source.contains("TenantHelper.getTenantId()"), service); + assertFalse(source.contains("LoginHelper.getTenantId()"), service); + } + } +} diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md index f2163343..750a45de 100644 --- a/docs/BRD_IMPLEMENTATION_AUDIT.md +++ b/docs/BRD_IMPLEMENTATION_AUDIT.md @@ -2,6 +2,7 @@ 更新时间:2026-07-14 +- 2026-07-14 BRD G3 多租户动态上下文修复:候选资料、案例、仪表盘、面试、组织同步和陪练服务此前从 `LoginHelper` 读取租户,后台 `TenantHelper.dynamic(...)` 场景可能回退到 `000000`;现统一改用 `TenantHelper.getTenantId()`,保留案例服务的 `LoginHelper` 仅用于当前操作人身份,并新增源码契约测试与 `demo-check` marker。未修改业务数据;正式多租户环境仍需跨租户 HTTP 回归。 - 2026-07-14 Figma/BRD 对账口径修正:`FIGMA_IMPLEMENTATION_MATRIX.md` 的 M2 总结此前仍把问答反馈写成视觉缺口;当前员工端问答反馈、状态提示和后端记录已在位,剩余仅为 Figma 画板中的收藏持久化契约与完整视觉状态复核,不把开放问题榜纳入本期。 - 2026-07-14 最新线上只读资源复核:生产根站、`/h5/` 和 `/prod-api/auth/tenant/list` 均返回 `200`;线上管理端仍加载 `assets/index-CJZ3Ax3Z.js`(SHA-256 `8b9278a26ccb760abce489b12a20b221748c64d4c4153613d2511777bb9677bc`),H5 仍加载 `assets/index-D4-NrEpb.js`(SHA-256 `ab15bfd17cabe58e2f34b0ac61ee198a837128ed85dc6bb0ddf77bc3e22dcd9c`);当前提交 `0de9704e` 重建后的本地资源为管理端 `assets/index-B9T505HT.js`(SHA-256 `66a827a7b3e5d794ae9da54c6e2276080995614fa52f54d49f746087663f8c94`)和 H5 `assets/index-CDn6TrX8.js`(SHA-256 `eecb4820f3887aceb952efe3e6f2210bab325be8b03f2813e6ec304c68b26f08`),两端仍未发布。本轮仅做 GET/hash 核验,未执行生产静态同步、后端重启或业务数据写入。 - 2026-07-14 BRD 5.4/G3 组织同步写入保护:`POST /api/aihr/org/sync` 现在要求请求显式传 `dryRun=true` 或 `dryRun=false`,省略请求体或传 `null` 会在外部拉取前直接拒绝,避免空请求因 `replaceExisting=true` 默认值意外写入组织快照;补充服务单测、`demo-check` marker 和 API 对接说明,未修改线上组织数据。 diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh index 6cabd172..38caa6ac 100755 --- a/scripts/demo-check.sh +++ b/scripts/demo-check.sh @@ -444,6 +444,9 @@ contains frontend/src/views/index.vue "不等于端到端验收" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrDashboardService.java "不等于端到端验收" contains frontend/src/views/index.vue "正式试点身份待核对" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrDashboardService.java "正式试点身份待核对" +contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "TenantHelper.getTenantId()" +contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrOrgSyncService.java "TenantHelper.getTenantId()" +contains backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrTenantContextContractTest.java "businessServicesUseDynamicTenantContext" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrDashboardService.java "String traineeExpression = storeDisplayFields" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "String nameExpression = !storeDisplayFields" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "PILOT_SESSION_ROWS_SQL.formatted(storeDisplayFields"