"""RESUME_ENRICHING 模块组件事件分发与结构化收集器(竞赛/标签/联系方式)。 记录类模块(RecordFields/ChoiceChips/条目确认/卡内调整)见 enrichment_record_collectors.py。 """ from __future__ import annotations from typing import Any from .enrichment_custom import ( CUSTOM_MODULES, custom_card_picker_transition, finish_custom_enrichment, ) from .enrichment_modules import ENRICHMENT_MODULES, TAG_SEQUENCE, ModuleSpec from .enrichment_record_collectors import ( collect_choice, collect_record_fields, confirm_module_entry, edit_module_entry, ) from .fsm import FSMError, Transition, assistant_turn, component from .fsm_enrichment import ( advance_or_finish, begin_module, current_module, defer_enrichment, ensure_enrichment_state, mark_completed, progress_block, skip_module, ) from .models import ComposerMode, Stage from .validators import competition_entry_errors, normalize_tags def process_module_event( profile: dict[str, Any], component_data: dict[str, Any], action: str, payload: dict[str, Any], ) -> Transition: ensure_enrichment_state(profile) name = component_data.get("component_name") if action in {"defer", "finish_enrichment"}: return defer_enrichment(profile) if name == "CustomCardPicker": return _handle_custom_card_picker(profile, payload) spec = current_module(profile) if spec is None: raise FSMError("no_active_module", "当前没有进行中的完善模块", status_code=409) if component_data.get("module") != spec.name: raise FSMError("stale_module", "该组件不属于当前模块", status_code=409) if action in {"skip", "skip_module"}: return skip_module(profile, spec) if action in {"edit", "edit_anchor"}: return edit_module_entry(profile, spec) if name == "ChoiceChips": return collect_choice(profile, spec, payload) if name == "RecordFields": return collect_record_fields(profile, spec, payload) if name == "CompetitionFields": return _collect_competition(profile, spec, payload) if name == "TagsInput": return _collect_tags(profile, component_data, spec, payload) if name == "ExperienceConfirmCard": return confirm_module_entry(profile, spec, payload) if name == "AddAnother": return _handle_add_another(profile, spec, payload) raise FSMError("invalid_component", f"Unsupported module component: {name}", status_code=422) def _collect_competition(profile: dict[str, Any], spec: ModuleSpec, payload: dict[str, Any]) -> Transition: entry = { "record_type": "competition", "module": spec.name, "name": str(payload.get("name") or "").strip(), "award": str(payload.get("award") or "").strip(), "date": str(payload.get("date") or "").strip(), "description": str(payload.get("description") or "").strip() or None, } errors = competition_entry_errors(entry) if errors: raise FSMError( "invalid_competition", "竞赛信息不完整或格式有误", status_code=422, missing_fields=errors ) profile["enrichment"]["module_draft"] = {"entry": entry} transition = Transition( Stage.RESUME_ENRICHING, profile, assistant_turn( "请确认这条竞赛记录。", [ progress_block(profile, spec), component( "ExperienceConfirmCard", module=spec.name, confirmation_kind="module_entry", title="确认竞赛记录", value={key: entry[key] for key in ("name", "award", "date", "description")}, labels={"name": "竞赛名称", "award": "获奖名称", "date": "获奖时间", "description": "经历描述"}, ), ], mode=ComposerMode.UI_ONLY, ), ) transition.polish_description = True return transition def _handle_add_another(profile: dict[str, Any], spec: ModuleSpec, payload: dict[str, Any]) -> Transition: value = str(payload.get("value") or "") if value == "again": profile["enrichment"]["module_draft"] = {} return begin_module(profile, spec) if value == "next": mark_completed(profile, spec.name) if profile["enrichment"].get("custom_mode"): return custom_card_picker_transition(profile, refresh=True) return advance_or_finish(profile) raise FSMError("invalid_action", "请选择再添加一段或进入下一项", status_code=422) def _handle_custom_card_picker( profile: dict[str, Any], payload: dict[str, Any] ) -> Transition: value = str(payload.get("value") or payload.get("card_type") or "") if value == "finish": return finish_custom_enrichment(profile) module_name = CUSTOM_MODULES.get(value) if module_name is None: raise FSMError("invalid_card_type", "请选择列出的简历卡片", status_code=422) enrichment = profile["enrichment"] enrichment["current"] = module_name enrichment["module_draft"] = {} enrichment["custom_mode"] = True return begin_module(profile, ENRICHMENT_MODULES[module_name]) def _collect_tags( profile: dict[str, Any], component_data: dict[str, Any], spec: ModuleSpec, payload: dict[str, Any], ) -> Transition: expected = component_data.get("field") field = str(payload.get("field") or "") if field != expected or field not in TAG_SEQUENCE: raise FSMError("invalid_field", "提交字段与当前组件不符", status_code=422) profile["tags"][field] = normalize_tags(payload.get("value") or payload.get("values") or []) mark_completed(profile, spec.name) return advance_or_finish(profile, refresh=True)