1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.trafficaudit.rulemanage.controller;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.trafficaudit.common.Result;
import com.trafficaudit.rulemanage.entity.AuditRule;
import com.trafficaudit.rulemanage.mapper.AuditRuleMapper;
import org.springframework.web.bind.annotation.*;
 
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.List;
 
/** 规则管理:按报表类型查看/启停/调整阈值 */
@RestController
@RequestMapping("/api/rules")
public class RuleManageController {
 
    @Resource
    private AuditRuleMapper ruleMapper;
 
    /** 规则列表,可按报表类型过滤 */
    @GetMapping("/list")
    public Result<List<AuditRule>> list(@RequestParam(value = "reportType", required = false) String reportType) {
        LambdaQueryWrapper<AuditRule> qw = new LambdaQueryWrapper<>();
        if (reportType != null && !reportType.trim().isEmpty()) {
            qw.eq(AuditRule::getReportType, reportType.trim());
        }
        qw.orderByAsc(AuditRule::getSortOrder);
        List<AuditRule> list = ruleMapper.selectList(qw);
        for (AuditRule r : list) syncThresholdText(r); // 名称/说明随阈值动态展示(如 ±10% → ±20%)
        return Result.ok(list);
    }
 
    /** 启停规则 */
    @PostMapping("/toggle")
    public Result<String> toggle(@RequestParam("id") Long id,
                                 @RequestParam("enabled") Integer enabled) {
        AuditRule rule = ruleMapper.selectById(id);
        if (rule == null) return Result.error("规则不存在");
        rule.setIsEnabled(enabled == null || enabled == 0 ? 0 : 1);
        rule.setUpdatedAt(LocalDateTime.now());
        ruleMapper.updateById(rule);
        return Result.ok("已更新");
    }
 
    /** 更新阈值/等级/描述 */
    @PostMapping("/update")
    public Result<String> update(@RequestBody AuditRule body) {
        if (body.getId() == null) return Result.error("缺少规则ID");
        AuditRule rule = ruleMapper.selectById(body.getId());
        if (rule == null) return Result.error("规则不存在");
        String oldThreshold = rule.getThreshold();
        if (body.getThreshold() != null) rule.setThreshold(body.getThreshold());
        if (body.getAlertLevel() != null) rule.setAlertLevel(body.getAlertLevel());
        if (body.getDescription() != null) rule.setDescription(body.getDescription());
        // 阈值变化时同步规则名称与说明(名称/说明里的 ±N% 按新阈值改写),并随保存持久化
        if (body.getThreshold() != null && !body.getThreshold().equals(oldThreshold)) {
            syncThresholdText(rule);
        }
        rule.setUpdatedAt(LocalDateTime.now());
        ruleMapper.updateById(rule);
        return Result.ok("已保存");
    }
 
    /** ±N% 字样匹配(名称/说明中随阈值动态变化的片段) */
    private static final Pattern PCT_TOKEN = Pattern.compile("±\\s*\\d+(?:\\.\\d+)?\\s*%");
 
    /** 把文本中的 ±N% 替换为 ±threshold%(含已带 ± 的前缀,避免双 ±) */
    private String decorateThresholdText(String text, String threshold) {
        if (text == null || text.trim().isEmpty() || threshold == null || threshold.trim().isEmpty()) return text;
        String token = "±" + threshold.trim() + "%";
        return PCT_TOKEN.matcher(text).replaceAll(Matcher.quoteReplacement(token));
    }
 
    /** 名称/说明随阈值同步(读列表时也动态校正,DB 中旧文本不阻塞显示) */
    private void syncThresholdText(AuditRule rule) {
        if (rule == null || rule.getThreshold() == null) return;
        rule.setRuleName(decorateThresholdText(rule.getRuleName(), rule.getThreshold()));
        rule.setDescription(decorateThresholdText(rule.getDescription(), rule.getThreshold()));
    }
}