pinyin_abbr.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. """名称拼音首字母缩写:库内存小写,检索时大小写不敏感。"""
  2. from __future__ import annotations
  3. import re
  4. from typing import Optional
  5. from pypinyin import Style, lazy_pinyin
  6. _MAX_LEN = 100
  7. _ALNUM = re.compile(r"[a-zA-Z0-9]")
  8. def normalize_name_pinyin_abbr(value: Optional[str]) -> str:
  9. raw = (value or "").strip().lower()
  10. if not raw:
  11. return ""
  12. return raw[:_MAX_LEN]
  13. def build_name_pinyin_abbr(name: Optional[str]) -> str:
  14. text = (name or "").strip()
  15. if not text:
  16. return ""
  17. parts: list[str] = []
  18. for ch in text:
  19. if "\u4e00" <= ch <= "\u9fff":
  20. pys = lazy_pinyin(ch, style=Style.FIRST_LETTER)
  21. if pys and pys[0]:
  22. parts.append(str(pys[0]).lower()[0])
  23. elif _ALNUM.match(ch):
  24. parts.append(ch.lower())
  25. # else: drop punctuation / spaces / % / brackets
  26. return "".join(parts)[:_MAX_LEN]
  27. def resolve_name_pinyin_abbr(
  28. *,
  29. name: Optional[str],
  30. submitted: Optional[str] = None,
  31. existing: Optional[str] = None,
  32. submitted_provided: bool = False,
  33. ) -> Optional[str]:
  34. """保存时解析拼音字段。
  35. - submitted_provided=True:用提交值(空则按 name 生成)
  36. - 否则:已有非空 existing 则保留;existing 空则按 name 生成
  37. """
  38. if submitted_provided:
  39. normalized = normalize_name_pinyin_abbr(submitted)
  40. if normalized:
  41. return normalized
  42. generated = build_name_pinyin_abbr(name)
  43. return generated or None
  44. existing_norm = normalize_name_pinyin_abbr(existing)
  45. if existing_norm:
  46. return existing_norm
  47. generated = build_name_pinyin_abbr(name)
  48. return generated or None