198 lines
8.2 KiB
Python
198 lines
8.2 KiB
Python
"""CLI:argparse 与分发(职称评审核验助手)。
|
||
|
||
只负责参数解析并转交 service;业务内核在 verify_service / threshold_service,
|
||
勿在此按入口复制逻辑。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import sys
|
||
from typing import List, Optional
|
||
|
||
from service.task_service import (
|
||
cmd_config_path,
|
||
cmd_health,
|
||
cmd_import_thresholds,
|
||
cmd_init_db,
|
||
cmd_list_cases,
|
||
cmd_render_html,
|
||
cmd_run,
|
||
cmd_set_threshold,
|
||
cmd_show_case,
|
||
cmd_stats,
|
||
cmd_verify_batch_input,
|
||
cmd_verify_metric,
|
||
cmd_version,
|
||
cmd_view_thresholds,
|
||
)
|
||
from util.config_bootstrap import bootstrap_skill_config
|
||
from util.argparse_zh import ZhArgumentParser
|
||
from util.constants import LOG_LOGGER_NAME, SKILL_SLUG
|
||
from util.logging_config import get_skill_logger, setup_skill_logging
|
||
|
||
|
||
def _cli_str_or_none(raw: Optional[str]) -> Optional[str]:
|
||
if raw is None:
|
||
return None
|
||
v = str(raw).strip()
|
||
return v or None
|
||
|
||
|
||
def _cli_int_or_none(raw: Optional[str]) -> Optional[int]:
|
||
raw = _cli_str_or_none(raw)
|
||
if raw is None:
|
||
return None
|
||
try:
|
||
return int(float(raw))
|
||
except ValueError:
|
||
return None
|
||
|
||
|
||
def _handle_run(args: argparse.Namespace) -> int:
|
||
tail = [str(x).strip() for x in (args.run_tail or []) if str(x).strip()]
|
||
if len(tail) > 2:
|
||
print("参数过多。")
|
||
print("用法:python main.py run [target [input_id]] | run [-t target] [-i input_id]")
|
||
return 1
|
||
t_target: Optional[str] = None
|
||
t_input: Optional[str] = None
|
||
if len(tail) == 2:
|
||
t_target, t_input = tail[0], tail[1]
|
||
elif len(tail) == 1:
|
||
if tail[0].isdigit():
|
||
t_input = tail[0]
|
||
else:
|
||
t_target = tail[0]
|
||
target = _cli_str_or_none(getattr(args, "target", None)) or t_target
|
||
input_id = _cli_str_or_none(getattr(args, "input_id", None)) or t_input
|
||
return cmd_run(target=target, input_id=input_id)
|
||
|
||
|
||
def _handle_set_threshold(args):
|
||
return cmd_set_threshold(
|
||
rank=str(args.rank or "").strip(),
|
||
metric_key=str(args.metric_key or "").strip(),
|
||
metric_name=_cli_str_or_none(args.metric_name) or "",
|
||
min_value=float(args.min_value),
|
||
unit=_cli_str_or_none(args.unit) or "",
|
||
basis_doc=_cli_str_or_none(args.basis_doc) or "",
|
||
clause=_cli_str_or_none(args.clause) or "",
|
||
)
|
||
|
||
|
||
def _handle_verify(args):
|
||
return cmd_verify_metric(
|
||
teacher_name=str(args.teacher or "").strip(),
|
||
apply_rank=str(args.apply_rank or "").strip(),
|
||
metrics_json=str(args.metrics_json or "").strip(),
|
||
department=_cli_str_or_none(args.department) or "",
|
||
)
|
||
|
||
|
||
def _handle_list_reports(args):
|
||
return cmd_list_cases(limit=int(args.limit or 20), verdict=_cli_str_or_none(args.verdict) or "")
|
||
|
||
|
||
def _handle_render_html(args):
|
||
report_id = getattr(args, "report_id", None)
|
||
return cmd_render_html(report_id=int(report_id) if report_id else None)
|
||
|
||
|
||
def _print_full_usage() -> None:
|
||
print("职称评审核验助手(main.py)可用命令:")
|
||
print(" python main.py verify-metric --teacher 张三 --apply-rank 副教授 --metrics-json <file|内联|-> [--department 学院]")
|
||
print(" python main.py verify-batch-input # 批量核验 input/ 目录申报案例")
|
||
print(" python main.py view-thresholds [--rank 副教授]")
|
||
print(" python main.py set-threshold --rank 副教授 --metric-key presiding_provincial --metric-name 主持省部级项目 --min-value 1 [--unit 项] [--basis-doc 文件] [--clause 条款]")
|
||
print(" python main.py import-thresholds --thresholds-json <file|->")
|
||
print(" python main.py list-cases [--limit N] [--verdict 硬伤] | show-case --id N | render-html [--report-id N]")
|
||
print(" python main.py stats")
|
||
print(" python main.py run [target [input_id]] [-t target] [-i input_id]")
|
||
print(" python main.py health | config-path | version | init-db")
|
||
|
||
|
||
def build_parser() -> ZhArgumentParser:
|
||
p = ZhArgumentParser(
|
||
prog="main.py",
|
||
description="职称评审核验助手:维护各级别刚性门槛库,对申报案例逐项比对生成达标矩阵与红黄绿三色结论,出具《核验报告》。",
|
||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||
)
|
||
sub = p.add_subparsers(dest="cmd", required=True, parser_class=ZhArgumentParser)
|
||
|
||
sp = sub.add_parser("verify-metric", help="职称硬指标核验(主命令)")
|
||
sp.add_argument("--teacher", required=True, metavar="教师姓名")
|
||
sp.add_argument("--apply-rank", required=True, metavar="申报级别(副教授/教授)", dest="apply_rank")
|
||
sp.add_argument("--metrics-json", required=True, metavar="指标JSON(file|内联|-)", dest="metrics_json")
|
||
sp.add_argument("--department", default=None, metavar="所属学院")
|
||
sp.set_defaults(handler=_handle_verify)
|
||
|
||
sp = sub.add_parser("verify-batch-input", help="批量核验 input/ 目录申报案例")
|
||
sp.set_defaults(handler=lambda _a: cmd_verify_batch_input())
|
||
|
||
sp = sub.add_parser("view-thresholds", help="查看评审门槛库")
|
||
sp.add_argument("--rank", default=None, metavar="级别筛选")
|
||
sp.set_defaults(handler=lambda a: cmd_view_thresholds(rank=_cli_str_or_none(a.rank) or ""))
|
||
|
||
sp = sub.add_parser("set-threshold", help="录入/更新评审门槛")
|
||
sp.add_argument("--rank", required=True, metavar="申报级别", dest="rank")
|
||
sp.add_argument("--metric-key", required=True, metavar="指标键", dest="metric_key")
|
||
sp.add_argument("--metric-name", default=None, metavar="指标名称", dest="metric_name")
|
||
sp.add_argument("--min-value", required=True, type=float, metavar="最低要求", dest="min_value")
|
||
sp.add_argument("--unit", default=None, metavar="单位")
|
||
sp.add_argument("--basis-doc", default=None, metavar="依据文件", dest="basis_doc")
|
||
sp.add_argument("--clause", default=None, metavar="条款")
|
||
sp.set_defaults(handler=_handle_set_threshold)
|
||
|
||
sp = sub.add_parser("import-thresholds", help="批量导入门槛")
|
||
sp.add_argument("--thresholds-json", required=True, metavar="JSON(file|-)", dest="thresholds_json")
|
||
sp.set_defaults(handler=lambda a: cmd_import_thresholds(str(a.thresholds_json)))
|
||
|
||
sp = sub.add_parser("list-cases", help="查询核验案例")
|
||
sp.add_argument("--limit", default=20, metavar="条数")
|
||
sp.add_argument("--verdict", default=None, metavar="结论筛选(安全/边缘/硬伤)")
|
||
sp.set_defaults(handler=_handle_list_reports)
|
||
|
||
sp = sub.add_parser("show-case", help="查看核验案例详情")
|
||
sp.add_argument("--id", required=True, type=int, metavar="案例编号", dest="case_id")
|
||
sp.set_defaults(handler=lambda a: cmd_show_case(case_id=int(a.case_id)))
|
||
|
||
sp = sub.add_parser("render-html", help="重建《核验报告》(缺省最近 10 份)")
|
||
sp.add_argument("--report-id", default=None, metavar="案例编号", dest="report_id")
|
||
sp.set_defaults(handler=_handle_render_html)
|
||
|
||
sp = sub.add_parser("stats", help="核验统计")
|
||
sp.set_defaults(handler=lambda _a: cmd_stats())
|
||
|
||
sp = sub.add_parser("run", help="任务执行命令骨架")
|
||
sp.add_argument("--target", "-t", default=None, metavar="目标")
|
||
sp.add_argument("--input-id", "-i", default=None, metavar="输入id", dest="input_id")
|
||
sp.add_argument("run_tail", nargs="*", metavar="位置参数")
|
||
sp.set_defaults(handler=_handle_run)
|
||
|
||
sp = sub.add_parser("health", help="健康检查")
|
||
sp.set_defaults(handler=lambda _a: cmd_health())
|
||
|
||
sp = sub.add_parser("config-path", help="输出用户 .env 与模板路径")
|
||
sp.set_defaults(handler=lambda _a: cmd_config_path())
|
||
|
||
sp = sub.add_parser("version", help="版本信息(JSON)")
|
||
sp.set_defaults(handler=lambda _a: cmd_version())
|
||
|
||
sp = sub.add_parser("init-db", help="幂等初始化本地数据库与数据管理元数据")
|
||
sp.set_defaults(handler=lambda _a: cmd_init_db())
|
||
return p
|
||
|
||
|
||
def main(argv: Optional[List[str]] = None) -> int:
|
||
argv = argv if argv is not None else sys.argv[1:]
|
||
bootstrap_skill_config()
|
||
setup_skill_logging(SKILL_SLUG, LOG_LOGGER_NAME)
|
||
get_skill_logger().info("cli_start argv=%s", sys.argv)
|
||
if not argv:
|
||
_print_full_usage()
|
||
return 1
|
||
parser = build_parser()
|
||
args = parser.parse_args(argv)
|
||
return int(args.handler(args))
|