档案数字化培训按次计费系统搭建与配置实操指南

一、系统核心架构与选型

本方案采用前后端分离架构,前端使用Vue 3 + Element Plus,后端使用Spring Boot 2.7,数据库使用MySQL 8.0。此组合技术栈成熟,社区资源丰富,适合快速开发企业级应用。

你需要准备以下环境:

  • JDK 17 或更高版本
  • Node.js 18 或更高版本
  • MySQL 8.0
  • Maven 3.8+

二、数据库表结构设计

创建数据库及核心表,用于记录培训项目、收费标准及收费记录。

1. 创建数据库与用户

登录MySQL,执行以下命令:

``` CREATE DATABASE IF NOT EXISTS archive_training DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'training_admin'@'localhost' IDENTIFIED BY 'YourStrongPassword123!'; GRANT ALL PRIVILEGES ON archive_training. TO 'training_admin'@'localhost'; FLUSH PRIVILEGES; USE archive_training; ```

2. 核心数据表SQL

执行以下SQL语句创建表:

``` -- 培训项目表 CREATE TABLE training_program ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', program_name VARCHAR(100) NOT NULL COMMENT '培训项目名称', description TEXT COMMENT '项目描述', base_price_per_session DECIMAL(10, 2) NOT NULL COMMENT '单次培训基准价格(元)', status TINYINT DEFAULT 1 COMMENT '状态:1-启用,0-停用', created_time DATETIME DEFAULT CURRENT_TIMESTAMP, updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_status (status) ) COMMENT='培训项目表'; -- 收费标准明细表(支持按次数阶梯定价) CREATE TABLE pricing_rule ( id BIGINT AUTO_INCREMENT PRIMARY KEY, program_id BIGINT NOT NULL COMMENT '关联培训项目ID', min_sessions INT NOT NULL COMMENT '最小次数(包含)', max_sessions INT COMMENT '最大次数(包含),NULL表示无上限', unit_price DECIMAL(10, 2) NOT NULL COMMENT '对应次数区间的单价', FOREIGN KEY (program_id) REFERENCES training_program(id) ON DELETE CASCADE, INDEX idx_program (program_id) ) COMMENT='按次阶梯收费规则表'; -- 培训订单记录表 CREATE TABLE training_order ( id VARCHAR(32) PRIMARY KEY COMMENT '订单号,规则:ORD+年月日+6位序列,如ORD20240520000001', program_id BIGINT NOT NULL, customer_name VARCHAR(50) NOT NULL COMMENT '客户单位名称', contact_phone VARCHAR(20) COMMENT '联系人电话', total_sessions INT NOT NULL COMMENT '购买的总培训次数', applied_sessions INT DEFAULT 0 COMMENT '已消耗次数', total_amount DECIMAL(12, 2) NOT NULL COMMENT '订单总金额', order_status TINYINT DEFAULT 0 COMMENT '状态:0-待支付,1-已支付,2-已完成,3-已取消', created_time DATETIME DEFAULT CURRENT_TIMESTAMP, updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (program_id) REFERENCES training_program(id) ) COMMENT='培训订单表'; -- 单次培训消耗记录表 CREATE TABLE session_consumption ( id BIGINT AUTO_INCREMENT PRIMARY KEY, order_id VARCHAR(32) NOT NULL, session_date DATE NOT NULL COMMENT '培训日期', trainer_name VARCHAR(50) NOT NULL COMMENT '培训师姓名', session_topic VARCHAR(200) COMMENT '本次培训主题', created_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (order_id) REFERENCES training_order(id) ON DELETE CASCADE, INDEX idx_order_date (order_id, session_date) ) COMMENT='单次培训消耗记录表'; ```

三、后端服务核心实现

在Spring Boot项目中,创建以下核心服务和接口。

1. Maven依赖配置

档案数字化培训按次计费系统搭建与配置实操指南

在pom.xml中添加必要依赖:

``` org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java runtime org.projectlombok lombok true ```

2. 按次计费核心算法服务

创建PricingService.java,实现根据培训次数计算费用的核心逻辑:

``` package com.archive.training.service; import com.archive.training.entity.PricingRule; import com.archive.training.repository.PricingRuleRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.List; @Service public class PricingService { @Autowired private PricingRuleRepository pricingRuleRepository; / 根据培训项目ID和购买次数,计算总费用 @param programId 培训项目ID @param totalSessions 购买的培训总次数 @return 计算出的总金额 / public BigDecimal calculateTotalPrice(Long programId, Integer totalSessions) { // 1. 获取该项目的所有阶梯价格规则,并按最小次数升序排序 List rules = pricingRuleRepository .findByProgramIdOrderByMinSessionsAsc(programId); if (rules.isEmpty()) { throw new RuntimeException("未找到项目ID为 " + programId + " 的收费标准"); } BigDecimal totalAmount = BigDecimal.ZERO; int remainingSessions = totalSessions; // 2. 遍历阶梯规则进行累加计算 for (PricingRule rule : rules) { Integer maxSessions = rule.getMaxSessions(); int sessionsInThisTier; if (maxSessions == null) { // 最后一档,无上限,剩余次数全算在此档 sessionsInThisTier = remainingSessions; } else { // 计算本档位可覆盖的次数 int availableSessionsInTier = maxSessions - rule.getMinSessions() + 1; sessionsInThisTier = Math.min(remainingSessions, availableSessionsInTier); } if (sessionsInThisTier > 0) { // 本档位金额 = 档位单价 本档位次数 BigDecimal tierAmount = rule.getUnitPrice() .multiply(BigDecimal.valueOf(sessionsInThisTier)); totalAmount = totalAmount.add(tierAmount); remainingSessions -= sessionsInThisTier; } // 如果剩余次数为0,计算结束 if (remainingSessions <= 0) { break; } } // 3. 验证:如果遍历完所有规则后仍有剩余次数,说明配置有误 if (remainingSessions > 0) { throw new RuntimeException("收费标准规则未能覆盖全部次数,请检查阶梯规则配置"); } return totalAmount; } } ```

3. 订单创建与培训消耗API

创建OrderController.java,提供订单创建和记录培训消耗的REST接口:

``` package com.archive.training.controller; import com.archive.training.service.OrderService; import com.archive.training.vo.OrderCreateVO; import com.archive.training.vo.SessionConsumeVO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.; @RestController @RequestMapping("/api/order") public class OrderController { @Autowired private OrderService orderService; / 创建新订单 POST /api/order/create / @PostMapping("/create") public ApiResult createOrder(@RequestBody OrderCreateVO createVO) { // 参数验证 if (createVO.getProgramId() == null) { return ApiResult.error("培训项目ID不能为空"); } if (createVO.getTotalSessions() == null || createVO.getTotalSessions() <= 0) { return ApiResult.error("培训次数必须大于0"); } String orderId = orderService.createNewOrder(createVO); return ApiResult.ok("订单创建成功", orderId); } / 记录一次培训消耗 POST /api/order/consume-session / @PostMapping("/consume-session") public ApiResult consumeSession(@RequestBody SessionConsumeVO consumeVO) { // 参数验证 if (consumeVO.getOrderId() == null || consumeVO.getOrderId().trim().isEmpty()) { return ApiResult.error("订单号不能为空"); } if (consumeVO.getTrainerName() == null || consumeVO.getTrainerName().trim().isEmpty()) { return ApiResult.error("培训师姓名不能为空"); } boolean success = orderService.recordSessionConsumption(consumeVO); if (success) { return ApiResult.ok("培训记录保存成功"); } else { return ApiResult.error("培训记录保存失败,请检查订单状态或剩余次数"); } } / 查询订单剩余次数 GET /api/order/remaining-sessions/{orderId} / @GetMapping("/remaining-sessions/{orderId}") public ApiResult getRemainingSessions(@PathVariable String orderId) { Integer remaining = orderService.getRemainingSessions(orderId); return ApiResult.ok(remaining); } } ```

四、前端管理界面关键组件

使用Vue 3和Element Plus构建管理后台的关键界面。

1. 安装依赖并初始化项目

使用Vite创建项目并安装UI库:

``` npm create vue@latest archive-training-frontend cd archive-training-frontend npm install npm install element-plus axios ```

2. 阶梯价格配置组件

创建PricingRuleConfig.vue,用于配置按次数阶梯收费规则:

``` ```

3. 订单创建与费用试算组件

创建OrderCreate.vue,实现订单创建和实时费用计算:

```