59 lines
1.7 KiB
Python
59 lines
1.7 KiB
Python
"""名称拼音首字母缩写:库内存小写,检索时大小写不敏感。"""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Optional
|
|
|
|
from pypinyin import Style, lazy_pinyin
|
|
|
|
_MAX_LEN = 100
|
|
_ALNUM = re.compile(r"[a-zA-Z0-9]")
|
|
|
|
|
|
def normalize_name_pinyin_abbr(value: Optional[str]) -> str:
|
|
raw = (value or "").strip().lower()
|
|
if not raw:
|
|
return ""
|
|
return raw[:_MAX_LEN]
|
|
|
|
|
|
def build_name_pinyin_abbr(name: Optional[str]) -> str:
|
|
text = (name or "").strip()
|
|
if not text:
|
|
return ""
|
|
parts: list[str] = []
|
|
for ch in text:
|
|
if "\u4e00" <= ch <= "\u9fff":
|
|
pys = lazy_pinyin(ch, style=Style.FIRST_LETTER)
|
|
if pys and pys[0]:
|
|
parts.append(str(pys[0]).lower()[0])
|
|
elif _ALNUM.match(ch):
|
|
parts.append(ch.lower())
|
|
# else: drop punctuation / spaces / % / brackets
|
|
return "".join(parts)[:_MAX_LEN]
|
|
|
|
|
|
def resolve_name_pinyin_abbr(
|
|
*,
|
|
name: Optional[str],
|
|
submitted: Optional[str] = None,
|
|
existing: Optional[str] = None,
|
|
submitted_provided: bool = False,
|
|
) -> Optional[str]:
|
|
"""保存时解析拼音字段。
|
|
|
|
- submitted_provided=True:用提交值(空则按 name 生成)
|
|
- 否则:已有非空 existing 则保留;existing 空则按 name 生成
|
|
"""
|
|
if submitted_provided:
|
|
normalized = normalize_name_pinyin_abbr(submitted)
|
|
if normalized:
|
|
return normalized
|
|
generated = build_name_pinyin_abbr(name)
|
|
return generated or None
|
|
existing_norm = normalize_name_pinyin_abbr(existing)
|
|
if existing_norm:
|
|
return existing_norm
|
|
generated = build_name_pinyin_abbr(name)
|
|
return generated or None
|