|
@@ -0,0 +1,903 @@
|
|
|
|
|
+# 校园二手书交易系统 — 详细设计文档
|
|
|
|
|
+
|
|
|
|
|
+## 1. 引言
|
|
|
|
|
+
|
|
|
|
|
+### 1.1 项目背景
|
|
|
|
|
+校园内二手教材流转需求旺盛,但缺乏统一的线上交易平台。本项目旨在构建一个 C/S 架构的校园二手书交易系统,为学生提供便捷的书籍买卖渠道,为管理员提供数据监控与统计能力。
|
|
|
|
|
+
|
|
|
|
|
+### 1.2 项目目标
|
|
|
|
|
+- 实现学生用户的注册、登录、浏览、搜索、购买书籍及订单管理
|
|
|
|
|
+- 支持卖家用户上架、编辑、下架书籍及查看销售记录
|
|
|
|
|
+- 提供管理员后台进行用户管理、商品管理、交易管理和数据统计
|
|
|
|
|
+- 预留 AI 分析扩展能力(固定流程 + LLM 调用)
|
|
|
|
|
+
|
|
|
|
|
+### 1.3 适用范围
|
|
|
|
|
+本系统面向高校在校学生与管理人员,部署于校园局域网环境。
|
|
|
|
|
+
|
|
|
|
|
+### 1.4 术语与缩略语
|
|
|
|
|
+
|
|
|
|
|
+| 术语 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| Buyer | 买家/普通学生用户 |
|
|
|
|
|
+| Seller | 卖家(买家身份的权限扩展) |
|
|
|
|
|
+| Admin | 系统管理员 |
|
|
|
|
|
+| C/S | Client/Server 架构 |
|
|
|
|
|
+| MyBatis-Plus | MyBatis 增强工具 |
|
|
|
|
|
+| LLM | Large Language Model,大语言模型 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 2. 总体设计
|
|
|
|
|
+
|
|
|
|
|
+### 2.1 系统架构
|
|
|
|
|
+
|
|
|
|
|
+本系统采用经典 C/S 两层架构:
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+flowchart TB
|
|
|
|
|
+ subgraph Client [JavaFX 客户端 space.anyi.client]
|
|
|
|
|
+ VIEW[FXML 视图层]
|
|
|
|
|
+ CTRL[Controller 层]
|
|
|
|
|
+ HSVC[HTTP Service 层]
|
|
|
|
|
+ end
|
|
|
|
|
+ subgraph Server [Spring Boot 服务端 space.anyi.server]
|
|
|
|
|
+ CTL[Controller 层]
|
|
|
|
|
+ SVC[Service 层]
|
|
|
|
|
+ MPR[Mapper 层]
|
|
|
|
|
+ end
|
|
|
|
|
+ subgraph DB [MySQL 8.0]
|
|
|
|
|
+ D[(campus_book_trade)]
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ Client <-->|HTTP/JSON RESTful API| Server
|
|
|
|
|
+ MPR <--> D
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+客户端与服务端之间仅通过 HTTP RESTful API 通信,无直接依赖。共享模块 `common` 提供实体类、DTO 和工具类。
|
|
|
|
|
+
|
|
|
|
|
+### 2.2 技术栈
|
|
|
|
|
+
|
|
|
|
|
+| 层次 | 技术 | 版本 |
|
|
|
|
|
+|------|------|------|
|
|
|
|
|
+| 客户端 UI | JavaFX + FXML + Scene Builder | 23.0.2 |
|
|
|
|
|
+| 客户端 HTTP | `java.net.http.HttpClient` | JDK 内置 |
|
|
|
|
|
+| JSON 序列化 | Jackson (`jackson-databind` + `jackson-datatype-jsr310`) | 2.17.3 |
|
|
|
|
|
+| 服务端框架 | Spring Boot Web | 3.4.4 |
|
|
|
|
|
+| ORM | MyBatis-Plus (`mybatis-plus-spring-boot3-starter`) | 3.5.9 |
|
|
|
|
|
+| 数据库 | MySQL 8.0+ (Connector 8.4.0) | |
|
|
|
|
|
+| 构建工具 | Maven (3.9+) | |
|
|
|
|
|
+| Java | Corretto-23 | 23 |
|
|
|
|
|
+
|
|
|
|
|
+### 2.3 模块划分
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+CampusUsedBookTradingSystem/
|
|
|
|
|
+├── common/ 共享模块 — 实体、DTO、枚举
|
|
|
|
|
+├── server/ Spring Boot 服务端
|
|
|
|
|
+│ ├── config/ 配置类(CORS、MyBatis-Plus、异常处理)
|
|
|
|
|
+│ ├── controller/ REST 控制器
|
|
|
|
|
+│ ├── service/ 业务接口
|
|
|
|
|
+│ ├── service/impl/ 业务实现
|
|
|
|
|
+│ └── mapper/ MyBatis-Plus Mapper + XML
|
|
|
|
|
+├── client/ JavaFX 客户端
|
|
|
|
|
+│ ├── controller/ JavaFX 控制器
|
|
|
|
|
+│ ├── service/ HTTP 调用封装
|
|
|
|
|
+│ └── util/ 工具类
|
|
|
|
|
+└── sql/ 数据库建表脚本
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+依赖关系:`server → common`,`client → common`。
|
|
|
|
|
+
|
|
|
|
|
+### 2.4 包结构总览
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+space.anyi
|
|
|
|
|
+├── common
|
|
|
|
|
+│ ├── entity/ User, Book, TransactionRecord
|
|
|
|
|
+│ ├── dto/ LoginRequest, RegisterRequest, R<T>, PageResult<T>,
|
|
|
|
|
+│ │ StatisticsSummary, DeptSalesDTO, DeptDiscountDTO, HotBookDTO
|
|
|
|
|
+│ └── enums/ UserRole
|
|
|
|
|
+├── server
|
|
|
|
|
+│ ├── ServerApplication.java
|
|
|
|
|
+│ ├── config/ WebConfig, MyBatisPlusConfig, GlobalExceptionHandler
|
|
|
|
|
+│ ├── controller/ UserController, BookController, TransactionController, StatisticsController
|
|
|
|
|
+│ ├── service/ UserService, BookService, TransactionService, StatisticsService
|
|
|
|
|
+│ ├── service/impl/ UserServiceImpl, BookServiceImpl, TransactionServiceImpl, StatisticsServiceImpl
|
|
|
|
|
+│ └── mapper/ UserMapper, BookMapper, TransactionRecordMapper, StatisticsMapper
|
|
|
|
|
+└── client
|
|
|
|
|
+ ├── App.java, Client.java
|
|
|
|
|
+ ├── controller/ LoginController, RegisterController, MainController
|
|
|
|
|
+ ├── service/ UserService, BookService, TransactionService, StatisticsService
|
|
|
|
|
+ └── util/ HttpClientUtil, LoginUserHolder
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 3. 数据库设计
|
|
|
|
|
+
|
|
|
|
|
+### 3.1 ER 图
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+erDiagram
|
|
|
|
|
+ USER {
|
|
|
|
|
+ int userid PK
|
|
|
|
|
+ varchar username
|
|
|
|
|
+ varchar password
|
|
|
|
|
+ varchar nickname
|
|
|
|
|
+ varchar email
|
|
|
|
|
+ varchar phone
|
|
|
|
|
+ varchar dept
|
|
|
|
|
+ int credit
|
|
|
|
|
+ int role
|
|
|
|
|
+ int is_seller
|
|
|
|
|
+ datetime created_at
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ BOOK {
|
|
|
|
|
+ int book_id PK
|
|
|
|
|
+ int seller_id FK
|
|
|
|
|
+ varchar title
|
|
|
|
|
+ varchar author
|
|
|
|
|
+ varchar category
|
|
|
|
|
+ decimal original_price
|
|
|
|
|
+ decimal selling_price
|
|
|
|
|
+ varchar image_url
|
|
|
|
|
+ datetime created_at
|
|
|
|
|
+ int stock
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ TRANSACTION_RECORD {
|
|
|
|
|
+ int trans_id PK
|
|
|
|
|
+ int book_id FK
|
|
|
|
|
+ int buyer_id FK
|
|
|
|
|
+ int transaction_num
|
|
|
|
|
+ decimal transaction_price
|
|
|
|
|
+ datetime transaction_time
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ USER ||--o{ BOOK : "seller"
|
|
|
|
|
+ USER ||--o{ TRANSACTION_RECORD : "buyer"
|
|
|
|
|
+ BOOK ||--o{ TRANSACTION_RECORD : "contains"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3.2 表结构
|
|
|
|
|
+
|
|
|
|
|
+#### 3.2.1 user 表
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
+|------|------|------|------|
|
|
|
|
|
+| userid | int | PK, AUTO_INCREMENT | 用户ID |
|
|
|
|
|
+| username | varchar(255) | | 用户名 |
|
|
|
|
|
+| password | varchar(255) | | 密码(明文存储,后续改进) |
|
|
|
|
|
+| nickname | varchar(255) | | 昵称 |
|
|
|
|
|
+| email | varchar(255) | | 邮箱 |
|
|
|
|
|
+| phone | varchar(255) | | 电话 |
|
|
|
|
|
+| dept | varchar(255) | | 院系 |
|
|
|
|
|
+| credit | int | DEFAULT 100 | 信用分 |
|
|
|
|
|
+| role | int | DEFAULT 0 | 角色(0=学生, 1=管理员) |
|
|
|
|
|
+| is_seller | int | DEFAULT 0 | 是否为卖家(0=否, 1=是) |
|
|
|
|
|
+| created_at | datetime | | 注册时间 |
|
|
|
|
|
+
|
|
|
|
|
+#### 3.2.2 book 表
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
+|------|------|------|------|
|
|
|
|
|
+| book_id | int | PK, AUTO_INCREMENT | 书籍ID |
|
|
|
|
|
+| seller_id | int | | 卖家ID(逻辑外键→user.userid) |
|
|
|
|
|
+| title | varchar(255) | | 书名 |
|
|
|
|
|
+| author | varchar(255) | | 作者 |
|
|
|
|
|
+| category | varchar(255) | | 分类 |
|
|
|
|
|
+| original_price | decimal(10,2) | | 原价 |
|
|
|
|
|
+| selling_price | decimal(10,2) | | 售价 |
|
|
|
|
|
+| image_url | varchar(255) | | 图片URL(预留) |
|
|
|
|
|
+| created_at | datetime | | 上架时间 |
|
|
|
|
|
+| stock | int | | 库存数量 |
|
|
|
|
|
+
|
|
|
|
|
+#### 3.2.3 transaction_record 表
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
+|------|------|------|------|
|
|
|
|
|
+| trans_id | int | PK, AUTO_INCREMENT | 交易ID |
|
|
|
|
|
+| book_id | int | | 书籍ID(逻辑外键→book.book_id) |
|
|
|
|
|
+| buyer_id | int | | 买家ID(逻辑外键→user.userid) |
|
|
|
|
|
+| transaction_num | int | | 购买数量 |
|
|
|
|
|
+| transaction_price | decimal(10,2) | | 交易总价 |
|
|
|
|
|
+| transaction_time | datetime | | 交易时间 |
|
|
|
|
|
+
|
|
|
|
|
+### 3.3 表关系说明
|
|
|
|
|
+
|
|
|
|
|
+- `book.seller_id` → `user.userid`:一个卖家可发布多本书(一对多)
|
|
|
|
|
+- `transaction_record.book_id` → `book.book_id`:一本书可被多次交易(一对多)
|
|
|
|
|
+- `transaction_record.buyer_id` → `user.userid`:一个买家可有多笔交易(一对多)
|
|
|
|
|
+
|
|
|
|
|
+当前 DDL 中未显式声明外键约束,由应用层(事务)保证数据一致性。
|
|
|
|
|
+
|
|
|
|
|
+### 3.4 SQL 脚本
|
|
|
|
|
+
|
|
|
|
|
+建库脚本位于 `sql/campus_book_trade.sql`,包含完整 CREATE TABLE 和示例初始数据。字符集采用 `utf8mb4`。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 4. 服务端详细设计
|
|
|
|
|
+
|
|
|
|
|
+### 4.1 分层架构
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+flowchart LR
|
|
|
|
|
+ subgraph Controller [Controller 层]
|
|
|
|
|
+ direction LR
|
|
|
|
|
+ UC[UserController]
|
|
|
|
|
+ BC[BookController]
|
|
|
|
|
+ TC[TransactionController]
|
|
|
|
|
+ SC[StatisticsController]
|
|
|
|
|
+ end
|
|
|
|
|
+ subgraph Service [Service 层]
|
|
|
|
|
+ direction LR
|
|
|
|
|
+ US[UserService]
|
|
|
|
|
+ BS[BookService]
|
|
|
|
|
+ TS[TransactionService]
|
|
|
|
|
+ SS[StatisticsService]
|
|
|
|
|
+ end
|
|
|
|
|
+ subgraph Mapper [Mapper 层]
|
|
|
|
|
+ direction LR
|
|
|
|
|
+ UM[UserMapper]
|
|
|
|
|
+ BM[BookMapper]
|
|
|
|
|
+ TM[TransactionRecordMapper]
|
|
|
|
|
+ SM[StatisticsMapper]
|
|
|
|
|
+ end
|
|
|
|
|
+ DB[(MySQL)]
|
|
|
|
|
+
|
|
|
|
|
+ Controller --> Service
|
|
|
|
|
+ Service --> Mapper
|
|
|
|
|
+ Mapper --> DB
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+各层职责:
|
|
|
|
|
+
|
|
|
|
|
+| 层次 | 职责 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| Controller | 请求映射、参数解析校验、调用 Service、封装 R<T> 响应 |
|
|
|
|
|
+| Service | 核心业务逻辑、事务控制、组合操作 |
|
|
|
|
|
+| Mapper | 数据访问(继承 BaseMapper 提供 CRUD,自定义 SQL 提供统计) |
|
|
|
|
|
+| Config | CORS 跨域配置、MyBatis-Plus 分页插件、全局异常处理 |
|
|
|
|
|
+
|
|
|
|
|
+### 4.2 RESTful API 接口定义
|
|
|
|
|
+
|
|
|
|
|
+#### 4.2.1 用户模块 — `/api/user`
|
|
|
|
|
+
|
|
|
|
|
+| 方法 | 路径 | 请求体/参数 | 响应 | 说明 |
|
|
|
|
|
+|------|------|-------------|------|------|
|
|
|
|
|
+| POST | `/api/user/login` | `LoginRequest` | `R<User>` | 登录认证 |
|
|
|
|
|
+| POST | `/api/user/register` | `RegisterRequest` | `R<User>` | 注册新用户 |
|
|
|
|
|
+| GET | `/api/user` | `?page=&size=` | `R<IPage<User>>` | 分页获取用户列表(Admin) |
|
|
|
|
|
+| GET | `/api/user/{id}` | | `R<User>` | 获取单个用户 |
|
|
|
|
|
+| PUT | `/api/user/{id}` | `User` JSON | `R<User>` | 更新用户信息 |
|
|
|
|
|
+| DELETE | `/api/user/{id}` | | `R<Void>` | 删除用户(Admin) |
|
|
|
|
|
+
|
|
|
|
|
+**LoginRequest**:
|
|
|
|
|
+```json
|
|
|
|
|
+{"username": "string", "password": "string"}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**RegisterRequest**:
|
|
|
|
|
+```json
|
|
|
|
|
+{"username": "string", "password": "string", "nickname": "string", "email": "string", "phone": "string", "dept": "string"}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 4.2.2 书籍模块 — `/api/book`
|
|
|
|
|
+
|
|
|
|
|
+| 方法 | 路径 | 参数 | 响应 | 说明 |
|
|
|
|
|
+|------|------|------|------|------|
|
|
|
|
|
+| GET | `/api/book` | keyword, category, page, size | `R<PageResult<Book>>` | 搜索书籍(分页) |
|
|
|
|
|
+| GET | `/api/book/all` | | `R<List<Book>>` | 获取所有书籍 |
|
|
|
|
|
+| GET | `/api/book/{id}` | | `R<Book>` | 获取书籍详情 |
|
|
|
|
|
+| GET | `/api/book/my` | sellerId | `R<List<Book>>` | 卖家查看自己的书籍 |
|
|
|
|
|
+| GET | `/api/book/{id}/sales` | | `R<List<SalesRecordDTO>>` | 查看书籍销售记录(卖家) |
|
|
|
|
|
+| GET | `/api/book/pending` | | `R<List<Book>>` | 查看待审核书籍列表(Admin) |
|
|
|
|
|
+| POST | `/api/book` | `Book` JSON | `R<Book>` | 创建/上架书籍(默认 status=0) |
|
|
|
|
|
+| PUT | `/api/book/{id}` | `Book` JSON | `R<Book>` | 更新书籍 |
|
|
|
|
|
+| PUT | `/api/book/{id}/audit` | `?status=` | `R<Book>` | 审核书籍(Admin: 0待审/1通过/2拒绝) |
|
|
|
|
|
+| DELETE | `/api/book/{id}` | | `R<Void>` | 删除书籍 |
|
|
|
|
|
+
|
|
|
|
|
+#### 4.2.3 交易模块 — `/api/transaction`
|
|
|
|
|
+
|
|
|
|
|
+| 方法 | 路径 | 请求体/参数 | 响应 | 说明 |
|
|
|
|
|
+|------|------|-------------|------|------|
|
|
|
|
|
+| POST | `/api/transaction` | `{bookId, buyerId, quantity}` | `R<TransactionRecord>` | 购买 |
|
|
|
|
|
+| GET | `/api/transaction` | `?page=&size=` | `R<IPage<TransactionRecord>>` | 分页查询所有交易 |
|
|
|
|
|
+| GET | `/api/transaction/{id}` | | `R<TransactionRecord>` | 交易详情 |
|
|
|
|
|
+| GET | `/api/transaction/user/{userId}` | | `R<List<TransactionRecord>>` | 用户交易记录 |
|
|
|
|
|
+| PUT | `/api/transaction/{id}` | `TransactionRecord` JSON | `R<TransactionRecord>` | 更新交易(预留) |
|
|
|
|
|
+| DELETE | `/api/transaction/{id}` | | `R<Void>` | 删除交易 |
|
|
|
|
|
+
|
|
|
|
|
+#### 4.2.4 统计模块 — `/api/statistics`
|
|
|
|
|
+
|
|
|
|
|
+| 方法 | 路径 | 响应 | 说明 |
|
|
|
|
|
+|------|------|------|------|
|
|
|
|
|
+| GET | `/api/statistics/summary` | `R<StatisticsSummary>` | 交易总金额和总笔数 |
|
|
|
|
|
+| GET | `/api/statistics/top-departments` | `R<List<DeptSalesDTO>>` | 销售额前三的院系 |
|
|
|
|
|
+| GET | `/api/statistics/top-books` | `R<List<HotBookDTO>>` | 销量前五的书籍 |
|
|
|
|
|
+| GET | `/api/statistics/discount-rates` | `R<List<DeptDiscountDTO>>` | 各院系平均折扣率 |
|
|
|
|
|
+
|
|
|
|
|
+#### 4.2.5 AI 分析模块 — `/api/ai`
|
|
|
|
|
+
|
|
|
|
|
+| 方法 | 路径 | 响应 | 说明 |
|
|
|
|
|
+|------|------|------|------|
|
|
|
|
|
+| GET | `/api/ai/analysis` | `R<String>` | 触发服务端固定分析流程,返回文本分析报告 |
|
|
|
|
|
+
|
|
|
|
|
+### 4.3 统一响应格式 R\<T\>
|
|
|
|
|
+
|
|
|
|
|
+所有 API 返回统一结构:
|
|
|
|
|
+
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "code": 200,
|
|
|
|
|
+ "message": "success",
|
|
|
|
|
+ "data": { ... }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+| code | 含义 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| 200 | 成功 |
|
|
|
|
|
+| 400 | 业务错误(参数错误、库存不足等) |
|
|
|
|
|
+| 500 | 服务器内部错误 |
|
|
|
|
|
+
|
|
|
|
|
+### 4.4 分页设计
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+sequenceDiagram
|
|
|
|
|
+ participant Client as JavaFX 客户端
|
|
|
|
|
+ participant Server as Spring Boot 服务端
|
|
|
|
|
+ participant DB as MySQL
|
|
|
|
|
+
|
|
|
|
|
+ Client->>Server: GET /api/book?keyword=&category=&page=1&size=20
|
|
|
|
|
+ Server->>DB: MyBatis-Plus Page + LambdaQueryWrapper
|
|
|
|
|
+ DB-->>Server: 分页数据 + 总数
|
|
|
|
|
+ Server->>Server: 转换为 PageResult<Book>
|
|
|
|
|
+ Server-->>Client: R<PageResult<Book>>
|
|
|
|
|
+ Client->>Client: FXCollections.observableArrayList(records) → TableView
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+服务端使用 MyBatis-Plus `IPage` 分页,通过 `PageResult<T>` DTO 传输给客户端。MyBatis-Plus `PaginationInnerInterceptor` 自动拦截并改写分页 SQL。
|
|
|
|
|
+
|
|
|
|
|
+### 4.5 关键配置
|
|
|
|
|
+
|
|
|
|
|
+#### WebConfig.java — CORS
|
|
|
|
|
+允许跨域访问(开发环境 JavaFX 直连服务端,无代理层)。
|
|
|
|
|
+
|
|
|
|
|
+#### MyBatisPlusConfig.java
|
|
|
|
|
+- 启用分页插件 `PaginationInnerInterceptor(DbType.MYSQL)`
|
|
|
|
|
+- 开启 `map-underscore-to-camel-case: true`
|
|
|
|
|
+- 主键生成策略:`id-type: auto`(数据库自增)
|
|
|
|
|
+
|
|
|
|
|
+#### GlobalExceptionHandler
|
|
|
|
|
+
|
|
|
|
|
+| 异常 | 响应 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| `DuplicateKeyException` | `R.error("用户名已存在")` |
|
|
|
|
|
+| `IllegalArgumentException` | `R.error(异常消息)` |
|
|
|
|
|
+| `Exception`(兜底) | `R.error("服务器内部错误: " + e.getMessage())` |
|
|
|
|
|
+
|
|
|
|
|
+### 4.6 核心业务逻辑
|
|
|
|
|
+
|
|
|
|
|
+#### 4.6.1 注册流程
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+sequenceDiagram
|
|
|
|
|
+ participant Client as JavaFX 客户端
|
|
|
|
|
+ participant Server as 服务端
|
|
|
|
|
+ participant DB as MySQL
|
|
|
|
|
+
|
|
|
|
|
+ Client->>Server: POST /api/user/register (RegisterRequest)
|
|
|
|
|
+ Server->>Server: 创建 User 对象
|
|
|
|
|
+ Note over Server: 设置默认值: <br/>credit=100, role=0, <br/>isSeller=0, createdAt=now
|
|
|
|
|
+ Server->>DB: INSERT INTO user
|
|
|
|
|
+ DB-->>Server: User (含自增ID)
|
|
|
|
|
+ Server-->>Client: R.ok(user)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 4.6.2 登录流程
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+sequenceDiagram
|
|
|
|
|
+ participant Client as JavaFX 客户端
|
|
|
|
|
+ participant Server as 服务端
|
|
|
|
|
+ participant DB as MySQL
|
|
|
|
|
+
|
|
|
|
|
+ Client->>Server: POST /api/user/login (LoginRequest)
|
|
|
|
|
+ Server->>DB: SELECT * FROM user WHERE username=? AND password=?
|
|
|
|
|
+ DB-->>Server: User / null
|
|
|
|
|
+ alt user == null
|
|
|
|
|
+ Server-->>Client: R.error("Invalid username or password")
|
|
|
|
|
+ else
|
|
|
|
|
+ Server-->>Client: R.ok(user)
|
|
|
|
|
+ Client->>Client: LoginUserHolder.set(user)
|
|
|
|
|
+ Client->>Client: App.showMainScene()
|
|
|
|
|
+ end
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 4.6.3 购买流程(事务)
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+sequenceDiagram
|
|
|
|
|
+ participant Client as JavaFX 客户端
|
|
|
|
|
+ participant Server as 服务端
|
|
|
|
|
+ participant DB as MySQL
|
|
|
|
|
+
|
|
|
|
|
+ Client->>Server: POST /api/transaction {bookId, buyerId, quantity}
|
|
|
|
|
+ Server->>Server: @Transactional 开启事务
|
|
|
|
|
+ Server->>DB: SELECT * FROM book WHERE book_id=?
|
|
|
|
|
+ DB-->>Server: {stock=N, sellingPrice=P}
|
|
|
|
|
+ alt stock < quantity
|
|
|
|
|
+ Server-->>Client: R.error("Insufficient stock")
|
|
|
|
|
+ Server->>Server: 回滚事务
|
|
|
|
|
+ else
|
|
|
|
|
+ Server->>DB: UPDATE book SET stock = stock - quantity
|
|
|
|
|
+ Server->>DB: INSERT INTO transaction_record (bookId, buyerId, transactionNum, transactionPrice, transactionTime)
|
|
|
|
|
+ Server->>Server: 提交事务
|
|
|
|
|
+ Server-->>Client: R.ok(transactionRecord)
|
|
|
|
|
+ end
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**事务边界**(`TransactionServiceImpl.purchase()`):
|
|
|
|
|
+1. 查询书籍,校验库存
|
|
|
|
|
+2. 扣减库存 `book.stock -= quantity`
|
|
|
|
|
+3. 创建交易记录(价格 = `sellingPrice × quantity`)
|
|
|
|
|
+4. 任一失败则 `@Transactional` 回滚
|
|
|
|
|
+
|
|
|
|
|
+#### 4.6.4 搜索流程
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+1. 客户端组装参数:keyword + category + page + size
|
|
|
|
|
+2. GET /api/book?keyword=&category=&page=&size=
|
|
|
|
|
+3. 服务端构建动态查询条件:
|
|
|
|
|
+ - keyword → LIKE title OR LIKE author
|
|
|
|
|
+ - category → EQ category
|
|
|
|
|
+ - 按 created_at DESC 排序
|
|
|
|
|
+4. MyBatis-Plus 分页查询 + 返回 PageResult<Book>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 4.7 统计实现
|
|
|
|
|
+
|
|
|
|
|
+统计模块全部使用自定义 SQL 在 `StatisticsMapper` 中通过 `@Select` 注解实现:
|
|
|
|
|
+
|
|
|
|
|
+| 统计项 | SQL 概要 |
|
|
|
|
|
+|--------|----------|
|
|
|
|
|
+| summary | `SELECT COALESCE(SUM(transaction_price),0), COUNT(*) FROM transaction_record` |
|
|
|
|
|
+| top-departments | JOIN `transaction_record` + `book` + `user`,按 `user.dept` 分组,销售额前3 |
|
|
|
|
|
+| top-books | JOIN `transaction_record` + `book`,按 `book` 分组,销量前5 |
|
|
|
|
|
+| discount-rates | `AVG((original_price - unit_price) / original_price * 100)`,按 `dept` 分组 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 5. 客户端详细设计
|
|
|
|
|
+
|
|
|
|
|
+### 5.1 界面导航
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+flowchart LR
|
|
|
|
|
+ A[login.fxml] -->|登录成功| C[main.fxml]
|
|
|
|
|
+ A -->|点击注册链接| B[register.fxml]
|
|
|
|
|
+ B -->|注册成功| A
|
|
|
|
|
+ B -->|返回登录| A
|
|
|
|
|
+ C -->|退出登录| A
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+`App.java` 作为 JavaFX Application 入口,通过静态方法实现场景切换。`Client.java` 为启动入口(`Application.launch(App.class, args)`)。
|
|
|
|
|
+
|
|
|
|
|
+### 5.2 FXML 视图结构
|
|
|
|
|
+
|
|
|
|
|
+#### login.fxml
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+VBox (400×350)
|
|
|
|
|
+├── Label "校园书市"(标题,22px bold)
|
|
|
|
|
+├── TextField #usernameField(用户名输入)
|
|
|
|
|
+├── PasswordField #passwordField(密码输入)
|
|
|
|
|
+├── Button "登录" → #handleLogin(btn-primary)
|
|
|
|
|
+└── Hyperlink "没有账号?立即注册" → #handleRegister
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### register.fxml
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+VBox (400×500)
|
|
|
|
|
+├── Label "创建账号"(标题,20px bold)
|
|
|
|
|
+├── TextField #usernameField(用户名 *)
|
|
|
|
|
+├── PasswordField #passwordField(密码 *)
|
|
|
|
|
+├── TextField #nicknameField(昵称)
|
|
|
|
|
+├── TextField #emailField(邮箱)
|
|
|
|
|
+├── TextField #phoneField(电话)
|
|
|
|
|
+├── TextField #deptField(院系)
|
|
|
|
|
+├── Button "注册" → #handleRegister(btn-primary)
|
|
|
|
|
+└── Hyperlink "已有账号?去登录" → #handleBack
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### main.fxml
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+BorderPane (1000×700)
|
|
|
|
|
+├── Top: HBox 顶部标题栏
|
|
|
|
|
+│ ├── Label #welcomeLabel "欢迎,xxx"
|
|
|
|
|
+│ └── Button "退出登录" → #handleLogout(btn-danger)
|
|
|
|
|
+│
|
|
|
|
|
+└── Center: TabPane(6个Tab)
|
|
|
|
|
+ │
|
|
|
|
|
+ ├── Tab "浏览书籍"(买家/卖家共有的 browse tab)
|
|
|
|
|
+ │ ├── HBox 搜索栏: TextField #searchField + ComboBox #categoryCombo + Button "搜索"
|
|
|
|
|
+ │ └── SplitPane (0.6)
|
|
|
|
|
+ │ ├── TableView #bookTable [编号,书名,作者,分类,价格,库存]
|
|
|
|
|
+ │ └── VBox: 详情 Label 组 + TextField #quantityField + Button "购买"
|
|
|
|
|
+ │
|
|
|
|
|
+ ├── Tab "我的交易"(买家/卖家)
|
|
|
|
|
+ │ ├── Button "刷新" → #handleLoadTransactions
|
|
|
|
|
+ │ └── TableView #transTable [交易编号,书籍编号,数量,总价,时间]
|
|
|
|
|
+ │
|
|
|
|
|
+ ├── Tab "个人信息"(买家/卖家)
|
|
|
|
|
+ │ └── VBox: #profileUsername(只读), #profileNickname, #profileEmail, #profilePhone, #profileDept, #profileCredit(只读) + Button "保存修改"
|
|
|
|
|
+ │
|
|
|
|
|
+ ├── Tab "卖家中心"(isSeller=1 启用)
|
|
|
|
|
+ │ ├── Label "我的书籍"
|
|
|
|
|
+ │ ├── Button "刷新" → #handleLoadMyBooks
|
|
|
|
|
+ │ ├── TableView #myBookTable [编号,书名,价格,库存]
|
|
|
|
|
+ │ ├── Button "删除选中" → #handleDeleteBook
|
|
|
|
|
+ │ └── TitledPane "添加新书"
|
|
|
|
|
+ │ └── GridPane: 书名/作者/分类/原价/售价/库存 输入 + Button "添加书籍"
|
|
|
|
|
+ │
|
|
|
|
|
+ ├── Tab "数据统计"(所有角色可见)
|
|
|
|
|
+ │ └── ScrollPane > VBox
|
|
|
|
|
+ │ ├── Button "刷新数据" → #handleLoadStatistics
|
|
|
|
|
+ │ ├── TitledPane "总览": statTotalAmount + statTotalCount
|
|
|
|
|
+ │ ├── TitledPane "热门院系(销量前三)": TableView #deptTable
|
|
|
|
|
+ │ ├── TitledPane "热门书籍(前五)": TableView #hotBookTable
|
|
|
|
|
+ │ └── TitledPane "各院系平均折扣率": TableView #discountTable
|
|
|
|
|
+ │
|
|
|
|
|
+ └── Tab "管理"(role=1 启用)
|
|
|
|
|
+ ├── Label "用户管理"
|
|
|
|
|
+ ├── Button "刷新用户" → #handleLoadAllUsers
|
|
|
|
|
+ ├── TableView #userTable [编号,用户名,昵称,院系,信用分,角色,卖家]
|
|
|
|
|
+ ├── Button "删除选中用户" → #handleDeleteUser
|
|
|
|
|
+ ├── Label "全部交易"
|
|
|
|
|
+ ├── Button "刷新交易" → #handleLoadAllTransactions
|
|
|
|
|
+ ├── TableView #allTransTable [交易编号,书籍编号,买家编号,数量,价格,时间]
|
|
|
|
|
+ └── Button "删除选中交易" → #handleDeleteTransaction
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 5.3 控制器设计
|
|
|
|
|
+
|
|
|
|
|
+#### LoginController
|
|
|
|
|
+
|
|
|
|
|
+| 字段/方法 | 类型 | 说明 |
|
|
|
|
|
+|-----------|------|------|
|
|
|
|
|
+| usernameField | TextField | 用户名输入框 |
|
|
|
|
|
+| passwordField | PasswordField | 密码输入框 |
|
|
|
|
|
+| userService | UserService | HTTP 服务层 |
|
|
|
|
|
+| handleLogin() | void | 校验非空 → 调用登录 API → 存入会话 → 跳转主界面 |
|
|
|
|
|
+| handleRegister() | void | 跳转到注册界面 |
|
|
|
|
|
+
|
|
|
|
|
+#### RegisterController
|
|
|
|
|
+
|
|
|
|
|
+| 字段/方法 | 类型 | 说明 |
|
|
|
|
|
+|-----------|------|------|
|
|
|
|
|
+| usernameField ~ deptField | TextField / PasswordField | 注册表单字段 |
|
|
|
|
|
+| userService | UserService | HTTP 服务层 |
|
|
|
|
|
+| handleRegister() | void | 校验必填 → 调用注册 API → 提示 → 跳回登录 |
|
|
|
|
|
+| handleBack() | void | 返回登录界面 |
|
|
|
|
|
+
|
|
|
|
|
+#### MainController
|
|
|
|
|
+
|
|
|
|
|
+| Tab | 核心方法 | 说明 |
|
|
|
|
|
+|-----|----------|------|
|
|
|
|
|
+| 浏览书籍 | `handleSearch()` | 搜索 + 刷新列表 |
|
|
|
|
|
+| | `handlePurchase()` | 校验 → 购买 → 刷新 |
|
|
|
|
|
+| | `initialize()` | 绑定表格列、设置角色权限、加载数据 |
|
|
|
|
|
+| 我的交易 | `handleLoadTransactions()` | 加载当前用户交易记录 |
|
|
|
|
|
+| 个人信息 | `handleUpdateProfile()` | 保存修改 + 更新会话 |
|
|
|
|
|
+| 卖家中心 | `handleLoadMyBooks()` | 加载卖家自己的书籍 |
|
|
|
|
|
+| | `handleAddBook()` | 上架新书 |
|
|
|
|
|
+| | `handleDeleteBook()` | 删除选中书籍 |
|
|
|
|
|
+| 数据统计 | `handleLoadStatistics()` | 加载4个统计指标 |
|
|
|
|
|
+| 管理 | `handleLoadAllUsers()` | 加载所有用户 |
|
|
|
|
|
+| | `handleDeleteUser()` | 删除选中用户 |
|
|
|
|
|
+| | `handleLoadAllTransactions()` | 加载所有交易 |
|
|
|
|
|
+| | `handleDeleteTransaction()` | 删除选中交易 |
|
|
|
|
|
+
|
|
|
|
|
+**会话初始化**(`initialize()` 方法):
|
|
|
|
|
+1. 从 `LoginUserHolder` 获取当前用户
|
|
|
|
|
+2. 设置欢迎语和个人信息回显
|
|
|
|
|
+3. 根据 `isSeller` 和 `role` 控制 sellerTab 和 adminTab 的启用状态
|
|
|
|
|
+
|
|
|
|
|
+### 5.4 HTTP 服务层设计
|
|
|
|
|
+
|
|
|
|
|
+#### HttpClientUtil
|
|
|
|
|
+
|
|
|
|
|
+单例模式的 `HttpClient` + Jackson `ObjectMapper`,提供泛型方法:
|
|
|
|
|
+
|
|
|
|
|
+| 方法 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| `get(path, Class<T>)` | GET 请求,简单类型反序列化 |
|
|
|
|
|
+| `get(path, TypeReference)` | GET 请求,泛型类型反序列化 |
|
|
|
|
|
+| `post(path, body, Class<T>)` | POST 请求 |
|
|
|
|
|
+| `put(path, body, Class<T>)` | PUT 请求 |
|
|
|
|
|
+| `delete(path, Class<T>)` | DELETE 请求 |
|
|
|
|
|
+
|
|
|
|
|
+基 URL = `http://localhost:8080`,错误时返回 code=500。
|
|
|
|
|
+
|
|
|
|
|
+#### 客户端 Service 封装
|
|
|
|
|
+
|
|
|
|
|
+| Service | 封装方法 | 对应 API |
|
|
|
|
|
+|---------|----------|----------|
|
|
|
|
|
+| UserService | login, register, getById, update, delete | `/api/user/*` |
|
|
|
|
|
+| BookService | search, getById, getMyBooks, listAll, create, update, delete | `/api/book/*` |
|
|
|
|
|
+| TransactionService | purchase, getById, getByUser, update, delete | `/api/transaction/*` |
|
|
|
|
|
+| StatisticsService | getSummary, getTopDepartments, getTopBooks, getDiscountRates | `/api/statistics/*` |
|
|
|
|
|
+
|
|
|
|
|
+### 5.5 会话管理
|
|
|
|
|
+
|
|
|
|
|
+`LoginUserHolder`:基于内存的静态会话管理。
|
|
|
|
|
+
|
|
|
|
|
+```java
|
|
|
|
|
+LoginUserHolder.set(user); // 登录成功后存入
|
|
|
|
|
+LoginUserHolder.get(); // 获取当前用户
|
|
|
|
|
+LoginUserHolder.isSeller(); // 判断是否为卖家
|
|
|
|
|
+LoginUserHolder.clear(); // 退出时清除
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+当前无 Token/JWT 机制,userId 通过请求参数/体明文传输。
|
|
|
|
|
+
|
|
|
|
|
+### 5.6 BootstrapFX 样式整合
|
|
|
|
|
+
|
|
|
|
|
+引入 `org.kordamp.bootstrapfx:bootstrapfx-core:0.4.0`,在场景加载时添加 bootstrapfx.css。额外定制 `css/style.css`:全局字体、按钮手型光标、表格边框圆角。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 6. 用户角色与权限设计
|
|
|
|
|
+
|
|
|
|
|
+### 6.1 角色模型
|
|
|
|
|
+
|
|
|
|
|
+用户角色由两个字段组合定义:
|
|
|
|
|
+
|
|
|
|
|
+| role | isSeller | 角色 |
|
|
|
|
|
+|:----:|:--------:|------|
|
|
|
|
|
+| 0 | 0 | 普通学生(买家) |
|
|
|
|
|
+| 0 | 1 | 卖家(同时具备买家权限) |
|
|
|
|
|
+| 1 | 0/1 | 管理员 |
|
|
|
|
|
+
|
|
|
|
|
+`UserRole.java` 枚举仅定义 `STUDENT(0)` 和 `ADMIN(1)`,卖家用 `isSeller` 标志区分。
|
|
|
|
|
+
|
|
|
|
|
+### 6.2 权限矩阵
|
|
|
|
|
+
|
|
|
|
|
+| 功能模块 | 功能点 | 买家 | 卖家 | 管理员 |
|
|
|
|
|
+|----------|--------|:----:|:----:|:------:|
|
|
|
|
|
+| 账号 | 注册 | ✅ | ✅ | ✅ |
|
|
|
|
|
+| 账号 | 登录 | ✅ | ✅ | ✅ |
|
|
|
|
|
+| 书籍 | 浏览/搜索 | ✅ | ✅ | ✅ |
|
|
|
|
|
+| 书籍 | 查看详情 | ✅ | ✅ | ✅ |
|
|
|
|
|
+| 书籍 | 购买 | ✅ | ✅ | ❌ |
|
|
|
|
|
+| 书籍 | 上架 | ❌ | ✅ | ✅ |
|
|
|
|
|
+| 书籍 | 编辑 | ❌ | ✅ | ✅ |
|
|
|
|
|
+| 书籍 | 下架/删除 | ❌ | ✅ | ✅ |
|
|
|
|
|
+| 书籍 | 查看自己的发布 | ❌ | ✅ | ✅ |
|
|
|
|
|
+| 书籍 | 审核(待实现) | ❌ | ❌ | ✅ |
|
|
|
|
|
+| 订单 | 查看自己的订单 | ✅ | ✅ | ✅ |
|
|
|
|
|
+| 订单 | 查看全部订单 | ❌ | ❌ | ✅ |
|
|
|
|
|
+| 订单 | 删除订单 | ❌ | ❌ | ✅ |
|
|
|
|
|
+| 用户 | CRUD | ❌ | ❌ | ✅ |
|
|
|
|
|
+| 用户 | 重置密码 | ❌ | ❌ | ✅ |
|
|
|
|
|
+| 统计 | 查看统计数据 | ✅ | ✅ | ✅ |
|
|
|
|
|
+| AI | 分析报告(待实现) | ❌ | ❌ | ✅ |
|
|
|
|
|
+
|
|
|
|
|
+### 6.3 客户端权限控制
|
|
|
|
|
+
|
|
|
|
|
+在 `MainController.initialize()` 中:
|
|
|
|
|
+
|
|
|
|
|
+```java
|
|
|
|
|
+if (user.getIsSeller() != 1) sellerTab.setDisable(true); // 非卖家禁用卖家中心
|
|
|
|
|
+if (user.getRole() != 1) adminTab.setDisable(true); // 非管理员禁用管理Tab
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Tab 被禁用后用户无法点击,但 FXML 元素仍保留。
|
|
|
|
|
+
|
|
|
|
|
+### 6.4 服务端校验(待完善)
|
|
|
|
|
+
|
|
|
|
|
+当前服务端未实现权限拦截,所有 API 均可被任意客户端调用。生产环境建议引入 Spring Security 或自定义拦截器。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 7. 数据流设计
|
|
|
|
|
+
|
|
|
|
|
+### 7.1 登录注册流程
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+sequenceDiagram
|
|
|
|
|
+ actor User as 用户
|
|
|
|
|
+ participant Login as 登录界面
|
|
|
|
|
+ participant Reg as 注册界面
|
|
|
|
|
+ participant Main as 主界面
|
|
|
|
|
+ participant Svc as 客户端Service
|
|
|
|
|
+ participant API as 服务端API
|
|
|
|
|
+ participant DB as 数据库
|
|
|
|
|
+
|
|
|
|
|
+ Note over User,DB: === 登录流程 ===
|
|
|
|
|
+ User->>Login: 输入用户名+密码
|
|
|
|
|
+ Login->>Svc: userService.login(username, password)
|
|
|
|
|
+ Svc->>API: POST /api/user/login
|
|
|
|
|
+ API->>DB: SELECT * FROM user WHERE username=? AND password=?
|
|
|
|
|
+ DB-->>API: User
|
|
|
|
|
+ API-->>Svc: R.ok(user)
|
|
|
|
|
+ Svc-->>Login: R<User>
|
|
|
|
|
+ Login->>Login: LoginUserHolder.set(user)
|
|
|
|
|
+ Login->>Main: App.showMainScene()
|
|
|
|
|
+
|
|
|
|
|
+ Note over User,DB: === 注册流程 ===
|
|
|
|
|
+ User->>Reg: 填写表单
|
|
|
|
|
+ Reg->>Svc: userService.register(RegisterRequest)
|
|
|
|
|
+ Svc->>API: POST /api/user/register
|
|
|
|
|
+ API->>API: 设置默认值 (credit=100,role=0,isSeller=0)
|
|
|
|
|
+ API->>DB: INSERT INTO user
|
|
|
|
|
+ DB-->>API: User
|
|
|
|
|
+ API-->>Svc: R.ok(user)
|
|
|
|
|
+ Svc-->>Reg: 注册成功
|
|
|
|
|
+ Reg->>Login: App.showLoginScene()
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 7.2 购买交易流程
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+sequenceDiagram
|
|
|
|
|
+ actor Buyer as 买家
|
|
|
|
|
+ participant Browse as 浏览Tab
|
|
|
|
|
+ participant Svc as TransactionService
|
|
|
|
|
+ participant API as 服务端
|
|
|
|
|
+ participant DB as 数据库
|
|
|
|
|
+
|
|
|
|
|
+ Buyer->>Browse: 选择书籍 → 输入数量 → 点击购买
|
|
|
|
|
+ Browse->>Svc: purchase(bookId, buyerId, quantity)
|
|
|
|
|
+ Svc->>API: POST /api/transaction
|
|
|
|
|
+ API->>API: @Transactional 开启
|
|
|
|
|
+ API->>DB: SELECT stock FROM book WHERE book_id=?
|
|
|
|
|
+ DB-->>API: stock=N
|
|
|
|
|
+ alt N < quantity
|
|
|
|
|
+ API-->>Svc: R.error("Insufficient stock")
|
|
|
|
|
+ Svc-->>Browse: Alert 警告
|
|
|
|
|
+ else
|
|
|
|
|
+ API->>DB: UPDATE book SET stock = stock - quantity
|
|
|
|
|
+ API->>DB: INSERT INTO transaction_record
|
|
|
|
|
+ API->>API: 提交事务
|
|
|
|
|
+ API-->>Svc: R.ok(record)
|
|
|
|
|
+ Svc-->>Browse: Alert 成功 + 刷新列表
|
|
|
|
|
+ end
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 7.3 搜索书籍流程
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+sequenceDiagram
|
|
|
|
|
+ actor User as 用户
|
|
|
|
|
+ participant Browse as 浏览Tab
|
|
|
|
|
+ participant Svc as BookService
|
|
|
|
|
+ participant API as 服务端
|
|
|
|
|
+ participant DB as 数据库
|
|
|
|
|
+
|
|
|
|
|
+ User->>Browse: 输入关键字 / 选择分类
|
|
|
|
|
+ User->>Browse: 点击"搜索"
|
|
|
|
|
+ Browse->>Svc: search(keyword, category, page, size)
|
|
|
|
|
+ Svc->>API: GET /api/book?keyword=&category=
|
|
|
|
|
+ API->>API: LambdaQueryWrapper 动态条件
|
|
|
|
|
+ API->>DB: SELECT ... WHERE title LIKE ? OR author LIKE ? AND category=? ORDER BY created_at DESC
|
|
|
|
|
+ DB-->>API: 分页结果
|
|
|
|
|
+ API-->>Svc: R.ok(PageResult<Book>)
|
|
|
|
|
+ Svc-->>Browse: 数据列表
|
|
|
|
|
+ Browse->>Browse: bookTable.setItems(...)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 8. 已实现功能清单
|
|
|
|
|
+
|
|
|
|
|
+以下列出所有基于 `demand.md` 需求已实现的功能及其对应代码位置:
|
|
|
|
|
+
|
|
|
|
|
+### 8.1 卖家-编辑书籍 — ✅ 已实现
|
|
|
|
|
+
|
|
|
|
|
+| 组件 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| FXML | 卖家中心 Tab 新增"编辑选中"按钮 (`main.fxml:92`) |
|
|
|
|
|
+| Controller | `handleEditBook()` — 选中书籍回填表单,切换为编辑模式 (`MainController.java`) |
|
|
|
|
|
+| 复用 | `handleAddBook()` — 检测 `editingBook` 字段,区分新增/更新逻辑 |
|
|
|
|
|
+| 重置 | `clearBookForm()` — 编辑完成后重置表单状态 |
|
|
|
|
|
+
|
|
|
|
|
+### 8.2 卖家-查看销售记录 — ✅ 已实现
|
|
|
|
|
+
|
|
|
|
|
+| 组件 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| API | `GET /api/book/{id}/sales` — 返回 `List<SalesRecordDTO>` (`BookController.java:56`) |
|
|
|
|
|
+| DTO | `SalesRecordDTO` — bookId, title, buyerId, buyerName, quantity, totalPrice, transactionTime |
|
|
|
|
|
+| Mapper | `BookMapper.selectSalesByBookId()` — JOIN transaction_record + book + user |
|
|
|
|
|
+| 客户端 | `handleViewSales()` — 弹出 Dialog 展示销售记录表格 (`MainController.java`) |
|
|
|
|
|
+
|
|
|
|
|
+### 8.3 管理员-用户管理完善 — ✅ 已实现
|
|
|
|
|
+
|
|
|
|
|
+| 组件 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| 编辑用户 | `handleEditUser()` — 选中用户回填表单,支持修改 (`MainController.java`) |
|
|
|
|
|
+| 添加用户 | `handleSaveUser()` — 创建用户(调用 Register API) |
|
|
|
|
|
+| 重置密码 | `handleResetPassword()` — 密码重置为 `123456` |
|
|
|
|
|
+| FXML | 用户表单 TitledPane (`main.fxml`) |
|
|
|
|
|
+
|
|
|
|
|
+### 8.4 管理员-商品管理 — ✅ 已实现
|
|
|
|
|
+
|
|
|
|
|
+| 组件 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| TableView | `adminBookTable` — 显示所有书籍(编号、书名、作者、分类、售价、库存、卖家ID) |
|
|
|
|
|
+| 刷新 | `handleLoadAllBooksAdmin()` — 调用 `GET /api/book/all` |
|
|
|
|
|
+| 删除 | `handleDeleteBookAdmin()` — 删除选中书籍 |
|
|
|
|
|
+
|
|
|
|
|
+### 8.5 管理员-审核书籍 — ✅ 已实现
|
|
|
|
|
+
|
|
|
|
|
+| 组件 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| Schema | `book` 表增加 `status` 字段: 0=待审核, 1=已上架, 2=已下架 |
|
|
|
|
|
+| Entity | `Book.java` 增加 `@TableField("status") private Integer status;` |
|
|
|
|
|
+| API | `GET /api/book/pending` — 获取待审核书籍 |
|
|
|
|
|
+| API | `PUT /api/book/{id}/audit?status=` — 审核通过/拒绝 |
|
|
|
|
|
+| 搜索过滤 | `searchBooks()` 仅返回 `status=1` 的书籍 |
|
|
|
|
|
+| 新书上架 | `create()` 默认 `status=0`(待审核) |
|
|
|
|
|
+| 客户端 | `pendingBookTable` + "通过"/"拒绝" 按钮 |
|
|
|
|
|
+
|
|
|
|
|
+### 8.6 AI 分析 — ✅ 已实现
|
|
|
|
|
+
|
|
|
|
|
+| 组件 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| Service | `AiServiceImpl.generateAnalysis()` — 汇总统计数据 → 格式化分析报告 |
|
|
|
|
|
+| Controller | `GET /api/ai/analysis` — 返回 `R<String>` 文本报告 |
|
|
|
|
|
+| 客户端 | `AiService` — HTTP 调用封装 |
|
|
|
|
|
+| UI | 管理 Tab 增加"AI 分析"区域: "生成分析报告"按钮 + `TextArea` 展示区 |
|
|
|
|
|
+| 后续 | LLM 接入方案(API Key、模型选择、固定提示词模板)待补充 |
|
|
|
|
|
+
|
|
|
|
|
+### 8.7 信用分修改 — ✅ 已实现
|
|
|
|
|
+
|
|
|
|
|
+| 组件 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| UI | 管理 Tab 用户管理区增加"修改信用分"按钮 |
|
|
|
|
|
+| 交互 | `TextInputDialog` 输入新分值 → 调用 `PUT /api/user/{id}` 更新 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 附录 A:配置文件
|
|
|
|
|
+
|
|
|
|
|
+### application.yml
|
|
|
|
|
+
|
|
|
|
|
+```yaml
|
|
|
|
|
+server:
|
|
|
|
|
+ port: 8080
|
|
|
|
|
+ servlet:
|
|
|
|
|
+ context-path: /api
|
|
|
|
|
+
|
|
|
|
|
+spring:
|
|
|
|
|
+ datasource:
|
|
|
|
|
+ url: jdbc:mysql://localhost:3306/campus_book_trade?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
|
|
|
|
|
+ username: root
|
|
|
|
|
+ password: root
|
|
|
|
|
+ driver-class-name: com.mysql.cj.jdbc.Driver
|
|
|
|
|
+
|
|
|
|
|
+mybatis-plus:
|
|
|
|
|
+ configuration:
|
|
|
|
|
+ map-underscore-to-camel-case: true
|
|
|
|
|
+ global-config:
|
|
|
|
|
+ db-config:
|
|
|
|
|
+ id-type: auto
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## 附录 B:构建命令
|
|
|
|
|
+
|
|
|
|
|
+```sh
|
|
|
|
|
+# 全量构建(需 JDK 23)
|
|
|
|
|
+JAVA_HOME=/path/to/corretto-23 mvn clean install
|
|
|
|
|
+
|
|
|
|
|
+# 运行服务端
|
|
|
|
|
+mvn spring-boot:run -pl server
|
|
|
|
|
+
|
|
|
|
|
+# 运行客户端
|
|
|
|
|
+mvn javafx:run -pl client
|
|
|
|
|
+```
|