"""CLI:高校人事请假考勤命令分发。""" from __future__ import annotations import argparse import sys from typing import List, Optional from service.task_service import ( cmd_calculate_leave, cmd_config_path, cmd_health, cmd_import_employees, cmd_init_db, cmd_render_html, cmd_run, cmd_version, ) from util.argparse_zh import ZhArgumentParser from util.config_bootstrap import bootstrap_skill_config 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 _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] pick_t = _cli_str_or_none(getattr(args, "target", None)) pick_i = _cli_str_or_none(getattr(args, "input_id", None)) target = pick_t or t_target input_id = pick_i or t_input return cmd_run(target=target, input_id=input_id) 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("run", help="兼容入口(需 calculate-leave 子命令)") sp.add_argument("--target", "-t", default=None, metavar="教职工id") 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("import-employees", help="从输入目录导入教职工 JSON") sp.add_argument("--file", "-f", default=None, metavar="JSON文件") sp.set_defaults(handler=lambda a: cmd_import_employees(file_path=a.file)) sp = sub.add_parser("calculate-leave", help="核算请假扣薪与审批层级") sp.add_argument("--employee-id", "-e", required=True, dest="employee_id") sp.add_argument("--leave-type", required=True, dest="leave_type") sp.add_argument("--start-date", required=True, dest="start_date") sp.add_argument("--end-date", required=True, dest="end_date") sp.add_argument("--has-certificate", default=None, dest="has_certificate") sp.add_argument("--certificate-type", default=None, dest="certificate_type") sp.set_defaults( handler=lambda a: cmd_calculate_leave( employee_id=a.employee_id, leave_type=a.leave_type, start_date=a.start_date, end_date=a.end_date, has_certificate=a.has_certificate, certificate_type=a.certificate_type, ) ) sp = sub.add_parser("render-html", help="生成请假审批与扣薪 HTML 报告") sp.add_argument("--request-id", "-r", default=None, dest="request_id") sp.set_defaults(handler=lambda a: cmd_render_html(request_id=a.request_id)) sp = sub.add_parser("health", help="健康检查") sp.set_defaults(handler=lambda _a: cmd_health()) sp = sub.add_parser("config-path", help="输出配置与数据路径") sp.set_defaults(handler=lambda _a: cmd_config_path()) sp = sub.add_parser("version", help="版本信息") 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( "高校人事请假考勤 — 用法:python main.py import-employees | calculate-leave | " "render-html | health | version | init-db" ) return 1 short = { "run", "import-employees", "calculate-leave", "render-html", "health", "config-path", "version", "init-db", "-h", "--help", } if len(argv) == 2 and argv[0] not in short: return cmd_run(target=argv[0], input_id=argv[1]) parser = build_parser() args = parser.parse_args(argv) return int(args.handler(args))