refactor: 四端切换改用JAR包直接运行,适配生产环境

main
SLMS Development Team 4 months ago
parent c42ce551c2
commit efb2b92b97

@ -769,18 +769,23 @@ public class CLIApplication {
System.out.println("\n╔════════════════════════════════════╗");
System.out.println("║ 切换到 GUI 桌面版本 ║");
System.out.println("╚════════════════════════════════════╝");
System.out.println("正在启动GUI...");
try {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"gradlew :gui:run --no-daemon -q");
pb.directory(new java.io.File(System.getProperty("user.dir")));
pb.start();
System.out.println("✓ GUI 正在启动CLI 即将退出...");
speechService.shutdown();
System.exit(0);
// 查找GUI的JAR包
java.io.File jarFile = findJar("gui");
if (jarFile != null && jarFile.exists()) {
System.out.println("正在启动GUI...");
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"java -jar \"" + jarFile.getAbsolutePath() + "\"");
pb.start();
System.out.println("✓ GUI 正在启动CLI 即将退出...");
speechService.shutdown();
System.exit(0);
} else {
System.out.println("未找到GUI JAR包请先构建gradlew :gui:shadowJar");
System.out.println("或直接运行java -jar gui/build/libs/gui-1.0.0-all.jar");
}
} catch (Exception e) {
System.out.println("✗ 切换失败: " + e.getMessage());
System.out.println("请手动运行: gradlew :gui:run");
}
}
@ -788,22 +793,57 @@ public class CLIApplication {
System.out.println("\n╔════════════════════════════════════╗");
System.out.println("║ 切换到 Web 浏览器版本 ║");
System.out.println("╚════════════════════════════════════╝");
System.out.println("正在启动Web服务...");
try {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"gradlew :backend:bootRun --no-daemon -q");
pb.directory(new java.io.File(System.getProperty("user.dir")));
pb.start();
System.out.println("✓ Web服务正在启动...");
System.out.println("请访问: http://localhost:8082");
System.out.println("CLI 即将退出...");
speechService.shutdown();
System.exit(0);
java.io.File jarFile = findJar("backend");
if (jarFile != null && jarFile.exists()) {
System.out.println("正在启动Web服务...");
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"java -jar \"" + jarFile.getAbsolutePath() + "\"");
pb.start();
System.out.println("✓ Web服务正在启动...");
System.out.println("请访问: http://localhost:8082");
// 延迟打开浏览器
new Thread(() -> {
try {
Thread.sleep(5000);
java.awt.Desktop.getDesktop().browse(new java.net.URI("http://localhost:8082"));
} catch (Exception ex) {}
}).start();
System.out.println("CLI 即将退出...");
speechService.shutdown();
System.exit(0);
} else {
System.out.println("未找到Web JAR包请先构建gradlew :backend:bootJar");
System.out.println("或直接运行java -jar backend/build/libs/backend-1.0-SNAPSHOT.jar");
}
} catch (Exception e) {
System.out.println("✗ 切换失败: " + e.getMessage());
System.out.println("请手动运行: gradlew :backend:bootRun");
}
}
private java.io.File findJar(String module) {
// 查找JAR包 - 支持多种命名格式
String[] basePaths = {"", "../"};
for (String base : basePaths) {
java.io.File libDir = new java.io.File(base + module + "/build/libs");
if (libDir.exists() && libDir.isDirectory()) {
java.io.File[] jars = libDir.listFiles((dir, name) ->
name.endsWith("-all.jar") ||
(name.endsWith(".jar") && !name.contains("-plain") && name.contains(module)));
if (jars != null && jars.length > 0) {
// 优先选择-all.jar
for (java.io.File jar : jars) {
if (jar.getName().endsWith("-all.jar")) return jar;
}
return jars[0];
}
}
}
// 检查libs目录
java.io.File simpleJar = new java.io.File("libs/" + module + ".jar");
if (simpleJar.exists()) return simpleJar;
return null;
}
private void showAppQRCode() {
System.out.println("\n╔════════════════════════════════════╗");

@ -0,0 +1,590 @@
# MCSLMS 各端开发指南
本文档详细介绍如何开发智能图书管理系统的四个客户端CLI、GUI、Web、Android。
> **项目地址**: https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
## 目录
1. [环境准备](#环境准备)
2. [Core核心模块开发](#core核心模块开发)
3. [CLI命令行端开发](#cli命令行端开发)
4. [GUI桌面端开发](#gui桌面端开发)
5. [Web浏览器端开发](#web浏览器端开发)
6. [Android移动端开发](#android移动端开发)
---
## 环境准备
### 必需软件
| 软件 | 版本要求 | 用途 |
|------|---------|------|
| JDK | 21+ | Java运行环境 |
| Gradle | 8.5+ | 构建工具 |
| Android Studio | 最新版 | Android开发 |
| Git | 最新版 | 版本控制 |
### 安装步骤
#### 1. 安装JDK 21
```bash
# Windows - 使用Chocolatey
choco install openjdk21
# 或下载安装
# https://adoptium.net/temurin/releases/
```
验证安装:
```bash
java -version
# 输出: openjdk version "21.x.x"
```
#### 2. 安装Gradle
```bash
# Windows - 使用Chocolatey
choco install gradle
# 或手动下载
# https://gradle.org/releases/
```
验证安装:
```bash
gradle -v
# 输出: Gradle 8.5
```
#### 3. 克隆项目
```bash
git clone https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
cd mcslms
```
---
## Core核心模块开发
Core模块是所有客户端的共享基础包含业务逻辑、数据模型和数据访问层。
### 项目结构
```
core/
├── src/main/java/com/smartlibrary/
│ ├── model/ # 数据模型
│ │ ├── Book.java
│ │ ├── Loan.java
│ │ └── User.java
│ ├── service/ # 业务服务
│ │ ├── BookService.java
│ │ ├── UserService.java
│ │ └── MockDataService.java
│ ├── database/ # 数据库访问
│ │ └── DatabaseConnection.java
│ └── ai/ # AI服务
│ ├── AIService.java
│ ├── AIModelFactory.java
│ ├── DeepSeekService.java
│ └── MockAIService.java
└── build.gradle
```
### 核心类说明
#### Book.java - 图书模型
```java
public class Book {
private String id;
private String title;
private String author;
private String isbn;
private String publisher;
private LocalDate publishDate;
private String category;
private boolean available;
private String bookType; // PHYSICAL, EBOOK, JOURNAL
// 构造函数、getter、setter...
}
```
#### BookService.java - 图书服务
```java
public class BookService {
// 添加图书
public boolean addBook(String bookType, String title, String author,
String isbn, String publisher, LocalDate publishDate,
String category);
// 查询所有图书
public List<Book> findAllBooks();
// 借阅图书
public boolean borrowBook(String bookId, String userId);
// 归还图书
public boolean returnBook(String bookId);
}
```
### 构建Core模块
```bash
# 编译
gradle :core:build
# 生成JAR
gradle :core:jar
```
---
## CLI命令行端开发
CLI端提供命令行交互界面适合服务器环境和自动化脚本。
### 项目结构
```
cli/
├── src/main/java/com/smartlibrary/cli/
│ └── CLIApplication.java
├── build.gradle
└── README.md
```
### CLIApplication.java 核心代码
```java
public class CLIApplication {
private final BookService bookService;
private final Scanner scanner;
public static void main(String[] args) {
new CLIApplication().run();
}
public void run() {
System.out.println("=== 智能图书管理系统 CLI ===");
while (true) {
showMenu();
int choice = scanner.nextInt();
switch (choice) {
case 1 -> listBooks();
case 2 -> addBook();
case 3 -> borrowBook();
case 4 -> returnBook();
case 5 -> aiChat();
case 0 -> { return; }
}
}
}
private void showMenu() {
System.out.println("\n1. 查看图书列表");
System.out.println("2. 添加图书");
System.out.println("3. 借阅图书");
System.out.println("4. 归还图书");
System.out.println("5. AI助手");
System.out.println("0. 退出");
System.out.print("请选择: ");
}
}
```
### build.gradle 配置
```groovy
plugins {
id 'java'
id 'application'
}
dependencies {
implementation project(':core')
}
application {
mainClass = 'com.smartlibrary.cli.CLIApplication'
}
// 打包可执行JAR
jar {
manifest {
attributes 'Main-Class': 'com.smartlibrary.cli.CLIApplication'
}
from {
configurations.runtimeClasspath.collect {
it.isDirectory() ? it : zipTree(it)
}
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
```
### 运行CLI
```bash
# 方式1: 使用Gradle
gradle :cli:run
# 方式2: 使用脚本
scripts/run-cli.bat
# 方式3: 运行JAR
java -jar cli/build/libs/cli-1.0.0-all.jar
```
---
## GUI桌面端开发
GUI端使用JavaFX构建桌面应用提供图形化操作界面。
### 项目结构
```
gui/
├── src/main/java/com/smartlibrary/gui/
│ ├── GUIApplication.java # 主应用
│ ├── MainController.java # 主控制器
│ └── AIController.java # AI控制器
├── src/main/resources/
│ └── fxml/
│ ├── main.fxml
│ └── ai.fxml
└── build.gradle
```
### GUIApplication.java 核心代码
```java
public class GUIApplication extends Application {
@Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/fxml/main.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root, 1200, 800);
primaryStage.setTitle("智能图书管理系统");
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
```
### build.gradle 配置
```groovy
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.1.0'
}
javafx {
version = "21"
modules = ['javafx.controls', 'javafx.fxml']
}
dependencies {
implementation project(':core')
}
application {
mainClass = 'com.smartlibrary.gui.GUIApplication'
}
```
### 运行GUI
```bash
# 方式1: 使用Gradle
gradle :gui:run
# 方式2: 使用脚本
scripts/run-gui.bat
```
---
## Web浏览器端开发
Web端使用Spring Boot + Thymeleaf构建提供浏览器访问界面。
### 项目结构
```
backend/
├── src/main/java/com/smartlibrary/web/
│ ├── WebApplication.java # Spring Boot启动类
│ └── controller/
│ └── WebController.java # Web控制器
├── src/main/resources/
│ ├── templates/ # Thymeleaf模板
│ │ ├── index.html
│ │ ├── books.html
│ │ ├── loans.html
│ │ └── login.html
│ └── application.properties
└── build.gradle
```
### WebApplication.java
```java
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
System.out.println("Web服务已启动: http://localhost:8082");
}
}
```
### WebController.java 核心路由
```java
@Controller
public class WebController {
private final BookService bookService;
@GetMapping("/")
public String index(Model model) {
model.addAttribute("bookCount", bookService.findAllBooks().size());
return "index";
}
@GetMapping("/books")
public String books(Model model) {
model.addAttribute("books", bookService.findAllBooks());
return "books";
}
@PostMapping("/books/borrow")
public String borrowBook(@RequestParam String bookId,
@RequestParam String userId) {
bookService.borrowBook(bookId, userId);
return "redirect:/loans?borrowSuccess=true";
}
}
```
### build.gradle 配置
```groovy
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
dependencies {
implementation project(':core')
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
springBoot {
mainClass = 'com.smartlibrary.web.WebApplication'
}
```
### 运行Web
```bash
# 方式1: 使用Gradle
gradle :backend:bootRun
# 方式2: 使用脚本
scripts/run-web.bat
# 访问地址
http://localhost:8082
```
---
## Android移动端开发
Android端使用Kotlin开发提供移动设备访问能力。
### 项目结构
```
android/
├── src/main/
│ ├── java/com/smartlibrary/android/
│ │ ├── MainActivity.kt
│ │ ├── ui/
│ │ │ ├── BookListActivity.kt
│ │ │ └── AIActivity.kt
│ │ └── service/
│ │ └── BookApiService.kt
│ ├── res/
│ │ ├── layout/
│ │ │ ├── activity_main.xml
│ │ │ └── activity_book_list.xml
│ │ └── values/
│ │ └── strings.xml
│ └── AndroidManifest.xml
└── build.gradle
```
### MainActivity.kt 核心代码
```kotlin
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setupNavigation()
}
private fun setupNavigation() {
binding.btnBooks.setOnClickListener {
startActivity(Intent(this, BookListActivity::class.java))
}
binding.btnAI.setOnClickListener {
startActivity(Intent(this, AIActivity::class.java))
}
}
}
```
### build.gradle 配置
```groovy
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.smartlibrary.android'
compileSdk 34
defaultConfig {
applicationId "com.smartlibrary.android"
minSdk 26
targetSdk 34
versionCode 1
versionName "1.0"
}
}
dependencies {
implementation project(':core')
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
}
```
### 运行Android
```bash
# 方式1: 使用Android Studio
# 打开项目 -> 选择android模块 -> Run
# 方式2: 命令行
gradle :android:installDebug
# 方式3: 使用脚本
scripts/run-android.bat
```
---
## 总结
| 端 | 技术栈 | 启动命令 | 访问方式 |
|----|--------|---------|---------|
| CLI | Java | `gradle :cli:run` | 终端 |
| GUI | JavaFX | `gradle :gui:run` | 桌面窗口 |
| Web | Spring Boot | `gradle :backend:bootRun` | http://localhost:8082 |
| Android | Kotlin | Android Studio | 手机/模拟器 |
所有端共享 `core` 模块,保证业务逻辑一致性。
---
## 初学者快速上手
### 第一步克隆并切换到develop分支
```bash
# 克隆项目
git clone https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
cd mcslms
# 切换到develop分支包含所有四端代码
git checkout develop
```
### 第二步:验证环境
```bash
# 检查Java版本
java -version
# 应显示: openjdk version "21.x.x"
# 检查Gradle
gradle -v
# 应显示: Gradle 8.5
```
### 第三步:一键构建所有模块
```bash
# Windows
gradlew.bat build
# Linux/Mac
./gradlew build
```
### 第四步:依次启动各端测试
```bash
# 1. 启动CLI命令行
gradlew.bat :cli:run
# 2. 启动GUI新开终端
gradlew.bat :gui:run
# 3. 启动Web新开终端
gradlew.bat :backend:bootRun
# 访问 http://localhost:8082
# 4. Android需要Android Studio打开android目录
```
### 常见问题排查
| 问题 | 解决方案 |
|------|---------|
| `java: command not found` | 安装JDK 21并配置JAVA_HOME |
| `gradle: command not found` | 使用项目自带的gradlew.bat |
| 端口8082被占用 | 修改application.properties中的server.port |
| Android编译失败 | 确保安装Android SDK 34 |

@ -0,0 +1,413 @@
# MCSLMS 四端切换指南
本文档介绍如何在CLI、GUI、Web、Android四个客户端之间无缝切换。
> **项目地址**: https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
## 目录
1. [切换原理](#切换原理)
2. [统一启动器](#统一启动器)
3. [手动切换方式](#手动切换方式)
4. [数据同步机制](#数据同步机制)
5. [常见问题](#常见问题)
---
## 切换原理
### 架构设计
```
┌─────────────────────────────────────────────────────┐
│ 用户界面层 │
├──────────┬──────────┬──────────┬───────────────────┤
│ CLI │ GUI │ Web │ Android │
│ 命令行 │ JavaFX │ Spring │ Kotlin │
└────┬─────┴────┬─────┴────┬─────┴────────┬──────────┘
│ │ │ │
└──────────┴──────────┴──────────────┘
┌───────┴───────┐
│ Core 模块 │
│ 业务逻辑层 │
└───────┬───────┘
┌───────┴───────┐
│ SQLite │
│ 数据库 │
└───────────────┘
```
### 核心特点
1. **共享Core模块**: 所有端使用相同的业务逻辑
2. **统一数据库**: SQLite数据库文件共享
3. **一致的API**: 相同的服务接口
4. **独立运行**: 各端可独立启动
---
## 统一启动器
### 启动器介绍
统一启动器 `launcher` 提供一个入口,让用户选择要使用的客户端。
### 使用方法
#### 方式1: 使用启动脚本
```bash
# Windows
start.bat
# 或
scripts\run-launcher.bat
```
#### 方式2: 直接运行
```bash
gradle :launcher:run
```
### 启动器界面
```
╔══════════════════════════════════════════════════╗
║ 智能图书管理系统 - 多客户端启动器 ║
╠══════════════════════════════════════════════════╣
║ ║
║ 请选择要启动的客户端: ║
║ ║
║ [1] CLI - 命令行界面 ║
║ [2] GUI - 图形界面 (JavaFX) ║
║ [3] Web - 浏览器界面 (Spring Boot) ║
║ [4] All - 同时启动所有客户端 ║
║ [0] Exit - 退出 ║
║ ║
╚══════════════════════════════════════════════════╝
请输入选项:
```
### 启动器源码
```java
// launcher/src/main/java/com/smartlibrary/launcher/Launcher.java
public class Launcher {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
printMenu();
int choice = scanner.nextInt();
switch (choice) {
case 1 -> launchCLI();
case 2 -> launchGUI();
case 3 -> launchWeb();
case 4 -> launchAll();
case 0 -> {
System.out.println("再见!");
return;
}
}
}
}
private static void launchCLI() {
System.out.println("启动CLI客户端...");
CLIApplication.main(new String[]{});
}
private static void launchGUI() {
System.out.println("启动GUI客户端...");
new Thread(() -> GUIApplication.main(new String[]{})).start();
}
private static void launchWeb() {
System.out.println("启动Web服务...");
new Thread(() -> WebApplication.main(new String[]{})).start();
System.out.println("Web服务地址: http://localhost:8082");
}
}
```
---
## 手动切换方式
### 方式1: 使用脚本切换
项目提供了便捷的启动脚本:
```bash
# 启动CLI
scripts\run-cli.bat
# 启动GUI
scripts\run-gui.bat
# 启动Web
scripts\run-web.bat
# 启动Android (需要模拟器)
scripts\run-android.bat
```
### 方式2: 使用Gradle切换
```bash
# 切换到CLI
gradle :cli:run
# 切换到GUI
gradle :gui:run
# 切换到Web
gradle :backend:bootRun
# 构建Android APK
gradle :android:assembleDebug
```
### 方式3: 运行JAR包
首先构建所有JAR
```bash
# 构建所有模块
gradle build
# 或单独构建
gradle :cli:jar
gradle :gui:jar
```
然后运行:
```bash
# 运行CLI
java -jar cli/build/libs/cli-1.0.0-all.jar
# 运行GUI
java -jar gui/build/libs/gui-1.0.0-all.jar
```
---
## 数据同步机制
### SQLite数据库共享
所有客户端使用同一个SQLite数据库文件
```
项目根目录/
└── library.db # 共享数据库文件
```
### 数据库配置
每个模块的 `datasource.properties`:
```properties
# 数据库类型
db.type=sqlite
# 数据库文件路径 (相对于项目根目录)
db.path=library.db
# 或使用绝对路径
# db.path=E:/MCSLMS/library.db
```
### 数据一致性保证
```java
// DatabaseConnection.java
public class DatabaseConnection {
private static final String DB_PATH = "library.db";
private static Connection connection;
public static synchronized Connection getConnection() {
if (connection == null) {
String url = "jdbc:sqlite:" + DB_PATH;
connection = DriverManager.getConnection(url);
}
return connection;
}
}
```
### 实时同步演示
1. **在CLI添加图书**:
```
CLI> 添加图书
书名: Java编程思想
作者: Bruce Eckel
添加成功!
```
2. **在GUI查看**:
- 打开GUI客户端
- 点击"刷新"按钮
- 新添加的图书立即显示
3. **在Web查看**:
- 访问 http://localhost:8082/books
- 页面显示最新图书列表
---
## 端间切换流程
### 场景1: CLI → GUI
```bash
# 1. 在CLI完成操作后退出
CLI> 0 (退出)
# 2. 启动GUI
gradle :gui:run
# 3. GUI自动加载最新数据
```
### 场景2: GUI → Web
```bash
# 1. GUI可以保持运行
# 2. 新开终端启动Web
gradle :backend:bootRun
# 3. 浏览器访问
http://localhost:8082
```
### 场景3: Web → Android
```bash
# 1. Web服务保持运行 (作为API服务器)
# 2. Android连接到Web API
# 配置 android/src/main/res/values/strings.xml
<string name="api_base_url">http://10.0.2.2:8082</string>
# 3. 启动Android模拟器
gradle :android:installDebug
```
---
## Web界面切换功能
Web端提供了可视化的客户端切换页面
### 访问切换页面
```
http://localhost:8082/switch
```
### 切换页面功能
```html
<!-- switch.html -->
<div class="client-switcher">
<h2>选择客户端</h2>
<div class="client-card" onclick="downloadCLI()">
<i class="bi bi-terminal"></i>
<h4>CLI 命令行</h4>
<p>适合服务器环境</p>
<button>下载 JAR</button>
</div>
<div class="client-card" onclick="downloadGUI()">
<i class="bi bi-window"></i>
<h4>GUI 桌面版</h4>
<p>图形化操作界面</p>
<button>下载 JAR</button>
</div>
<div class="client-card">
<i class="bi bi-globe"></i>
<h4>Web 浏览器</h4>
<p>当前正在使用</p>
<span class="badge">当前</span>
</div>
<div class="client-card" onclick="downloadAPK()">
<i class="bi bi-phone"></i>
<h4>Android 移动端</h4>
<p>手机随时访问</p>
<button>下载 APK</button>
</div>
</div>
```
---
## 常见问题
### Q1: 数据库被锁定怎么办?
**问题**: 多个客户端同时写入时可能出现锁定
**解决方案**:
```java
// 使用WAL模式
connection.createStatement().execute("PRAGMA journal_mode=WAL");
```
### Q2: 端口冲突怎么办?
**问题**: Web端口8082被占用
**解决方案**:
```properties
# application.properties
server.port=8083
```
### Q3: Android无法连接Web服务
**问题**: 模拟器无法访问localhost
**解决方案**:
```kotlin
// 使用10.0.2.2代替localhost
val BASE_URL = "http://10.0.2.2:8082"
```
### Q4: 如何同时运行多个客户端?
**方案**: 使用启动器的"All"选项,或分别在不同终端启动:
```bash
# 终端1
gradle :cli:run
# 终端2
gradle :gui:run
# 终端3
gradle :backend:bootRun
```
---
## 快速参考
| 操作 | 命令 |
|------|------|
| 启动CLI | `gradle :cli:run` |
| 启动GUI | `gradle :gui:run` |
| 启动Web | `gradle :backend:bootRun` |
| 启动Android | `gradle :android:installDebug` |
| 启动全部 | `start.bat` → 选择4 |
| 构建全部 | `gradle build` |

@ -0,0 +1,579 @@
# MCSLMS 合并开发指南
本文档介绍如何将各个功能分支合并到develop分支实现最终的集成开发。
> **项目地址**: https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
## 目录
1. [分支策略](#分支策略)
2. [合并前准备](#合并前准备)
3. [分支合并步骤](#分支合并步骤)
4. [冲突解决](#冲突解决)
5. [集成测试](#集成测试)
6. [发布流程](#发布流程)
---
## 分支策略
### Git Flow 分支模型
```
main (生产分支)
├── develop (开发主分支)
│ │
│ ├── feature/core (核心模块)
│ ├── feature/cli (CLI客户端)
│ ├── feature/gui (GUI客户端)
│ ├── feature/web (Web客户端)
│ └── feature/app (Android客户端)
└── release/v1.0 (发布分支)
```
### 分支说明
| 分支 | 用途 | 生命周期 |
|------|------|---------|
| main | 生产环境代码 | 永久 |
| develop | 开发集成分支 | 永久 |
| feature/* | 功能开发分支 | 临时 |
| release/* | 发布准备分支 | 临时 |
| hotfix/* | 紧急修复分支 | 临时 |
---
## 合并前准备
### 步骤1: 查看当前分支状态
```bash
# 查看所有分支
git branch -a
# 输出示例:
# * develop
# feature/app
# feature/cli
# feature/core
# feature/gui
# feature/web
# main
# remotes/origin/develop
# remotes/origin/feature/app
# ...
```
### 步骤2: 更新本地仓库
```bash
# 获取远程更新
git fetch origin
# 切换到develop分支
git checkout develop
# 拉取最新代码
git pull origin develop
```
### 步骤3: 确保各分支可编译
```bash
# 测试core分支
git checkout feature/core
gradle :core:build
# 测试cli分支
git checkout feature/cli
gradle :cli:build
# 测试gui分支
git checkout feature/gui
gradle :gui:build
# 测试web分支
git checkout feature/web
gradle :backend:build
# 测试app分支
git checkout feature/app
gradle :android:assembleDebug
```
---
## 分支合并步骤
### 合并顺序
按照依赖关系,推荐的合并顺序:
```
1. feature/core → develop (核心模块优先)
2. feature/cli → develop (CLI依赖core)
3. feature/gui → develop (GUI依赖core)
4. feature/web → develop (Web依赖core)
5. feature/app → develop (App依赖core)
```
### 步骤1: 合并Core模块
```bash
# 切换到develop
git checkout develop
# 合并core分支
git merge feature/core -m "Merge feature/core: 核心业务模块"
# 如果有冲突,解决后继续
git add .
git commit -m "Resolve conflicts in core merge"
# 验证编译
gradle :core:build
```
### 步骤2: 合并CLI模块
```bash
# 确保在develop分支
git checkout develop
# 合并cli分支
git merge feature/cli -m "Merge feature/cli: 命令行客户端"
# 验证编译
gradle :cli:build
gradle :cli:run # 测试运行
```
### 步骤3: 合并GUI模块
```bash
git checkout develop
git merge feature/gui -m "Merge feature/gui: 图形界面客户端"
# 验证
gradle :gui:build
```
### 步骤4: 合并Web模块
```bash
git checkout develop
git merge feature/web -m "Merge feature/web: Web浏览器客户端"
# 验证
gradle :backend:build
gradle :backend:bootRun # 测试启动
```
### 步骤5: 合并Android模块
```bash
git checkout develop
git merge feature/app -m "Merge feature/app: Android移动客户端"
# 验证
gradle :android:assembleDebug
```
### 步骤6: 推送到远程
```bash
# 推送develop分支
git push origin develop
```
---
## 冲突解决
### 常见冲突类型
#### 1. build.gradle 冲突
```groovy
<<<<<<< HEAD
dependencies {
implementation 'org.xerial:sqlite-jdbc:3.45.1.0'
}
=======
dependencies {
implementation 'org.xerial:sqlite-jdbc:3.44.0.0'
}
>>>>>>> feature/web
```
**解决方案**: 选择较新版本
```groovy
dependencies {
implementation 'org.xerial:sqlite-jdbc:3.45.1.0'
}
```
#### 2. settings.gradle 冲突
```groovy
<<<<<<< HEAD
include ':core'
include ':cli'
=======
include ':core'
include ':cli'
include ':gui'
>>>>>>> feature/gui
```
**解决方案**: 合并所有模块
```groovy
include ':core'
include ':cli'
include ':gui'
include ':backend'
include ':android'
include ':launcher'
```
#### 3. 代码逻辑冲突
```java
<<<<<<< HEAD
public void addBook(Book book) {
// CLI实现
books.add(book);
}
=======
public boolean addBook(Book book) {
// Web实现
return bookRepository.save(book) != null;
}
>>>>>>> feature/web
```
**解决方案**: 统一接口设计
```java
public boolean addBook(Book book) {
try {
books.add(book);
return true;
} catch (Exception e) {
return false;
}
}
```
### 冲突解决工具
#### 使用VS Code
```bash
# VS Code会自动识别冲突
code .
# 点击冲突文件,选择:
# - Accept Current Change (保留当前)
# - Accept Incoming Change (接受传入)
# - Accept Both Changes (两者都要)
```
#### 使用命令行
```bash
# 查看冲突文件
git status
# 手动编辑解决冲突
vim <冲突文件>
# 标记为已解决
git add <冲突文件>
# 继续合并
git commit
```
---
## 集成测试
### 测试清单
合并完成后,执行以下测试:
#### 1. 编译测试
```bash
# 清理并重新构建
gradle clean build
# 预期结果: BUILD SUCCESSFUL
```
#### 2. 单元测试
```bash
# 运行所有测试
gradle test
# 查看测试报告
# build/reports/tests/test/index.html
```
#### 3. 功能测试
```bash
# 测试CLI
gradle :cli:run
# 执行: 添加图书 → 查看列表 → 借阅 → 归还
# 测试GUI
gradle :gui:run
# 执行: 图形界面操作
# 测试Web
gradle :backend:bootRun
# 访问: http://localhost:8082
# 执行: 登录 → 图书管理 → 借阅管理
# 测试Android
gradle :android:installDebug
# 在模拟器中测试
```
#### 4. 集成测试
```bash
# 同时启动多个客户端
# 终端1
gradle :cli:run
# 终端2
gradle :backend:bootRun
# 测试数据同步:
# 1. CLI添加图书
# 2. Web刷新查看
# 3. 确认数据一致
```
### 测试脚本
创建自动化测试脚本:
```bash
# scripts/integration-test.bat
@echo off
echo === MCSLMS 集成测试 ===
echo [1/4] 编译测试...
call gradle clean build
if %errorlevel% neq 0 (
echo 编译失败!
exit /b 1
)
echo [2/4] 单元测试...
call gradle test
if %errorlevel% neq 0 (
echo 单元测试失败!
exit /b 1
)
echo [3/4] CLI测试...
call gradle :cli:run --args="--test"
echo [4/4] Web测试...
start /b gradle :backend:bootRun
timeout /t 10
curl http://localhost:8082/api/books
echo === 测试完成 ===
```
---
## 发布流程
### 步骤1: 创建发布分支
```bash
# 从develop创建release分支
git checkout develop
git checkout -b release/v1.0.0
# 更新版本号
# 编辑 build.gradle
version = '1.0.0'
```
### 步骤2: 发布准备
```bash
# 最终测试
gradle clean build test
# 生成发布包
gradle :cli:shadowJar
gradle :gui:shadowJar
gradle :android:assembleRelease
```
### 步骤3: 合并到main
```bash
# 合并到main
git checkout main
git merge release/v1.0.0 -m "Release v1.0.0"
# 打标签
git tag -a v1.0.0 -m "Version 1.0.0"
# 推送
git push origin main
git push origin v1.0.0
```
### 步骤4: 同步回develop
```bash
# 将release合并回develop
git checkout develop
git merge release/v1.0.0
# 删除release分支
git branch -d release/v1.0.0
```
---
## 最终项目结构
合并完成后的项目结构:
```
MCSLMS/
├── core/ # 核心业务模块
│ ├── src/main/java/
│ │ └── com/smartlibrary/
│ │ ├── model/
│ │ ├── service/
│ │ ├── database/
│ │ └── ai/
│ └── build.gradle
├── cli/ # CLI客户端
│ ├── src/main/java/
│ └── build.gradle
├── gui/ # GUI客户端
│ ├── src/main/java/
│ ├── src/main/resources/fxml/
│ └── build.gradle
├── backend/ # Web后端
│ ├── src/main/java/
│ ├── src/main/resources/templates/
│ └── build.gradle
├── android/ # Android客户端
│ ├── src/main/java/
│ ├── src/main/res/
│ └── build.gradle
├── launcher/ # 统一启动器
│ └── src/main/java/
├── scripts/ # 脚本文件
│ ├── run-cli.bat
│ ├── run-gui.bat
│ ├── run-web.bat
│ └── run-android.bat
├── docs/ # 文档
├── build.gradle # 根构建文件
├── settings.gradle # 模块配置
├── gradlew.bat # Gradle包装器
├── Jenkinsfile # CI/CD配置
└── README.md # 项目说明
```
---
## 快速参考
| 操作 | 命令 |
|------|------|
| 查看分支 | `git branch -a` |
| 切换分支 | `git checkout <branch>` |
| 合并分支 | `git merge <branch>` |
| 解决冲突 | 编辑文件 → `git add``git commit` |
| 推送代码 | `git push origin <branch>` |
| 打标签 | `git tag -a v1.0.0 -m "message"` |
| 构建全部 | `gradle clean build` |
| 运行测试 | `gradle test` |
---
## 初学者完整操作流程
### 场景从零开始合并所有分支到develop
```bash
# 1. 克隆项目
git clone https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
cd mcslms
# 2. 查看所有分支
git branch -a
# 输出:
# * main
# remotes/origin/develop
# remotes/origin/feature/app
# remotes/origin/feature/cli
# remotes/origin/feature/gui
# remotes/origin/feature/web
# 3. 切换到develop分支
git checkout develop
# 4. 如果develop已包含所有代码直接构建测试
gradlew.bat build
# 5. 如果需要手动合并各分支
git merge origin/feature/core -m "合并core模块"
git merge origin/feature/cli -m "合并CLI模块"
git merge origin/feature/gui -m "合并GUI模块"
git merge origin/feature/web -m "合并Web模块"
git merge origin/feature/app -m "合并Android模块"
# 6. 解决可能的冲突后提交
git add .
git commit -m "完成四端合并"
# 7. 推送到远程
git push origin develop
```
### 验证合并成功
```bash
# 构建所有模块
gradlew.bat clean build
# 依次测试各端
gradlew.bat :cli:run # CLI正常运行
gradlew.bat :gui:run # GUI窗口打开
gradlew.bat :backend:bootRun # Web服务启动在8082端口
```
### 注意事项
1. **合并顺序很重要**: core → cli → gui → web → app
2. **冲突优先保留新版本**: 特别是版本号和依赖
3. **合并后必须测试**: 确保所有模块都能正常编译运行
4. **保持settings.gradle完整**: 确保包含所有模块声明

@ -0,0 +1,708 @@
# MCSLMS CI/CD 流水线指南
本文档介绍如何配置和使用Jenkins流水线实现持续集成和持续部署。
> **项目地址**: https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
## 目录
1. [CI/CD概述](#cicd概述)
2. [环境准备](#环境准备)
3. [Jenkins配置](#jenkins配置)
4. [Jenkinsfile详解](#jenkinsfile详解)
5. [SonarQube集成](#sonarqube集成)
6. [自动化部署](#自动化部署)
---
## CI/CD概述
### 什么是CI/CD
- **CI (持续集成)**: 自动化构建和测试代码
- **CD (持续部署)**: 自动化部署到生产环境
### 流水线流程
```
代码提交 → 触发构建 → 编译 → 测试 → 代码分析 → 打包 → 部署
│ │ │ │ │ │ │
└──────────┴────────┴──────┴────────┴─────────┴───────┘
Jenkins Pipeline
```
### 本项目流水线
```
┌─────────────────────────────────────────────────────────────┐
│ MCSLMS Pipeline │
├─────────────────────────────────────────────────────────────┤
│ Stage 1: Checkout - 拉取代码 │
│ Stage 2: Build - 编译所有模块 │
│ Stage 3: Test - 运行单元测试 │
│ Stage 4: SonarQube - 代码质量分析 │
│ Stage 5: Package - 打包JAR/APK │
│ Stage 6: Deploy - 部署到服务器 │
└─────────────────────────────────────────────────────────────┘
```
---
## 环境准备
### 必需软件
| 软件 | 版本 | 用途 |
|------|------|------|
| Jenkins | 2.400+ | CI/CD服务器 |
| JDK | 21 | Java运行环境 |
| Gradle | 8.5 | 构建工具 |
| SonarQube | 9.0+ | 代码质量分析 |
| Git | 最新版 | 版本控制 |
### 安装Jenkins
#### Windows安装
```bash
# 下载Jenkins WAR
# https://www.jenkins.io/download/
# 运行Jenkins
java -jar jenkins.war --httpPort=8080
# 访问
http://localhost:8080
```
#### Docker安装
```bash
# 拉取镜像
docker pull jenkins/jenkins:lts
# 运行容器
docker run -d -p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
--name jenkins \
jenkins/jenkins:lts
```
### 安装必要插件
在Jenkins管理界面安装以下插件
1. **Git Plugin** - Git集成
2. **Gradle Plugin** - Gradle构建
3. **Pipeline** - 流水线支持
4. **SonarQube Scanner** - 代码分析
5. **Blue Ocean** - 现代化UI
---
## Jenkins配置
### 步骤1: 配置JDK
```
Jenkins管理 → 全局工具配置 → JDK
名称: JDK21
JAVA_HOME: C:\Program Files\Java\jdk-21
```
### 步骤2: 配置Gradle
```
Jenkins管理 → 全局工具配置 → Gradle
名称: Gradle8.5
GRADLE_HOME: C:\Gradle\gradle-8.5
```
### 步骤3: 配置Git
```
Jenkins管理 → 全局工具配置 → Git
Path to Git executable: C:\Program Files\Git\bin\git.exe
```
### 步骤4: 配置凭据
```
Jenkins管理 → 凭据 → 系统 → 全局凭据
添加:
- Git仓库凭据 (用户名/密码或SSH密钥)
- SonarQube Token
```
### 步骤5: 创建Pipeline任务
```
新建任务 → 输入名称: MCSLMS-Pipeline → 选择: Pipeline
配置:
- 定义: Pipeline script from SCM
- SCM: Git
- Repository URL: <你的Git仓库地址>
- Script Path: Jenkinsfile
```
---
## Jenkinsfile详解
### 完整Jenkinsfile
```groovy
// Jenkinsfile
pipeline {
agent any
environment {
JAVA_HOME = tool 'JDK21'
GRADLE_HOME = tool 'Gradle8.5'
PATH = "${JAVA_HOME}/bin:${GRADLE_HOME}/bin:${PATH}"
}
stages {
// 阶段1: 拉取代码
stage('Checkout') {
steps {
echo '📥 拉取代码...'
checkout scm
script {
// 获取提交信息
env.GIT_COMMIT_MSG = sh(
script: 'git log -1 --pretty=%B',
returnStdout: true
).trim()
}
}
}
// 阶段2: 编译
stage('Build') {
steps {
echo '🔨 编译项目...'
// Windows
bat 'gradlew.bat clean build -x test'
// Linux/Mac
// sh './gradlew clean build -x test'
}
}
// 阶段3: 测试
stage('Test') {
steps {
echo '🧪 运行测试...'
bat 'gradlew.bat test'
}
post {
always {
// 发布测试报告
junit '**/build/test-results/test/*.xml'
}
}
}
// 阶段4: 代码质量分析
stage('SonarQube Analysis') {
steps {
echo '🔍 代码质量分析...'
withSonarQubeEnv('SonarQube') {
bat 'gradlew.bat sonarqube'
}
}
}
// 阶段5: 质量门禁
stage('Quality Gate') {
steps {
echo '🚦 检查质量门禁...'
timeout(time: 5, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
// 阶段6: 打包
stage('Package') {
parallel {
stage('Package CLI') {
steps {
echo '📦 打包CLI...'
bat 'gradlew.bat :cli:shadowJar'
}
}
stage('Package GUI') {
steps {
echo '📦 打包GUI...'
bat 'gradlew.bat :gui:shadowJar'
}
}
stage('Package Android') {
steps {
echo '📦 打包Android...'
bat 'gradlew.bat :android:assembleRelease'
}
}
}
}
// 阶段7: 归档制品
stage('Archive') {
steps {
echo '📁 归档制品...'
archiveArtifacts artifacts: '**/build/libs/*.jar',
fingerprint: true
archiveArtifacts artifacts: '**/build/outputs/apk/**/*.apk',
fingerprint: true
}
}
// 阶段8: 部署
stage('Deploy') {
when {
branch 'main'
}
steps {
echo '🚀 部署到服务器...'
// 部署Web服务
bat 'scripts\\deploy-tomcat.bat'
}
}
}
post {
success {
echo '✅ 构建成功!'
// 发送成功通知
}
failure {
echo '❌ 构建失败!'
// 发送失败通知
}
always {
// 清理工作空间
cleanWs()
}
}
}
```
### 各阶段说明
#### Stage 1: Checkout
```groovy
stage('Checkout') {
steps {
// 从SCM拉取代码
checkout scm
}
}
```
#### Stage 2: Build
```groovy
stage('Build') {
steps {
// 编译所有模块,跳过测试
bat 'gradlew.bat clean build -x test'
}
}
```
#### Stage 3: Test
```groovy
stage('Test') {
steps {
bat 'gradlew.bat test'
}
post {
always {
// 收集测试报告
junit '**/build/test-results/test/*.xml'
}
}
}
```
#### Stage 4: SonarQube
```groovy
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('SonarQube') {
bat 'gradlew.bat sonarqube'
}
}
}
```
---
## SonarQube集成
### 配置sonar-project.properties
```properties
# sonar-project.properties
sonar.projectKey=mcslms
sonar.projectName=MCSLMS
sonar.projectVersion=1.0
# 源代码路径
sonar.sources=core/src/main/java,cli/src/main/java,gui/src/main/java,backend/src/main/java
# 测试代码路径
sonar.tests=core/src/test/java,cli/src/test/java
# 编译输出路径
sonar.java.binaries=**/build/classes/java/main
# 排除文件
sonar.exclusions=**/build/**,**/node_modules/**
# 编码
sonar.sourceEncoding=UTF-8
```
### 配置build.gradle
```groovy
// build.gradle
plugins {
id 'org.sonarqube' version '4.4.1.3373'
}
sonarqube {
properties {
property 'sonar.projectKey', 'mcslms'
property 'sonar.projectName', 'MCSLMS'
property 'sonar.host.url', 'http://localhost:9000'
property 'sonar.login', System.getenv('SONAR_TOKEN')
}
}
```
### Jenkins配置SonarQube
```
Jenkins管理 → 系统配置 → SonarQube servers
名称: SonarQube
Server URL: http://localhost:9000
Server authentication token: <your-token>
```
### 质量门禁配置
在SonarQube中配置质量门禁
```
Quality Gates → Create
条件:
- Coverage < 80%
- Duplicated Lines > 3% → 失败
- Maintainability Rating worse than A → 失败
- Reliability Rating worse than A → 失败
- Security Rating worse than A → 失败
```
---
## 自动化部署
### 部署脚本
```batch
@echo off
REM scripts/deploy-tomcat.bat
echo === 部署MCSLMS Web服务 ===
REM 停止现有服务
echo 停止Tomcat...
call %TOMCAT_HOME%\bin\shutdown.bat
REM 等待停止
timeout /t 5
REM 备份旧版本
echo 备份旧版本...
if exist %TOMCAT_HOME%\webapps\mcslms.war (
move %TOMCAT_HOME%\webapps\mcslms.war %TOMCAT_HOME%\webapps\mcslms.war.bak
)
REM 复制新版本
echo 部署新版本...
copy backend\build\libs\backend-1.0.0.war %TOMCAT_HOME%\webapps\mcslms.war
REM 启动服务
echo 启动Tomcat...
call %TOMCAT_HOME%\bin\startup.bat
echo === 部署完成 ===
echo 访问地址: http://localhost:8080/mcslms
```
### Docker部署
```dockerfile
# Dockerfile
FROM openjdk:21-slim
WORKDIR /app
COPY backend/build/libs/backend-1.0.0.jar app.jar
EXPOSE 8082
ENTRYPOINT ["java", "-jar", "app.jar"]
```
```yaml
# docker-compose.yml
version: '3.8'
services:
mcslms-web:
build: .
ports:
- "8082:8082"
volumes:
- ./library.db:/app/library.db
restart: always
```
### 部署流水线
```groovy
stage('Deploy to Docker') {
steps {
script {
// 构建Docker镜像
sh 'docker build -t mcslms:latest .'
// 停止旧容器
sh 'docker stop mcslms || true'
sh 'docker rm mcslms || true'
// 启动新容器
sh 'docker run -d --name mcslms -p 8082:8082 mcslms:latest'
}
}
}
```
---
## 触发器配置
### 代码提交触发
```groovy
pipeline {
triggers {
// 轮询SCM每5分钟检查一次
pollSCM('H/5 * * * *')
// 或使用Webhook
// githubPush()
}
}
```
### 定时构建
```groovy
triggers {
// 每天凌晨2点构建
cron('0 2 * * *')
}
```
### Webhook配置
```
Git仓库设置 → Webhooks → Add webhook
Payload URL: http://jenkins-server:8080/github-webhook/
Content type: application/json
Events: Push events
```
---
## 通知配置
### 邮件通知
```groovy
post {
failure {
emailext (
subject: "构建失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
构建失败!
项目: ${env.JOB_NAME}
构建号: ${env.BUILD_NUMBER}
URL: ${env.BUILD_URL}
""",
to: 'team@example.com'
)
}
}
```
### 钉钉通知
```groovy
post {
success {
dingtalk (
robot: 'dingtalk-robot-id',
type: 'MARKDOWN',
title: '构建成功',
text: [
"### 构建成功 ✅",
"- 项目: ${env.JOB_NAME}",
"- 构建号: #${env.BUILD_NUMBER}",
"- [查看详情](${env.BUILD_URL})"
]
)
}
}
```
---
## 常见问题
### Q1: 构建超时怎么办?
```groovy
options {
timeout(time: 30, unit: 'MINUTES')
}
```
### Q2: 如何跳过某个阶段?
```groovy
stage('Deploy') {
when {
branch 'main' // 只在main分支执行
}
steps {
// ...
}
}
```
### Q3: 如何并行执行?
```groovy
stage('Parallel Build') {
parallel {
stage('Build A') { steps { /* ... */ } }
stage('Build B') { steps { /* ... */ } }
}
}
```
---
## 快速参考
| 操作 | 命令/配置 |
|------|----------|
| 手动触发构建 | Jenkins → 项目 → Build Now |
| 查看构建日志 | Jenkins → 项目 → #构建号 → Console Output |
| 查看测试报告 | Jenkins → 项目 → #构建号 → Test Result |
| 下载制品 | Jenkins → 项目 → #构建号 → Artifacts |
| 配置Webhook | Git仓库 → Settings → Webhooks |
---
## 初学者完整配置流程
### 第一步安装JenkinsWindows
```bash
# 1. 下载Jenkins WAR包
# 访问 https://www.jenkins.io/download/ 下载jenkins.war
# 2. 启动Jenkins
java -jar jenkins.war --httpPort=8080
# 3. 浏览器访问
http://localhost:8080
# 4. 获取初始密码
type C:\Users\<用户名>\.jenkins\secrets\initialAdminPassword
# 5. 安装推荐插件
```
### 第二步配置Jenkins
```
1. 安装必要插件:
Jenkins管理 → 插件管理 → 可选插件
- Git Plugin
- Gradle Plugin
- Pipeline
- SonarQube Scanner
2. 配置JDK:
Jenkins管理 → 全局工具配置 → JDK
名称: JDK21
JAVA_HOME: C:\Program Files\Java\jdk-21
3. 配置Gradle:
Jenkins管理 → 全局工具配置 → Gradle
名称: Gradle8.5
自动安装: 勾选
```
### 第三步创建Pipeline任务
```
1. 新建任务 → 输入名称: MCSLMS → 选择Pipeline
2. 配置Pipeline:
定义: Pipeline script from SCM
SCM: Git
Repository URL: https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
Branch: */develop
Script Path: Jenkinsfile
3. 保存并点击"Build Now"
```
### 第四步:查看构建结果
```
1. 点击构建号 → Console Output 查看日志
2. 构建成功后在 Artifacts 下载JAR/APK
3. 如果失败,根据日志排查问题
```
### 常见问题
| 问题 | 解决方案 |
|------|---------|
| Git拉取失败 | 配置Git凭据 |
| Gradle构建超时 | 增加timeou

File diff suppressed because it is too large Load Diff

@ -704,9 +704,13 @@ public class GUIApplication extends Application {
confirm.showAndWait().ifPresent(response -> {
if (response == ButtonType.OK) {
try {
java.io.File jarFile = findJar("backend");
if (jarFile == null || !jarFile.exists()) {
showAlert(Alert.AlertType.WARNING, "提示", "未找到Web JAR包\n请先构建gradlew :backend:bootJar");
return;
}
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"gradlew :backend:bootRun --no-daemon -q");
pb.directory(new java.io.File(System.getProperty("user.dir")));
"java -jar \"" + jarFile.getAbsolutePath() + "\"");
pb.start();
// 延迟打开浏览器
@ -729,9 +733,13 @@ public class GUIApplication extends Application {
private void startWebService() {
try {
java.io.File jarFile = findJar("backend");
if (jarFile == null || !jarFile.exists()) {
showAlert(Alert.AlertType.WARNING, "提示", "未找到Web JAR包\n请先构建gradlew :backend:bootJar");
return;
}
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"gradlew :backend:bootRun --no-daemon -q");
pb.directory(new java.io.File(System.getProperty("user.dir")));
"java -jar \"" + jarFile.getAbsolutePath() + "\"");
pb.start();
new Thread(() -> {
@ -790,15 +798,41 @@ public class GUIApplication extends Application {
private void switchToCLI() {
try {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"gradlew :cli:run --no-daemon -q");
pb.directory(new java.io.File(System.getProperty("user.dir")));
pb.start();
javafx.application.Platform.exit();
java.io.File jarFile = findJar("cli");
if (jarFile != null && jarFile.exists()) {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start", "cmd", "/k",
"java -jar \"" + jarFile.getAbsolutePath() + "\"");
pb.start();
javafx.application.Platform.exit();
} else {
showAlert(Alert.AlertType.WARNING, "提示",
"未找到CLI JAR包\n请先构建gradlew :cli:shadowJar\n或运行java -jar cli/build/libs/cli-1.0.0-all.jar");
}
} catch (Exception e) {
showAlert(Alert.AlertType.ERROR, "错误", "切换失败: " + e.getMessage());
}
}
private java.io.File findJar(String module) {
String[] basePaths = {"", "../"};
for (String base : basePaths) {
java.io.File libDir = new java.io.File(base + module + "/build/libs");
if (libDir.exists() && libDir.isDirectory()) {
java.io.File[] jars = libDir.listFiles((dir, name) ->
name.endsWith("-all.jar") ||
(name.endsWith(".jar") && !name.contains("-plain") && name.contains(module)));
if (jars != null && jars.length > 0) {
for (java.io.File jar : jars) {
if (jar.getName().endsWith("-all.jar")) return jar;
}
return jars[0];
}
}
}
java.io.File simpleJar = new java.io.File("libs/" + module + ".jar");
if (simpleJar.exists()) return simpleJar;
return null;
}
private void showAlert(Alert.AlertType alertType, String title, String content) {
Alert alert = new Alert(alertType);

Loading…
Cancel
Save