Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3a3a42f
feat(security): 阶段1 安全与认证(JWT/限流/RBAC/认证端点) (#2)
1na-ko Jun 15, 2026
a663ef2
feat(deps): 添加安全加密库和优化镜像源配置
nana112233445566 Jun 16, 2026
cc8a091
feat(core): 阶段2 核心业务数据层 — 全表 ORM 映射 + 基础服务 + 分类 API (#4)
1na-ko Jun 16, 2026
216c4ef
Merge branch 'develop' of https://github.com/1na-ko/LibrarySystem-SIT…
nana112233445566 Jun 16, 2026
4db01b7
feat(android): 实现人员B全部前端模块 — 借阅管理/预约管理/知识图谱/系统管理/条码扫描 (#5)
nana112233445566 Jun 16, 2026
09cbbba
feat(model & 依赖注入): 根据 OpenAPI 规范生成全部 VO/DTO 模型类 & 使用 Hilt 重构应用程序,添加网…
1na-ko Jun 16, 2026
e534748
feat(core): 阶段3 图书检索 — ES全文搜索/自动补全/热门榜/管理端编目 (#7)
1na-ko Jun 16, 2026
f5c094c
feat(core): 阶段4 借阅与预约 — 借阅全生命周期/预约排队/个人统计/超期定时检查 (#8)
1na-ko Jun 16, 2026
c69a7d1
fix(core): 阶段4质量审计修复 — 消除N+1/闭合预约状态机/补齐RBAC (#9)
1na-ko Jun 16, 2026
28f1f0e
fix(core): 阶段4第三轮综合质量审计修复 (#10)
1na-ko Jun 16, 2026
a99fcd8
feat(ai): 阶段5 AI基础设施 + 跨阶段审计修正 (#11)
1na-ko Jun 16, 2026
010477a
feat(core): 阶段6 图书推荐引擎 + 跨阶段综合审计修复 (#12)
1na-ko Jun 16, 2026
ef9b0d0
feat: 阶段7+8 学科知识图谱与智能采编 & 阶段8后综合质量审计修复(三轮) (#13)
1na-ko Jun 16, 2026
ff59377
docs: 同步文档索引与开发指南至阶段8完成状态
1na-ko Jun 16, 2026
62747e0
fix: 阶段9后综合质量审计修复(P0/P1/P2/P3 共33项) (#14)
1na-ko Jun 17, 2026
8295777
feat(frontend): complete 分工A - 基础架构 + 图书检索 + 个人中心 (#15)
1na-ko Jun 17, 2026
3fd3859
fix: 阶段9后综合审计修复 (#16)
1na-ko Jun 17, 2026
d28c599
refactor(android): UI redesign v2.1 for library-android (#17)
nana112233445566 Jun 17, 2026
6cccb7b
feat(android): 登录页中式学术美学重设计 + 体验修复 (#18)
nana112233445566 Jun 17, 2026
f3c53d1
feat: 阶段10 完整交付 — RabbitMQ 事件总线 + 集成测试 + 生产部署 + OWASP 安全加固 + 全端点验证 (#19)
1na-ko Jun 18, 2026
5308c3a
refactor(android):对前端代码规范化、已知缺陷及测试不充分等问题进行修复 (#20)
1na-ko Jun 22, 2026
daaeeb8
docs: 更新项目文档并增强Android端测试套件
1na-ko Jun 22, 2026
4b48428
chore: 20260622-汇总完成全量功能迭代与修复
1na-ko Jun 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=guest

# ---- JWT ----
# 生成方式: openssl rand -base64 64
# HS256 要求密钥 >= 32 字节(启动时 fail-fast 校验,不满足则拒绝启动)
# 生成方式: openssl rand -base64 48
JWT_SECRET=

# ---- LLM & Embedding ----
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ buildNumber.properties
out/
# VSCode(个人偏好不入库;共享配置如需提交请用 .vscode/extensions.json 等)
.vscode/
# Trae
*.trae

# ====== Android / Gradle ======
.gradle/
Expand Down
426 changes: 413 additions & 13 deletions CLAUDE.md

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# =============================================================================
# 图书馆智能管理系统 — 本地一键验证脚本(阶段10)
# Windows 用 git bash / WSL 运行(make 需 GNU make 3.82+,支持 .RECIPEPREFIX)
# 集成测试需 docker-compose 预启动 5 中间件(MySQL/Redis/ES+IK/Neo4j/RabbitMQ)
# =============================================================================
.RECIPEPREFIX = >

.PHONY: up down test itest itest-tcp package coverage verify-all es-ik-check wait-middleware

# 启动本地开发中间件(集成测试与应用调试共用)
up:
>docker-compose up -d
>@echo "中间件已启动。ES 首次需安装 IK 分词器后重启:make es-ik-check"

down:
>docker-compose down

# ES IK 分词器安装检查与提示(首次安装后需 restart ES 才生效)
es-ik-check:
>@echo "检查 ES IK 插件..."
>@docker exec library-es ls /usr/share/elasticsearch/plugins/analysis-ik >/dev/null 2>&1 \
&& echo "✓ IK 已安装" \
|| (echo "⚠ IK 未安装,执行:docker-compose up -d es-ik-installer && docker-compose restart elasticsearch")

# 仅单元测试(快,日常开发,不需 Docker)
test:
>cd library-server && mvn test

# 等待 5 中间件端口就绪(启动前检查;若未启动则提示 make up)
wait-middleware:
>@echo "等待中间件健康..."
>@for svc in mysql:3306 redis:6379 elasticsearch:9200 neo4j:7687 rabbitmq:5672; do \
port=$${svc##*:}; name=$${svc%%:*}; \
for i in 1 2 3 4 5 6 7 8 9 10; do \
(echo > /dev/tcp/localhost/$$port) 2>/dev/null && break; \
echo "等待 $$name ($$port)..."; sleep 3; \
done; \
(echo > /dev/tcp/localhost/$$port) 2>/dev/null || { echo "✗ $$name ($$port) 未就绪,请先 make up"; exit 1; }; \
done
>@echo "✓ 5 中间件就绪"

# 集成测试(需 docker-compose 5 中间件运行中,首次约 5-10 分钟)
itest: wait-middleware
>cd library-server && mvn test -Pintegration

# 集成测试(Docker Desktop 29 兼容方案:通过 TCP 2375 直连 Docker daemon
# 绕过 CLI 代理拦截;需在 Docker Desktop → Settings → General 勾选
# "Expose daemon on tcp://localhost:2375 without TLS",
# 详见 docs/implementation/阶段10完成记录.md §5)
itest-tcp: wait-middleware
>cd library-server && DOCKER_HOST=tcp://localhost:2375 mvn test -Pintegration

# 打包(跳过测试)
package:
>cd library-server && mvn clean package -DskipTests

# 覆盖率报告(含集成测试,需 Docker;对照架构文档 §11.4 目标)
coverage: wait-middleware
>cd library-server && mvn verify -Pintegration
>@echo "聚合覆盖率报告:library-server/library-bootstrap/target/site/jacoco-aggregate/index.html"

# 一键全验证
verify-all: itest coverage
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
| **搜索** | Elasticsearch 8.11 + IK 分词器 |
| **图库** | Neo4j 5.17 + APOC + GDS(PageRank / Dijkstra) |
| **缓存** | Redis 7.2(缓存 / 分布式锁 / ZSET 排队 / 令牌桶限流) |
| **消息** | RabbitMQ 3.12(异步事件,待引入 Starter) |
| **消息** | RabbitMQ 3.12(事件总线 / 异步消息) |
| **迁移** | Flyway 9.22(V1 基线 10 表 + V2 种子数据 + V3 索引补充) |
| **文档** | SpringDoc OpenAPI 2.6 |
| **NLP** | HanLP 1.8 portable(分词 / 关键词提取) |
Expand Down
125 changes: 125 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# =============================================================================
# 图书馆智能管理系统 — 生产环境 Docker Compose
# 安全设计:
# 1. 所有中间件端口仅绑定 127.0.0.1(不暴露公网),仅应用 8080 对外
# 2. 密码全部从 .env.prod 读取(不入库),部署时在服务器生成强随机值
# 3. 与开发 docker-compose.yml 分离,互不影响
# 启动:docker compose -f docker-compose.prod.yml --env-file .env.prod up -d
# =============================================================================
services:
mysql:
image: mysql:8.0.35
container_name: library-mysql-prod
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME:-library_db}
# 仅绑 127.0.0.1,不暴露公网;应用通过 localhost:3306 连接
ports:
- "127.0.0.1:3306:3306"
volumes:
- mysql_data:/var/lib/mysql
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 10s
timeout: 5s
retries: 10

redis:
image: redis:7.2-alpine
container_name: library-redis-prod
restart: unless-stopped
# 强密码从环境变量注入,仅绑 127.0.0.1
command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes
ports:
- "127.0.0.1:6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "PING"]
interval: 10s
timeout: 5s
retries: 10

elasticsearch:
image: elasticsearch:8.11.0
container_name: library-es-prod
restart: unless-stopped
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms1g -Xmx1g
- xpack.security.enabled=false
# ES 仅绑 127.0.0.1(9200 HTTP + 9300 transport 都不公网)
ports:
- "127.0.0.1:9200:9200"
volumes:
- es_data:/usr/share/elasticsearch/data
- es_plugins:/usr/share/elasticsearch/plugins

# IK 分词器安装器(首次安装后需 restart elasticsearch 生效)
es-ik-installer:
image: elasticsearch:8.11.0
container_name: library-es-ik-install-prod
command: >
bash -c "
if [ -d /usr/share/elasticsearch/plugins/analysis-ik ]; then
echo 'IK plugin already installed, skipping.'
else
echo 'Installing IK plugin...'
bin/elasticsearch-plugin install --batch https://get.infini.cloud/elasticsearch/analysis-ik/8.11.0
echo 'IK plugin installed. Please restart elasticsearch: docker compose -f docker-compose.prod.yml restart elasticsearch'
fi
"
volumes:
- es_plugins:/usr/share/elasticsearch/plugins
depends_on:
- elasticsearch

neo4j:
image: neo4j:5.17.0-community
container_name: library-neo4j-prod
restart: unless-stopped
environment:
NEO4J_AUTH: ${NEO4J_USERNAME}/${NEO4J_PASSWORD}
NEO4J_PLUGINS: '["apoc", "graph-data-science"]'
# 7474 (HTTP) + 7687 (Bolt) 仅绑 127.0.0.1
ports:
- "127.0.0.1:7474:7474"
- "127.0.0.1:7687:7687"
volumes:
- neo4j_data:/data
- neo4j_logs:/logs
healthcheck:
test: ["CMD", "cypher-shell", "-u", "${NEO4J_USERNAME}", "-p", "${NEO4J_PASSWORD}", "RETURN 1"]
interval: 15s
timeout: 10s
retries: 10

rabbitmq:
image: rabbitmq:3.12-management-alpine
container_name: library-rabbitmq-prod
restart: unless-stopped
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USERNAME}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
# 5672 (AMQP) + 15672 (管理界面) 仅绑 127.0.0.1
ports:
- "127.0.0.1:5672:5672"
- "127.0.0.1:15672:15672"
volumes:
- rabbitmq_data:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"]
interval: 10s
timeout: 5s
retries: 10

volumes:
mysql_data:
redis_data:
es_data:
es_plugins:
neo4j_data:
neo4j_logs:
rabbitmq_data:
17 changes: 14 additions & 3 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ public static final int days = 30; // 非 final 且未大写
| library-acquisition | 80% |
| library-security | 90% |
| library-bootstrap | 70% |
| library-android | 50% |
| library-android | 50%(**当前:35 测试类 / 178 tests,ViewModel + Repository 全覆盖**) |

### 7.2 测试命名规范

Expand Down Expand Up @@ -687,6 +687,17 @@ class BookServiceTest {
}
```

### 7.4 集成测试规范(阶段10)

集成测试连接 **docker-compose 预启动的真实中间件**(MySQL/Redis/ES+IK/Neo4j/RabbitMQ),与单元测试物理隔离:

- **位置**:`library-bootstrap/src/test/java/com/library/integration/`,继承 `AbstractIntegrationTest`(5 中间件健康前置 + Flyway clean+migrate 重置基线)
- **前置**:`make up` 启动 docker-compose 中间件(首次需 `make es-ik-check` 安装 IK 分词器)
- **运行**:`make itest`(或 Docker Desktop 29 兼容方案 `make itest-tcp`);日常 `mvn test` 仅跑单元测试(surefire 排除 `**/integration/**` 与 `LibraryApplicationTests`)
- **种子数据**:`src/test/resources/db/test-data/V100__test_seed.sql`,仅 test profile 加载(物理+配置+版本号三重隔离,防污染生产)
- **异步断言**:MQ 消费等异步场景用 Awaitility `await().atMost(...).untilAsserted()`,禁用 `Thread.sleep` 轮询
- **命名**:仍遵循 `should{预期行为}When{条件}`,集成测试类命名 `{场景}IntegrationTest`

---

## 8. PR 模板
Expand Down Expand Up @@ -758,8 +769,8 @@ class BookServiceTest {
| 缩进 | 4 个空格 |
| Code Style | Google Java Style |
| 最小 SDK | API 26 (Android 8.0) |
| 目标 SDK | API 34 (Android 14) |
| 编译 SDK | API 34 |
| 目标 SDK | API 35 (Android 15) |
| 编译 SDK | API 35 |

### 9.3 共享 EditorConfig

Expand Down
Loading
Loading