本系统采用前后端分离架构,前端负责用户交互界面,后端处理业务逻辑与数据存储,通过API进行通信。这种架构便于团队分工、独立部署和扩展。
以下是经过生产环境验证的稳定技术组合:
在开始编码前,先创建标准的项目目录结构:
``` 档案培训系统/ ├── frontend/ 前端项目 │ ├── public/ │ ├── src/ │ │ ├── api/ 接口定义 │ │ ├── components/ 组件 │ │ ├── views/ 页面 │ │ └── router/ 路由 │ └── package.json └── backend/ 后端项目 ├── src/main/java/com/archive/training/ │ ├── controller/ 控制器 │ ├── service/ 业务层 │ ├── mapper/ 数据层 │ └── entity/ 实体类 └── pom.xml ```执行以下SQL语句创建数据库和表:
``` CREATE DATABASE archive_training DEFAULT CHARACTER SET utf8mb4; USE archive_training; -- 用户表 CREATE TABLE `user` ( `id` bigint NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL COMMENT '用户名', `real_name` varchar(50) NOT NULL COMMENT '真实姓名', `department` varchar(100) NOT NULL COMMENT '所属部门', `position` varchar(100) NOT NULL COMMENT '职位', `password` varchar(255) NOT NULL COMMENT '加密密码', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 培训课程表 CREATE TABLE `course` ( `id` bigint NOT NULL AUTO_INCREMENT, `title` varchar(200) NOT NULL COMMENT '课程标题', `description` text COMMENT '课程描述', `category` varchar(50) NOT NULL COMMENT '课程分类', `difficulty_level` tinyint NOT NULL COMMENT '难度等级1-5', `duration_minutes` int NOT NULL COMMENT '预计学习分钟数', `cover_image` varchar(500) COMMENT '封面图URL', `creator_id` bigint NOT NULL COMMENT '创建人ID', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_category` (`category`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 用户学习记录表 CREATE TABLE `learning_record` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL, `course_id` bigint NOT NULL, `progress_percent` int DEFAULT 0 COMMENT '学习进度百分比', `last_learn_time` datetime COMMENT '最后学习时间', `total_learn_minutes` int DEFAULT 0 COMMENT '累计学习分钟数', `is_completed` tinyint DEFAULT 0 COMMENT '是否完成', `complete_time` datetime COMMENT '完成时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_user_course` (`user_id`, `course_id`), KEY `idx_user` (`user_id`), KEY `idx_course` (`course_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 个性化推荐权重表 CREATE TABLE `recommendation_weight` ( `user_id` bigint NOT NULL, `category` varchar(50) NOT NULL COMMENT '课程分类', `weight` decimal(5,4) DEFAULT 0.5 COMMENT '权重0-1', `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`user_id`, `category`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ```插入基础测试数据:
``` -- 插入测试用户 INSERT INTO `user` (username, real_name, department, position, password) VALUES ('zhangsan', '张三', '档案管理部', '档案管理员', '$2a$10$YourEncryptedPasswordHere'), ('lisi', '李四', '人事档案科', '科长', '$2a$10$YourEncryptedPasswordHere'); -- 插入测试课程 INSERT INTO `course` (title, description, category, difficulty_level, duration_minutes, creator_id) VALUES ('档案数字化基础', '学习档案扫描、图像处理等基础操作', '数字化', 2, 120, 1), ('档案分类与编目', '掌握档案分类原则和编目方法', '分类编目', 3, 180, 1), ('电子档案管理规范', '了解电子档案的保存和管理要求', '电子档案', 4, 150, 1); ```使用Spring Initializr创建项目,或直接使用以下pom.xml关键依赖:
```在RecommendationService.java中实现核心推荐逻辑:
``` @Service public class RecommendationService { @Autowired private LearningRecordMapper learningRecordMapper; @Autowired private RecommendationWeightMapper weightMapper; / 为用户生成个性化课程推荐 / public List在application.yml中配置MinIO:
``` minio: endpoint: http://localhost:9000 accessKey: your-access-key secretKey: your-secret-key bucket: archive-training ```
实现文件上传控制器:
``` @RestController @RequestMapping("/api/file") public class FileController { @Autowired private MinioClient minioClient; @PostMapping("/upload") public ApiResult创建Vue项目并安装必要依赖:
``` npm create vue@latest archive-training-frontend cd archive-training-frontend npm install element-plus axios vue-router@4 npm install --save-dev sass ```配置main.js:
``` import { createApp } from 'vue' import App from './App.vue' import router from './router' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' const app = createApp(App) app.use(router) app.use(ElementPlus) app.mount('app') ```创建CourseLearning.vue组件:
```创建RecommendationList.vue:
```{{ course.description }}
创建docker-compose.yml文件:
``` version: '3.8' services: mysql: image: mysql:8.0 container_name: archive-mysql environment: MYSQL_ROOT_PASSWORD: root_password_here MYSQL_DATABASE: archive_training ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql command: --default-authentication-plugin=mysql_native_password redis: image: redis:6.2-alpine container_name: archive-redis ports: - "6379:6379" volumes: - redis_data:/data minio: image: minio/minio:latest container_name: archive-minio ports: - "9000:9000" - "9001:9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin123 volumes: - minio_data:/data command: server --console-address ":9001" /data backend: build: ./backend container_name: archive-backend ports: - "8080:8080" depends_on: - mysql - redis - minio environment: SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/archive_training SPRING_REDIS_HOST: redis frontend: build: ./frontend container_name: archive-frontend ports: - "80:80" depends_on: - backend volumes: mysql_data: redis_data: minio_data: ```在backend目录创建Dockerfile:
``` FROM openjdk:11-jre-slim WORKDIR /app COPY target/archive-training-backend.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"] ```在frontend目录创建Dockerfile:
``` FROM nginx:al