# SpringBoot儿童玩具共享平台:玩具循环租赁与消毒追踪系统
儿童玩具共享平台是基于SpringBoot框架开发的社区化玩具循环租赁系统,旨在促进亲子玩具的资源共享,通过科学的消毒追踪和信用积分管理,构建安全可靠的玩具共享生态。
## 系统架构设计
### 技术栈选型
**后端技术栈:**
- Spring Boot 2.7.x
- Spring Data JPA
- Spring Security
- MySQL 8.0
- Redis
- Maven
**前端技术栈:**
- Thymeleaf模板引擎
- Bootstrap 5.x
- jQuery
- ECharts数据可视化
### 数据库设计
```sql
-- 用户表
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
phone VARCHAR(20),
credit_score INT DEFAULT 100,
user_type ENUM('PARENT', 'ADMIN') DEFAULT 'PARENT',
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 玩具信息表
CREATE TABLE toys (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
category ENUM('EDUCATIONAL', 'MUSICAL', 'SPORTS', 'PUZZLE', 'OTHER') NOT NULL,
age_range VARCHAR(20),
purchase_price DECIMAL(10,2),
rental_price_per_day DECIMAL(8,2),
status ENUM('AVAILABLE', 'RENTED', 'MAINTENANCE', 'CLEANING') DEFAULT 'AVAILABLE',
owner_id BIGINT,
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (owner_id) REFERENCES users(id)
<"qotr.jiebaobifen.com">
<"zeyk.jiebaobifen.com">
<"xnfr.jiebaobifen.com">
);
-- 消毒记录表
CREATE TABLE disinfection_records (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
toy_id BIGINT NOT NULL,
disinfection_method VARCHAR(50) NOT NULL,
disinfection_time DATETIME NOT NULL,
operator_id BIGINT NOT NULL,
next_suggested_date DATE,
notes TEXT,
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (toy_id) REFERENCES toys(id),
FOREIGN KEY (operator_id) REFERENCES users(id)
);
```
## 核心功能实现
### 1. 用户管理与信用积分系统
```java
@Entity
@Table(name = "users")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(unique = true, nullable = false)
private String email;
@JsonIgnore
private String password;
private String phone;
@Column(name = "credit_score")
private Integer creditScore = 100;
@Enumerated(EnumType.STRING)
@Column(name = "user_type")
private UserType userType = UserType.PARENT;
@CreationTimestamp
private LocalDateTime createdTime;
@UpdateTimestamp
private LocalDateTime updatedTime;
public enum UserType {
PARENT, ADMIN
}
}
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private CreditScoreLogRepository creditScoreLogRepository;
public void updateCreditScore(Long userId, Integer scoreChange, String reason) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("用户不存在"));
int newScore = user.getCreditScore() + scoreChange;
newScore = Math.max(0, Math.min(newScore, 100)); // 限制在0-100之间
user.setCreditScore(newScore);
userRepository.save(user);
// 记录信用分变更日志
CreditScoreLog log = new CreditScoreLog();
log.setUserId(userId);
log.setScoreChange(scoreChange);
log.setNewScore(newScore);
log.setReason(reason);
log.setCreatedTime(LocalDateTime.now());
creditScoreLogRepository.save(log);
}
public boolean canRentToy(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("用户不存在"));
return user.getCreditScore() >= 60; // 信用分60分以上可租赁
}
}
```
### 2. 玩具租赁管理
```java
@Entity
@Table(name = "toys")
@Data
public class Toy {
<"dxsx.jiebaobifen.com">
<"fduj.jiebaobifen.com">
<"geqh.jiebaobifen.com">
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
private String description;
@Enumerated(EnumType.STRING)
private ToyCategory category;
private String ageRange;
@Column(name = "purchase_price")
private BigDecimal purchasePrice;
@Column(name = "rental_price_per_day")
private BigDecimal rentalPricePerDay;
@Enumerated(EnumType.STRING)
private ToyStatus status = ToyStatus.AVAILABLE;
@ManyToOne
@JoinColumn(name = "owner_id")
private User owner;
@CreationTimestamp
private LocalDateTime createdTime;
public enum ToyCategory {
EDUCATIONAL, MUSICAL, SPORTS, PUZZLE, OTHER
}
public enum ToyStatus {
AVAILABLE, RENTED, MAINTENANCE, CLEANING
}
}
@Service
@Transactional
public class RentalService {
@Autowired
private RentalOrderRepository rentalOrderRepository;
@Autowired
private ToyRepository toyRepository;
@Autowired
private UserService userService;
public RentalOrder createRentalOrder(Long toyId, Long userId, LocalDate startDate,
LocalDate endDate) {
// 检查用户信用
if (!userService.canRentToy(userId)) {
throw new RuntimeException("信用分不足,无法租赁玩具");
}
Toy toy = toyRepository.findById(toyId)
.orElseThrow(() -> new RuntimeException("玩具不存在"));
if (toy.getStatus() != Toy.ToyStatus.AVAILABLE) {
throw new RuntimeException("玩具当前不可用");
}
// 计算租赁天数
long days = ChronoUnit.DAYS.between(startDate, endDate);
if (days <= 0) {
throw new RuntimeException("租赁天数必须大于0");
}
// 计算总费用
BigDecimal totalAmount = toy.getRentalPricePerDay().multiply(BigDecimal.valueOf(days));
// 创建租赁订单
RentalOrder order = new RentalOrder();
order.setToy(toy);
order.setRenter(userService.getUserById(userId));
order.setStartDate(startDate);
order.setEndDate(endDate);
order.setTotalAmount(totalAmount);
order.setStatus(RentalOrder.OrderStatus.PENDING);
order.setCreatedTime(LocalDateTime.now());
// 更新玩具状态
toy.setStatus(Toy.ToyStatus.RENTED);
toyRepository.save(toy);
return rentalOrderRepository.save(order);
}
public void completeRental(Long orderId, Long adminId) {
RentalOrder order = rentalOrderRepository.findById(orderId)
.orElseThrow(() -> new RuntimeException("订单不存在"));
// 检查玩具是否归还
if (order.getActualReturnDate() == null) {
throw new RuntimeException("玩具尚未归还");
}
// 更新订单状态
order.setStatus(RentalOrder.OrderStatus.COMPLETED);
order.setCompletedBy(adminId);
order.setCompletedTime(LocalDateTime.now());
rentalOrderRepository.save(order);
// 更新玩具状态为待清洁
Toy toy = order.getToy();
toy.setStatus(Toy.ToyStatus.CLEANING);
toyRepository.save(toy);
// 更新用户信用分(按时归还可获得信用加分)
if (!order.getActualReturnDate().isAfter(order.getEndDate())) {
userService.updateCreditScore(order.getRenter().getId(), 5, "按时归还玩具");
}
}
}
```
### 3. 消毒追踪系统
```java
@Entity
<"awdi.jiebaobifen.com">
<"lsof.jiebaobifen.com">
<"ftbw.jiebaobifen.com">
@Table(name = "disinfection_records")
@Data
public class DisinfectionRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "toy_id", nullable = false)
private Toy toy;
@Column(name = "disinfection_method", nullable = false)
private String disinfectionMethod;
@Column(name = "disinfection_time", nullable = false)
private LocalDateTime disinfectionTime;
@ManyToOne
@JoinColumn(name = "operator_id", nullable = false)
private User operator;
@Column(name = "next_suggested_date")
private LocalDate nextSuggestedDate;
private String notes;
@CreationTimestamp
private LocalDateTime createdTime;
}
@Service
@Transactional
public class DisinfectionService {
@Autowired
private DisinfectionRecordRepository disinfectionRecordRepository;
@Autowired
private ToyRepository toyRepository;
public DisinfectionRecord recordDisinfection(Long toyId, Long operatorId,
String method, String notes) {
Toy toy = toyRepository.findById(toyId)
.orElseThrow(() -> new RuntimeException("玩具不存在"));
DisinfectionRecord record = new DisinfectionRecord();
record.setToy(toy);
record.setDisinfectionMethod(method);
record.setDisinfectionTime(LocalDateTime.now());
record.setOperator(new User(operatorId));
record.setNextSuggestedDate(LocalDate.now().plusDays(7)); // 建议7天后再次消毒
record.setNotes(notes);
// 更新玩具状态为可用
toy.setStatus(Toy.ToyStatus.AVAILABLE);
toyRepository.save(toy);
return disinfectionRecordRepository.save(record);
}
public List<Toy> getToysNeedDisinfection() {
return toyRepository.findByStatus(Toy.ToyStatus.CLEANING);
}
public boolean isToyDisinfectedRecently(Long toyId) {
Optional<DisinfectionRecord> latestRecord =
disinfectionRecordRepository.findTopByToyIdOrderByDisinfectionTimeDesc(toyId);
if (latestRecord.isPresent()) {
LocalDateTime lastDisinfection = latestRecord.get().getDisinfectionTime();
return lastDisinfection.isAfter(LocalDateTime.now().minusDays(1));
}
return false;
}
}
```
### 4. 控制器层实现
```java
@RestController
<"sssv.jiebaobifen.com">
<"nrgr.jiebaobifen.com">
<"tgxu.jiebaobifen.com">
@RequestMapping("/api/toys")
@PreAuthorize("hasRole('PARENT')")
public class ToyController {
@Autowired
private ToyService toyService;
@Autowired
private RentalService rentalService;
@GetMapping
public ResponseEntity<Page<Toy>> getAvailableToys(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String category) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdTime").descending());
Page<Toy> toys = toyService.findAvailableToys(category, pageable);
return ResponseEntity.ok(toys);
}
@PostMapping("/{toyId}/rent")
public ResponseEntity<RentalOrder> rentToy(
@PathVariable Long toyId,
@RequestBody RentalRequest request,
Authentication authentication) {
User user = (User) authentication.getPrincipal();
RentalOrder order = rentalService.createRentalOrder(
toyId, user.getId(), request.getStartDate(), request.getEndDate());
return ResponseEntity.ok(order);
}
@Data
public static class RentalRequest {
@NotNull
private LocalDate startDate;
@NotNull
private LocalDate endDate;
}
}
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')")
public class AdminController {
@Autowired
private DisinfectionService disinfectionService;
@GetMapping("/toys/cleaning")
public ResponseEntity<List<Toy>> getToysNeedCleaning() {
List<Toy> toys = disinfectionService.getToysNeedDisinfection();
return ResponseEntity.ok(toys);
}
@PostMapping("/toys/{toyId}/disinfect")
public ResponseEntity<DisinfectionRecord> recordDisinfection(
@PathVariable Long toyId,
@RequestBody DisinfectionRequest request,
Authentication authentication) {
User admin = (User) authentication.getPrincipal();
DisinfectionRecord record = disinfectionService.recordDisinfection(
toyId, admin.getId(), request.getMethod(), request.getNotes());
return ResponseEntity.ok(record);
}
@Data
public static class DisinfectionRequest {
@NotBlank
private String method;
private String notes;
}
}
```
### 5. 安全配置
```java
<"iwff.jiebaobifen.com">
<"cags.jiebaobifen.com">
<"espj.jiebaobifen.com">
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
}
```
## 系统特色功能
### 1. 信用积分算法
```java
@Service
public class CreditScoreAlgorithm {
private static final int BASE_SCORE = 100;
private static final int MAX_SCORE = 100;
private static final int MIN_SCORE = 0;
public int calculateScore(User user) {
int score = BASE_SCORE;
// 基于租赁历史计算
score += calculateRentalHistoryScore(user);
// 基于归还及时性计算
score += calculateReturnTimelinessScore(user);
// 基于玩具维护状况计算
score += calculateToyMaintenanceScore(user);
return Math.max(MIN_SCORE, Math.min(MAX_SCORE, score));
}
private int calculateRentalHistoryScore(User user) {
// 实现具体的信用分计算逻辑
return 0;
}
private int calculateReturnTimelinessScore(User user) {
// 实现归还及时性评分逻辑
return 0;
}
private int calculateToyMaintenanceScore(User user) {
// 实现玩具维护状况评分逻辑
return 0;
}
}
```
### 2. 数据统计与可视化
```java
@Service
<"gkpc.jiebaobifen.com">
<"jtas.jiebaobifen.com">
<"impa.jiebaobifen.com">
public class StatisticsService {
@Autowired
private RentalOrderRepository rentalOrderRepository;
@Autowired
private ToyRepository toyRepository;
public Map<String, Object> getPlatformStatistics() {
Map<String, Object> stats = new HashMap<>();
// 平台总用户数
stats.put("totalUsers", userRepository.count());
// 在线玩具数量
stats.put("availableToys", toyRepository.countByStatus(Toy.ToyStatus.AVAILABLE));
// 本月租赁次数
LocalDateTime startOfMonth = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0);
stats.put("monthlyRentals", rentalOrderRepository.countByCreatedTimeAfter(startOfMonth));
// 最 受欢迎玩具类别
stats.put("popularCategories", getPopularCategories());
return stats;
}
private List<Map<String, Object>> getPopularCategories() {
// 实现类别受欢迎度统计逻辑
return new ArrayList<>();
}
}
```
## 总结
基于SpringBoot的儿童玩具共享平台实现了以下核心价值:
1. **资源循环利用**:通过玩具共享减少资源浪费,促进环保
2. **安全健康保障**:完善的消毒追踪系统确保儿童健康安全
3. **信用体系建设**:科学的信用积分机制维护平台秩序
4. **社区互动促进**:构建亲子家庭间的资源共享社区
该系统不仅解决了家庭中闲置玩具的处理问题,还为儿童提供了更丰富的玩具体验机会,同时培养了孩子们的共享意识和环保观念。平台的可扩展性强,未来可以进一步集成物联网设备实现自动化消毒追踪,或者引入区块链技术增强信用体系的透明度。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3102317/ ,如需转载,请注明出处,否则将追究法律责任。