"""T7.5 分享页 WebUI 纯函数与默认文件加载器。""" from __future__ import annotations import json import re from html import escape from pathlib import Path from typing import Any, Iterable, Optional from data.share.short_link import ( STATUS_EXPIRED, STATUS_NOT_FOUND, STATUS_PASSWORD_REQUIRED, STATUS_PASSWORD_WRONG, STATUS_REVOKED, ) _STATUS_META = { STATUS_NOT_FOUND: (404, "分享链接不存在", "请确认链接是否完整,或联系龙老师重新生成。"), STATUS_REVOKED: (410, "分享已撤销", "该分享链接已被撤销,无法继续访问。"), STATUS_EXPIRED: (410, "分享已过期", "该分享链接已经过期,请联系龙老师重新分享。"), STATUS_PASSWORD_REQUIRED: (401, "需要访问密码", "该分享页已加密,请输入访问密码继续查看。"), STATUS_PASSWORD_WRONG: (401, "密码错误", "密码不正确,请重新输入。"), } def load_report_from_directory(report_id: str, report_dir: str | Path) -> Optional[dict[str, Any]]: """从目录加载 ``{report_id}.json`` 报告。不存在或格式错误时返回 None。""" if not report_id: return None if re.fullmatch(r"[A-Za-z0-9._-]+", report_id) is None: return None if report_id.startswith(".") or ".." in report_id: return None base_dir = Path(report_dir).resolve() path = (base_dir / f"{report_id}.json").resolve() if base_dir not in path.parents: return None if not path.is_file(): return None try: data = json.loads(path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): return None return data if isinstance(data, dict) else None def status_code_for_result(result: dict[str, Any]) -> int: status = str(result.get("status") or "") if status == "ok": return 200 return _STATUS_META.get(status, (400, "访问失败", "分享页当前不可用。"))[0] def render_share_page(result: dict[str, Any], *, password: str | None = None) -> str: status = str(result.get("status") or "") if status != "ok": return _render_status_page(status, code=str(result.get("code") or ""), password=password) return _render_ok_page(result) def _render_status_page(status: str, *, code: str, password: str | None) -> str: _, title, message = _STATUS_META.get(status, (400, "访问失败", "分享页当前不可用。")) error_block = "" form_block = "" if status == STATUS_PASSWORD_WRONG: error_block = '

密码错误,请重新输入。

' if status in {STATUS_PASSWORD_REQUIRED, STATUS_PASSWORD_WRONG}: form_block = f"""
""" return _page_shell( title, f"""
分享访问

{escape(title)}

{escape(message)}

{error_block} {form_block}
""", ) def _render_ok_page(result: dict[str, Any]) -> str: rendered = result.get("rendered") or {} payload = rendered.get("payload") or {} policy = rendered.get("policy") or {} permission = str(rendered.get("permission") or payload.get("permission") or "read") title = _pick_first(payload, "title") or "高考志愿填报方案" summary = _pick_first(payload, "summary") or "微信内打开也能直接查看,支持手机端快速浏览。" candidate_name = _pick_first(payload, "candidate_name", "customer_name", "student_name", "name") score = payload.get("score") rank = payload.get("rank") province = payload.get("province") year = payload.get("year") report_id = payload.get("report_id") or result.get("report_id") share_url = payload.get("share_url") or result.get("url") info_cards = [] if candidate_name: info_cards.append(_metric_card("考生", str(candidate_name))) if score is not None: info_cards.append(_metric_card("分数", str(score))) if rank is not None: info_cards.append(_metric_card("位次", _format_number(rank))) if province or year: info_cards.append(_metric_card("地区/年份", " / ".join([str(x) for x in (province, year) if x]))) info_cards_html = "".join(info_cards) if info_cards else _metric_card("状态", "已授权查看") recommendations = _render_recommendations(payload.get("recommendations")) volunteers = _render_volunteers(payload.get("volunteers")) permission_hint = _permission_hint(permission, policy) limited_block = "" if permission == "read": limited_block = """

分享信息受限

当前链接只开放最小信息展示,完整方案需更高权限或联系龙老师。

""" report_meta = [] if report_id: report_meta.append(f"报告ID:{escape(str(report_id))}") if share_url: report_meta.append(f"分享链接:{escape(str(share_url))}") report_meta_html = "
".join(report_meta) if report_meta else "公开分享页" copy_button = "" if share_url: copy_button = f'' body = f"""
龙老师 · 高考志愿填报方案

{escape(str(title))}

{escape(str(summary))}

{permission_hint}

{copy_button}
{info_cards_html}
{limited_block} {recommendations} {volunteers} """ return _page_shell(str(title), body) def _pick_first(payload: dict[str, Any], *keys: str) -> Any: for key in keys: value = payload.get(key) if value not in (None, ""): return value return None def _render_recommendations(items: Any) -> str: rows = [] for item in _take_dicts(items, limit=3): school = _pick_from_item(item, "school", "name") or "院校待补充" major = _pick_from_item(item, "major") or "专业待补充" prob = _pick_from_item(item, "prob", "probability") prob_text = _format_probability(prob) rows.append(f"
  • {escape(str(school))}{escape(str(major))}{escape(prob_text)}
  • ") if not rows: return "" return f"""

    推荐院校 TOP3

      {''.join(rows)}
    """ def _render_volunteers(items: Any) -> str: rows = [] for item in _take_dicts(items, limit=3): school = _pick_from_item(item, "school", "name") or "志愿待补充" majors = item.get("majors") if isinstance(item.get("majors"), list) else None if majors: detail = " / ".join(str(x) for x in majors[:3]) else: detail = _pick_from_item(item, "major", "type") or "" rows.append(f"
  • {escape(str(school))}{escape(str(detail))}
  • ") if not rows: return "" return f"""

    志愿预览

    """ def _take_dicts(items: Any, *, limit: int) -> Iterable[dict[str, Any]]: if not isinstance(items, list): return [] out = [] for item in items: if isinstance(item, dict): out.append(item) if len(out) >= limit: break return out def _pick_from_item(item: dict[str, Any], *keys: str) -> Any: for key in keys: value = item.get(key) if value not in (None, ""): return value return None def _permission_hint(permission: str, policy: dict[str, Any]) -> str: labels = [] if policy.get("can_comment"): labels.append("可评论") if policy.get("can_edit"): labels.append("可编辑") if not labels: labels.append("仅查看") return f"权限:{escape(permission)} · {' / '.join(labels)}" def _metric_card(label: str, value: str) -> str: return f"""
    {escape(label)}
    {escape(value)}
    """ def _format_probability(value: Any) -> str: if value in (None, ""): return "" try: num = float(value) except (TypeError, ValueError): return str(value) if num <= 1: num *= 100 return f"录取概率 {num:.0f}%" def _format_number(value: Any) -> str: try: return f"{int(value):,}" except (TypeError, ValueError): return str(value) def _page_shell(title: str, body: str) -> str: return f""" {escape(title)}
    {body}
    """