日常更新

from NUC
This commit is contained in:
liubiren 2025-12-23 16:56:44 +08:00
parent 27a1b5e07b
commit 3fc3ced425
44 changed files with 181 additions and 381178 deletions

View File

@ -1,55 +0,0 @@
import csv
import chardet
def convert_csv_to_utf8(input_csv: str, output_csv: str, encoding: str = None):
"""
将非UTF-8编码的CSV文件转换为UTF-8编码
:param input_csv: 输入CSV文件路径
:param output_csv: 输出UTF-8编码的CSV文件路径
:param encoding: 手动指定输入文件编码"gbk"若为None则自动检测
"""
# 步骤1检测输入文件的原始编码若未手动指定
if not encoding:
print(f"🔍 正在检测 {input_csv} 的编码...")
with open(input_csv, "rb") as f:
raw_data = f.read(10240) # 读取前10KB数据用于检测足够识别编码
result = chardet.detect(raw_data)
encoding = result["encoding"]
confidence = result["confidence"]
print(f"✅ 检测到编码:{encoding}(置信度:{confidence:.2f}")
# 处理chardet检测结果为空的情况兜底用gbk适配中文常见编码
if not encoding:
encoding = "gbk"
print(f"⚠️ 编码检测失败,兜底使用 {encoding}")
# 步骤2按原始编码读取CSV并转换为UTF-8保存
try:
# 读取原始CSV处理编码错误replace表示用<E7A4BA>替换无法解码的字符避免程序崩溃
with open(input_csv, "r", encoding=encoding, errors="replace") as infile:
# 兼容CSV的不同分隔符默认逗号若为制表符可改delimiter='\t'
reader = csv.reader(infile)
rows = list(reader) # 读取所有行
# 保存为UTF-8编码的CSVnewline=''避免空行encoding='utf-8-sig'带BOM适配Excel打开
with open(output_csv, "w", encoding="utf-8-sig", newline="") as outfile:
writer = csv.writer(outfile)
writer.writerows(rows)
print(f"✅ 转换完成UTF-8编码文件已保存至{output_csv}")
return True
except Exception as e:
print(f"❌ 转换失败:{str(e)}")
return False
# ========== 示例调用 ==========
if __name__ == "__main__":
# 输入/输出文件路径(替换为你的实际路径)
input_path = "转换后_UTF8.csv"
output_path = "转换后_UTF8.csv"
# 自动检测编码并转换
convert_csv_to_utf8(input_path, output_path)

Binary file not shown.

View File

@ -118,10 +118,10 @@ if __name__ == "__main__":
# 初始化药品表
self._execute(
sql="""
CREATE TABLE IF NOT EXISTS drugs
CREATE TABLE IF NOT EXISTS medicines
(
--药品
drug TEXT PRIMARY KEY
--药品/医疗服务
medicine TEXT PRIMARY KEY
)
"""
)
@ -218,35 +218,36 @@ if __name__ == "__main__":
raise RuntimeError("查询并获取多条个单和被保险人记录发生异常")
# noinspection PyShadowingNames
def query_drug(
def query_medicine(
self,
content: str,
) -> Optional[str]:
"""
根据明细项具体内容查询药品
根据明细项名称中具体内容查询药品/医疗服务
:param content: 明细项具体内容
:return: 药品
:return: 药品/医疗服务
"""
# TODO: 暂仅支持查询药品,后续完善查询医疗服务
# noinspection PyBroadException
try:
with self:
# noinspection SqlResolve
result = self._query_all(
sql="""
SELECT drug
FROM drugs
WHERE ? LIKE '%' || drug || '%'
SELECT medicine
FROM medicines
WHERE ? LIKE '%' || medicine || '%'
""",
parameters=(content,),
)
if result:
return max(result, key=lambda x: len(x["drug"]))[
"drug"
] # 返回最大长度的药品
return max(result, key=lambda x: len(x["medicine"]))[
"medicine"
] # 返回药品最大长度的药品
raise
# TODO: 若根据明细项具体内容查询药品发生异常则流转至主数据人工处理
# TODO: 若根据明细项名称中具体内容查询药品/医疗服务发生异常则流转至主数据人工处理
except Exception:
raise RuntimeError("根据明细项具体内容查询药品发生异常")
raise RuntimeError("根据明细项名称中具体内容查询药品/医疗服务发生异常")
# 实例化主数据
master_data = MasterData()
@ -859,6 +860,23 @@ if __name__ == "__main__":
else None
)
def parse_name(name: str) -> Tuple[str, Optional[str]]:
"""
根据明细项名称解析明细项类别和具体内容并根据明细项名称中具体内容查询药品/医疗服务
:param name: 明细项名称
return 明细项类别和药品/医疗服务
"""
if match := re.match(
r"^\*(?P<category>.*?)\*(?P<specific>.*)$",
name,
):
return match.group("category"), master_data.query_medicine(
match.group("specific")
)
# 一般增值税发票明细项格式形如*{category}*{specific}其中category为明细项类别例如中成药specific为明细项具体内容例如[同仁堂]金贵肾气水蜜丸 300丸/瓶,需要据此查询药品。其它格式则将明细项内容作为明细项类别,药品为空值
else:
return name, None
# 初始化票据数据
receipt = {"影像件编号": image["影像件编号"]}
# 请求深圳快瞳票据查验接口(兼容增值税发票、医疗门诊/住院收费票据)
@ -1291,24 +1309,22 @@ if __name__ == "__main__":
lambda dataframe: dataframe["金额"] != 0
] # 仅保留金额非0的明细项
.reset_index()
.to_dict("records")
.pipe(
lambda dataframe: dataframe.join(
dataframe["名称"]
.apply(
parse_name
) # 根据明细项名称解析明细项类别和具体内容,并根据明细项名称中具体内容查询药品/医疗服务
.apply(
pandas.Series
) # 就明细项类别和药品/医疗服务元组展开为两列
.rename(columns={0: "类别", 1: "药品/医疗服务"})
)
)
)
for item in items:
# 匹配并解析明细项大类和具体内容
if match := re.match(
r"^\*(?P<category>.*?)\*(?P<content>.*)$",
item["名称"],
):
category = match.group("category") # 明细项大类
# 根据明细项具体内容查询药品
drug = master_data.query_drug(match.group("content"))
# TODO: 若匹配明细项大类和具体内容发生异常则流转至人工处理
else:
raise RuntimeError("匹配明细项大类和具体内容发生异常")
print(dossier["被保险人层"])
exit()
print(items)
print()
case ("增值税发票", "私立医院"):
receipt["购药及就医类型"] = "门诊就医"

View File

@ -0,0 +1,135 @@
{
"contentType": "application/vnd.gorules.decision",
"nodes": [
{
"id": "d0fbd74f-6514-4c42-87e5-fdf849b8ab6f",
"name": "request",
"type": "inputNode",
"content": {
"schema": ""
},
"position": {
"x": 110,
"y": 292.5
}
},
{
"id": "d717ec6d-d082-4f23-8fe6-3fa52b228e65",
"name": "decisionTable",
"type": "decisionTableNode",
"content": {
"rules": [
{
"_id": "16c78c24-882b-4428-b429-e66ed67e0e85",
"_description": "中银保险有限公司苏州分公司就中成药不扣除",
"1fdeb8d9-62c5-4f07-b5d1-69dbaf6020fe": "amount",
"2522d0a7-437b-421b-90e7-165e2365ebba": "\"中银保险有限公司苏州分公司\"",
"4ed5e43b-f519-46cb-8c92-80097788d21a": "\"中成药\"",
"8a5837ec-3df9-4445-a515-34762a244a68": "",
"cd1dc117-39f5-4dc2-96bb-f67236199851": ""
},
{
"_id": "33343bbe-ee06-44f2-8247-84106cdaad8a",
"_description": "中银保险有限公司苏州分公司就化学药品制剂不扣除",
"1fdeb8d9-62c5-4f07-b5d1-69dbaf6020fe": "amount",
"2522d0a7-437b-421b-90e7-165e2365ebba": "\"中银保险有限公司苏州分公司\"",
"4ed5e43b-f519-46cb-8c92-80097788d21a": "\"化学药品制剂\"",
"8a5837ec-3df9-4445-a515-34762a244a68": "",
"cd1dc117-39f5-4dc2-96bb-f67236199851": ""
},
{
"_id": "87dd3e93-5b9b-4aa3-a7f8-899f0745260a",
"_description": "中银保险有限公司苏州分公司就医疗仪器器械不扣除",
"1fdeb8d9-62c5-4f07-b5d1-69dbaf6020fe": "amount",
"2522d0a7-437b-421b-90e7-165e2365ebba": "\"中银保险有限公司苏州分公司\"",
"4ed5e43b-f519-46cb-8c92-80097788d21a": "\"医疗仪器器械\"",
"8a5837ec-3df9-4445-a515-34762a244a68": "",
"cd1dc117-39f5-4dc2-96bb-f67236199851": ""
},
{
"_id": "5a39b06b-deb9-411b-9aa3-e110588f3f7a",
"_description": "中银保险有限公司苏州分公司就其它明细项类别扣除",
"1fdeb8d9-62c5-4f07-b5d1-69dbaf6020fe": "\"0.00\"",
"2522d0a7-437b-421b-90e7-165e2365ebba": "\"中银保险有限公司苏州分公司\"",
"4ed5e43b-f519-46cb-8c92-80097788d21a": "",
"8a5837ec-3df9-4445-a515-34762a244a68": "",
"cd1dc117-39f5-4dc2-96bb-f67236199851": ""
},
{
"_id": "cd1b883f-2dc8-459a-8eba-bbae94b3d9b2",
"_description": "其它保险分公司就所有明细项类别扣除",
"1fdeb8d9-62c5-4f07-b5d1-69dbaf6020fe": "\"0.00\"",
"2522d0a7-437b-421b-90e7-165e2365ebba": "",
"4ed5e43b-f519-46cb-8c92-80097788d21a": "",
"8a5837ec-3df9-4445-a515-34762a244a68": "",
"cd1dc117-39f5-4dc2-96bb-f67236199851": ""
}
],
"inputs": [
{
"id": "2522d0a7-437b-421b-90e7-165e2365ebba",
"name": "保险分公司",
"field": "insurer_company"
},
{
"id": "4ed5e43b-f519-46cb-8c92-80097788d21a",
"name": "明细项类别",
"field": "category"
},
{
"id": "cd1dc117-39f5-4dc2-96bb-f67236199851",
"name": "药品/医疗服务",
"field": "medicine"
},
{
"id": "8a5837ec-3df9-4445-a515-34762a244a68",
"name": "金额",
"field": "amount"
}
],
"outputs": [
{
"id": "1fdeb8d9-62c5-4f07-b5d1-69dbaf6020fe",
"name": "合理金额",
"field": "reasonable_amount"
}
],
"hitPolicy": "first",
"inputField": null,
"outputPath": null,
"passThrough": true,
"executionMode": "single"
},
"position": {
"x": 430,
"y": 292.5
}
},
{
"id": "b7e720d7-9ef7-4470-be68-a38a1a711b45",
"name": "response",
"type": "outputNode",
"content": {
"schema": ""
},
"position": {
"x": 750,
"y": 292.5
}
}
],
"edges": [
{
"id": "0b72f551-884f-41c9-b9a7-2eb711e93181",
"type": "edge",
"sourceId": "d0fbd74f-6514-4c42-87e5-fdf849b8ab6f",
"targetId": "d717ec6d-d082-4f23-8fe6-3fa52b228e65"
},
{
"id": "9dc2590c-8061-4974-b06e-40e7c49a1d97",
"type": "edge",
"sourceId": "d717ec6d-d082-4f23-8fe6-3fa52b228e65",
"targetId": "b7e720d7-9ef7-4470-be68-a38a1a711b45"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff