revert: 恢复误删文件(回退 81f500160)

This commit is contained in:
2026-06-12 16:00:06 +08:00
parent cec2f47a1f
commit a45b6e7955
925 changed files with 44427 additions and 455 deletions

351
scripts/repair_bug_318.py Executable file
View File

@@ -0,0 +1,351 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Bug #318 历史数据修复脚本
为已存在但未生成手术医嘱的手术申请单补齐数据
"""
import psycopg2
import json
import random
import string
from datetime import datetime
# 数据库连接配置
DB_CONFIG = {
"host": "47.116.196.11",
"port": 15432,
"database": "postgresql",
"user": "postgresql",
"password": "postgresql", # 请根据实际情况修改
}
def generate_bus_no():
"""生成4位随机bus_no"""
return "".join(random.choices(string.digits, k=4))
def check_repair_needed(conn):
"""检查需要修复的记录数"""
cursor = conn.cursor()
sql = """
SELECT COUNT(*)
FROM doc_request_form rf
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
AND sr.delete_flag = '0'
WHERE rf.type_code = 'PROCEDURE'
AND rf.delete_flag = '0'
AND sr.id IS NULL
"""
cursor.execute(sql)
count = cursor.fetchone()[0]
cursor.close()
return count
def get_repair_list(conn):
"""获取需要修复的手术申请单列表"""
cursor = conn.cursor()
sql = """
SELECT
rf.id,
rf.prescription_no,
rf.encounter_id,
rf.patient_id,
rf.requester_id,
rf.create_time,
rf.org_id,
rf.desc_json
FROM doc_request_form rf
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
AND sr.delete_flag = '0'
WHERE rf.type_code = 'PROCEDURE'
AND rf.delete_flag = '0'
AND sr.id IS NULL
ORDER BY rf.create_time DESC
"""
cursor.execute(sql)
results = cursor.fetchall()
cursor.close()
return results
def parse_surgery_info(desc_json):
"""解析手术信息"""
if not desc_json:
return {}
try:
if isinstance(desc_json, str):
return json.loads(desc_json)
return desc_json
except:
return {}
def repair_service_request(conn, repair_list):
"""修复手术医嘱ServiceRequest"""
cursor = conn.cursor()
insert_sql = """
INSERT INTO wor_service_request (
bus_no, prescription_no, status_enum, generate_source_enum,
therapy_enum, quantity, unit_code, category_enum,
patient_id, requester_id, encounter_id, authored_time,
org_id, content_json, delete_flag, create_time, create_by, tenant_id
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
RETURNING id
"""
new_requests = []
for record in repair_list:
(
rf_id,
prescription_no,
encounter_id,
patient_id,
requester_id,
create_time,
org_id,
desc_json,
) = record
# 解析手术信息
surgery_info = parse_surgery_info(desc_json)
content_json = (
json.dumps(surgery_info, ensure_ascii=False) if surgery_info else None
)
# 生成bus_no
bus_no = generate_bus_no()
# 插入ServiceRequest
cursor.execute(
insert_sql,
(
bus_no, # bus_no
prescription_no, # prescription_no
1, # status_enum: 1-待签发
1, # generate_source_enum: 1-医生处方
2, # therapy_enum: 2-临时医嘱
1, # quantity
"", # unit_code
4, # category_enum: 4-手术
patient_id, # patient_id
requester_id, # requester_id
encounter_id, # encounter_id
create_time, # authored_time
org_id, # org_id
content_json, # content_json
"0", # delete_flag
create_time, # create_time
requester_id, # create_by
1, # tenant_id
),
)
service_request_id = cursor.fetchone()[0]
new_requests.append(
{
"service_request_id": service_request_id,
"bus_no": bus_no,
"prescription_no": prescription_no,
"patient_id": patient_id,
"encounter_id": encounter_id,
"requester_id": requester_id,
"create_time": create_time,
"org_id": org_id,
"surgery_info": surgery_info,
}
)
conn.commit()
cursor.close()
return new_requests
def repair_charge_items(conn, new_requests):
"""修复收费项目ChargeItem"""
cursor = conn.cursor()
insert_sql = """
INSERT INTO adm_charge_item (
bus_no, status_enum, generate_source_enum, patient_id,
context_enum, encounter_id, enterer_id, entered_date,
service_table, service_id, product_table, requesting_org_id,
quantity_value, quantity_unit, unit_price, total_price,
delete_flag, create_time, create_by, tenant_id
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
for req in new_requests:
surgery_info = req["surgery_info"]
# 手术费用
surgery_fee = 0
if surgery_info and "surgeryFee" in surgery_info:
try:
surgery_fee = float(surgery_info["surgeryFee"])
except:
surgery_fee = 0
# 插入手术费用收费项目
cursor.execute(
insert_sql,
(
"CI" + req["bus_no"], # bus_no
1, # status_enum: 1-草稿
1, # generate_source_enum: 1-医生处方
req["patient_id"], # patient_id
3, # context_enum: 3-诊疗
req["encounter_id"], # encounter_id
req["requester_id"], # enterer_id
req["create_time"], # entered_date
"wor_service_request", # service_table
req["service_request_id"], # service_id
"wor_activity_definition", # product_table
req["org_id"], # requesting_org_id
1, # quantity_value
"", # quantity_unit
surgery_fee, # unit_price
surgery_fee, # total_price
"0", # delete_flag
req["create_time"], # create_time
req["requester_id"], # create_by
1, # tenant_id
),
)
# 麻醉费用如果存在且大于0
anesthesia_fee = 0
if surgery_info and "anesthesiaFee" in surgery_info:
try:
anesthesia_fee = float(surgery_info["anesthesiaFee"])
except:
anesthesia_fee = 0
if anesthesia_fee > 0:
cursor.execute(
insert_sql,
(
"CI" + req["bus_no"] + "_A", # bus_no
1, # status_enum
1, # generate_source_enum
req["patient_id"], # patient_id
3, # context_enum
req["encounter_id"], # encounter_id
req["requester_id"], # enterer_id
req["create_time"], # entered_date
"wor_service_request", # service_table
req["service_request_id"], # service_id
"wor_activity_definition", # product_table
req["org_id"], # requesting_org_id
1, # quantity_value
"", # quantity_unit
anesthesia_fee, # unit_price
anesthesia_fee, # total_price
"0", # delete_flag
req["create_time"], # create_time
req["requester_id"], # create_by
1, # tenant_id
),
)
conn.commit()
cursor.close()
def verify_repair(conn):
"""验证修复结果"""
cursor = conn.cursor()
# 统计手术医嘱数量
cursor.execute("""
SELECT COUNT(*)
FROM wor_service_request
WHERE category_enum = 4 AND delete_flag = '0'
""")
service_request_count = cursor.fetchone()[0]
# 统计收费项目数量
cursor.execute("""
SELECT COUNT(*)
FROM adm_charge_item ci
WHERE ci.service_table = 'wor_service_request'
AND EXISTS (
SELECT 1 FROM wor_service_request sr
WHERE sr.id = ci.service_id AND sr.category_enum = 4
)
""")
charge_item_count = cursor.fetchone()[0]
cursor.close()
return service_request_count, charge_item_count
def main():
"""主函数"""
print("=" * 60)
print("Bug #318 历史数据修复脚本")
print("=" * 60)
print()
try:
# 连接数据库
print("正在连接数据库...")
conn = psycopg2.connect(**DB_CONFIG)
print("✓ 数据库连接成功")
print()
# 步骤1检查需要修复的记录数
print("步骤1: 检查需要修复的记录...")
need_repair_count = check_repair_needed(conn)
print(f"✓ 发现 {need_repair_count} 条需要修复的手术申请单")
print()
if need_repair_count == 0:
print("没有需要修复的数据,退出")
return
# 步骤2获取修复列表
print("步骤2: 获取修复列表...")
repair_list = get_repair_list(conn)
print(f"✓ 获取到 {len(repair_list)} 条记录")
print()
# 步骤3修复ServiceRequest
print("步骤3: 生成手术医嘱ServiceRequest...")
new_requests = repair_service_request(conn, repair_list)
print(f"✓ 成功生成 {len(new_requests)} 条手术医嘱")
print()
# 步骤4修复ChargeItem
print("步骤4: 生成收费项目ChargeItem...")
repair_charge_items(conn, new_requests)
print(f"✓ 成功生成收费项目")
print()
# 步骤5验证修复结果
print("步骤5: 验证修复结果...")
service_count, charge_count = verify_repair(conn)
print(f"✓ 当前手术医嘱总数: {service_count}")
print(f"✓ 当前手术收费项目总数: {charge_count}")
print()
print("=" * 60)
print("✓ 修复完成!")
print("=" * 60)
except Exception as e:
print(f"✗ 错误: {e}")
import traceback
traceback.print_exc()
finally:
if "conn" in locals():
conn.close()
print("\n数据库连接已关闭")
if __name__ == "__main__":
main()

156
scripts/sync-ai-rules.sh Executable file
View File

@@ -0,0 +1,156 @@
#!/usr/bin/env bash
# ============================================================
# sync-ai-rules.sh — 将 RULES.md 完整内容同步到所有 AI 工具配置文件
#
# 用法: bash scripts/sync-ai-rules.sh
#
# 设计原则:
# RULES.md 是唯一信源,本脚本将其内容嵌入到各工具配置文件
# 开发者只需编辑 RULES.md然后运行本脚本即可同步所有工具
# ============================================================
set -euo pipefail
cd "$(dirname "$0")/.."
RULES_FILE="RULES.md"
if [ ! -f "$RULES_FILE" ]; then
echo "$RULES_FILE not found"
exit 1
fi
RULES_CONTENT=$(cat "$RULES_FILE")
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
echo "📝 Syncing RULES.md → AI tool configs..."
# ============================================================
# 1. AGENTS.md (Codex CLI / Claude Code)
# ============================================================
cat > AGENTS.md << HEREDOC
# HealthLink-HIS — AI 开发规范
> 🤖 本文件由 Codex CLI、Claude Code 等工具自动读取。
> 工具进入项目目录时会自动加载此文件作为开发规范上下文。
---
${RULES_CONTENT}
---
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
HEREDOC
echo " ✅ AGENTS.md"
# ============================================================
# 2. .cursorrules (Cursor IDE / Codeium Windsurf)
# ============================================================
cat > .cursorrules << HEREDOC
# HealthLink-HIS — AI 开发规范 (Cursor)
> 🤖 Cursor IDE 打开本项目时自动加载此文件。
---
${RULES_CONTENT}
---
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
HEREDOC
echo " ✅ .cursorrules"
# ============================================================
# 3. .github/copilot-instructions.md (GitHub Copilot)
# ============================================================
mkdir -p .github
cat > .github/copilot-instructions.md << HEREDOC
# HealthLink-HIS — AI 开发规范 (GitHub Copilot)
> 🤖 GitHub Copilot 打开本项目时自动加载此文件。
---
${RULES_CONTENT}
---
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
HEREDOC
echo " ✅ .github/copilot-instructions.md"
# ============================================================
# 4. .windsurfrules (Windsurf / Codeium)
# ============================================================
cat > .windsurfrules << HEREDOC
# HealthLink-HIS — AI 开发规范 (Windsurf)
> 🤖 Windsurf 打开本项目时自动加载此文件。
---
${RULES_CONTENT}
---
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
HEREDOC
echo " ✅ .windsurfrules"
# ============================================================
# 5. .clinerules (Cline)
# ============================================================
cat > .clinerules << HEREDOC
# HealthLink-HIS — AI 开发规范 (Cline)
> 🤖 Cline 打开本项目时自动加载此文件。
---
${RULES_CONTENT}
---
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
HEREDOC
echo " ✅ .clinerules"
# ============================================================
# 6. .qwenrules (Qwen Coder / 通义灵码)
# ============================================================
cat > .qwenrules << HEREDOC
# HealthLink-HIS — AI 开发规范 (Qwen Coder)
> 🤖 通义灵码 / Qwen Coder 打开本项目时自动加载此文件。
---
${RULES_CONTENT}
---
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
HEREDOC
echo " ✅ .qwenrules"
# ============================================================
# 7. .aider.conf.yml (Aider) — YAML格式嵌入指令
# ============================================================
# Aider 支持 instruction-files 指向文件,同时也支持直接在 .aider.conf.yml 中写 instructions
# 这里用 instructions 指令把内容内联
cat > .aider.conf.yml << HEREDOC
# Aider configuration for HealthLink-HIS
# Aider 自动读取此文件获取开发规范
instructions: |
$(echo "$RULES_CONTENT" | sed 's/^/ /')
HEREDOC
echo " ✅ .aider.conf.yml"
echo ""
echo "🎉 All 7 AI tool configs synced from RULES.md"
echo " 文件大小:"
for f in AGENTS.md .cursorrules .github/copilot-instructions.md .windsurfrules .clinerules .qwenrules .aider.conf.yml; do
size=$(wc -c < "$f" 2>/dev/null || echo "0")
echo " $f: ${size} bytes"
done