企业级Java项目金融应用领域——银行系统(补充)

发布于:2025-08-18 ⋅ 阅读:(16) ⋅ 点赞:(0)

7. 报表与分析

财务报表

业务分析报表

监管报表

数据可视化

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    
    <!-- Reporting -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
    
    <!-- Other -->
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.6.14</version>
    </dependency>
</dependencies>
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/bank_reporting_db?useSSL=false&serverTimezone=UTC
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver

reporting:
  output-directory: ./reports
  retention-days: 30

server:
  port: 8080
@Entity
@Table(name = "report_definition")
@Data
public class ReportDefinition {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String reportCode;
    
    @Column(nullable = false)
    private String reportName;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ReportType reportType;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ReportFrequency frequency;
    
    @Column(nullable = false, columnDefinition = "TEXT")
    private String sqlQuery;
    
    @Column(nullable = false)
    private String outputFields;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ReportFormat defaultFormat;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ReportStatus status = ReportStatus.ACTIVE;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}
@Entity
@Table(name = "generated_report")
@Data
public class GeneratedReport {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String reportCode;
    
    @Column(nullable = false)
    private String reportName;
    
    @Column(nullable = false)
    private LocalDate reportDate;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ReportFormat format;
    
    @Column(nullable = false)
    private String filePath;
    
    @Column(nullable = false)
    private Long fileSize;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ReportStatus status = ReportStatus.PENDING;
    
    @Column
    private String generatedBy;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
}
@Entity
@Table(name = "report_schedule")
@Data
public class ReportSchedule {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String reportCode;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ReportFrequency frequency;
    
    @Column
    private LocalTime dailyTime;
    
    @Column
    private Integer dayOfMonth;
    
    @Column
    private Integer weekDay;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ScheduleStatus status = ScheduleStatus.ACTIVE;
    
    @Column
    private String recipients;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}
public enum ReportType {
    FINANCIAL,          // 财务报表
    BUSINESS,           // 业务报表
    REGULATORY,         // 监管报表
    OPERATIONAL,        // 运营报表
    ANALYTICAL          // 分析报表
}

public enum ReportFrequency {
    DAILY,              // 每日
    WEEKLY,             // 每周
    MONTHLY,            // 每月
    QUARTERLY,          // 每季度
    YEARLY,             // 每年
    ON_DEMAND           // 按需
}

public enum ReportFormat {
    PDF,                // PDF格式
    EXCEL,              // Excel格式
    CSV,                // CSV格式
    HTML,               // HTML格式
    JSON                // JSON格式
}

public enum ReportStatus {
    ACTIVE,             // 活跃
    INACTIVE,           // 不活跃
    PENDING,            // 待处理
    GENERATING,         // 生成中
    COMPLETED,          // 已完成
    FAILED              // 失败
}

public enum ScheduleStatus {
    ACTIVE,             // 活跃
    INACTIVE,           // 不活跃
    PAUSED              // 暂停
}
@Data
public class ReportDefinitionDTO {
    private Long id;
    private String reportCode;
    private String reportName;
    private ReportType reportType;
    private ReportFrequency frequency;
    private String sqlQuery;
    private String outputFields;
    private ReportFormat defaultFormat;
    private ReportStatus status;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}
@Data
public class ReportRequestDTO {
    @NotNull
    private String reportCode;
    
    private LocalDate reportDate;
    
    @NotNull
    private ReportFormat format;
    
    private String parameters; // JSON格式的参数
}
@Data
public class ReportRequestDTO {
    @NotNull
    private String reportCode;
    
    private LocalDate reportDate;
    
    @NotNull
    private ReportFormat format;
    
    private String parameters; // JSON格式的参数
}
@Data
public class ReportScheduleDTO {
    private Long id;
    private String reportCode;
    private ReportFrequency frequency;
    private LocalTime dailyTime;
    private Integer dayOfMonth;
    private Integer weekDay;
    private ScheduleStatus status;
    private String recipients;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Data
public class ReportDataDTO {
    private String reportCode;
    private String reportName;
    private List<String> headers;
    private List<Map<String, Object>> data;
    private long totalRecords;
}
@Data
public class DashboardDataDTO {
    private BigDecimal totalDeposits;
    private BigDecimal totalLoans;
    private BigDecimal totalAssets;
    private BigDecimal totalLiabilities;
    private BigDecimal netIncome;
    private Map<LocalDate, BigDecimal> dailyTransactions;
    private Map<String, Long> customerDistribution;
    private List<Map<String, Object>> recentTransactions;
    private List<Map<String, Object>> loanPortfolio;
}

Repository层

public interface ReportDefinitionRepository extends JpaRepository<ReportDefinition, Long> {
    Optional<ReportDefinition> findByReportCode(String reportCode);
    
    List<ReportDefinition> findByReportType(ReportType reportType);
    
    List<ReportDefinition> findByStatus(ReportStatus status);
}
public interface GeneratedReportRepository extends JpaRepository<GeneratedReport, Long> {
    List<GeneratedReport> findByReportCodeAndReportDateBetween(
            String reportCode, LocalDate startDate, LocalDate endDate);
    
    List<GeneratedReport> findByReportCodeAndFormatAndStatus(
            String reportCode, ReportFormat format, ReportStatus status);
    
    Optional<GeneratedReport> findByReportCodeAndReportDateAndFormat(
            String reportCode, LocalDate reportDate, ReportFormat format);
}
public interface ReportScheduleRepository extends JpaRepository<ReportSchedule, Long> {
    List<ReportSchedule> findByReportCode(String reportCode);
    
    List<ReportSchedule> findByFrequencyAndStatus(ReportFrequency frequency, ScheduleStatus status);
}

Service层

@Service
@RequiredArgsConstructor
@Slf4j
public class ReportGenerationService {
    private final ReportDefinitionRepository definitionRepository;
    private final GeneratedReportRepository generatedReportRepository;
    private final ReportQueryExecutor queryExecutor;
    private final ReportFileGenerator fileGenerator;
    
    @Transactional
    public GeneratedReportDTO generateReport(ReportRequestDTO request) {
        LocalDate reportDate = request.getReportDate() != null ? 
                request.getReportDate() : LocalDate.now();
        
        // 检查是否已存在相同报告
        Optional<GeneratedReport> existingReport = generatedReportRepository
                .findByReportCodeAndReportDateAndFormat(
                        request.getReportCode(), 
                        reportDate, 
                        request.getFormat());
        
        if (existingReport.isPresent()) {
            return convertToDTO(existingReport.get());
        }
        
        // 获取报告定义
        ReportDefinition definition = definitionRepository.findByReportCode(request.getReportCode())
                .orElseThrow(() -> new AccountException(ErrorCode.REPORT_DEFINITION_NOT_FOUND));
        
        // 创建报告记录
        GeneratedReport report = new GeneratedReport();
        report.setReportCode(definition.getReportCode());
        report.setReportName(definition.getReportName());
        report.setReportDate(reportDate);
        report.setFormat(request.getFormat());
        report.setStatus(ReportStatus.PENDING);
        
        GeneratedReport saved = generatedReportRepository.save(report);
        log.info("Report generation requested: {}", saved.getId());
        
        // 异步生成报告
        generateReportAsync(saved.getId(), definition, request.getParameters());
        
        return convertToDTO(saved);
    }
    
    @Async
    public void generateReportAsync(Long reportId, ReportDefinition definition, String parameters) {
        try {
            // 更新状态为生成中
            GeneratedReport report = generatedReportRepository.findById(reportId)
                    .orElseThrow(() -> new AccountException(ErrorCode.REPORT_NOT_FOUND));
            
            report.setStatus(ReportStatus.GENERATING);
            generatedReportRepository.save(report);
            
            // 执行SQL查询获取数据
            Map<String, Object> params = parseParameters(parameters);
            ReportDataDTO reportData = queryExecutor.executeQuery(definition.getSqlQuery(), params);
            
            // 生成报告文件
            String filePath = fileGenerator.generateReportFile(
                    reportData, 
                    definition.getOutputFields(), 
                    report.getFormat(),
                    definition.getReportCode(),
                    report.getReportDate());
            
            // 更新报告记录
            report.setFilePath(filePath);
            report.setFileSize(getFileSize(filePath));
            report.setStatus(ReportStatus.COMPLETED);
            generatedReportRepository.save(report);
            
            log.info("Report generated successfully: {}", reportId);
        } catch (Exception e) {
            log.error("Failed to generate report: " + reportId, e);
            generatedReportRepository.findById(reportId).ifPresent(r -> {
                r.setStatus(ReportStatus.FAILED);
                generatedReportRepository.save(r);
            });
        }
    }
    
    @Transactional(readOnly = true)
    public ReportDataDTO getReportData(String reportCode, String parameters) {
        ReportDefinition definition = definitionRepository.findByReportCode(reportCode)
                .orElseThrow(() -> new AccountException(ErrorCode.REPORT_DEFINITION_NOT_FOUND));
        
        Map<String, Object> params = parseParameters(parameters);
        return queryExecutor.executeQuery(definition.getSqlQuery(), params);
    }
    
    private Map<String, Object> parseParameters(String parameters) {
        // 实现JSON参数解析
        // 实际项目中可以使用Jackson或Gson
        return Map.of(); // 简化处理
    }
    
    private long getFileSize(String filePath) {
        // 实现获取文件大小逻辑
        return 0; // 简化处理
    }
    
    private GeneratedReportDTO convertToDTO(GeneratedReport report) {
        GeneratedReportDTO dto = new GeneratedReportDTO();
        dto.setId(report.getId());
        dto.setReportCode(report.getReportCode());
        dto.setReportName(report.getReportName());
        dto.setReportDate(report.getReportDate());
        dto.setFormat(report.getFormat());
        dto.setFilePath(report.getFilePath());
        dto.setFileSize(report.getFileSize());
        dto.setStatus(report.getStatus());
        dto.setGeneratedBy(report.getGeneratedBy());
        dto.setCreatedAt(report.getCreatedAt());
        return dto;
    }
}
/**
	报表查询执行器
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class ReportQueryExecutor {
    private final JdbcTemplate jdbcTemplate;
    
    public ReportDataDTO executeQuery(String sqlQuery, Map<String, Object> parameters) {
        try {
            ReportDataDTO result = new ReportDataDTO();
            List<Map<String, Object>> data = new ArrayList<>();
            
            // 执行查询
            SqlRowSet rowSet = jdbcTemplate.queryForRowSet(sqlQuery, parameters);
            
            // 获取列信息
            List<String> headers = new ArrayList<>();
            if (rowSet.next()) {
                String[] columnNames = rowSet.getMetaData().getColumnNames();
                for (String columnName : columnNames) {
                    headers.add(columnName);
                }
                
                // 处理第一行数据
                data.add(extractRowData(rowSet, headers));
                
                // 处理剩余数据
                while (rowSet.next()) {
                    data.add(extractRowData(rowSet, headers));
                }
            }
            
            result.setHeaders(headers);
            result.setData(data);
            result.setTotalRecords(data.size());
            
            return result;
        } catch (Exception e) {
            log.error("Error executing report query: " + e.getMessage(), e);
            throw new AccountException(ErrorCode.REPORT_QUERY_EXECUTION_FAILED);
        }
    }
    
    private Map<String, Object> extractRowData(SqlRowSet rowSet, List<String> headers) {
        Map<String, Object> rowData = new HashMap<>();
        for (String column : headers) {
            rowData.put(column, rowSet.getObject(column));
        }
        return rowData;
    }
}
/**
	报表文件生成器
*/
@Component
@Slf4j
public class ReportFileGenerator {
    @Value("${reporting.output-directory}")
    private String outputDirectory;
    
    public String generateReportFile(
            ReportDataDTO reportData,
            String outputFields,
            ReportFormat format,
            String reportCode,
            LocalDate reportDate) throws IOException {
        
        String fileName = String.format("%s_%s.%s", 
                reportCode, 
                reportDate.format(DateTimeFormatter.BASIC_ISO_DATE), 
                format.name().toLowerCase());
        
        Path outputPath = Paths.get(outputDirectory, fileName);
        
        switch (format) {
            case EXCEL:
                generateExcelFile(reportData, outputPath);
                break;
            case PDF:
                // 实现PDF生成逻辑
                break;
            case CSV:
                // 实现CSV生成逻辑
                break;
            case HTML:
                // 实现HTML生成逻辑
                break;
            case JSON:
                // 实现JSON生成逻辑
                break;
            default:
                throw new IllegalArgumentException("Unsupported report format: " + format);
        }
        
        return outputPath.toString();
    }
    
    private void generateExcelFile(ReportDataDTO reportData, Path outputPath) throws IOException {
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet("Report");
            
            // 创建标题行
            Row headerRow = sheet.createRow(0);
            List<String> headers = reportData.getHeaders();
            for (int i = 0; i < headers.size(); i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers.get(i));
            }
            
            // 填充数据
            List<Map<String, Object>> data = reportData.getData();
            for (int i = 0; i < data.size(); i++) {
                Row row = sheet.createRow(i + 1);
                Map<String, Object> rowData = data.get(i);
                
                for (int j = 0; j < headers.size(); j++) {
                    Cell cell = row.createCell(j);
                    Object value = rowData.get(headers.get(j));
                    
                    if (value instanceof Number) {
                        cell.setCellValue(((Number) value).doubleValue());
                    } else {
                        cell.setCellValue(value != null ? value.toString() : "");
                    }
                }
            }
            
            // 自动调整列宽
            for (int i = 0; i < headers.size(); i++) {
                sheet.autoSizeColumn(i);
            }
            
            // 写入文件
            try (FileOutputStream outputStream = new FileOutputStream(outputPath.toFile())) {
                workbook.write(outputStream);
            }
        }
    }
}
/**
	定时任务服务
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class ReportSchedulingService {
    private final ReportScheduleRepository scheduleRepository;
    private final ReportGenerationService generationService;
    
    @Scheduled(cron = "0 0 6 * * ?") // 每天6点执行
    public void generateDailyReports() {
        log.info("Starting daily report generation");
        List<ReportSchedule> schedules = scheduleRepository
                .findByFrequencyAndStatus(ReportFrequency.DAILY, ScheduleStatus.ACTIVE);
        
        schedules.forEach(schedule -> {
            try {
                generateScheduledReport(schedule);
            } catch (Exception e) {
                log.error("Failed to generate daily report: " + schedule.getReportCode(), e);
            }
        });
    }
    
    @Scheduled(cron = "0 0 6 * * MON") // 每周一6点执行
    public void generateWeeklyReports() {
        log.info("Starting weekly report generation");
        List<ReportSchedule> schedules = scheduleRepository
                .findByFrequencyAndStatus(ReportFrequency.WEEKLY, ScheduleStatus.ACTIVE);
        
        schedules.forEach(schedule -> {
            try {
                generateScheduledReport(schedule);
            } catch (Exception e) {
                log.error("Failed to generate weekly report: " + schedule.getReportCode(), e);
            }
        });
    }
    
    @Scheduled(cron = "0 0 6 1 * ?") // 每月1号6点执行
    public void generateMonthlyReports() {
        log.info("Starting monthly report generation");
        List<ReportSchedule> schedules = scheduleRepository
                .findByFrequencyAndStatus(ReportFrequency.MONTHLY, ScheduleStatus.ACTIVE);
        
        schedules.forEach(schedule -> {
            try {
                generateScheduledReport(schedule);
            } catch (Exception e) {
                log.error("Failed to generate monthly report: " + schedule.getReportCode(), e);
            }
        });
    }
    
    private void generateScheduledReport(ReportSchedule schedule) {
        ReportRequestDTO request = new ReportRequestDTO();
        request.setReportCode(schedule.getReportCode());
        request.setFormat(ReportFormat.EXCEL); // 默认生成Excel格式
        
        generationService.generateReport(request);
        log.info("Scheduled report generated: {}", schedule.getReportCode());
    }
}
/**
	数据可视化服务
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class DashboardService {
    private final JdbcTemplate jdbcTemplate;
    
    public DashboardDataDTO getDashboardData() {
        DashboardDataDTO dashboard = new DashboardDataDTO();
        
        // 获取总存款
        dashboard.setTotalDeposits(getTotalDeposits());
        
        // 获取总贷款
        dashboard.setTotalLoans(getTotalLoans());
        
        // 获取总资产和总负债
        Map<String, BigDecimal> assetsAndLiabilities = getAssetsAndLiabilities();
        dashboard.setTotalAssets(assetsAndLiabilities.get("assets"));
        dashboard.setTotalLiabilities(assetsAndLiabilities.get("liabilities"));
        
        // 获取净收入
        dashboard.setNetIncome(getNetIncome());
        
        // 获取每日交易量
        dashboard.setDailyTransactions(getDailyTransactions());
        
        // 获取客户分布
        dashboard.setCustomerDistribution(getCustomerDistribution());
        
        // 获取最近交易
        dashboard.setRecentTransactions(getRecentTransactions());
        
        // 获取贷款组合
        dashboard.setLoanPortfolio(getLoanPortfolio());
        
        return dashboard;
    }
    
    private BigDecimal getTotalDeposits() {
        String sql = "SELECT SUM(balance) FROM account WHERE account_type IN ('PERSONAL_SAVINGS', 'PERSONAL_CURRENT', 'CORPORATE_CURRENT')";
        return jdbcTemplate.queryForObject(sql, BigDecimal.class);
    }
    
    private BigDecimal getTotalLoans() {
        String sql = "SELECT SUM(outstanding_amount) FROM loan_account WHERE status = 'ACTIVE'";
        return jdbcTemplate.queryForObject(sql, BigDecimal.class);
    }
    
    private Map<String, BigDecimal> getAssetsAndLiabilities() {
        String sql = "SELECT 'assets' AS type, SUM(balance) AS amount FROM account " +
                     "UNION ALL " +
                     "SELECT 'liabilities' AS type, SUM(outstanding_amount) AS amount FROM loan_account";
        
        return jdbcTemplate.query(sql, rs -> {
            Map<String, BigDecimal> result = new HashMap<>();
            while (rs.next()) {
                result.put(rs.getString("type"), rs.getBigDecimal("amount"));
            }
            return result;
        });
    }
    
    private BigDecimal getNetIncome() {
        String sql = "SELECT (SELECT SUM(amount) FROM transaction WHERE amount > 0 AND created_at >= DATE_TRUNC('month', CURRENT_DATE)) - " +
                     "(SELECT SUM(amount) FROM transaction WHERE amount < 0 AND created_at >= DATE_TRUNC('month', CURRENT_DATE))";
        return jdbcTemplate.queryForObject(sql, BigDecimal.class);
    }
    
    private Map<LocalDate, BigDecimal> getDailyTransactions() {
        String sql = "SELECT DATE(created_at) AS day, SUM(ABS(amount)) AS volume " +
                     "FROM transaction " +
                     "WHERE created_at >= CURRENT_DATE - INTERVAL '30 days' " +
                     "GROUP BY day " +
                     "ORDER BY day";
        
        return jdbcTemplate.query(sql, rs -> {
            Map<LocalDate, BigDecimal> result = new HashMap<>();
            while (rs.next()) {
                result.put(rs.getDate("day").toLocalDate(), rs.getBigDecimal("volume"));
            }
            return result;
        });
    }
    
    private Map<String, Long> getCustomerDistribution() {
        String sql = "SELECT tier, COUNT(*) AS count FROM customer GROUP BY tier";
        
        return jdbcTemplate.query(sql, rs -> {
            Map<String, Long> result = new HashMap<>();
            while (rs.next()) {
                result.put(rs.getString("tier"), rs.getLong("count"));
            }
            return result;
        });
    }
    
    private List<Map<String, Object>> getRecentTransactions() {
        String sql = "SELECT t.id, t.amount, t.description, a.account_number, c.first_name, c.last_name " +
                     "FROM transaction t " +
                     "JOIN account a ON t.account_number = a.account_number " +
                     "JOIN customer c ON a.customer_id = c.id " +
                     "ORDER BY t.created_at DESC LIMIT 10";
        
        return jdbcTemplate.queryForList(sql);
    }
    
    private List<Map<String, Object>> getLoanPortfolio() {
        String sql = "SELECT loan_type, SUM(outstanding_amount) AS amount, COUNT(*) AS count " +
                     "FROM loan_account " +
                     "WHERE status = 'ACTIVE' " +
                     "GROUP BY loan_type";
        
        return jdbcTemplate.queryForList(sql);
    }
}

Controller层

@RestController
@RequestMapping("/api/reports")
@RequiredArgsConstructor
public class ReportController {
    private final ReportGenerationService generationService;
    private final ReportSchedulingService schedulingService;
    
    @PostMapping("/generate")
    @PreAuthorize("hasAnyRole('REPORT_USER', 'ADMIN')")
    public GeneratedReportDTO generateReport(@Valid @RequestBody ReportRequestDTO request) {
        return generationService.generateReport(request);
    }
    
    @GetMapping("/data/{reportCode}")
    @PreAuthorize("hasAnyRole('REPORT_USER', 'ADMIN')")
    public ReportDataDTO getReportData(
            @PathVariable String reportCode,
            @RequestParam(required = false) String parameters) {
        return generationService.getReportData(reportCode, parameters);
    }
}

// DashboardController.java
package com.bank.reporting.controller;

import com.bank.reporting.dto.DashboardDataDTO;
import com.bank.reporting.service.DashboardService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/dashboard")
@RequiredArgsConstructor
public class DashboardController {
    private final DashboardService dashboardService;
    
    @GetMapping
    public DashboardDataDTO getDashboardData() {
        return dashboardService.getDashboardData();
    }
}

8. 系统管理

用户权限管理

角色管理

系统参数配置

操作日志审计

@Entity
@Table(name = "system_user")
@Data
public class SystemUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String username;
    
    @Column(nullable = false)
    private String password;
    
    @Column(nullable = false)
    private String fullName;
    
    @Column(nullable = false, unique = true)
    private String email;
    
    @Column
    private String phone;
    
    @Column(nullable = false)
    private String department;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private UserStatus status = UserStatus.ACTIVE;
    
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
        name = "user_role",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<SystemRole> roles = new HashSet<>();
    
    @Column
    private LocalDateTime lastLoginTime;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
    
    @Version
    private Long version;
}
@Entity
@Table(name = "system_role")
@Data
public class SystemRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String roleCode;
    
    @Column(nullable = false)
    private String roleName;
    
    @Column
    private String description;
    
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
        name = "role_permission",
        joinColumns = @JoinColumn(name = "role_id"),
        inverseJoinColumns = @JoinColumn(name = "permission_id")
    )
    private Set<SystemPermission> permissions = new HashSet<>();
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}
@Entity
@Table(name = "system_permission")
@Data
public class SystemPermission {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String permissionCode;
    
    @Column(nullable = false)
    private String permissionName;
    
    @Column
    private String description;
    
    @Column(nullable = false)
    private String resource;
    
    @Column(nullable = false)
    private String action;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}
@Entity
@Table(name = "system_parameter")
@Data
public class SystemParameter {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String paramKey;
    
    @Column(nullable = false)
    private String paramName;
    
    @Column(nullable = false)
    private String paramValue;
    
    @Column
    private String description;
    
    @Column(nullable = false)
    private Boolean isEditable = true;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}

@Entity
@Table(name = "audit_log")
@Data
public class AuditLog {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private Long userId;
    
    @Column(nullable = false)
    private String username;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private AuditAction action;
    
    @Column(nullable = false)
    private String entityType;
    
    @Column
    private Long entityId;
    
    @Column(columnDefinition = "TEXT")
    private String oldValue;
    
    @Column(columnDefinition = "TEXT")
    private String newValue;
    
    @Column
    private String ipAddress;
    
    @Column
    private String userAgent;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
}
public enum UserStatus {
    ACTIVE,         // 活跃
    INACTIVE,       // 不活跃
    LOCKED,         // 锁定
    PASSWORD_EXPIRED // 密码过期
}

public enum AuditAction {
    CREATE,         // 创建
    UPDATE,         // 更新
    DELETE,         // 删除
    LOGIN,          // 登录
    LOGOUT,         // 登出
    ACCESS          // 访问
}
public enum AuditAction {
    CREATE,         // 创建
    UPDATE,         // 更新
    DELETE,         // 删除
    LOGIN,          // 登录
    LOGOUT,         // 登出
    ACCESS          // 访问
}
@Data
public class UserCreateRequest {
    @NotBlank
    private String username;
    
    @NotBlank
    @Size(min = 8)
    private String password;
    
    @NotBlank
    private String fullName;
    
    @Email
    @NotBlank
    private String email;
    
    private String phone;
    
    @NotBlank
    private String department;
}

@Data
public class UserUpdateRequest {
    @NotBlank
    private String fullName;
    
    @Email
    @NotBlank
    private String email;
    
    private String phone;
    
    @NotBlank
    private String department;
}

@Data
public class RoleDTO {
    private Long id;
    private String roleCode;
    private String roleName;
    private String description;
    private Set<String> permissions;
    private LocalDateTime createdAt;
}

@Data
public class RoleDTO {
    private Long id;
    private String roleCode;
    private String roleName;
    private String description;
    private Set<String> permissions;
    private LocalDateTime createdAt;
}

@Data
public class ParameterDTO {
    private Long id;
    private String paramKey;
    private String paramName;
    private String paramValue;
    private String description;
    private Boolean isEditable;
    private LocalDateTime createdAt;
}
@Data
public class AuditLogDTO {
    private Long id;
    private Long userId;
    private String username;
    private AuditAction action;
    private String entityType;
    private Long entityId;
    private String oldValue;
    private String newValue;
    private String ipAddress;
    private String userAgent;
    private LocalDateTime createdAt;
}

Repository层

public interface UserRepository extends JpaRepository<SystemUser, Long> {
    Optional<SystemUser> findByUsername(String username);
    
    Optional<SystemUser> findByEmail(String email);
    
    boolean existsByUsername(String username);
    
    boolean existsByEmail(String email);
    
    @Query("SELECT u FROM SystemUser u JOIN u.roles r WHERE r.roleCode = :roleCode")
    List<SystemUser> findByRoleCode(@Param("roleCode") String roleCode);
}
public interface RoleRepository extends JpaRepository<SystemRole, Long> {
    Optional<SystemRole> findByRoleCode(String roleCode);
    
    boolean existsByRoleCode(String roleCode);
}

public interface RoleRepository extends JpaRepository<SystemRole, Long> {
    Optional<SystemRole> findByRoleCode(String roleCode);
    
    boolean existsByRoleCode(String roleCode);
}

public interface ParameterRepository extends JpaRepository<SystemParameter, Long> {
    Optional<SystemParameter> findByParamKey(String paramKey);
    
    boolean existsByParamKey(String paramKey);
}
public interface AuditLogRepository extends JpaRepository<AuditLog, Long> {
    List<AuditLog> findByUserId(Long userId);
    
    List<AuditLog> findByAction(AuditAction action);
    
    List<AuditLog> findByEntityTypeAndEntityId(String entityType, Long entityId);
    
    List<AuditLog> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
}

Service层

@Service
@RequiredArgsConstructor
@Slf4j
public class UserService {
    private final UserRepository userRepository;
    private final RoleRepository roleRepository;
    private final PasswordEncoder passwordEncoder;
    private final AuditLogService auditLogService;
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public UserDTO createUser(UserCreateRequest request) {
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new AccountException(ErrorCode.USERNAME_ALREADY_EXISTS);
        }
        
        if (userRepository.existsByEmail(request.getEmail())) {
            throw new AccountException(ErrorCode.EMAIL_ALREADY_EXISTS);
        }
        
        SystemUser user = new SystemUser();
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setFullName(request.getFullName());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setDepartment(request.getDepartment());
        user.setStatus(UserStatus.ACTIVE);
        
        SystemUser saved = userRepository.save(user);
        log.info("User created: {}", saved.getUsername());
        
        auditLogService.logUserAction(saved.getId(), "CREATE", "User created");
        
        return convertToDTO(saved);
    }
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN') or #username == authentication.principal.username")
    public UserDTO updateUser(String username, UserUpdateRequest request) {
        SystemUser user = userRepository.findByUsername(username)
                .orElseThrow(() -> new AccountException(ErrorCode.USER_NOT_FOUND));
        
        user.setFullName(request.getFullName());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setDepartment(request.getDepartment());
        
        SystemUser saved = userRepository.save(user);
        log.info("User updated: {}", username);
        
        auditLogService.logUserAction(saved.getId(), "UPDATE", "User updated");
        
        return convertToDTO(saved);
    }
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public UserDTO updateUserStatus(String username, UserStatus status) {
        SystemUser user = userRepository.findByUsername(username)
                .orElseThrow(() -> new AccountException(ErrorCode.USER_NOT_FOUND));
        
        user.setStatus(status);
        
        SystemUser saved = userRepository.save(user);
        log.info("User status updated to {}: {}", status, username);
        
        auditLogService.logUserAction(saved.getId(), "UPDATE", "Status updated to " + status);
        
        return convertToDTO(saved);
    }
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN') or #username == authentication.principal.username")
    public void changePassword(String username, String newPassword) {
        SystemUser user = userRepository.findByUsername(username)
                .orElseThrow(() -> new AccountException(ErrorCode.USER_NOT_FOUND));
        
        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);
        log.info("Password changed for user: {}", username);
        
        auditLogService.logUserAction(user.getId(), "UPDATE", "Password changed");
    }
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public UserDTO assignRoles(String username, Set<String> roleCodes) {
        SystemUser user = userRepository.findByUsername(username)
                .orElseThrow(() -> new AccountException(ErrorCode.USER_NOT_FOUND));
        
        Set<SystemRole> roles = roleCodes.stream()
                .map(roleCode -> roleRepository.findByRoleCode(roleCode)
                        .orElseThrow(() -> new AccountException(ErrorCode.ROLE_NOT_FOUND)))
                .collect(Collectors.toSet());
        
        user.setRoles(roles);
        
        SystemUser saved = userRepository.save(user);
        log.info("Roles assigned to user {}: {}", username, roleCodes);
        
        auditLogService.logUserAction(saved.getId(), "UPDATE", "Roles assigned: " + roleCodes);
        
        return convertToDTO(saved);
    }
    
    @Transactional(readOnly = true)
    @PreAuthorize("hasRole('ADMIN') or #username == authentication.principal.username")
    public UserDTO getUser(String username) {
        SystemUser user = userRepository.findByUsername(username)
                .orElseThrow(() -> new AccountException(ErrorCode.USER_NOT_FOUND));
        
        return convertToDTO(user);
    }
    
    @Transactional(readOnly = true)
    @PreAuthorize("hasRole('ADMIN')")
    public List<UserDTO> getAllUsers() {
        return userRepository.findAll()
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Transactional(readOnly = true)
    @PreAuthorize("hasRole('ADMIN')")
    public List<UserDTO> getUsersByRole(String roleCode) {
        return userRepository.findByRoleCode(roleCode)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    private UserDTO convertToDTO(SystemUser user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId());
        dto.setUsername(user.getUsername());
        dto.setFullName(user.getFullName());
        dto.setEmail(user.getEmail());
        dto.setPhone(user.getPhone());
        dto.setDepartment(user.getDepartment());
        dto.setStatus(user.getStatus());
        dto.setRoles(user.getRoles().stream()
                .map(SystemRole::getRoleCode)
                .collect(Collectors.toSet()));
        dto.setLastLoginTime(user.getLastLoginTime());
        dto.setCreatedAt(user.getCreatedAt());
        return dto;
    }
}
/**
	角色与权限服务
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class RoleService {
    private final RoleRepository roleRepository;
    private final PermissionRepository permissionRepository;
    private final AuditLogService auditLogService;
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public RoleDTO createRole(String roleCode, String roleName, String description) {
        if (roleRepository.existsByRoleCode(roleCode)) {
            throw new AccountException(ErrorCode.ROLE_ALREADY_EXISTS);
        }
        
        SystemRole role = new SystemRole();
        role.setRoleCode(roleCode);
        role.setRoleName(roleName);
        role.setDescription(description);
        
        SystemRole saved = roleRepository.save(role);
        log.info("Role created: {}", roleCode);
        
        auditLogService.logRoleAction(saved.getId(), "CREATE", "Role created");
        
        return convertToDTO(saved);
    }
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public RoleDTO updateRole(String roleCode, String roleName, String description) {
        SystemRole role = roleRepository.findByRoleCode(roleCode)
                .orElseThrow(() -> new AccountException(ErrorCode.ROLE_NOT_FOUND));
        
        role.setRoleName(roleName);
        role.setDescription(description);
        
        SystemRole saved = roleRepository.save(role);
        log.info("Role updated: {}", roleCode);
        
        auditLogService.logRoleAction(saved.getId(), "UPDATE", "Role updated");
        
        return convertToDTO(saved);
    }
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public RoleDTO assignPermissions(String roleCode, Set<String> permissionCodes) {
        SystemRole role = roleRepository.findByRoleCode(roleCode)
                .orElseThrow(() -> new AccountException(ErrorCode.ROLE_NOT_FOUND));
        
        Set<SystemPermission> permissions = permissionCodes.stream()
                .map(code -> permissionRepository.findByPermissionCode(code)
                        .orElseThrow(() -> new AccountException(ErrorCode.PERMISSION_NOT_FOUND)))
                .collect(Collectors.toSet());
        
        role.setPermissions(permissions);
        
        SystemRole saved = roleRepository.save(role);
        log.info("Permissions assigned to role {}: {}", roleCode, permissionCodes);
        
        auditLogService.logRoleAction(saved.getId(), "UPDATE", "Permissions assigned: " + permissionCodes);
        
        return convertToDTO(saved);
    }
    
    @Transactional(readOnly = true)
    public List<RoleDTO> getAllRoles() {
        return roleRepository.findAll()
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Transactional(readOnly = true)
    public RoleDTO getRole(String roleCode) {
        SystemRole role = roleRepository.findByRoleCode(roleCode)
                .orElseThrow(() -> new AccountException(ErrorCode.ROLE_NOT_FOUND));
        
        return convertToDTO(role);
    }
    
    private RoleDTO convertToDTO(SystemRole role) {
        RoleDTO dto = new RoleDTO();
        dto.setId(role.getId());
        dto.setRoleCode(role.getRoleCode());
        dto.setRoleName(role.getRoleName());
        dto.setDescription(role.getDescription());
        dto.setPermissions(role.getPermissions().stream()
                .map(SystemPermission::getPermissionCode)
                .collect(Collectors.toSet()));
        dto.setCreatedAt(role.getCreatedAt());
        return dto;
    }
}
/**
	系统参数服务
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class ParameterService {
    private final ParameterRepository parameterRepository;
    private final AuditLogService auditLogService;
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public ParameterDTO createParameter(String key, String name, String value, String description, Boolean isEditable) {
        if (parameterRepository.existsByParamKey(key)) {
            throw new AccountException(ErrorCode.PARAMETER_ALREADY_EXISTS);
        }
        
        SystemParameter parameter = new SystemParameter();
        parameter.setParamKey(key);
        parameter.setParamName(name);
        parameter.setParamValue(value);
        parameter.setDescription(description);
        parameter.setIsEditable(isEditable);
        
        SystemParameter saved = parameterRepository.save(parameter);
        log.info("System parameter created: {}", key);
        
        auditLogService.logParameterAction(saved.getId(), "CREATE", "Parameter created");
        
        return convertToDTO(saved);
    }
    
    @Transactional
    @PreAuthorize("hasRole('ADMIN')")
    public ParameterDTO updateParameter(String key, String value, String description) {
        SystemParameter parameter = parameterRepository.findByParamKey(key)
                .orElseThrow(() -> new AccountException(ErrorCode.PARAMETER_NOT_FOUND));
        
        if (!parameter.getIsEditable()) {
            throw new AccountException(ErrorCode.PARAMETER_NOT_EDITABLE);
        }
        
        parameter.setParamValue(value);
        parameter.setDescription(description);
        
        SystemParameter saved = parameterRepository.save(parameter);
        log.info("System parameter updated: {}", key);
        
        auditLogService.logParameterAction(saved.getId(), "UPDATE", "Parameter updated");
        
        return convertToDTO(saved);
    }
    
    @Transactional(readOnly = true)
    public ParameterDTO getParameter(String key) {
        SystemParameter parameter = parameterRepository.findByParamKey(key)
                .orElseThrow(() -> new AccountException(ErrorCode.PARAMETER_NOT_FOUND));
        
        return convertToDTO(parameter);
    }
    
    @Transactional(readOnly = true)
    public List<ParameterDTO> getAllParameters() {
        return parameterRepository.findAll()
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    private ParameterDTO convertToDTO(SystemParameter parameter) {
        ParameterDTO dto = new ParameterDTO();
        dto.setId(parameter.getId());
        dto.setParamKey(parameter.getParamKey());
        dto.setParamName(parameter.getParamName());
        dto.setParamValue(parameter.getParamValue());
        dto.setDescription(parameter.getDescription());
        dto.setIsEditable(parameter.getIsEditable());
        dto.setCreatedAt(parameter.getCreatedAt());
        return dto;
    }
}
/**
	审计日志服务
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class AuditLogService {
    private final AuditLogRepository auditLogRepository;
    
    @Transactional
    public void logUserAction(Long userId, String action, String description) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        
        AuditLog logEntry = new AuditLog();
        logEntry.setUserId(userId);
        logEntry.setUsername(username);
        logEntry.setAction(AuditAction.valueOf(action));
        logEntry.setEntityType("USER");
        logEntry.setEntityId(userId);
        logEntry.setIpAddress(request.getRemoteAddr());
        logEntry.setUserAgent(request.getHeader("User-Agent"));
        
        auditLogRepository.save(logEntry);
    }
    
    @Transactional
    public void logRoleAction(Long roleId, String action, String description) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        
        AuditLog logEntry = new AuditLog();
        logEntry.setUserId(getCurrentUserId());
        logEntry.setUsername(username);
        logEntry.setAction(AuditAction.valueOf(action));
        logEntry.setEntityType("ROLE");
        logEntry.setEntityId(roleId);
        logEntry.setIpAddress(request.getRemoteAddr());
        logEntry.setUserAgent(request.getHeader("User-Agent"));
        
        auditLogRepository.save(logEntry);
    }
    
    @Transactional
    public void logParameterAction(Long parameterId, String action, String description) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        
        AuditLog logEntry = new AuditLog();
        logEntry.setUserId(getCurrentUserId());
        logEntry.setUsername(username);
        logEntry.setAction(AuditAction.valueOf(action));
        logEntry.setEntityType("PARAMETER");
        logEntry.setEntityId(parameterId);
        logEntry.setIpAddress(request.getRemoteAddr());
        logEntry.setUserAgent(request.getHeader("User-Agent"));
        
        auditLogRepository.save(logEntry);
    }
    
    @Transactional(readOnly = true)
    public List<AuditLogDTO> getLogsByUser(Long userId) {
        return auditLogRepository.findByUserId(userId)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Transactional(readOnly = true)
    public List<AuditLogDTO> getLogsByEntity(String entityType, Long entityId) {
        return auditLogRepository.findByEntityTypeAndEntityId(entityType, entityId)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Transactional(readOnly = true)
    public List<AuditLogDTO> getLogsBetweenDates(LocalDateTime start, LocalDateTime end) {
        return auditLogRepository.findByCreatedAtBetween(start, end)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 实际项目中需要从认证信息中获取用户ID
        return 1L; // 简化处理
    }
    
    private AuditLogDTO convertToDTO(AuditLog log) {
        AuditLogDTO dto = new AuditLogDTO();
        dto.setId(log.getId());
        dto.setUserId(log.getUserId());
        dto.setUsername(log.getUsername());
        dto.setAction(log.getAction());
        dto.setEntityType(log.getEntityType());
        dto.setEntityId(log.getEntityId());
        dto.setOldValue(log.getOldValue());
        dto.setNewValue(log.getNewValue());
        dto.setIpAddress(log.getIpAddress());
        dto.setUserAgent(log.getUserAgent());
        dto.setCreatedAt(log.getCreatedAt());
        return dto;
    }
}

Controller层

@RestController
@RequestMapping("/api/admin/users")
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    public UserDTO createUser(@Valid @RequestBody UserCreateRequest request) {
        return userService.createUser(request);
    }
    
    @PutMapping("/{username}")
    public UserDTO updateUser(
            @PathVariable String username,
            @Valid @RequestBody UserUpdateRequest request) {
        return userService.updateUser(username, request);
    }
    
    @PutMapping("/{username}/status/{status}")
    @PreAuthorize("hasRole('ADMIN')")
    public UserDTO updateUserStatus(
            @PathVariable String username,
            @PathVariable String status) {
        return userService.updateUserStatus(username, UserStatus.valueOf(status));
    }
    
    @PutMapping("/{username}/password")
    public void changePassword(
            @PathVariable String username,
            @RequestParam String newPassword) {
        userService.changePassword(username, newPassword);
    }
    
    @PutMapping("/{username}/roles")
    @PreAuthorize("hasRole('ADMIN')")
    public UserDTO assignRoles(
            @PathVariable String username,
            @RequestBody Set<String> roleCodes) {
        return userService.assignRoles(username, roleCodes);
    }
    
    @GetMapping("/{username}")
    public UserDTO getUser(@PathVariable String username) {
        return userService.getUser(username);
    }
    
    @GetMapping
    @PreAuthorize("hasRole('ADMIN')")
    public List<UserDTO> getAllUsers() {
        return userService.getAllUsers();
    }
    
    @GetMapping("/by-role/{roleCode}")
    @PreAuthorize("hasRole('ADMIN')")
    public List<UserDTO> getUsersByRole(@PathVariable String roleCode) {
        return userService.getUsersByRole(roleCode);
    }
}
@RestController
@RequestMapping("/api/admin/roles")
@RequiredArgsConstructor
public class RoleController {
    private final RoleService roleService;
    
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    public RoleDTO createRole(
            @RequestParam String roleCode,
            @RequestParam String roleName,
            @RequestParam(required = false) String description) {
        return roleService.createRole(roleCode, roleName, description);
    }
    
    @PutMapping("/{roleCode}")
    @PreAuthorize("hasRole('ADMIN')")
    public RoleDTO updateRole(
            @PathVariable String roleCode,
            @RequestParam String roleName,
            @RequestParam(required = false) String description) {
        return roleService.updateRole(roleCode, roleName, description);
    }
    
    @PutMapping("/{roleCode}/permissions")
    @PreAuthorize("hasRole('ADMIN')")
    public RoleDTO assignPermissions(
            @PathVariable String roleCode,
            @RequestBody Set<String> permissionCodes) {
        return roleService.assignPermissions(roleCode, permissionCodes);
    }
    
    @GetMapping("/{roleCode}")
    public RoleDTO getRole(@PathVariable String roleCode) {
        return roleService.getRole(roleCode);
    }
    
    @GetMapping
    public List<RoleDTO> getAllRoles() {
        return roleService.getAllRoles();
    }
}

@RestController
@RequestMapping("/api/admin/parameters")
@RequiredArgsConstructor
public class ParameterController {
    private final ParameterService parameterService;
    
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    public ParameterDTO createParameter(
            @RequestParam String key,
            @RequestParam String name,
            @RequestParam String value,
            @RequestParam(required = false) String description,
            @RequestParam(defaultValue = "true") Boolean isEditable) {
        return parameterService.createParameter(key, name, value, description, isEditable);
    }
    
    @PutMapping("/{key}")
    @PreAuthorize("hasRole('ADMIN')")
    public ParameterDTO updateParameter(
            @PathVariable String key,
            @RequestParam String value,
            @RequestParam(required = false) String description) {
        return parameterService.updateParameter(key, value, description);
    }
    
    @GetMapping("/{key}")
    public ParameterDTO getParameter(@PathVariable String key) {
        return parameterService.getParameter(key);
    }
    
    @GetMapping
    public List<ParameterDTO> getAllParameters() {
        return parameterService.getAllParameters();
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到