# qms **Repository Path**: bukcn/qms ## Basic Information - **Project Name**: qms - **Description**: Travel Management System - **Primary Language**: Java - **License**: GPL-3.0 - **Default Branch**: tms-java25 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2024-11-19 - **Last Updated**: 2026-09-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: buk-cn ## README # TMS 差旅管理系统 > **版本**: 2.0.0 | **语言**: Java 25 | **框架**: Spring Boot 4.1.1 | **ORM**: Hibernate 7.2 (JPA 3) 企业商旅管理(TMC)平台,提供机票预订、酒店查询、火车票/租车/增值服务订单管理、支付结算、报表统计等综合商旅服务,并内置 AI 代理网关,支持通过自然语言直接查询报表与业务数据。 ## License 本项目基于 **GNU General Public License v3.0 (GPL v3)** 开源,详见 [LICENSE](LICENSE) 文件。 ## 技术栈 | 类别 | 技术 | |------|------| | 语言 | Java 25 | | 框架 | Spring Boot 4.1.1 | | 安全 | Spring Security + BCryptPasswordEncoder(兼容 MD5 渐进升级) | | ORM | Hibernate 7.2 (JPA 3) | | 数据库 | MySQL 5.7 / 8.0+(HikariCP 连接池) | | 迁移 | Flyway(`classpath:db/migration`) | | 缓存 | Redis:Spring Data Redis(RedisTemplate / RedisCacheService) | | 本地缓存 | Caffeine(用户令牌验证等高频校验) | | 并发控制 | Redis 分布式锁:EntBalanceLock(企业余额写互斥)+ IdempotentService(核心写操作幂等) | | 会话 | Spring Session(Redis 多实例会话共享) | | 消息 | ActiveMQ (JMS) | | API 文档 | SpringDoc OpenAPI 3.0(`/self/**` 独立分组) | | 监控 | Spring Boot Actuator + Micrometer Prometheus | | 日志 | Logback + logstash-logback-encoder(结构化 JSON,含 MDC traceId) | | AI | AI 代理网关(LLM + OpenAPI 工具自动注册) | | 构建 | Maven 多模块,JaCoCo 覆盖率门禁(单元 + 集成测试)+ Checkstyle 门禁 | | 测试 | JUnit 5 + Mockito + Testcontainers(Docker MySQL) | | 打包 | 可执行 JAR(embedded Tomcat,产物 `qms.jar`) | ## 项目模块 ``` qms/ ├── qms-dao # 数据访问层(实体 + DAO) ├── qms-service # 业务逻辑层 ├── qms-alert-service # 告警通知服务(ActiveMQ) └── qms-bijia-webapp # Web 应用(主入口,打包为可执行 JAR) ``` ## 主要功能 - **订单管理**:机票、酒店、火车票、租车、增值服务(VAS)订单及退改签、审批、附件、评论 - **客户与企业**:企业客户、部门、员工、差旅政策、审批人配置 - **基础数据**:城市、机场、航司、国家/省份/地区、证件类型等,含开放数据 API(`/public/**`) - **账单结算**:机票/酒店/火车/租车/增值服务账单导出、收款单、对账结算 - **报表统计**:按供应商、客户、航线等多维度统计,支持 Excel/PDF 导出 - **支付与短信**:支付配置、短信验证码(注册/重置密码) - **验证码**:自研图形验证码生成器(`/captcha`,替换已停更的 kaptcha) - **对外自助 API**:`/self/**` 在 SpringDoc 中独立分组(`self-api` 组),运行时生成 OpenAPI 规范(`/api/v1/v3/api-docs/self-api`)交付前端 - **AI 代理网关**:启动时按规则将 `/report/**`、`/public/**` 接口自动注册为 LLM 工具,支持多轮工具调用、SSE 流式对话、会话认证透传 ## 环境要求 - JDK 25+ - Maven 3.8+ - MySQL 5.7 / 8.0+ - Redis - Docker(仅运行集成测试时需要) ## 快速开始 ### 1. 克隆代码 ```bash git clone cd qms ``` ### 2. 配置环境变量 ```bash cp env.properties.example .env ``` 编辑 `.env` 文件,填入实际的数据库连接信息和服务地址。 ### 3. 构建项目 ```bash # 全量构建(跳过测试,加快构建速度) mvn clean package -Dmaven.test.skip=true ``` 构建产物:`qms-bijia-webapp/target/qms.jar` ### 4. 启动应用 **方式一:使用启动脚本(推荐)** 脚本会加载 `.env` 环境变量、自动构建,并以 UTC 时区启动应用: ```bash ./start.sh ``` > 脚本要求已设置 `JAVA_HOME`(macOS 可执行 `export JAVA_HOME=$(/usr/libexec/java_home -v 25)`); > 也可使用 `./build.sh` 一键完成构建并启动(自动定位本机 JDK 25)。 **方式二:直接运行** ```bash # 先加载环境变量 source .env # 启动应用 export JAVA_HOME=/path/to/jdk-25 # 请替换为本地 JDK 25 路径 java -jar qms-bijia-webapp/target/qms.jar ``` 默认端口 `8080`,接口统一前缀 `/api/v1`(`spring.servlet.context-path`)。 ## 测试 ### 单元测试 ```bash mvn test ``` ### 集成测试(Testcontainers) 集成测试使用 Testcontainers 启动 Docker MySQL 容器(通过 `qms-bijia-webapp/src/integration-test/resources/testcontainers/seed.sql` 初始化): ```bash ./run-it.sh # 运行全部集成测试(mvn verify -pl qms-bijia-webapp -am) ./run-it.sh AuthE2eIT # 运行单个集成测试 ``` 前提条件: - 本机安装并运行 Docker(脚本默认适配 colima,自动设置 `DOCKER_HOST` 与 `TESTCONTAINERS_RYUK_DISABLED`) - 可通过环境变量 `TESTCONTAINERS_MYSQL_IMAGE` 指定 MySQL 镜像(Docker Hub 被墙时可用 `docker.m.daocloud.io/library/mysql:8.0`) `mvn verify` 还会执行质量门禁,不满足将构建失败: - **JaCoCo 覆盖率**:单元测试与单元+集成(E2E)合并覆盖率均设有阈值门禁 - **Checkstyle**:代码规范检查(`checkstyle.xml`,含文件长度限制,测试目录一并检查) ## Docker 部署 提供两个 Docker Compose 文件,支持本地 MySQL 和外部 MySQL 两种部署方式。 ### 文件说明 | 文件 | 适用场景 | |------|----------| | `docker-compose.yml` | 本地 MySQL(单机全量部署) | | `docker-compose.external.yml` | 外部 MySQL(仅部署 Redis + 应用) | ### 快速启动 ```bash # 本地 MySQL 版(推荐) docker compose up -d # 外部 MySQL 版(需通过 .env 配置 DB_HOST 等) docker compose -f docker-compose.external.yml up -d ``` ### 环境变量 复制环境变量模板并编辑: ```bash cp env.properties.example .env ``` `.env` 文件和 `.yml` 文件放在同一目录即可,Docker Compose 会自动加载。 关键变量说明: | 变量 | 默认值 | 说明 | |------|--------|------| | `DB_HOST` | `mysql` | MySQL 地址(外部版需改为实际 IP) | | `DB_PORT` | `3306` | MySQL 端口 | | `DB_NAME` | `buk` | 数据库名 | | `DB_USERNAME` | `root` | 数据库用户名 | | `MYSQL_PASSWORD` | 安全默认值 | MySQL root 密码 | | `REDIS_PASSWORD` | 安全默认值 | Redis 密码 | | `DEMO_MODE` | `false` | 演示模式 | > 密码已有安全默认值,也可在 `.env` 中覆盖。 ### 数据目录 启动后会在当前目录自动创建以下目录: | 目录 | 内容 | |------|------| | `data/mysql/` | MySQL 数据库文件 | | `data/redis/` | Redis 持久化数据 | | `logs/` | 应用日志 | ### 首次部署 — 初始化数据库 生产环境 `spring.jpa.hibernate.ddl-auto` 为 `validate`,Hibernate 不会自动建表。应用启动时 Flyway 会自动执行 `classpath:db/migration` 下的迁移脚本完成建表与权限初始化(`spring.flyway.enabled=true`),无需手工导入 SQL。 若需在其他环境复用本地数据,可导入本地库备份或 `qms-bijia-webapp/src/integration-test/resources/testcontainers/seed.sql` 快照,再通过 Flyway 增量迁移。 ### 停止 ```bash docker compose down docker compose -f docker-compose.external.yml down ``` --- ## 已移除的外部依赖 | 模块 | 说明 | |------|------| | 南航 NDC 接口 | 移除 CZ NDC 自动出票、退改签、订单状态同步及相关 API | | 深圳科技 SZKJ-ETERM | 移除 SZKJ 接口依赖、ETERM 自动出票及 PNR 详情获取 | | ETERM 指令通道 | 移除 eterm 客户端及指令执行能力(保留降级占位逻辑) | | 企业微信集成 | 移除企微消息推送、用户同步、登录绑定等功能 | | kaptcha 验证码库 | 替换为自研验证码生成器(`cn.buk.qms.captcha`) | | JSP 视图 | 移除 JSP 页面及视图解析器配置(纯 REST API,打包为可执行 JAR) | | 独立航班模块 | `qms-flight-dao` / `qms-flight-service` 已并入 `qms-dao` / `qms-service` | ## 环境变量说明 | 变量名 | 说明 | |--------|------| | `DB_HOST` / `DB_PORT` / `DB_NAME` / `DB_USERNAME` / `DB_PASSWORD` | MySQL 连接信息 | | `SPRING_PROFILES_ACTIVE` | Spring Profile(`dev` / `prod` / `test`,默认 `dev`) | | `SPRING_JPA_HIBERNATE_DDL_AUTO` | Hibernate ddl-auto(dev 默认 `none`,prod 强制 `validate`) | | `REDIS_USED` / `REDIS_HOST` / `REDIS_PORT` / `REDIS_PASSWORD` / `REDIS_DB` | Redis 连接信息 | | `REDIS_NAMESPACE` | Redis key 前缀(含 Spring Session 命名空间) | | `API_HOTEL_URL` | 酒店 API 地址 | | `SMS_API_URL` / `SMS_SIGN_NAME` | 短信服务地址与签名 | | `SMS_TEMPLATE_CODE_REGISTER` / `SMS_TEMPLATE_CODE_RESET_PASSWORD` | 短信模板编码 | | `AI_LLM_API_URL` / `AI_LLM_API_KEY` / `AI_LLM_MODEL` | AI 代理网关 LLM 配置(兼容 OpenAI 接口格式) | | `ACTIVEMQ_BROKER_URL` | ActiveMQ 地址(默认 `tcp://localhost:61616`) | | `DEMO_MODE` | 演示模式(dev 默认 `true`,prod 默认 `false`) | | `MYSQL_PASSWORD` | Docker Compose 本地 MySQL root 密码 | ## 文档 - [系统功能介绍](doc/系统功能介绍.md) — 功能与 AI 代理网关详解 - [项目实体关系](doc/系统实体关系.md) — 数据模型说明 - [OpenAPI 契约试点](doc/api-spec.yaml) — 登录/用户模块 Contract-First 试点(`/self/**` 运行时规范见 SpringDoc `self-api` 分组) - [开放数据定义](doc/openapi/) — 国家/省份/城市/机场/航司/航站楼开放数据 XML