本系统采用前后端分离架构,确保高可维护性和扩展性。前端使用Vue 3 + Element Plus构建用户界面,后端使用Spring Boot 2.7提供RESTful API,数据库选用MySQL 8.0存储结构化数据,MinIO作为文件存储服务。
确保你的开发环境已安装以下软件:
验证安装:
``` java -version node --version mysql --version mvn -v ```登录MySQL后执行:
``` CREATE DATABASE employee_archive DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'archive_admin'@'localhost' IDENTIFIED BY 'YourSecurePassword123!'; GRANT ALL PRIVILEGES ON employee_archive. TO 'archive_admin'@'localhost'; FLUSH PRIVILEGES; ```创建员工基本信息表:
``` CREATE TABLE employee_basic ( id BIGINT PRIMARY KEY AUTO_INCREMENT, employee_id VARCHAR(20) UNIQUE NOT NULL COMMENT '工号', name VARCHAR(50) NOT NULL COMMENT '姓名', gender TINYINT COMMENT '性别:0-女,1-男', id_card VARCHAR(18) UNIQUE NOT NULL COMMENT '身份证号', birth_date DATE NOT NULL COMMENT '出生日期', department_id INT NOT NULL COMMENT '部门ID', position VARCHAR(50) NOT NULL COMMENT '职位', hire_date DATE NOT NULL COMMENT '入职日期', status TINYINT DEFAULT 1 COMMENT '状态:1-在职,2-离职,3-休假', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_department (department_id), INDEX idx_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ```创建档案文件表:
``` CREATE TABLE archive_file ( id BIGINT PRIMARY KEY AUTO_INCREMENT, employee_id VARCHAR(20) NOT NULL COMMENT '关联员工工号', file_type TINYINT NOT NULL COMMENT '文件类型:1-身份证,2-学历证,3-劳动合同,4-职称证书', file_name VARCHAR(255) NOT NULL COMMENT '原始文件名', storage_path VARCHAR(500) NOT NULL COMMENT '存储路径', file_size BIGINT NOT NULL COMMENT '文件大小(字节)', upload_user VARCHAR(50) NOT NULL COMMENT '上传人', upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, is_valid TINYINT DEFAULT 1 COMMENT '是否有效:1-有效,0-无效', FOREIGN KEY (employee_id) REFERENCES employee_basic(employee_id) ON DELETE CASCADE, INDEX idx_employee (employee_id), INDEX idx_type (file_type) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ```使用Spring Initializr生成项目:
``` curl https://start.spring.io/starter.zip \ -d type=maven-project \ -d language=java \ -d bootVersion=2.7.12 \ -d baseDir=employee-archive-backend \ -d groupId=com.company.archive \ -d artifactId=employee-archive \ -d name=EmployeeArchive \ -d description=Employee Archive Management System \ -d packageName=com.company.archive \ -d packaging=jar \ -d javaVersion=11 \ -d dependencies=web,data-jpa,mysql,validation,security \ -o employee-archive.zip ```application.yml完整配置:
``` server: port: 8080 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/employee_archive?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: archive_admin password: YourSecurePassword123! driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 20 minimum-idle: 5 idle-timeout: 30000 max-lifetime: 1800000 connection-timeout: 30000 jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect format_sql: true servlet: multipart: max-file-size: 50MB max-request-size: 100MB minio: endpoint: http://localhost:9000 accessKey: your-minio-access-key secretKey: your-minio-secret-key bucket: employee-archives ```创建FileStorageService:
``` @Service public class FileStorageService { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.bucket}") private String bucketName; private MinioClient minioClient; @PostConstruct public void init() throws Exception { minioClient = MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); boolean found = minioClient.bucketExists( BucketExistsArgs.builder().bucket(bucketName).build()); if (!found) { minioClient.makeBucket( MakeBucketArgs.builder().bucket(bucketName).build()); } } public String uploadFile(MultipartFile file, String employeeId, Integer fileType) throws Exception { String originalFilename = file.getOriginalFilename(); String extension = originalFilename.substring( originalFilename.lastIndexOf(".")); String objectName = employeeId + "/" + System.currentTimeMillis() + extension; minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build()); return objectName; } public byte[] downloadFile(String objectName) throws Exception { try (InputStream stream = minioClient.getObject( GetObjectArgs.builder() .bucket(bucketName) .object(objectName) .build())) { return IOUtils.toByteArray(stream); } } } ```EmployeeController核心方法:
``` @RestController @RequestMapping("/api/employees") public class EmployeeController { @Autowired private EmployeeService employeeService; @PostMapping public ResponseEntity
使用Vite创建项目:
``` npm create vue@latest employee-archive-frontend cd employee-archive-frontend npm install element-plus axios vue-router@4 pinia npm install sass --save-dev ```EmployeeList.vue核心代码:
```FileUpload.vue实现:
```打包Spring Boot应用:
``` cd employee-archive-backend mvn clean package -DskipTests ```创建Dockerfile:
``` FROM openjdk:11-jre-slim WORKDIR /app COPY target/employee-archive-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"] ```构建并运行容器:
``` docker build -t employee-archive-backend . docker run -d -p 8080:8080 \ -e SPRING_DATASOURCE_URL=jdbc:mysql://mysql-host:3306/employee_archive \ -e SPRING_DATASOURCE_USERNAME=archive_admin \ -e SPRING_DATASOURCE_PASSWORD=YourSecurePassword123! \ --name archive-backend \ employee-archive-backend ```构建生产版本:
``` cd employee-archive-frontend npm run build ```创建Nginx配置文件:
``` server { listen 80; server_name archive.yourcompany.com; root /var/www/employee-archive-frontend/dist; index index.html; location / { try_files $uri $uri/ /index.html; } location /api { proxy_pass http://localhost:8080/api; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ```使用Docker部署MinIO:
``` docker run -d \ -p 9000:9000 \ -p 9001:9001 \ -v /data/minio:/data \ -e "MINIO_ROOT_USER=your-minio-access-key" \ -e "MINIO_ROOT_PASSWORD=your-minio-secret-key" \ --name minio \ minio/minio server /data --console-address ":9001" ```访问MinIO控制台:http://localhost:9001,创建名为employee-archives的存储桶,并设置访问策略。
执行以下SQL验证数据一致性:
``` -- 检查员工与档案关联 SELECT e.employee_id, e.name, COUNT(f.id) as file_count FROM employee_basic e LEFT JOIN archive_file f ON e.employee_id = f.employee_id WHERE f.is_valid = 1 GROUP BY e.employee_id, e.name ORDER BY file_count DESC; -- 检查文件存储路径有效性 SELECT f.file_name, f.storage_path, LENGTH(f.storage_path) as path_length FROM archive_file f WHERE f.storage