"""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"""
龙老师 · 高考志愿填报方案
"""
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"
{''.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"""
志愿预览
{''.join(rows)}
"""
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}
"""