ITPub博客

首页 > 应用开发 > Java > SpringBoot儿童玩具共享平台:玩具循环租赁与消毒追踪系统

SpringBoot儿童玩具共享平台:玩具循环租赁与消毒追踪系统

Java 作者:bhluo 时间:2025-11-19 11:28:50 0 删除 编辑

# 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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    933664