feat: 增强风险规则生成引擎与预算中心页面
后端拆分风险规则生成为解释器、语义分析、本体对齐等子模块, 优化模板执行和流程图生成,完善员工种子数据和导入逻辑,增强 报销单权限策略和草稿持久化,前端新增预算中心视图和趋势图 组件,重构审计页面和风险规则测试对话框交互,完善文档中心 和报销创建页面细节,补充单元测试覆盖。
This commit is contained in:
148
server/src/app/services/user_agent_application_locations.py
Normal file
148
server/src/app/services/user_agent_application_locations.py
Normal file
@@ -0,0 +1,148 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
|
||||
DIRECT_MUNICIPALITY_DISPLAY = {
|
||||
"北京": "北京市",
|
||||
"北京市": "北京市",
|
||||
"上海": "上海市",
|
||||
"上海市": "上海市",
|
||||
"天津": "天津市",
|
||||
"天津市": "天津市",
|
||||
"重庆": "重庆市",
|
||||
"重庆市": "重庆市",
|
||||
}
|
||||
|
||||
PROVINCE_ALIASES = {
|
||||
"新疆维吾尔自治区": "新疆",
|
||||
"新疆": "新疆",
|
||||
"广东省": "广东",
|
||||
"广东": "广东",
|
||||
"浙江省": "浙江",
|
||||
"浙江": "浙江",
|
||||
"江苏省": "江苏",
|
||||
"江苏": "江苏",
|
||||
"四川省": "四川",
|
||||
"四川": "四川",
|
||||
"湖北省": "湖北",
|
||||
"湖北": "湖北",
|
||||
"陕西省": "陕西",
|
||||
"陕西": "陕西",
|
||||
"山东省": "山东",
|
||||
"山东": "山东",
|
||||
"湖南省": "湖南",
|
||||
"湖南": "湖南",
|
||||
"河南省": "河南",
|
||||
"河南": "河南",
|
||||
"安徽省": "安徽",
|
||||
"安徽": "安徽",
|
||||
"福建省": "福建",
|
||||
"福建": "福建",
|
||||
"云南省": "云南",
|
||||
"云南": "云南",
|
||||
"江西省": "江西",
|
||||
"江西": "江西",
|
||||
"辽宁省": "辽宁",
|
||||
"辽宁": "辽宁",
|
||||
}
|
||||
|
||||
CITY_TO_PROVINCE = {
|
||||
"伊犁": "新疆",
|
||||
"伊犁哈萨克自治州": "新疆",
|
||||
"乌鲁木齐": "新疆",
|
||||
"克拉玛依": "新疆",
|
||||
"喀什": "新疆",
|
||||
"广州": "广东",
|
||||
"深圳": "广东",
|
||||
"佛山": "广东",
|
||||
"东莞": "广东",
|
||||
"杭州": "浙江",
|
||||
"宁波": "浙江",
|
||||
"南京": "江苏",
|
||||
"苏州": "江苏",
|
||||
"无锡": "江苏",
|
||||
"成都": "四川",
|
||||
"武汉": "湖北",
|
||||
"西安": "陕西",
|
||||
"青岛": "山东",
|
||||
"济南": "山东",
|
||||
"长沙": "湖南",
|
||||
"郑州": "河南",
|
||||
"合肥": "安徽",
|
||||
"福州": "福建",
|
||||
"厦门": "福建",
|
||||
"昆明": "云南",
|
||||
"南昌": "江西",
|
||||
"沈阳": "辽宁",
|
||||
"大连": "辽宁",
|
||||
}
|
||||
|
||||
LOCATION_NOISE_PATTERN = re.compile(
|
||||
r"(?:出差|驻场|现场|支撑|支持|部署|上线|实施|拜访|验收|会议|采购|培训|协助|处理|办理|参加|进行).*$"
|
||||
)
|
||||
|
||||
|
||||
def normalize_application_location(value: str) -> str:
|
||||
text = _cleanup_location_text(value)
|
||||
if not text:
|
||||
return ""
|
||||
|
||||
direct = _resolve_direct_municipality(text)
|
||||
if direct:
|
||||
return direct
|
||||
|
||||
province_city = _resolve_province_city(text)
|
||||
if province_city:
|
||||
return province_city
|
||||
|
||||
return text[:12]
|
||||
|
||||
|
||||
def _cleanup_location_text(value: str) -> str:
|
||||
text = re.sub(r"\s+", "", str(value or ""))
|
||||
text = text.strip("::,,。;;、")
|
||||
text = re.sub(r"^(?:地点|业务地点|发生地点)[::]", "", text)
|
||||
text = re.sub(r"^(?:去|到|赴|前往)", "", text)
|
||||
text = LOCATION_NOISE_PATTERN.sub("", text)
|
||||
return text.strip("::,,。;;、")
|
||||
|
||||
|
||||
def _resolve_direct_municipality(text: str) -> str:
|
||||
for key, display in DIRECT_MUNICIPALITY_DISPLAY.items():
|
||||
if text.startswith(key):
|
||||
return display
|
||||
return ""
|
||||
|
||||
|
||||
def _resolve_province_city(text: str) -> str:
|
||||
for province_alias, province_display in PROVINCE_ALIASES.items():
|
||||
if not text.startswith(province_alias):
|
||||
continue
|
||||
remainder = text[len(province_alias) :].strip("省市地区自治州盟,,、")
|
||||
if not remainder:
|
||||
return province_display
|
||||
city = _resolve_city_name(remainder)
|
||||
return f"{province_display},{city}" if city else province_display
|
||||
|
||||
city = _resolve_city_name(text)
|
||||
if city:
|
||||
province = CITY_TO_PROVINCE.get(city)
|
||||
return f"{province},{city}" if province else city
|
||||
return ""
|
||||
|
||||
|
||||
def _resolve_city_name(text: str) -> str:
|
||||
normalized = text.strip(",,、")
|
||||
if not normalized:
|
||||
return ""
|
||||
for city in sorted(CITY_TO_PROVINCE, key=len, reverse=True):
|
||||
if normalized.startswith(city):
|
||||
return _display_city_name(city)
|
||||
return ""
|
||||
|
||||
|
||||
def _display_city_name(city: str) -> str:
|
||||
if city == "伊犁哈萨克自治州":
|
||||
return "伊犁"
|
||||
return city.removesuffix("市")
|
||||
Reference in New Issue
Block a user