字段说明获取
All checks were successful
API接口参数变更检测 / api-param-check (push) Successful in 16s

This commit is contained in:
2026-06-05 15:04:13 +08:00
parent 77479a40a1
commit f7fc0dd453
4 changed files with 40 additions and 5 deletions

View File

@@ -31,6 +31,7 @@ class ParameterChange:
required: Optional[bool] = None required: Optional[bool] = None
old_required: Optional[bool] = None old_required: Optional[bool] = None
detail: Optional[str] = None detail: Optional[str] = None
description: Optional[str] = None
def to_markdown_line(self, *, plain: bool = False) -> str: def to_markdown_line(self, *, plain: bool = False) -> str:
""" """
@@ -46,7 +47,8 @@ class ParameterChange:
if req_required if req_required
else '<font color="comment">可选</font>' else '<font color="comment">可选</font>'
) )
return f'> `{self.param_type}` **{self.param_name}** · {tag}' desc = f" <font color=\"comment\">{self.description}</font>" if self.description else ""
return f'> `{self.param_type}` **{self.param_name}** · {tag}{desc}'
if self.change_type == ChangeType.REMOVED: if self.change_type == ChangeType.REMOVED:
return ( return (
@@ -59,9 +61,10 @@ class ParameterChange:
if req_required if req_required
else '<font color="comment">可选</font>' else '<font color="comment">可选</font>'
) )
desc = f" <font color=\"comment\">{self.description}</font>" if self.description else ""
return ( return (
f'<font color="info">【新增】</font> ' f'<font color="info">【新增】</font> '
f'`{self.param_type}` **{self.param_name}** · {tag}' f'`{self.param_type}` **{self.param_name}** · {tag}{desc}'
) )
if self.change_type == ChangeType.RENAMED: if self.change_type == ChangeType.RENAMED:
return ( return (
@@ -209,6 +212,7 @@ def compare_parameters(
param_name=param.name, param_name=param.name,
param_type=param.type, param_type=param.type,
required=param.required, required=param.required,
description=param.description,
) )
) )
@@ -365,6 +369,7 @@ def compare_endpoints(
param_name=p.name, param_name=p.name,
param_type=p.type, param_type=p.type,
required=p.required, required=p.required,
description=p.description,
) )
for p in ep.parameters for p in ep.parameters
], ],

View File

@@ -233,6 +233,27 @@ def _param_required(param: FormalParameter) -> bool:
return not _has_ann(param, "Nullable") return not _has_ann(param, "Nullable")
def _param_description(param: FormalParameter) -> Optional[str]:
"""提取参数描述,优先 Swagger 注解,其次 @RequestParam 的 value。"""
# 1. Swagger @ApiParam
ann = _find_ann(param, "ApiParam")
if ann:
desc = _ann_string(ann, "value", "name")
if desc:
return desc
# 2. Swagger @ApiImplicitParam方法级注解较少见暂不实现
# 3. Fallback: @RequestParam 的 value 作为描述提示
ann = _find_ann(param, "RequestParam")
if ann:
val = _ann_string(ann, "value", "name")
if val and val != param.name:
return val
return None
class ControllerAstParser: class ControllerAstParser:
""" """
基于 javalang 的 Controller 解析器。 基于 javalang 的 Controller 解析器。
@@ -325,12 +346,14 @@ class ControllerAstParser:
if _has_ann(param, "RequestBody"): if _has_ann(param, "RequestBody"):
return self._expand_dto(type_name, "body") return self._expand_dto(type_name, "body")
desc = _param_description(param)
return [ return [
ApiParameter( ApiParameter(
name=name, name=name,
type=type_name, type=type_name,
required=_param_required(param), required=_param_required(param),
source=_param_source(param), source=_param_source(param),
description=desc,
) )
] ]
@@ -361,12 +384,19 @@ class ControllerAstParser:
if "static" in (field.modifiers or []): if "static" in (field.modifiers or []):
continue continue
for decl in field.declarators: for decl in field.declarators:
# 尝试提取 @ApiModelProperty 的描述
desc = None
api_model_ann = _find_ann(field, "ApiModelProperty")
if api_model_ann:
desc = _ann_string(api_model_ann, "value")
fields.append( fields.append(
ApiParameter( ApiParameter(
name=decl.name, name=decl.name,
type=_type_to_str(field.type), type=_type_to_str(field.type),
required=not _has_ann(field, "Nullable"), required=not _has_ann(field, "Nullable"),
source=source, source=source,
description=desc,
) )
) )

View File

@@ -327,8 +327,8 @@ def send_parameter_change_notification(
if changed_reports: if changed_reports:
# 构建参数变更通知(只包含参数变更报告) # 构建参数变更通知(只包含参数变更报告)
parts: List[str] = [] parts: List[str] = []
parts.append("# API参数变更通知") parts.append("# API参数变更通知")
parts.append(f"- **修改人:** {push_user if push_user.startswith('@') else '@' + push_user}") parts.append(f"- **修改人:** {push_user}")
parts.append(f"- **修改时间:** {push_time}") parts.append(f"- **修改时间:** {push_time}")
parts.append("") parts.append("")
for report in changed_reports: for report in changed_reports:

View File

@@ -132,7 +132,7 @@ public class CultureClockInController {
* @return jnpf.base.ActionResult<jnpf.model.culture.vo.RecordListVo> * @return jnpf.base.ActionResult<jnpf.model.culture.vo.RecordListVo>
*/ */
@GetMapping(value = "/dynamic1") @GetMapping(value = "/dynamic1")
public ActionResult<RecordListVo> getRecordList(@RequestParam(value = "cursorDate", required = false) Boolean cursorDate, public ActionResult<RecordListVo> getRecordList(@RequestParam(value = "cursorDate1", required = false) Boolean cursorDate,
@RequestParam(value = "limitNum", required = false, defaultValue = "10") Integer limitNum) { @RequestParam(value = "limitNum", required = false, defaultValue = "10") Integer limitNum) {
limitNum = Math.max(10, Math.min(limitNum, 30)); limitNum = Math.max(10, Math.min(limitNum, 30));