Skip to content
markdown
---
trigger: model_decision
description: 代码审查(code review)时使用规则
---
{
"rules": [
{
"pattern": "**/*.cs",
"rule": "## C# 代码审查规则\n\n### 公用方法影响评估(必须执行)\n- 对每个新增/修改的public方法,使用code_search搜索所有调用方,列出所有调用位置\n- 评估方法签名变更(参数增减、返回类型变更)是否导致调用方编译错误\n- 评估方法行为变更(逻辑修改、异常策略变更)是否影响调用方的预期\n- 如果方法被外部系统(LMIS、AC、IIS接口等)通过反射或RPC调用,需特别标注兼容性风险\n\n### 代码变更副作用评估(必须执行)\n- 当修改的代码涉及共享组件时,必须评估对其他使用方的副作用:\n  - 共享基类/控件变更:如果修改了基类Form、用户控件、公共UI组件(如ToolStrip、工具栏按钮),必须搜索所有继承/引用方,评估变更是否影响其他窗体的显示/行为\n  - 共享状态变量变更:如果新增了类级标志变量(如_isLoadingData、_isBatchMode等),必须检查同一类中所有事件处理方法,评估该变量是否会干扰已有逻辑(如CellValueChanged、Validating等事件)\n  - 注意:如果标志变量在异常路径中未被重置(如catch/finally未处理),可能导致后续所有校验被错误跳过;优先使用业务固有状态(如`billid.Contains(\"草\")``PK <= 0`)判断,而非类级布尔标志变量;如果必须使用标志变量,必须在finally块中确保重置\n  - 共享工具方法变更:如果修改了公共工具方法(如SafeCol、Conv.NS、CenterQuery等)的行为或签名,必须追踪所有调用方\n- 对修改的窗体/控件,必须检查同一窗体在不同业务场景下的使用(如新建、编辑、草稿、复制、冲红等场景),评估变更是否破坏了其他场景的行为\n- 特别关注:条件判断逻辑的变更(如从`if (PK > 0)`改为其他条件),可能导致原来不会执行的代码路径在新条件下被执行\n\n### 共享库模块新增注册类名称冲突检查(阻断级,必须执行)\n- 在共享库模块(如Common、共享Service等被多个应用依赖的模块)中新增会被DI容器注册的类时,必须使用code_search在整个项目范围内检索是否存在同名类\n- 共享库中的类会被所有依赖此库的应用同时加载,如果已有同名类,可能导致DI容器注册冲突\n- 如果存在同名类,必须采用以下任一方案规避:\n  - 显式指定唯一的注册名称\n  - 将类名改为更具业务含义的唯一名称\n- 验证方法:grep搜索`class 新类名`确认项目中无同名类\n\n### 新增功能对已有方法的影响评估(必须执行)\n- 当新增功能(如草稿保存、批量提取、审批流程等)改变了窗体的状态机或业务流程时,必须检查同一窗体中所有**未被修改的已有操作方法**是否需要适配新功能引入的新状态:\n  - 读取同一类文件的完整内容,搜索所有与变更方法同级的其他操作方法(如切换方案、复制、冲红、重新发起等)\n  - 对每个操作方法,评估其在新功能场景下是否缺少必要的状态重置、UI更新或条件判断\n  - 特别检查:单据编号(billid)、单据状态(BillID/WorkFlowState)、界面按钮可见性等是否需要在新功能触发的场景下重置\n- 对修改了工具栏/按钮可见性逻辑的变更,必须检查同一工具栏中所有其他按钮在所有场景(新建、编辑、草稿、复制等)下的可见性是否正确\n- 对新增了实体类方法(如IsSupportBillSaveToDraft、BillSaveToDraft等)的变更,必须检查基类中所有调用这些方法的代码路径,确认是否有遗漏的状态处理\n\n### 实体字段赋值完整性检查(必须执行)\n- 当Entity/VO/DTO新增字段时,必须使用code_search搜索该实体类的所有实例化位置\n- 检查所有new对象后是否有对应的字段赋值(包括对象初始化器和逐行赋值)\n- 检查所有Map/Dictionary映射代码(如手动映射、AutoMapper配置)是否包含新字段\n- 检查所有SQL查询(包括存储过程结果映射、DataTable转实体)是否SELECT了新字段\n- 检查所有序列化/反序列化场景(JSON、XML)是否需要处理新字段\n- 特别关注:同一实体在不同模块(Controller、Service、Interface)中的赋值是否都已覆盖\n- 当已有对象之间通过手动逐字段赋值进行属性复制(非BeanUtils/AutoMapper/对象初始化器)时,必须逐一核对所有业务字段是否都已复制,新增字段(如RegionDesc)容易在复制代码中遗漏\n- 当SQL查询新增/修改SELECT字段时,需反向检查对应的VO/DTO类是否已同步新增字段(包括类型、注解),内层子查询的SELECT列也需同步\n\n### 实体字段与源头一致性校验(必须执行)\n- 当Entity/VO/DTO新增或修改字段时,必须验证字段与源头的一致性:\n  - 字段名(包括大小写):与数据库表列名、上游API字段名、源实体属性名是否一致\n  - 字段类型:与数据库列类型(如NUMBER→decimal、VARCHAR2→string、DATE→DateTime)是否匹配\n  - 字段精度:数值类型的小数位数(如NUMBER(18,4)→decimal精度)是否与源头一致,防止精度丢失\n- 对从数据库表映射的字段,检查EF Column注解或Dapper返回列名与表定义是否一致\n- 对从上游API/DTO映射的字段,检查属性名大小写是否与源头JSON字段名匹配(C#默认不区分大小写但应显式确认)\n- 特别关注:金额字段(amount/price)的精度是否与数据库NUMBER类型的scale一致\n\n### 主单与明细实体字段命名一致性校验(必须执行)\n- 当新增主单实体(如BillSum/Bill)和明细实体(如BillDet/Detail)时,必须检查两者中相同含义的字段命名是否一致:\n  - 相同业务含义的字段必须使用相同的字段名(如主单用branchid,明细也必须用branchid,不能一个用branchid另一个用branch_id)\n  - 特别检查常见关联字段:branchid、proid、lotno、ioid、ouid、usageid、customerid、supplierid等\n  - 检查字段名的拼写、大小写、缩写方式是否在主单和明细间保持统一\n- 对已有主单/明细实体对,新增字段时必须参照已有命名惯例\n- 如果发现命名不一致,必须标注为风险并建议统一\n\n### Map/字典赋值字段名评估(必须执行)\n- 对使用Dictionary、JObject、ExpandoObject等动态键值赋值的代码,检查字段名拼写是否正确\n- 检查Map的Key是否与目标实体的属性名一致(注意大小写、命名风格差异)\n- 检查JSON序列化时的字段名映射(JsonProperty/DataMember注解)是否与Map的Key匹配\n- 对字符串硬编码的字段名(如dict[\"express_name\"]),评估是否存在拼写错误或遗漏更新的风险\n\n### EF Include/导航属性变更审查(阻断级,必须执行)\n- 当删除或注释Include()调用时,这是阻断级变更,必须标记为严重风险\n- 必须使用code_search搜索被Include的导航属性(如SaleStockOutDets、ChongHongDetails等)在整个项目中的所有引用位置\n- 特别检查:单据再现、打印预览、报表导出、API序列化等场景是否依赖这些导航属性\n- 特别检查:是否有其他功能模块(如Controller、其他Service)通过同一Repository方法获取数据后访问这些属性\n- 如果无法确认所有引用方都不依赖该导航属性,必须建议保留Include或提供替代加载方案\n- 注意:Include删除不是性能优化问题,而是可能导致功能完全不可用的阻断性变更\n\n### HTTP API端点变更全链路追踪(必须执行)\n- 当Service层方法的行为发生变更时,必须追踪到对应的Controller HTTP端点(通过HttpGet/HttpPost/Route等注解定位)\n- 找到HTTP端点后,必须跨项目搜索所有调用该API的消费方:\n  - ERP客户端(WinForm):搜索WebApiClient.GetWebApi或HttpWebRequest调用\n  - Java微服务(jzterp-server/jztac-server):搜索OkHttpUtils/RestTemplate/Feign调用\n  - 外部系统接口(LMIS/AC/IIS):搜索接口文档或调用代码\n- 对每个消费方,评估变更是否影响其数据处理逻辑(如明细为空、字段缺失、类型不匹配等)\n- 特别注意:同一实体可能有多个查询入口(EF版 vs SQL版),需确认消费方调用的是哪个版本\n- 列出完整的影响链路图:Service方法 → Controller端点 → 各消费方场景 → 具体影响\n\n### 反向业务场景路径覆盖(必须执行)\n- 当变更涉及单据处理流程时,必须评估以下反向场景是否被覆盖:\n  - 冲红/红字冲销:冲红入库 vs 正常入库走不同代码路径\n  - 退货/退回:退回通知单 vs 正常销售出库\n  - 反审核/撤回:已审核单据的反向操作\n- 对每个反向场景,追踪变更的代码路径是否能被正确触发(特别关注Kafka消息、事件通知、定时任务等异步机制)\n- 检查Kafka/消息发布位置在所有触发场景(正常、冲红、批量)下是否都能被执行到\n- 检查发布位置之前是否有条件分支可能导致跳过\n- 评估发布位置是否在正确的事务边界内(事务提交前 vs 提交后)\n- 冲红/反向操作时对原单的状态回写(如isChonghong=true、删除关联单据)必须位于主单SaveChanges成功之后,避免校验失败时污染原单\n- 冲红/反向操作时,所有金额类字段必须逐一评估是否需要取反(negate/取相反数),不能仅处理部分金额字段(含税金额、未税金额、税额、确认金额等都需检查)\n\n### 新增SQL查询业务语义校验(必须执行)\n- 对新增的SQL查询(特别是涉及金额计算的聚合查询),必须验证业务正确性:\n  - GROUP BY的键是否与业务维度匹配(如按结算单 vs 按订单明细)\n  - JOIN关系的完整性(是否需要跨多层表关联,如det→billdet→billsum)\n  - 聚合函数(SUM/COUNT/AVG)的字段是否是正确的业务口径\n  - SQL中的金额字段名是否与业务含义一致(amount vs totalamount vs taxincludedamount)\n- 对Dapper/ADO.NET查询,检查返回列名与代码访问字段名是否完全匹配(区分大小写和拼写)\n- GROUP BY列只能是分组维度列,不能包含聚合函数结果(如不能`GROUP BY ..., ABS(t.AMOUNT)`)\n- INNER JOIN vs LEFT JOIN的选择必须与业务语义一致(必须的关联用INNER JOIN,可选的用LEFT JOIN)\n- 复杂聚合场景(多表JOIN+聚合)考虑使用子查询先聚合再外层JOIN,避免GROUP BY粒度过细\n\n### 新增Controller认证策略检查(必须执行)\n- 对新增的Controller/Action,必须明确认证策略:\n  - 系统间调用接口(ERP客户端、Java微服务、外部系统调用)需要[AllowAnonymous]或其他认证机制\n  - 用户操作接口需要[Authorize] + 权限校验\n- 检查Controller类级别的认证注解是否被Action级别覆盖\n- 评估接口是否需要IP白名单或其他访问控制\n\n### HTTP API幂等性评估(必须执行)\n- 对写操作的HTTP API(POST/PUT),评估用户重复提交时的行为:\n  - 是否会报错 vs 幂等更新 vs 重复插入\n  - 前端重试机制下的安全性\n  - 是否需要\"先删后增\"或UPSERT模式\n- 特别关注:保存类接口(Save/Update)在用户修改后重新保存的场景\n\n### SQL参数绑定一致性检查(必须执行)\n- 检查Mapper XML/SQL中引用的参数名是否与代码端设置的字段名完全一致(如`<foreach collection=\"branchIds\">` vs Service层`vo.setBranchId()`)\n- 如果SQL中有日期函数(如`trunc(sysdate)``sysdate-1`),检查是否与代码端传入的日期参数含义一致(今天 vs 昨天)\n- 检查参数类型是否匹配(DateTime vs String vs Long)\n- 反模式:SQL用`trunc(sysdate)-1`而代码传`today()`;Service设`setBranchId()`但Mapper用`collection=\"branchIds\"`\n\n### DELETEFLAG过滤陷阱检查(必须执行)\n- 对单据进行版本校验、状态校验、存在性校验时,检查WHERE条件中`DELETEFLAG = 0`是否合理:\n  - 如果目的是\"防止对已删除单据执行操作\",应保留`DELETEFLAG = 0`并对查不到的情况返回错误\n  - 如果目的是\"检测单据是否已被操作过\"(如冲红检测、版本校验),则不应带`DELETEFLAG = 0`,否则已删除的记录会绕过检查\n- 反模式:`WHERE PK=@pk AND DELETEFLAG=0` → 删除后查不到 → 跳过校验\n\n### 布尔条件语义检查(必须执行)\n- 开关判断:`if (rule.xxxSwitch)` vs `if (!rule.xxxSwitch)`,确认\"开启时执行\"还是\"关闭时跳过\"的语义方向正确\n- 序列化方法一致性:同一项目中多处序列化时,检查是否使用了相同的方法(如`JSONObject.toJSONString` vs `YvanUtil.toJson`),不同方法可能丢失不同字段;变更序列化方法时必须评估字段完整性差异\n\n### 验证逻辑early return检查(阻断级,必须执行)\n- 输入验证/前置条件校验后,必须在报错后立即`return`阻断后续执行\n- 反模式:`MsgBox.ShowErr(\"不能为空\"); // 缺少return` → 后续代码继续执行,使用无效数据\n- 特别检查:日期为空校验、金额为负校验、必填字段校验等场景\n\n### 批量操作附件/资源绑定检查(必须执行)\n- 批量创建多条记录且涉及附件/资源绑定时,每条记录必须有独立的附件ID\n- 非首条记录的附件需要通过克隆/复制接口绑定到新ID(如`i == 0 ? AttachmentId : Guid.NewGuid()`)\n- 附件复制后必须在提交前检查上传结果,失败时early return\n\n### 分页/全量切换参数一致性检查(必须执行)\n- 查询页面同时支持“分页”和“加载全部”模式时,分页关闭时(isPageAct=false) pageSize必须设为足够大值(如long.MaxValue)\n- 反模式:`{ \"pageSize\", pageSize.SelectedIndex }` → 应为 `{ \"pageSize\", isPageAct ? pageSize.SelectedIndex : long.MaxValue }`\n- 同一查询的多个变体页面(按档案/按明细/按政策等)必须全部检查\n\n### 特殊业务编码/分公司特殊路径检查(必须执行)\n- 通用业务方法中如果已有针对特定分公司/业务编码的特殊逻辑(如`if (\"ZDA\".equals(branchId))`),新增场景时必须明确是走通用路径还是特殊路径\n- 条件分支必须完整覆盖所有已知的特殊场景,不能默认走通用逻辑\n- 特别关注:同一方法被多个分公司/业务编码调用时,各路径的数据过滤、金额计算、推送方式是否都正确\n\n### 主单金额字段必须从明细汇总检查(必须执行)\n- 主单(Sum/Head)的金额字段赋值必须评估是否应从明细.Sum()汇总,而非直接赋值或硬编码为0\n- 反模式:`redemption.Amount = 0;` → 应为 `redemption.Amount = detailList.Sum(i => i.UnPaidAmount)`\n- 特别关注:创建单据时主单金额字段是否从明细行汇总计算\n\n### 硬编码业务常量vs可配置参数检查(必须执行)\n- 定时任务、业务规则中使用的天数、阈值等业务参数,如果不同分公司/业务线可能需要不同值,必须从配置表/规则服务读取,不能硬编码为常量\n- 反模式:`LocalDate.now().minusDays(Constants.EXPIRED_DAYS)` → 应为可配置的carryoverDays\n\n### UI控件初始化硬编码检查(必须执行)\n- 窗体Designer.cs/初始化代码中,年份/月份/日期等时间相关默认值不能硬编码为固定值\n- 反模式:`new DateTime(2026, 1, 1)``comboBox.EditValue = 2` → 应为 `DateTime.Now.AddMonths(-1).Year` 等动态值\n\n### 正确性\n- 空引用检查:对可能为null的对象(数据库查询结果、外部接口返回值、字典/集合取值)必须先做null判断\n- equals()空指针防护:字符串比较时必须将常量放在左边,如`\"常量\".Equals(obj.Field)`,避免`obj.Field.Equals(\"常量\")`导致NPE\n- 异常处理:catch块不能为空或仅Console.WriteLine,必须记录完整异常(含StackTrace)\n- 资源释放:IDisposable对象(DbConnection、HttpClient、Stream)必须使用using或显式Dispose\n- 第三方接口调用超时:调用第三方接口(HttpClient、WebRequest等)必须设置超时时间,禁止使用默认无限超时\n- 类型转换:强制类型转换必须用as+null检查,或使用TryParse;字符串转数字(如`int.Parse``Convert.ToInt32`)必须确保输入格式符合预期,对可能的非数字输入(如中文\"是\"/\"否\")需先转换再解析\n- 集合操作:遍历中不能修改集合,LINQ查询注意延迟执行陷阱\n\n### 影响分析(必须执行)\n- 对新增/修改的实体字段(Entity/VO/DTO),追踪该字段在序列化、数据库映射、接口传递中的完整链路\n- 对修改的接口参数或返回值,评估下游消费方(尤其是LMIS、AC等外部系统)是否需要适配\n- 对修改的SQL查询或存储过程调用,评估对索引命中和执行计划的影响\n\n### 安全性\n- SQL拼接:禁止字符串拼接SQL参数,必须使用参数化查询(SqlParameter/OracleParameter)\n- 敏感信息:密码、密钥、连接字符串不能硬编码或出现在日志中\n- 权限校验:涉及数据修改的接口必须校验操作权限和数据归属(BranchId)\n\n### 性能\n- 循环内禁止数据库查询(N+1问题),应改为批量查询\n- 大数据量查询必须分页,禁止全量加载到内存\n- 字符串拼接超过3处必须使用StringBuilder\n- 注意Entity Framework的延迟加载陷阱,避免产生隐式N+1查询\n\n### 命名规范\n- C#代码必须使用PascalCase(类名、方法名、属性名)\n- 私有字段使用_前缀camelCase(如_branchId)\n- 局部变量使用camelCase\n- 接口字段与JSON字段映射时,通过JsonProperty等注解处理命名差异,不能直接在C#中使用下划线命名\n\n### 业务逻辑\n- 金额计算必须使用decimal,禁止float/double\n- 单据状态变更必须有状态机校验,防止非法跳转\n- BranchId相关过滤不能遗漏(多公司数据隔离)\n- 涉及OGG同步的表变更,需评估对同步链路的影响\n\n### 对外接口规范(必须执行)\n- 对外接口必须记录日志(请求参数、响应结果、耗时)\n- 对外接口异常返回规范:校验拦截信息不能以异常形式抛出,内部异常也应通过HTTP 200返回(业务错误码),不要以500方式返回\n- 固定值判断必须使用枚举:不能用写死的字符串/数字进行业务判断,必须定义枚举常量"
},
{
"pattern": "**/*.java",
"rule": "## Java 代码审查规则\n\n### 公用方法影响评估(必须执行)\n- 对每个新增/修改的public方法,使用code_search搜索所有调用方,列出所有调用位置\n- 评估方法签名变更(参数增减、返回类型变更)是否导致调用方编译错误\n- 评估方法行为变更(逻辑修改、异常策略变更)是否影响调用方的预期\n- 如果方法被其他微服务通过Feign/REST调用,需特别标注接口兼容性风险\n\n### 代码变更副作用评估(必须执行)\n- 当修改的代码涉及共享组件时,必须评估对其他使用方的副作用:\n  - 共享基类/接口变更:如果修改了基类Controller、公共Service、抽象类,必须搜索所有继承/实现方,评估变更是否影响其他模块的行为\n  - 共享状态变量变更:如果新增了类级标志变量或ThreadLocal变量,必须检查同一类中所有方法,评估该变量是否会干扰已有逻辑\n  - 注意:如果标志变量在异常路径中未被重置(如catch/finally未处理),可能导致后续所有校验被错误跳过;优先使用业务固有状态(如`billid.contains(\"草\")``pk <= 0`)判断,而非类级布尔标志变量;如果必须使用标志变量,必须在finally块中确保重置\n  - 共享工具类变更:如果修改了公共工具方法的行为或签名,必须追踪所有调用方\n  - 共享配置变更:如果修改了公共配置项(如Redis Key、Kafka Topic、Feign超时),必须评估对其他消费方的影响\n- 对修改的Service/Controller,必须检查其在不同业务场景下的调用链路,评估变更是否破坏了其他场景的行为\n- 特别关注:条件判断逻辑的变更(如从`if (id != null)`改为其他条件),可能导致原来不会执行的代码路径在新条件下被执行\n\n### 共享库模块新增Bean类名称冲突检查(阻断级,必须执行)\n- 在共享库模块(如*-biz、*-common、*-contracts等被多个host应用依赖的模块)中新增@Configuration、@Component、@Service、@Controller类时,必须使用code_search在整个项目范围内检索是否存在同名类(简单类名相同)\n- 共享库中的配置类会被所有依赖此库的host应用(如bpm-host、schedules-host、mc-host等)同时加载,如果host应用中已有同名@Configuration类,Spring组件扫描会因简单类名相同触发ConflictingBeanDefinitionException,导致host应用无法启动\n- 如果存在同名类,必须采用以下任一方案规避:\n  - 使用@Configuration(\"唯一Bean名称\")显式指定唯一Bean名称\n  - 将类名改为更具业务含义的唯一名称(如CacheClearExecutorConfig替代AsyncExecutorConfig)\n- 验证方法:grep搜索`class 新类名`确认项目中无同名类\n\n### 新增功能对已有方法的影响评估(必须执行)\n- 当新增功能(如草稿保存、批量处理、审批流程等)改变了Service/Controller的业务流程时,必须检查同一类中所有**未被修改的已有方法**是否需要适配新功能引入的新状态:\n  - 读取同一类文件的完整内容,搜索所有与变更方法同级的其他方法\n  - 对每个方法,评估其在新功能场景下是否缺少必要的状态重置或条件判断\n  - 特别检查:单据编号、状态字段、缓存Key等是否需要在新功能触发的场景下重置\n- 对新增了实体类方法或接口方法的变更,必须检查基类/接口中所有调用这些方法的代码路径\n\n### 实体字段赋值完整性检查(必须执行)\n- 当Entity/VO/DTO新增字段时,必须使用code_search搜索该实体类的所有使用位置\n- 检查所有BeanUtils.copyProperties、BeanCopy等拷贝方法是否覆盖了新字段(尤其是字段名不一致时)\n- 检查所有手动字段映射代码(如source.getXxx() -> target.setYyy())是否包含新字段\n- 检查MyBatis的ResultMap和SQL查询是否映射了新字段\n- 检查所有序列化/反序列化场景(JSON、MessagePack)是否需要处理新字段\n- 特别关注:同一实体在不同模块(Controller、Service、Feign Client)中的赋值是否都已覆盖\n- 当已有对象之间通过手动逐字段赋值进行属性复制(source.getXxx() → target.setYyy())时,必须逐一核对所有业务字段是否都已复制,新增字段容易在复制代码中遗漏\n- 当SQL查询新增/修改SELECT字段时,需反向检查对应的VO/DTO类是否已同步新增字段(包括类型、注解),内层子查询的SELECT列也需同步\n\n### 实体字段与源头一致性校验(必须执行)\n- 当Entity/VO/DTO新增或修改字段时,必须验证字段与源头的一致性:\n  - 字段名(包括大小写):与数据库表列名、上游API字段名、源实体属性名是否一致\n  - 字段类型:与数据库列类型(如NUMBER→BigDecimal、VARCHAR2→String、DATE→Date/LocalDateTime)是否匹配\n  - 字段精度:数值类型的小数位数(如NUMBER(18,4)→BigDecimal精度)是否与源头一致,防止精度丢失\n- 对从数据库表映射的字段,检查MyBatis ResultMap的column属性与表定义是否一致,或@JSONField/@Column注解是否匹配\n- 对从上游API/Feign映射的字段,检查属性名是否与源头JSON字段名匹配(驼峰/下划线转换是否正确)\n- 特别关注:金额字段(amount/price)的精度是否与数据库NUMBER类型的scale一致\n\n### 主单与明细实体字段命名一致性校验(必须执行)\n- 当新增主单实体(如BillSum/Bill)和明细实体(如BillDet/Detail)时,必须检查两者中相同含义的字段命名是否一致:\n  - 相同业务含义的字段必须使用相同的字段名(如主单用branchid,明细也必须用branchid,不能一个用branchid另一个用branch_id)\n  - 特别检查常见关联字段:branchid、proid、lotno、ioid、ouid、usageid、customerid、supplierid等\n  - 检查字段名的拼写、大小写、缩写方式是否在主单和明细间保持统一\n- 对已有主单/明细实体对,新增字段时必须参照已有命名惯例\n- 如果发现命名不一致,必须标注为风险并建议统一\n\n### Map赋值字段名评估(必须执行)\n- 对使用Map.put()、JSONObject等动态键值赋值的代码,检查Key拼写是否正确\n- 检查Map的Key是否与目标实体的属性名一致(注意驼峰/下划线命名差异)\n- 对字符串硬编码的字段名(如map.put(\"express_name\", value)),评估是否存在拼写错误或遗漏更新的风险\n- 检查@JSONField/@JsonProperty注解的name是否与Map的Key匹配\n\n### HTTP API端点变更全链路追踪(必须执行)\n- 当Service层方法的行为发生变更时,必须追踪到对应的Controller HTTP端点(通过@GetMapping/@PostMapping等注解定位)\n- 找到HTTP端点后,必须跨项目搜索所有调用该API的消费方:\n  - C#客户端(ERP_HPService/ERP_Client):搜索WebApiClient/HttpWebRequest调用\n  - 其他微服务(jzterp-server/jztac-server):搜索OkHttpUtils/RestTemplate/Feign调用\n  - 外部系统接口(LMIS/AC/IIS):搜索接口文档或调用代码\n- 对每个消费方,评估变更是否影响其数据处理逻辑(如字段缺失、类型不匹配等)\n- 特别注意:Java微服务可能调用的是C#端的SQL版接口(如_xxx_sql),需确认调用链路\n- 列出完整的影响链路图:Service方法 → Controller端点 → 各消费方场景 → 具体影响\n\n### JSON序列化/反序列化字段完整性校验(必须执行)\n- 当使用JSON.parseArray/parseObject(JSON.toJSONString(source), TargetClass.class)进行类型转换时,必须检查源类的所有业务字段在目标类中是否有对应属性\n- 如果目标类缺少源类的字段,该字段数据在反序列化时会丢失,必须标注为风险\n- 检查丢失的字段是否后续通过其他方式补回(如手动赋值、DB查询、MDM回查)\n- 如果补回逻辑依赖匹配条件(如按某个字段equals匹配),必须验证匹配在所有业务场景下的有效性\n- 特别检查:同一licenseName/ID可能存在多条记录时,findFirst()的不确定性\n- 变更序列化方法时(如从`JSONObject.toJSONString`改为`YvanUtil.toJson`),必须对比新旧方法的字段覆盖差异,评估对下游消费方的影响\n\n### 业务需求-代码一致性校验(必须执行)\n- 当变更涉及字段新增/赋值逻辑调整时,必须明确该字段的业务需求\n- 追踪该字段在前端的展示/编辑控制逻辑,评估变更是否影响字段的可编辑性判断\n- 区分不同业务场景(如试点/非试点公司、首营/非首营)分别验证代码行为\n- 检查新增逻辑是否对非目标场景产生副作用\n\n### 同类代码路径一致性检查(必须执行)\n- 当同一文件中存在多个相似代码块处理相同实体时,必须逐一对比各代码块的过滤条件、校验逻辑\n- 识别差异项并评估是否为有意设计\n- 如果是\"补充到另一个路径\"的变更,确认两个路径最终行为一致\n- 特别检查:两个路径的stream().filter()条件是否完全一致\n\n### 反向业务场景路径覆盖(必须执行)\n- 当变更涉及单据处理流程时,必须评估以下反向场景是否被覆盖:\n  - 冲红/红字冲销:冲红入库 vs 正常入库走不同代码路径\n  - 退货/退回:退回通知单 vs 正常销售出库\n  - 反审核/撤回:已审核单据的反向操作\n- 对每个反向场景,追踪变更的代码路径是否能被正确触发(特别关注Kafka/RocketMQ消息、事件通知、定时任务等异步机制)\n- 检查消息发布位置在所有触发场景(正常、冲红、批量)下是否都能被执行到\n- 评估发布位置是否在正确的事务边界内(@Transactional提交前 vs 提交后)\n- 冲红/反向操作时对原单的状态回写(如isChonghong=true、删除关联单据)必须位于主单SaveChanges/commit成功之后,避免校验失败时污染原单\n- 冲红/反向操作时,所有金额类字段必须逐一评估是否需要取反(negate/取相反数),不能仅处理部分金额字段(含税金额、未税金额、税额、确认金额等都需检查)\n\n### 新增SQL查询业务语义校验(必须执行)\n- 对新增的MyBatis SQL查询(特别是涉及金额计算的聚合查询),必须验证业务正确性:\n  - GROUP BY的键是否与业务维度匹配\n  - JOIN关系的完整性(是否需要跨多层表关联)\n  - 聚合函数的字段是否是正确的业务口径\n  - SQL中的金额字段名是否与业务含义一致\n- 检查MyBatis ResultMap的column是否与SQL SELECT别名完全匹配\n- GROUP BY列只能是分组维度列,不能包含聚合函数结果(如不能`GROUP BY ..., ABS(t.AMOUNT)`)\n- INNER JOIN vs LEFT JOIN的选择必须与业务语义一致(必须的关联用INNER JOIN,可选的用LEFT JOIN)\n- 复杂聚合场景(多表JOIN+聚合)考虑使用子查询先聚合再外层JOIN,避免GROUP BY粒度过细\n\n### MyBatis Mapper XML 格式合法性检查(阻断级,必须执行)\n- 当变更涉及Mapper XML文件(新增或修改)时,必须读取该XML文件的**完整内容**(不仅是diff变更行),检查SQL语句内是否存在`--`注释\n- `--`(双连字符)在XML元素文本内容中是非法的,会导致SAXParseException: \"The content of elements must consist of well-formed character data or markup\",**服务将无法启动**\n- SQL注释必须使用XML注释格式`<!-- 注释内容 -->`,或用`<![CDATA[...]]>`包裹整个SQL语句块\n- 必须检查`<select>``<update>``<insert>``<delete>`元素内的所有SQL注释\n- 特别注意:MERGE语句、多行复杂SQL中最容易遗漏SQL注释\n\n### 新增Controller认证策略检查(必须执行)\n- 对新增的Controller/Action,必须明确认证策略:\n  - 系统间调用接口(Feign、REST)需要明确的认证配置或白名单\n  - 用户操作接口需要权限校验注解\n- 检查SecurityConfig中的URL白名单是否包含新接口\n\n### HTTP API幂等性评估(必须执行)\n- 对写操作的HTTP API(POST/PUT),评估用户重复提交时的行为:\n  - 是否会报错 vs 幂等更新 vs 重复插入\n  - 前端重试机制下的安全性\n  - 是否需要\"先删后增\"或UPSERT模式\n- 分布式场景下消息消费和定时任务必须保证幂等性\n\n### SQL参数绑定一致性检查(必须执行)\n- 检查Mapper XML中引用的参数名是否与Service层设置的字段名完全一致(如`<foreach collection=\"branchIds\">` vs `vo.setBranchId()`)\n- 如果SQL中有日期函数(如`trunc(sysdate)``sysdate-1`),检查是否与代码端传入的日期参数含义一致(今天 vs 昨天)\n- 检查参数类型是否匹配(Date vs String vs Long)\n- 反模式:SQL用`trunc(sysdate)-1`而Java传`DateUtils.today()`;Service设`setBranchId()`但Mapper用`collection=\"branchIds\"`\n\n### DELETEFLAG过滤陷阱检查(必须执行)\n- 对单据进行版本校验、状态校验、存在性校验时,检查WHERE条件中`DELETEFLAG = 0`是否合理:\n  - 如果目的是\"防止对已删除单据执行操作\",应保留`DELETEFLAG = 0`并对查不到的情况返回错误\n  - 如果目的是\"检测单据是否已被操作过\"(如冲红检测、版本校验),则不应带`DELETEFLAG = 0`,否则已删除的记录会绕过检查\n- 反模式:`WHERE PK=@pk AND DELETEFLAG=0` → 删除后查不到 → 跳过校验\n\n### 布尔条件语义检查(必须执行)\n- 开关判断:`if (rule.xxxSwitch)` vs `if (!rule.xxxSwitch)`,确认\"开启时执行\"还是\"关闭时跳过\"的语义方向正确\n- 类型转换:`Integer.valueOf(字符串)` 必须确保字符串为数字格式,对中文值(如\"是\"/\"否\")需先转换再解析\n- 序列化方法一致性:同一项目中多处序列化时,检查是否使用了相同的方法(如`JSONObject.toJSONString` vs `YvanUtil.toJson`),不同方法可能丢失不同字段\n\n### 验证逻辑early return检查(阻断级,必须执行)\n- 输入验证/前置条件校验后,必须在报错后立即`return``throw`阻断后续执行\n- 反模式:`if (isEmpty(date)) { throw new BusinessException(\"不能为空\"); } // 缺少return` → 后续代码继续执行\n- 特别检查:日期为空校验、金额为负校验、必填字段校验等场景\n\n### 批量操作附件/资源绑定检查(必须执行)\n- 批量创建多条记录且涉及附件/资源绑定时,每条记录必须有独立的附件ID\n- 非首条记录的附件需要通过克隆/复制接口绑定到新ID\n- 附件复制后必须在提交前检查上传结果,失败时early return\n\n### 特殊业务编码/分公司特殊路径检查(必须执行)\n- 通用业务方法中如果已有针对特定分公司/业务编码的特殊逻辑(如`if (\"ZDA\".equals(branchId))`),新增场景时必须明确是走通用路径还是特殊路径\n- 条件分支必须完整覆盖所有已知的特殊场景,不能默认走通用逻辑\n- 特别关注:同一方法被多个分公司/业务编码调用时,各路径的数据过滤、金额计算、推送方式是否都正确\n\n### 主单金额字段必须从明细汇总检查(必须执行)\n- 主单(Sum/Head)的金额字段赋值必须评估是否应从明细.stream().map().reduce()汇总,而非直接赋值或硬编码为0\n- 反模式:`sum.setAmount(BigDecimal.ZERO)` → 应为 `sum.setAmount(detailList.stream().map(Detail::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add))`\n\n### 硬编码业务常量vs可配置参数检查(必须执行)\n- 定时任务、业务规则中使用的天数、阈值等业务参数,如果不同分公司/业务线可能需要不同值,必须从配置表/规则服务读取,不能硬编码为常量\n- 反模式:`LocalDate.now().minusDays(Constants.EXPIRED_DAYS)` → 应为可配置的carryoverDays\n\n### 正确性\n- NPE防护:对Optional、Map.get()、外部接口返回值、数据库查询结果做null检查\n- equals()空指针防护:字符串比较时必须将常量放在左边,如“常量”.equals(obj.getField()),而非常量在右obj.getField().equals(“常量”),防止getField()为null时NPE\n- 异常处理:catch块必须记录日志(含异常堆栈),不能吞掉异常\n- 事务管理:多表写入操作必须有@Transactional注解,注意事务传播行为和回滚规则\n- 事务内禁止调用第三方接口(HTTP/REST/Feign/RPC),防止长事务锁表和超时;查询操作也应尽量放在事务外\n- 第三方接口调用超时:调用第三方接口(RestTemplate、OkHttpClient、Feign等)必须设置超时时间(connectTimeout+readTimeout),禁止使用默认无限超时\n- 并发安全:共享状态修改必须有同步机制,注意Spring Bean默认单例\n- 字符串转数字(如`Integer.valueOf``Long.parseLong`)必须确保输入格式符合预期,对可能的非数字输入(如中文\"是\"/\"否\")需先转换再解析\n\n### 影响分析(必须执行)\n- 对修改的Entity字段,追踪该字段在ORM映射(JPA/MyBatis)、DTO转换、API响应中的完整链路\n- 对修改的Repository/Mapper接口,评估SQL变更对现有查询的影响\n- 对修改的Feign/REST接口,评估调用方(其他微服务)是否需要适配\n\n### 安全性\n- SQL注入:MyBatis中使用#{}占位符,禁止${}拼接(除非是动态表名/列名且做了白名单校验)\n- 参数校验:Controller入参必须有@Valid/@Validated注解\n- 权限控制:涉及数据修改的接口必须校验BranchId和操作权限\n\n### 性能\n- N+1查询:循环内禁止调用Repository/Mapper,使用批量查询替代\n- 大列表处理:超过1000条数据的集合操作必须分批处理\n- 定时任务避免全公司循环:不要查询组织结构表所有branchid再循环处理,应只查询有业务数据的branchid,减少无意义空跑\n- 刷数据分批提交:超过5万条必须分批提交,每批之间要有合理的sleep,并评估对OGG/AMS下游同步的影响\n- 缓存一致性:修改数据后必须清理相关Redis缓存\n- Stream操作:注意parallelStream在IO密集场景的线程安全问题\n\n### Spring Boot 规范\n- 配置项不能硬编码,必须通过@Value或@ConfigurationProperties注入\n- FeignClient超时和重试配置必须合理\n- 日志级别:生产环境禁止DEBUG级别日志\n\n### 对外接口规范(必须执行)\n- 对外接口必须记录日志(请求参数、响应结果、耗时)\n- 对外接口异常返回规范:校验拦截信息不能以异常形式抛出,内部异常也应通过HTTP 200返回(业务错误码),不要以500方式返回\n- 固定值判断必须使用枚举:不能用写死的字符串/数字进行业务判断,必须定义枚举常量\n\n### 业务逻辑\n- 金额计算必须使用BigDecimal,禁止double/float\n- 单据状态变更必须有状态机校验\n- 分布式场景下注意幂等性设计(尤其是消息消费和定时任务)\n- BranchId过滤不能遗漏(多公司数据隔离)"
},
{
"pattern": "**/*.sql",
"rule": "## SQL 审查规则\n\n### 正确性\n- WHERE条件必须完整,UPDATE/DELETE必须有WHERE子句且包含主键或唯一索引\n- JOIN条件必须完整,防止笛卡尔积\n- 子查询和关联查询注意NULL值处理(NOT IN子查询含NULL的陷阱)\n- GROUP BY字段必须包含SELECT中所有非聚合列\n- 使用LISTAGG/STRING_AGG/GROUP_CONCAT等字符串聚合函数时,必须评估聚合结果是否可能超过目标类型最大长度(Oracle VARCHAR2=4000字符,超过会报ORA-01489);Oracle 12c+必须使用`ON OVERFLOW TRUNCATE`防护\n- 特别关注关联数据量可能随业务增长无限扩大的场景(如一个供应商关联的所有客户名)\n\n### SQL LEFT JOIN条件位置检查(阻断级,必须执行)\n- 对LEFT JOIN语句,检查右表的过滤条件是否放在JOIN的ON子句中\n- 如果条件是过滤右表数据(如`b.workflowstate = '10'`),必须放在ON子句\n- 如果放在WHERE子句中,LEFT JOIN会隐式变成INNER JOIN,导致应保留的左表记录被丢弃\n- 反模式:`LEFT JOIN tableB b ON a.fk = b.pk ... WHERE b.workflowstate = '10'` → 应为 `LEFT JOIN tableB b ON a.fk = b.pk AND b.workflowstate = '10'`\n\n### SQL列别名和表别名完整性检查(必须执行)\n- 多表JOIN查询中,SELECT列必须带表别名前缀(如`a.CREATETIME`而非`CREATETIME`),避免同名列歧义\n- 结果列名必须与代码端DTO/VO的属性名匹配(如`b.CALSUMBILLID AS calRebateBillId`)\n- 反模式:`SELECT CREATETIME, CALSUMBILLID FROM ... JOIN ...` → 缺表别名+缺结果别名\n\n### 性能\n- 查询必须命中索引,避免全表扫描(使用EXPLAIN验证)\n- 禁止SELECT *,必须明确列出所需字段\n- 大表JOIN必须确保关联字段有索引\n- LIKE查询避免前导通配符('%xxx'无法走索引)\n- 避免在WHERE条件中对字段使用函数(如TO_CHAR、UPPER),会导致索引失效\n- IN子句元素不超过1000个(Oracle限制)\n- 大数据量操作使用分批提交,需评估是否有OGG/AMS推送影响,超过5万条必须分批提交,每批之间要有合理的sleep\n\n### 索引规范\n- 新建索引前必须检查是否已存在等效索引(前导列覆盖)\n- 索引命名规范:IDX_表名缩写_列名,长度不超过28位(ERP分公司库Oracle 11g最大支持29位,预留安全余量)\n- 外键列必须有索引\n- 复合索引列顺序应遵循等值条件在前、范围条件在后的原则\n\n### 影响分析\n- DDL变更(加字段、改类型)必须评估对应用层ORM映射的影响\n- 表结构变更需评估OGG同步兼容性\n- 索引变更需评估对其他查询执行计划的影响(不能仅优化当前查询)\n\n### 安全\n- 禁止在SQL中硬编码密码、密钥等敏感信息\n- 动态SQL必须做参数绑定,禁止字符串拼接"
},
{
"pattern": "**/*.{xml,yml,yaml,properties,json}",
"rule": "## 配置文件审查规则\n\n### MyBatis Mapper XML 格式合法性检查(阻断级,必须执行)\n- MyBatis Mapper XML 文件中的 SQL 语句内**禁止使用 `--` 作为 SQL 注释**`--`(双连字符)在 XML 元素文本内容中是非法的,会导致 SAXParseException: \"The content of elements must consist of well-formed character data or markup\"\n- SQL 注释必须使用 XML 注释格式 `<!-- 注释内容 -->`,或用 `<![CDATA[...]]>` 包裹整个 SQL 语句块\n- 对新增/修改的 Mapper XML 文件,必须逐行检查 `<select>``<update>``<insert>``<delete>` 元素内是否存在 `--` SQL 注释\n- 特别注意:MERGE 语句、多行复杂 SQL 中最容易遗漏 SQL 注释\n\n### 安全性\n- 不能包含硬编码的密码、密钥、Token(必须使用环境变量或配置中心如Nacos引用)\n- 数据库连接字符串不能包含明文密码\n- 不能暴露内部IP地址到对外配置\n\n### 正确性\n- YAML缩进必须正确(使用空格,禁止Tab)\n- JSON格式必须合法(注意逗号、括号匹配)\n- Spring Boot配置项拼写必须正确(IDE可能不报错但运行时忽略)\n- 多环境配置(dev/test/pre/prod)必须保持一致性,差异项明确标注\n\n### 影响分析\n- 配置变更需评估对运行时行为的影响(如超时时间、连接池大小、线程数)\n- 新增配置项需确认Nacos或配置中心已同步\n- 环境差异化配置需确认目标环境已就绪"
},
{
"pattern": "**/*.{ts,js}",
"rule": "## TypeScript/JavaScript 代码审查规则\n\n### 正确性\n- 异步操作必须有await,禁止忽略Promise rejection\n- 空值处理:使用可选链(?.)和空值合并(??)处理可能为null/undefined的值\n- 类型安全:TypeScript中避免使用any,必须定义明确的类型\n\n### 安全性\n- 用户输入必须做校验和转义,防止XSS\n- API调用必须处理错误响应\n- 敏感信息不能出现在前端代码或日志中\n\n### 性能\n- 避免在循环中进行DOM操作或网络请求\n- 大数据集使用分页或虚拟滚动\n- 注意内存泄漏(事件监听器、定时器未清理)"
},
{
"pattern": "**/*.{py}",
"rule": "## Python 代码审查规则\n\n### 正确性\n- 异常处理:使用try/except捕获具体异常类型,禁止裸except\n- 资源管理:文件、数据库连接使用with语句\n- 类型提示:函数参数和返回值应有type hints\n\n### 安全性\n- SQL查询必须使用参数化查询,禁止字符串格式化拼接\n- 文件路径操作必须校验,防止路径穿越\n- 敏感信息从环境变量读取,禁止硬编码\n\n### 性能\n- 大数据处理使用生成器(yield)替代列表\n- 数据库操作使用批量插入/更新\n- 避免在循环中进行IO操作"
}
]
}

页脚:版权前显示的信息