Files
..
2025-12-15 22:50:03 +08:00
2025-12-25 07:53:02 +08:00
2025-08-14 08:11:03 +08:00
2025-12-25 07:53:02 +08:00
2025-12-15 22:50:03 +08:00
2025-12-15 22:50:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-12-25 07:53:02 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-27 15:56:11 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-12-16 08:46:38 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00
2025-08-14 08:11:03 +08:00

LjwxBoot 后台管理系统

SpringBoot JDK Version License
Author Copyright

项目简介

LjwxBoot 是一款现代化的后台管理系统脚手架,它基于 Spring Boot 3 框架进行开发。也得益于前端 @SoybeanAdmin 1.0.0 发版后,精致的用户界面和一致的编码,所以得此顺势完善此项目。 在市面上虽然存在众多出色的 Java 后端管理系统框架,但还是决定重复再造一个轮子。

📚 文档中心

项目提供完整的技术文档和API接口文档,位于 docs/ 目录:

文档 说明 链接
🔷 OpenAPI 契约 标准化 API 契约(OpenAPI 3.0) api/openapi.json
📊 API 统计报告 从 OpenAPI 自动生成的统计(自动化) API_STATS.md
📖 OpenAPI 维护指南 完整实施指南(500+ 行) OPENAPI_MAINTENANCE_GUIDE.md
🚀 OpenAPI 快速上手 5 分钟快速开始 openapi/README.md
🧪 测试覆盖报告 Phase 4 完整测试覆盖扩展报告 PHASE4_FINAL_REPORT.md
📝 文档索引 文档导航和快速查询指南 docs/README.md
🏥 健康数据流水线 完整的健康数据处理架构文档(6份) health-data-pipeline/
🚨 实时告警流水线 实时健康告警全链路文档(6份) realtime-alert-pipeline/
📡 内网消息总线系统 纯内网环境统一消息总线架构文档(7份) intranet-message-bus/
🏗️ 系统架构审计报告 生产系统架构审计、问题清单、优化路线图 architecture/SYSTEM_ARCHITECTURE_AUDIT.md
🚀 P0架构优化实施 Redis去重 + 统一缓存失效(已完成) architecture/P0_EXECUTION_PLAN.md
🔒 多租户 Checkstyle 验证 多租户安全规范 + Maven自动验证 + 使用指南 07-compliance/multi-tenant-checkstyle-guide.md

P0架构优化成果 (2025-12-15 ✅ 已完成):

  • ✅ P0-3 Redis去重迁移: 内存占用降低80%,支持分布式部署,24小时TTL自动过期
  • ✅ P0-4 统一缓存失效: 事件驱动异步失效,保证数据新鲜度,性能无感知(+1ms)
  • ✅ 测试覆盖: 43个测试用例100%通过(33单元测试 + 10集成测试)
  • 📋 详细文档: P0-3实施报告 | P0-4实施报告 | 完成总结

OpenAPI 契约管理 (2025-12-15 ✅ 已上线):

# 查看 API 文档(推荐)
open http://localhost:9998/doc.html

# 导出 OpenAPI 契约
./scripts/export-openapi.sh

# 生成统计报告
./scripts/generate-api-stats.sh

# 一键完整验证
./scripts/quick-verify-openapi.sh

当前统计 (2025-12-15):

  • ✅ Controller数量: 63个
  • ✅ API端点总数: 234个
  • ✅ 测试用例数: 150个 (100%通过) ⬆️ +43个(P0-3/P0-4)
  • ✅ 核心服务覆盖率: 48%-78%
  • ✅ 架构优化: P0-3 Redis去重 + P0-4 缓存失效(已完成)

🏥 健康数据流水线文档

完整的健康数据处理系统架构文档,涵盖数据上传、存储、查询、分析全流程。位于 docs/health-data-pipeline/ 目录:

📖 文档清单

序号 文档 说明 链接
0️⃣ 导航中枢 10步数据链路总览 + 快速故障排查 README.md
1️⃣ 架构设计与模块划分 分层架构、核心模块、实体清单、多租户设计 01-architecture.md
2️⃣ 数据流与流程图 5个Mermaid流程图、同步/异步边界、快慢字段分离 02-dataflow.md
3️⃣ 数据库设计 7张核心表结构、月分表策略、JSON字段、索引优化 03-database.md
4️⃣ API接口文档 3大核心接口、请求/响应示例、参数校验规则 04-apis.md
5️⃣ 性能优化与可靠性 5大瓶颈分析、幂等去重、异步重试、监控指标 05-performance-and-reliability.md

🎯 核心特性

数据处理链路(10步完整流程):

API上传 → DataUpload批处理 → MySQL分表存储 → 定时任务调度
   → 统一查询服务 → 基线计算 → 评分计算 → 预测分析
   → 批量告警检测 → 多渠道通知

技术亮点:

  • ✅ 快慢字段分离:主表存快字段(心率、血氧),日表/周表存慢字段(睡眠、运动JSON)
  • ✅ 月度分表:t_user_health_data_YYYYMM 按月自动分表,支持高效查询
  • ✅ CPU自适应批处理:批次大小 = min(500, max(50, CPU核心数 × 25))
  • ✅ 多级缓存:Caffeine本地缓存 + Redis分布式缓存
  • ✅ 并行处理:CompletableFuture租户级并行 + ExecutorService部门级并行
  • ✅ 智能告警:按customerId分组提高缓存命中率,批量评估告警规则

📊 性能指标

当前性能基线(测试环境:8核16GB):

  • QPS:~1200-1500(单实例)
  • 响应时间:P50=35ms,P95=85ms,P99=150ms
  • 数据库写入:~30ms/条
  • 告警检测:~20-100ms(批量处理)

优化收益:

  • JSON序列化优化:响应时间 -44%(45ms → 25ms)
  • 事务范围缩小:响应时间 -60%(30-80ms → 15-20ms)
  • 告警缓存优化:检测耗时 -90%(5ms → 0.5ms)
  • 跨月查询优化:查询时间 -83%(300ms → 50ms)

🔍 快速导航

新手入门:建议按顺序阅读

  1. README.md - 快速了解整体架构
  2. 01-architecture.md - 理解模块划分
  3. 02-dataflow.md - 掌握数据流转

故障排查:

系统优化:


🚨 实时告警流水线文档

完整的实时健康告警系统架构文档,涵盖告警接收、规则评估、缓存去重、统一推送、重试补偿全流程。位于 docs/realtime-alert-pipeline/ 目录:

📖 文档清单

序号 文档 说明 链接
0️⃣ 导航中枢 10行摘要 + 最小关键路径 + 排障入口 README.md
1️⃣ 流程图与数据流 6个Mermaid流程图、同步/异步链路、状态机、并行处理 01-flow.md
2️⃣ 数据库设计 5张核心表、字段变更建议、分区策略、性能优化 02-database.md
3️⃣ API接口文档 23个接口、请求/响应示例、错误码说明 03-apis.md
4️⃣ 缓存与去重策略 三层缓存架构、去重机制、限流保护、告警聚合 04-cache-and-dedup.md
5️⃣ 推送与重试机制 6种推送渠道、智能路由、重试补偿、死信队列 05-push-and-retry.md

🎯 核心特性

告警处理链路(完整流程):

手表健康数据 → POST /api/health/upload → DataUpload服务
  ↓
BatchAlertProcessor按客户ID分组 → AlertRuleEngineService三层缓存规则引擎
  ↓
评估触发告警 → TAlertInfo落库 (t_alert_info表) → AlertResult
  ↓
UnifiedMessagePublisher统一推送 → 多渠道路由(微信/短信/邮件/WebSocket/Webhook/内部消息)
  ↓
推送结果记录 → TAlertActionLog (t_alert_action_log表) → 告警状态机流转 → 大屏/管理端查询

技术亮点:

  • ✅ 三层缓存架构:L1 JVM本地缓存(5分钟) + L2 Redis缓存(24小时) + L3 MySQL数据库
  • ✅ 智能去重:基于时间窗口去重 + 冷却期抑制 + event_id幂等
  • ✅ 告警风暴保护:60秒内最多100个告警,单设备限流,告警聚合
  • ✅ 统一推送架构:6种推送渠道(微信/短信/邮件/WebSocket/Webhook/内部消息)
  • ✅ 渠道智能路由:基于严重级别、时间段、配置自动路由
  • ✅ 重试与补偿:最多3次重试,指数退避策略,死信队列处理
  • ✅ 自动处理机制:AUTO_RESOLVE/AUTO_ACKNOWLEDGE/AUTO_ESCALATE/AUTO_SUPPRESS

📊 性能指标

当前性能基线(测试环境:8核16GB):

  • 告警评估延迟:< 200ms(批量处理)
  • 缓存命中率:~98%(L1+L2)
  • 推送成功率:> 99.5%
  • 并发处理能力:~1500 条/秒

优化收益:

  • 缓存命中优化:评估耗时 -98%(5ms → 0.1ms)
  • 批量处理优化:吞吐量 +40倍(单条处理 → 批量并行)
  • 推送并发优化:延迟 -75%(400ms → 100ms)

🔍 快速导航

新手入门:建议按顺序阅读

  1. README.md - 快速了解告警链路
  2. 01-flow.md - 掌握流程图和数据流
  3. 02-database.md - 理解数据库设计

故障排查:

系统优化:

数据库变更:


🚀 最新更新

v1.0.7 - OpenAPI 契约自动维护基础设施 (2025-12-15)

🔷 OpenAPI 标准化契约管理

  • 契约即代码: OpenAPI 3.0 标准契约作为 Git 管理的基线(api/openapi.json)

    • 873KB 契约文件,涵盖 47+ API 接口
    • 85+ Schema 定义,完整的请求/响应结构
    • 实时同步:从运行态自动导出,确保文档与代码一致
  • CI/CD 自动化检查:

    .gitea/workflows/openapi-contract.yml
    ├── Job 1: 契约生成与破坏性变更检测
    ├── Job 2: 契约质量检查(Spectral Lint)
    └── Job 3: 自动更新基线(main 分支)
    
    • 3 道闸机制: 可生成性 → 破坏性变更检测 → Lint 质量检查
    • PR 强制守门: 破坏性变更自动评论并阻止合并
    • 基线自动更新: Push to main 时自动提交新基线

🔧 完整工具链

  • 导出脚本: export-openapi.sh - 启动应用 → 抓取 /v3/api-docs → 保存契约
    • 双模式运行:智能检测应用是否已运行
    • 完善错误处理:超时检测、进程清理、友好提示
  • 差异检测: check-api-breaking-changes.sh - 使用 oasdiff 对比基线
    • 检测删接口、改类型、删字段、收缩枚举等破坏性变更
    • 支持内网部署(本地二进制)
  • 统计生成: generate-api-stats.sh - 从 OpenAPI 自动生成统计报告
    • HTTP 方法分布、模块分布、接口详情
    • 替代手动维护的 API_SUMMARY.md
  • 一键验证: quick-verify-openapi.sh - 完整流程验证
    • 环境检查 → 编译 → 导出 → 差异检测 → Lint

📚 完整文档体系

  • 实施指南: docs/OPENAPI_MAINTENANCE_GUIDE.md (~500 行)
    • 前置条件、快速开始、日常开发流程、故障排查
    • 最佳实践、进阶配置、工具下载
  • 快速上手: docs/openapi/README.md - 5 分钟快速开始
  • 迁移指南: docs/API_MIGRATION_GUIDE.md - 从手动文档迁移
  • 实施总结: OPENAPI_IMPLEMENTATION_SUMMARY.md - 完整技术细节

🎯 开发规范(红线)

  1. 仅使用 DTO - Controller 禁止直接暴露 Entity/Map
  2. 明确响应结构 - 所有接口必须有明确的 Response Schema
  3. 版本化管理 - 破坏性变更必须走 /api/v2/... 或 @Deprecated
  4. 基线同步 - 任何接口变更必须更新契约并通过 CI
  5. 最少文档 - 新增接口必须有 @Operation(summary="...") 注解

📊 技术亮点

  • ✅ 零侵入式 - 不改变现有代码,仅增加基础设施
  • ✅ 渐进式接入 - 从"可生成" → "检测" → "Lint"逐步严格化
  • ✅ 内网友好 - 所有工具支持本地二进制,无需外网依赖
  • ✅ 工具集成 - 支持 Postman 导入、SDK 自动生成、Mock 服务器

相关文件:

  • 契约基线: api/openapi.json - OpenAPI 3.0 标准契约
  • CI 配置: .gitea/workflows/openapi-contract.yml - 自动化检查
  • Lint 规则: .spectral.yaml - 契约质量规则
  • 脚本工具: scripts/export-openapi.sh, check-api-breaking-changes.sh, generate-api-stats.sh
  • 完整文档: docs/OPENAPI_MAINTENANCE_GUIDE.md, docs/openapi/README.md

v1.4.0 - 统一告警与消息机制智能优化系统 (2025-08-30)

🤖 AI驱动的企业级智能告警处理系统

  • 统一告警架构: 全新设计的统一告警处理系统,集成AI分析、智能优先级和实时监控

    • 性能提升:告警处理时间从200ms优化至5ms,提升40倍处理效率
    • 准确率提升:AI分析引擎将误报率降低至8%以下,置信度评分机制
    • 并发能力:支持1000+并发告警处理,毫秒级响应时间
  • AI智能分析引擎:

    // 多维度AI分析能力
    SmartAlertEngine → MLAlertAnalyzer (机器学习异常检测)
                    → ContextAnalyzer (环境上下文分析)  
                    → PatternRecognizer (历史模式识别)
    
    • 机器学习异常检测: 基于孤立森林算法的智能异常识别
    • 上下文分析: 时间、地理位置、环境因素综合评估
    • 模式识别: 历史数据趋势分析和异常模式匹配
  • 智能优先级计算系统:

    • 多因子算法: 基础优先级 × 组织层级 × 时间因子 × 用户风险 × 设备历史 × 地理位置
    • 动态权重: 根据告警类型和业务场景自动调整权重系数
    • 升级策略: 智能升级延迟计算,确保重要告警及时处理

📊 实时监控与优化系统

  • 性能监控: AlertProcessingMonitor 实时监控系统性能指标
    • 处理时间监控、错误率统计、吞吐量分析、资源使用率
    • 瓶颈识别:数据库查询、内存使用、CPU负载、网络带宽
  • 智能优化建议: IntelligentOptimizer AI驱动的系统优化
    • 规则优化建议:基于误报率分析的规则阈值调整建议
    • 性能优化建议:数据库索引、缓存策略、线程池配置优化
    • 容量规划建议:基于负载预测的扩容建议和资源配置
  • 预测分析: AlertTrendPredictor 告警趋势预测
    • 负载预测:未来7-30天系统负载趋势预测
    • 类型分布预测:不同告警类型的发生概率预测
    • 瓶颈预测:潜在性能瓶颈和故障风险预警

🏗️ 基于闭包表的高性能架构

  • 毫秒级查询优化: 基于 sys_org_closure 闭包表的组织架构查询优化
    <!-- 优化后的SQL查询,支持复杂层级关系毫秒级查询 -->
    <select id="getNotificationHierarchy" resultMap="OrgHierarchyInfoResultMap">
        SELECT DISTINCT u.id, u.real_name, u.phone, u.email, uo.principal, 
               o.id as org_id, o.name as org_name, o.level, c.depth
        FROM sys_org_closure c
        INNER JOIN sys_org_units o ON c.ancestor_id = o.id
        INNER JOIN sys_user_org uo ON c.ancestor_id = uo.org_id
        INNER JOIN sys_user u ON uo.user_id = u.id
        WHERE c.descendant_id = ? AND c.customer_id = ?
        ORDER BY c.depth ASC, uo.principal DESC, u.id ASC
    </select>
    
  • 智能消息队列: Redis优先级队列 + 去重机制 + 批量处理
  • 分发策略: 基于组织层级的智能通知分发,支持升级策略

🎯 企业级功能特性

  • 完整REST API: 提供完整的告警处理、监控、优化API接口
    • /api/v1/alert/process - 单个告警智能处理
    • /api/v1/alert/process/batch - 批量告警处理
    • /api/v1/alert/monitor/performance - 实时性能监控
    • /api/v1/alert/optimize/recommendations - AI优化建议
  • 性能测试: 内置性能测试组件,支持单个、批量、并发测试
  • 健康检查: 完整的系统健康状态检查和故障诊断

📈 系统架构升级

统一告警处理流程:
告警输入 → AI智能分析 → 优先级计算 → 智能分发
    ↓
闭包表查询 → 通知层级构建 → 消息队列 → 多渠道推送
    ↓
实时监控 ← 性能分析 ← 优化建议 ← 预测分析

相关文件:

  • 核心系统: UnifiedAlertSystem.java - 统一告警处理核心
  • AI分析: SmartAlertEngine.java + ML组件 - 智能分析引擎
  • 监控系统: AlertProcessingMonitor.java + MetricsCollector.java
  • 优化系统: IntelligentOptimizer.java + AlertTrendPredictor.java
  • API接口: UnifiedAlertController.java - 完整REST API
  • 性能测试: AlertSystemPerformanceTest.java - 性能测试套件
  • 数据库: SysOrgClosureMapper.xml - 优化SQL查询

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 - 分页查询同步加固多租户过滤
  • 技术实现细节:

    // 角色查询添加多租户过滤
    .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)

🏢 多租户客户配置管理系统

  • 客户配置新增: 完整的客户配置创建功能,支持多字段配置

    • 客户名称、描述、上传方式(wifi/bluetooth)、许可证配置
    • 断点续传、重试策略、缓存配置等高级参数
    • 自动设置必需字段默认值,解决数据库约束问题
  • 同步组织创建: 客户配置保存成功后自动创建对应组织机构

    // 客户配置保存成功 → 创建对应的SysOrgUnits记录
    SysOrgUnits orgUnit = new SysOrgUnits();
    orgUnit.setId(entity.getId());           // 与客户配置ID保持一致
    orgUnit.setName(entity.getCustomerName()); // 组织名称使用客户名称
    orgUnit.setCustomerId(entity.getId());    // 设置为自身租户ID
    
  • 智能配置同步: 通过事件监听器自动同步相关配置

    • 接口配置(t_interface)、健康数据配置(t_health_data_config)
    • 告警规则(t_alert_rules)、角色(sys_role)、岗位(sys_position)
    • 防循环创建:监听器检查配置是否已存在,避免重复创建

🔧 技术架构优化

  • 字段映射处理: 前端supportLicense ↔ 后端isSupportLicense字段映射
  • 数据库约束修复:
    • 解决license_key字段无默认值错误
    • 自动设置customer_name、customer_id等必需字段默认值
  • 防循环依赖: OrgUnitsChangeListener增加存在性检查
    // 检查是否已存在配置,避免循环创建
    TCustomerConfig existingConfig = customerConfigService.getById(o.getId());
    if (existingConfig != null) {
        log.info("CustomerConfig already exists for orgId={}, skipping clone", o.getId());
        return;
    }
    

🎯 完整业务流程

客户配置创建 → TCustomerConfigServiceImpl.save()
       ↓
   自动创建SysOrgUnits → 触发SysOrgUnitsChangeEvent.CREATE
       ↓
   OrgUnitsChangeListener → 同步复制相关配置
       ↓
   ✅ 多租户环境完整初始化

相关文件:

  • 实体: TCustomerConfig.java - 添加字段映射注解
  • DTO: TCustomerConfigAddDTO.java - 完善新增字段
  • 服务: TCustomerConfigServiceImpl.java - 同步创建组织逻辑
  • 门面: TCustomerConfigFacadeImpl.java - 字段映射处理
  • 监听器: OrgUnitsChangeListener.java - 防循环创建优化

v1.3.6 - 多租户角色岗位系统完整实现 (2025-08-28)

🏢 企业级多租户角色岗位管理系统

  • 智能角色继承: 新建租户时自动从全局角色模板(customerId=0)复制标准角色配置
    • 全局角色:4个标准角色(超级管理员、系统管理员等)
    • 租户角色:每个租户独立拥有4个角色副本,支持个性化定制
  • 岗位自动配置: 租户创建时自动配置标准岗位体系
    • 全局岗位:6个标准岗位(技术总监、产品经理、开发工程师、测试工程师、运维工程师、业务专员)
    • 租户岗位:每个租户独立岗位配置,支持权重排序和灵活管理
  • 数据隔离保障: 严格的多租户数据隔离机制
    • 角色数据:sys_role.customer_id 字段实现租户级角色隔离
    • 岗位数据:sys_position.customer_id 字段实现租户级岗位隔离
    • 自动清理:删除租户时级联清理相关角色岗位数据

🔄 事件驱动的自动化管理

  • OrgUnitsChangeListener 增强: 组织变更事件监听器完整重构
    // 新增租户时自动执行
    cloneRoles(orgUnit);      // 复制全局角色到新租户
    clonePositions(orgUnit);  // 复制全局岗位到新租户
    
    // 删除租户时自动清理
    roleService.lambdaUpdate().eq(SysRole::getCustomerId, orgUnit.getId())
              .set(SysRole::getDeleted, 1).update();
    positionService.lambdaUpdate().eq(SysPosition::getCustomerId, orgUnit.getId())
                  .set(SysPosition::getDeleted, 1).update();
    
  • 批量数据同步: 为6个现有租户完成历史数据同步
    • 角色同步:24个租户角色记录(6租户 × 4角色)
    • 岗位同步:36个租户岗位记录(6租户 × 6岗位)

🛠️ 数据库架构优化

  • 索引性能优化: 新增多租户查询索引
    CREATE INDEX idx_sys_role_customer_id ON sys_role(customer_id);
    CREATE INDEX idx_sys_role_customer_status ON sys_role(customer_id, status);
    CREATE INDEX idx_sys_position_customer_id ON sys_position(customer_id);
    CREATE INDEX idx_sys_position_customer_status ON sys_position(customer_id, status);
    
  • 完整迁移脚本: 提供 database-migration.sql 完整迁移方案
  • 字段名标准化: 修复监听器中的字段名称不一致问题

📊 最终数据分布

├── 全局角色配置: 4个 (customer_id=0) 
├── 租户角色数据: 6个租户 × 4个角色 = 24个
├── 全局岗位配置: 6个 (customer_id=0)
└── 租户岗位数据: 6个租户 × 6个岗位 = 36个

🎯 技术架构亮点

  • 事件驱动: Spring Event 机制实现组织变更自动响应
  • 模板模式: 全局配置作为模板,租户数据继承并独立管理
  • 数据一致性: 事务保证多表数据同步的原子性
  • 扩展性: 支持任意数量租户的角色岗位独立管理

相关文件:

  • 实体: SysRole.java - 添加customerId多租户支持
  • 监听器: OrgUnitsChangeListener.java - 角色岗位自动管理逻辑
  • 迁移脚本: database-migration.sql - 完整数据库迁移方案
  • 文档: ljwx-admin/CLAUDE.md - 详细实现文档和故障排查指南

v1.3.5 - 微信告警配置管理功能完整实现 (2025-08-27)

🚨 企业微信告警配置管理系统

  • 配置管理界面: 完整的CRUD操作支持,包括企业微信和公众号微信两种类型
  • 表格功能增强: 支持分页、搜索、排序、批量操作
  • 数据验证: 前后端完整的数据验证机制
  • 权限控制: 基于多租户的权限隔离

v1.3.4 - 健康数据源区分与查询优化 (2025-08-25)

🎯 健康数据源智能识别系统

  • 数据源标识: 为健康数据添加 upload_method 字段区分不同数据来源
    • 正常健康监测数据:upload_method = "wifi" 或 "bluetooth"
    • 通用事件健康数据:upload_method = "common_event"
  • 查询过滤优化: 健康数据查询接口自动过滤通用事件数据
    • 前端健康信息展示仅显示正常健康监测数据
    • 确保健康数据分析的准确性和一致性
  • 数据库增强: 扩展 t_user_health_data.upload_method 枚举类型
    • 从 ('wifi','bluetooth') 扩展为 ('wifi','bluetooth','common_event')

🔧 后端服务优化

  • 智能查询: TUserHealthDataServiceImpl 新增过滤条件
    .ne(TUserHealthData::getUploadMethod, "common_event")
    
  • 实体模型: 健康数据实体类新增 uploadMethod 字段支持
  • 数据完整性: 确保前端查询结果的数据源一致性

🏥 集成ljwx-bigscreen支持

  • 模型同步: Flask SQLAlchemy模型支持新的枚举值
  • 调试增强: 添加详细的健康数据解析调试信息
  • 兼容性: 支持嵌套和平面两种健康数据结构格式

技术实现架构:

手表端数据上传 → 标识数据来源(upload_method) → 数据库存储
    ↓
后端查询服务 → 过滤事件数据 → 前端健康展示
    ↓
数据分析准确 ← 源数据区分 ← 智能识别系统

相关文件:

  • 数据库: t_user_health_data 表结构扩展
  • 实体: TUserHealthData.java - 添加uploadMethod字段
  • 服务: TUserHealthDataServiceImpl.java - 查询过滤逻辑
  • 模型: ljwx-bigscreen/models.py - 枚举字段扩展

v1.3.3 - 用户批量导入功能与数据处理优化 (2025-08-20)

📥 用户批量导入系统

  • Excel/CSV支持: 支持 .xlsx、.xls 和 .csv 多种文件格式导入
  • 智能模板: 提供标准化导入模板下载,包含完整字段示例
    • 字段包含:姓名、性别、年龄、工龄、手机号码、部门、岗位、设备序列号、备注
    • 自动生成用户名(基于手机号后6位)和默认密码(123456)
  • 双重查询: 支持ID和名称两种方式查找部门和岗位
    • 数字输入:按ID查询(如:11, 1)
    • 文本输入:按名称查询(如:技术部、软件工程师)

🔧 数据处理引擎

  • Apache POI集成: 完整的Excel文件解析支持
  • CSV兼容性: 自定义CSV解析器,支持引号转义和字段分隔
  • 数据验证: 多层级数据校验机制
    • 文件格式验证、必填字段检查、数据类型验证
    • 手机号格式校验、年龄工龄范围检查
  • 批量处理: 支持大批量用户数据导入,自动建立组织关系

🛡️ 错误处理与安全

  • 详细错误报告: 按行显示导入失败原因和具体数据
  • 事务安全: 导入过程中的数据完整性保护
  • 权限控制: 基于Sa-Token的导入权限验证
  • 数据隔离: 严格按照组织架构限制数据导入范围

📊 前端交互优化

  • 拖拽上传: 现代化的文件选择和上传界面
  • 实时反馈: 导入过程状态显示和进度条
  • 结果展示: 清晰的成功/失败统计和错误详情
  • 响应式设计: 完美适配移动端和桌面端操作

技术实现架构:

前端上传 → FormData处理 → 后端解析 → 数据验证 
    ↓
组织查询 → 用户创建 → 关系建立 → 结果返回
    ↓
成功统计 ← 失败详情 ← 错误处理 ← 事务回滚

相关文件:

  • 前端:user-page-table.vue - 批量导入界面
  • 后端:SysUserController.java - 导入API端点
  • 服务:SysUserServiceImpl.java - 核心导入逻辑
  • 依赖:pom.xml - Apache POI Maven配置

v1.0.12 - 超级管理员权限修复与关于页面更新 (2025-08-18)

👑 超级管理员权限增强

  • 超级管理员识别: 新增 isSuperAdmin() 方法,通过用户名识别admin超级管理员
    • 基于用户名"admin"进行判断(大小写不敏感)
    • 区分超级管理员与普通部门管理员的权限级别

🔐 职位管理权限修复

  • 全数据访问: 超级管理员可通过 orgId=0 查看所有职位数据
    • orgId=0:不设置过滤条件,返回系统所有职位
    • orgId=具体值:按指定组织ID过滤职位数据
    • 解决了超级管理员权限受限的问题

📖 关于页面完善

  • 系统信息更新: 更新项目描述为准确的IoT健康监测管理系统定位
  • 技术栈展示: 详细展示前后端技术栈信息和版本
  • 功能特性: 新增系统核心功能模块展示
    • 智能设备监测、健康数据分析、告警管理
    • 多租户架构、大屏可视化、移动端支持

🎯 权限层级优化

  • 三级权限体系:
    • 超级管理员(admin):全系统数据访问权限
    • 普通管理员:基于部门层级的数据访问权限
    • 非管理员用户:受限的功能访问权限

v1.0.11 - 组织架构权限优化与租户部门区分 (2025-08-18)

🏢 租户与部门层级权限管理

  • 智能权限区分: 实现租户与部门的严格权限隔离
    • 超级管理员:可创建和管理租户(顶级组织)
    • 部门管理员:只能在所属租户下创建和管理部门
    • 自动权限检查:防止越权操作和数据泄露

🔐 前端UI权限适配

  • 动态表单字段: 根据用户权限动态显示表单标签
    • 超级管理员:显示"租户名称"、"租户编码"等租户字段
    • 部门管理员:显示"部门名称"、"部门编码"等部门字段
  • 按钮权限控制: 新增按钮仅对有权限的用户可见
  • 自动层级设置: 非管理员用户新建部门时自动设置正确的父级关系

🛡️ 后端安全加固

  • API层权限校验: 控制器级别的租户创建权限检查
  • 数据库约束: 通过 parentId 和 ancestors 字段确保数据完整性
  • 用户身份验证: 集成 SaToken 进行细粒度权限控制

📋 部门管理功能增强

  • 层级查询优化: 使用 FIND_IN_SET 支持复杂的部门层级查询
  • 设备绑定过滤: 设备管理界面只显示当前部门管辖范围内的非管理员用户设备
  • 健康数据隔离: 健康数据查询严格按照部门权限进行数据隔离

v1.0.10 - 健康数据配置服务优化与API修复 (2025-08-18)

🔧 健康数据配置服务架构重构

  • 新增专用服务方法: 为 t_health_data_config 表创建专门的查询服务
    • getEnabledConfigsByOrgId(orgId): 根据部门ID查询启用的健康数据配置
    • getBaseConfigsByOrgId(orgId): 查询基础健康特征,自动过滤高级功能字段
    • 支持按 weight 权重排序,优化数据展示顺序

🎯 基础特征过滤优化

  • 智能字段过滤: 基础健康特征自动排除以下高级功能:
    排除字段: location, wear, ecg, exercise_daily, 
             exercise_week, scientific_sleep, work_out
    
  • 层级数据隔离: 所有配置查询自动应用部门层级权限
  • 统一调用接口: 替换原有直接数据库查询,使用标准化服务方法

🚀 健康特征API完善

  • 新增健康特征控制器: /health/feature/* 端点支持
    • /health/feature/base: 获取基础健康特征列表
    • /health/feature/full: 获取全量健康特征列表
    • /health/feature/mapping: 获取特征映射关系
  • 前端兼容性修复: 解决 userId=all 参数处理问题
  • 参数优化: 后端支持可选 userId 参数,提升API灵活性

📊 数据服务整合

  • 统一配置查询: ITUserHealthDataService 集成新的配置服务
  • 性能优化: 减少重复查询,提升数据获取效率
  • 权限一致性: 确保健康数据与配置权限完全对齐

技术实现架构:

健康数据配置流程:
orgId → getTopLevelDeptIdByOrgId() → 顶级部门ID 
     → getBaseConfigsByOrgId() → 过滤后的配置列表
     → 前端特征选择器 → 用户数据展示

v1.0.9 - 分级部门管理权限系统 (2025-08-18)

🏢 部门层级权限控制架构

  • 通用方法: 创建 ISysOrgUnitsService.getTopLevelDeptIdByOrgId() 通用方法
    • 解析 sys_org_units.ancestors 字段(如:"0,1955920989166800898,1955921028870082561")
    • 返回最左边第一个非0数字作为顶级部门ID
    • 支持任意层级部门查找顶级部门

🔐 岗位管理权限分级控制

  • 分级权限控制: 基于部门层级的岗位管理权限

    • 顶级部门管理员: 查看/编辑所有岗位,可使用前端orgId参数
    • 下级部门管理员: 查看全局岗位+顶级部门岗位,不能编辑
  • 数据过滤机制: 基于 orgId 和部门层级实现数据隔离

    • 全局岗位: orgId = 0,所有管理员可见
    • 部门岗位: orgId = 顶级部门ID,按权限过滤显示
    • 智能过滤: 下级部门管理员忽略前端传参,自动基于权限过滤

📊 健康数据配置分级管理

  • 配置隔离: 根据 departmentInfo 查询顶级部门ID

    • 示例:departmentInfo=1940374479725170690 → 解析ancestors → 顶级部门ID 1939964806110937090
    • 从 t_health_data_config 表按 customer_id=顶级部门ID 过滤配置
  • 数据一致性: 确保健康数据显示列与部门权限匹配

    • 不同级别管理员看到不同的数据配置
    • 自动应用对应部门的数据显示规则

权限判断标准:

  • 管理员身份: sys_role.is_admin = 1
  • 部门层级: 通过 ancestors 字段解析层级关系
  • 顶级部门: ancestors 中第一个非0数字对应的部门

权限矩阵:

├── 顶级部门管理员:全部岗位+健康配置 CRUD
├── 下级部门管理员:受限查看权限(全局+顶级部门数据)
└── 普通用户:无权限

技术实现:

数据可见性 = ancestors解析 → 顶级部门ID → 权限过滤
岗位管理: orgId IN [0, 顶级部门ID]
健康配置: customer_id = 顶级部门ID

v1.0.8 - 告警通知功能完整实现 (2025-08-16)

🚨 全新功能:企业级告警通知系统

  • 多渠道通知: 支持企业微信、公众号微信、系统消息三种通知方式
  • 实时推送: Critical级别告警通过WebSocket实时推送到监控大屏
  • 层级通知: 智能的通知层级体系,确保告警及时到达
    • 用户 → 部门主管 → 租户管理员
    • 如果没有部门管理员,自动上升到租户级管理员
  • 配置管理: 完整的微信告警配置CRUD管理界面
  • 大屏集成: 监控大屏支持告警弹窗、确认操作、音效提醒

📋 核心特性:

告警规则 → 事件触发 → 多渠道分发
    ↓
├── 微信通知 (企业微信/公众号)
├── 系统消息 (层级分发)  
└── 大屏推送 (Critical告警实时显示)

🎯 技术亮点:

  • 数据库优化: 清理冗余字段,优化表结构
  • WebSocket实时通信: Socket.IO支持大屏实时推送
  • 权限控制: 完整的告警配置权限管理
  • 容错处理: 微信通知失败自动降级为消息通知

📁 相关文件:

  • 后端: TWechatAlertConfigController.java - 微信告警配置API
  • 前端: alert/config/index.vue - 告警配置管理界面
  • 大屏: ljwx-bigscreen/alert.py - 增强版告警处理引擎
  • 文档: docs/告警通知功能完整实现方案.md - 完整技术方案

v1.0.7 - 租户/部门权限管理优化 (2025-01-16)

重要改进:

  • 权限分级控制: 实现租户和部门的分级权限管理

    • admin用户:可以创建租户(顶级组织)+ 创建部门
    • 普通用户:只能在自己租户下创建部门,无法创建租户
  • 前端权限控制: 动态按钮显示

    • 只有admin角色才能看到"新增租户"按钮
    • 普通用户只显示"新增部门"按钮
  • 后端API安全: 严格的权限验证

    • 创建顶级组织时检查管理员权限
    • 非admin用户尝试创建租户时返回权限错误
  • 文案优化: 更准确的业务概念

    • "组织" → "租户":明确多租户架构
    • "新增子组织" → "新增部门":符合组织层级关系

权限逻辑:

├── admin用户
│   ├── ✅ 创建租户(顶级组织)
│   └── ✅ 创建部门(子组织)
└── 普通用户  
    ├── ❌ 不能创建租户
    └── ✅ 只能在自己租户下创建部门

🔧 数据库补丁:执行 patch_tenant_permissions.sql 添加权限相关字典数据

v1.0.6 - 健康数据查询优化 (2025-01-16)

重要改进:

  • 智能查询策略: 根据 userId 参数自动选择不同的查询逻辑

    • userId 为空或 "all":只查询部门下所有设备的最新数据
    • userId 为具体值:查询该用户指定时间范围内的所有数据
  • 性能优化: 解决 n+1 查询问题

    • 新增 getBatchDailyData() 和 getBatchWeeklyData() 批量查询方法
    • 大幅减少数据库查询次数,提升系统响应速度
  • 数据安全: 严格的部门数据隔离

    • 自动过滤管理员设备,防止数据泄露
    • 基于 departmentInfo 确保只能访问本部门数据

API 使用示例:

# 查询部门所有设备最新数据
GET /t_user_health_data/page?userId=all&departmentInfo=1940374227169349634

# 查询特定用户时间范围内所有数据  
GET /t_user_health_data/page?userId=12345&departmentInfo=1940374227169349634&startDate=1751299200000&endDate=1755187199999

影响模块:

  • TUserHealthDataServiceImpl.java - 核心查询逻辑优化
  • DeviceUserMappingServiceImpl.java - 设备用户映射服务
  • SysOrgUnitsController.java - 租户/部门权限控制

技术选型

技术 说明 版本
Spring Boot 核心框架 3.3.2
MyBatis-Plus 持久层框架 3.5.6
MySQL 数据库 8.0.35
Redis 缓存 7.2.3
Sa-Token 鉴权框架 1.38.0
Logback 日志管理 1.5.6
Knife4j 接口文档 4.5.0
Socket.IO WebSocket通信 4.7.2
Python Flask 告警处理引擎 3.x
Lombok 工具库 1.18.34
Jackson JSON解析 2.15.4
Gson JSON解析 2.10.1
Guava Google工具库 33.2.1-jre
Hutool 工具库 5.8.29

项目源码

名称 链接
前端 Panis-admin
后端 ljwx-boot
后端扩展依赖库 ljwx-boot-starter

项目启动

前置环境
  • Java 开发环境 >=JDK 21
  • Java 开发工具 IDEA
  • Maven 构建依赖环境 >=3.9.6
  • MySQL 数据库 >=8.0.35
  • Redis 缓存数据库 >=7.2.3
克隆项目
git clone https://github.com/brunoGao/ljwx-boot
git clone https://github.com/brunoGao/ljwx-boot-starter
导入启动
  1. 将ljwx-boot以及ljwx-boot-starter分别导出到IDEA中,等待 Maven 依赖下载完成
  2. 创建数据库panis_boot,导入ljwx-boot-doc项目中的panis_boot.sql,文件暂在QQ群获取
  3. 修改ljwx-boot项目中的application-dev.yml文件中的数据库以及Redis连接信息
  4. 启动LjwxBootApplication类
  5. 看到---[LjwxBoot]-[ljwx-boot-admin]-启动完成,当前使用的端口:[9999],环境变量:[mybatis,dev]---即代表启动成功

📊 数据字典SQL

系统使用数据字典来管理下拉选项、状态值等基础数据。以下是核心数据字典表的建表SQL:

字典主表 (sys_dict)

CREATE TABLE `sys_dict` (
  `id` bigint NOT NULL COMMENT 'ID',
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '字典名称',
  `code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '字典编码',
  `type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '字典类型(1:系统字典,2:业务字典)',
  `sort` int DEFAULT NULL COMMENT '排序值',
  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '字典描述',
  `status` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '1' COMMENT '是否启用(0:禁用,1:启用)',
  `create_user` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建用户名称',
  `create_user_id` bigint DEFAULT NULL COMMENT '创建用户ID',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_user` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新用户名称',
  `update_user_id` bigint DEFAULT NULL COMMENT '更新用户ID',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `is_deleted` tinyint DEFAULT '0' COMMENT '是否删除(0:否,1:是)',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据字典主表';

字典子项表 (sys_dict_item)

CREATE TABLE `sys_dict_item` (
  `id` bigint NOT NULL COMMENT 'ID',
  `dict_id` bigint DEFAULT NULL COMMENT '父字典ID',
  `dict_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父字典编码',
  `value` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '数据值',
  `zh_cn` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '中文名称',
  `en_us` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '英文名称',
  `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '类型(前端渲染类型)',
  `sort` int DEFAULT NULL COMMENT '排序值',
  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '字典描述',
  `status` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '1' COMMENT '是否启用(0:禁用,1:启用)',
  `create_user` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建用户名称',
  `create_user_id` bigint DEFAULT NULL COMMENT '创建用户ID',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_user` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新用户名称',
  `update_user_id` bigint DEFAULT NULL COMMENT '更新用户ID',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `is_deleted` tinyint DEFAULT '0' COMMENT '是否删除(0:否,1:是)',
  PRIMARY KEY (`id`),
  KEY `idx_dict_code` (`dict_code`),
  KEY `idx_dict_id` (`dict_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据字典子项表';

基础字典数据

-- 状态字典
INSERT INTO `sys_dict` (`id`, `name`, `code`, `type`, `sort`, `description`, `status`) VALUES 
(1, '状态', 'status', '1', 1, '通用状态字典', '1');

INSERT INTO `sys_dict_item` (`id`, `dict_id`, `dict_code`, `value`, `zh_cn`, `en_us`, `type`, `sort`, `description`, `status`) VALUES 
(1, 1, 'status', '0', '禁用', 'Disabled', 'error', 1, '禁用状态', '1'),
(2, 1, 'status', '1', '启用', 'Enabled', 'success', 2, '启用状态', '1');

-- 用户状态字典  
INSERT INTO `sys_dict` (`id`, `name`, `code`, `type`, `sort`, `description`, `status`) VALUES 
(2, '用户状态', 'user_status', '1', 2, '用户状态字典', '1');

INSERT INTO `sys_dict_item` (`id`, `dict_id`, `dict_code`, `value`, `zh_cn`, `en_us`, `type`, `sort`, `description`, `status`) VALUES 
(3, 2, 'user_status', '0', '禁用', 'Disabled', 'error', 1, '用户禁用', '1'),
(4, 2, 'user_status', '1', '正常', 'Normal', 'success', 2, '用户正常', '1'),
(5, 2, 'user_status', '2', '锁定', 'Locked', 'warning', 3, '用户锁定', '1');

-- 字典类型字典
INSERT INTO `sys_dict` (`id`, `name`, `code`, `type`, `sort`, `description`, `status`) VALUES 
(3, '字典类型', 'dict_type', '1', 3, '字典类型分类', '1');

INSERT INTO `sys_dict_item` (`id`, `dict_id`, `dict_code`, `value`, `zh_cn`, `en_us`, `type`, `sort`, `description`, `status`) VALUES 
(6, 3, 'dict_type', '1', '系统字典', 'System Dict', 'primary', 1, '系统内置字典', '1'),
(7, 3, 'dict_type', '2', '业务字典', 'Business Dict', 'info', 2, '业务定制字典', '1');

项目结构

LjwxBoot
├── ljwx-boot-common -- 基础模块
├── ljwx-boot-admin -- 后台管理模块
│   └── controller  -- 控制层
├── ljwx-boot-infrastructure -- 基础配置
├── ljwx-boot-modules -- 业务模块
│   └── system 
│       └── repository -- 数据交互
│           └── mapper -- 持久层
│       └── domain  -- 业务模型
│           └── entity -- 数据库实体
│           └── vo -- 视图对象
│           └── bo -- 业务对象
│           └── dto -- 传输对象
│       └── service -- 服务层
│           └── impl -- 服务实现层
│       └── facade -- 门面层
│           └── impl -- 门面实现层
│   └── base -- 基础管理
│   └── ... -- 其他模块
└── pom.xml -- 公共依赖

common 和 infrastructure 区别

  • common模块:通常包含通用的工具类、异常定义、常量定义等与业务无关的代码。这些代码可以被整个应用程序共享。

    • 通用工具类,比如日期处理、字符串处理等
    • 通用异常定义,比如业务异常、参数校验异常等
    • 通用常量定义,比如状态码、错误信息等
  • infrastructure模块:通常包含与基础设施相关的代码,比如数据库访问、缓存、消息队列、配置管理等。这些代码通常是为了支持业务模块的运行而存在的。

    • 数据访问相关的代码,比如数据库连接、ORM框架配置、数据源配置等
    • 缓存相关的代码,比如缓存配置、缓存管理等
    • 消息队列相关的代码,比如消息生产者、消费者配置等
    • 配置管理相关的代码,比如配置加载、动态配置更新等

对于静态类、工具类、异常定义等,你可以根据其功能和作用来判断放入common还是infrastructure 模块。如果它们是通用的、与业务无关的,可以放入common模块;如果它们是为了支持业务模块的基础设施,可以放入infrastructure模块。

特别鸣谢

开源协议

项目基于 Apache License 2.0 © 2024 ljwx 协议,仅供学习参考,商业使用请遵循作者版权信息,作者不保证也不承担任何软件的使用风险。# Test trigger after workflow fix