更新
This commit is contained in:
@@ -0,0 +1,348 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SRC = ROOT / "src"
|
||||
if str(SRC) not in sys.path:
|
||||
sys.path.insert(0, str(SRC))
|
||||
|
||||
from PySide6.QtCore import Qt # noqa: E402
|
||||
from PySide6.QtGui import QFont, QFontDatabase # noqa: E402
|
||||
from PySide6.QtWidgets import QApplication, QFrame, QLabel, QVBoxLayout # noqa: E402
|
||||
|
||||
from doctor_workstation.ui.diagnosis_drawer import DIAGNOSIS_QSS # noqa: E402
|
||||
from doctor_workstation.ui.diagnosis_media import ( # noqa: E402
|
||||
InlineRecordingPlayer,
|
||||
RecordingPlaybackCell,
|
||||
)
|
||||
from doctor_workstation.ui.dialogs.diagnosis import DiagnosisDialog # noqa: E402
|
||||
|
||||
|
||||
class RenderRepository:
|
||||
def get_prescription_order(self, order_id: int) -> dict[str, Any]:
|
||||
return {"id": order_id}
|
||||
|
||||
def set_revisit_slot_start_offset(self, diagnosis_id: int, offset: int) -> dict[str, Any]:
|
||||
return {"diagnosis_id": diagnosis_id, "revisit_slot_start_offset": offset}
|
||||
|
||||
def upload_call_recording(
|
||||
self,
|
||||
path: str,
|
||||
diagnosis_id: int,
|
||||
*,
|
||||
call_record_id: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"path": path,
|
||||
"diagnosis_id": diagnosis_id,
|
||||
"call_record_id": call_record_id,
|
||||
}
|
||||
|
||||
|
||||
def order_detail() -> dict[str, Any]:
|
||||
return {
|
||||
"id": 801,
|
||||
"order_no": "RX-20260811-0801",
|
||||
"gancao_reciperl_order_no": "GC-260811-4728",
|
||||
"diagnosis_id": 501,
|
||||
"amount": 428.5,
|
||||
"linked_pay_paid_total": 300,
|
||||
"refund_amount": 20,
|
||||
"agency_collect_amount": 128.5,
|
||||
"fulfillment_status": 5,
|
||||
"prescription_audit_status": 1,
|
||||
"payment_slip_audit_status": 1,
|
||||
"doctor_name": "陈医生",
|
||||
"creator_name": "赵医助",
|
||||
"creator_account": "assistant.zhao",
|
||||
"create_time": "2026-08-11 09:26",
|
||||
"recipient_name": "林晓岚",
|
||||
"recipient_phone": "18600004218",
|
||||
"shipping_province": "河南省",
|
||||
"shipping_city": "洛阳市",
|
||||
"shipping_district": "洛龙区",
|
||||
"shipping_address": "开元大道 88 号",
|
||||
"is_follow_up": 1,
|
||||
"medication_days": 14,
|
||||
"service_channel": "线上复诊",
|
||||
"service_package": ["调理服务", "复诊随访"],
|
||||
"fee_type": 3,
|
||||
"tracking_number": "SF164208110801",
|
||||
"express_company": "sf",
|
||||
"remark_assistant": "工作日下午送达",
|
||||
"prescription_audit_remark": "辨证与用量已复核",
|
||||
"payment_slip_audit_remark": "收款凭证已核验",
|
||||
"prescription": {
|
||||
"id": 601,
|
||||
"sn": "RX601",
|
||||
"patient_name": "林晓岚",
|
||||
"gender_desc": "女",
|
||||
"age": 34,
|
||||
"phone": "18600004218",
|
||||
"prescription_date": "2026-08-11",
|
||||
"doctor_name": "陈医生",
|
||||
"prescription_type": "饮片",
|
||||
"clinical_diagnosis": "气阴两虚",
|
||||
"dose_count": 14,
|
||||
"dose_unit": "剂",
|
||||
"usage_instruction": "水煎服",
|
||||
"amount": 428.5,
|
||||
"audit_status": 1,
|
||||
"dosage_amount": 180,
|
||||
"dosage_unit": "g",
|
||||
"need_decoction": 1,
|
||||
"times_per_day": 2,
|
||||
"usage_days": 14,
|
||||
"dietary_taboo": ["辛辣", "生冷"],
|
||||
"void_status": 0,
|
||||
},
|
||||
"linked_pay_orders": [
|
||||
{
|
||||
"id": 9101,
|
||||
"order_no": "PAY-9101",
|
||||
"order_type_desc": "药品费用",
|
||||
"amount": 300,
|
||||
"status_desc": "已支付",
|
||||
"creator_name": "赵医助",
|
||||
"create_time": "2026-08-11 09:32",
|
||||
}
|
||||
],
|
||||
"unlinked_pay_orders": [],
|
||||
"logistics_trace": {
|
||||
"state_text": "运输中",
|
||||
"carrier_label": "顺丰速运",
|
||||
"traces": [
|
||||
{
|
||||
"time": "2026-08-11 16:10",
|
||||
"status": "运输中",
|
||||
"context": "快件已离开洛阳集散中心",
|
||||
},
|
||||
{
|
||||
"time": "2026-08-11 13:06",
|
||||
"status": "已揽收",
|
||||
"context": "顺丰速运已收取快件",
|
||||
},
|
||||
],
|
||||
},
|
||||
"logs": [
|
||||
{
|
||||
"admin_name": "赵医助",
|
||||
"action": "ship",
|
||||
"summary": "确认发货并填写顺丰运单",
|
||||
"create_time": "2026-08-11 13:08",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def render_order(app: QApplication, output: Path) -> None:
|
||||
host = DiagnosisDialog(RenderRepository(), permissions=["*"])
|
||||
host.resize(1440, 900)
|
||||
host.show()
|
||||
drawer = host._build_order_detail_dialog(order_detail(), 801)
|
||||
drawer.show()
|
||||
app.processEvents()
|
||||
image = drawer.grab()
|
||||
if not image.save(str(output), "PNG"):
|
||||
raise RuntimeError(f"failed to save {output}")
|
||||
host.resize(1024, 640)
|
||||
drawer.sync_to_owner()
|
||||
app.processEvents()
|
||||
compact = output.parent / "diagnosis_state_order_detail_drawer_1024x640.png"
|
||||
if not drawer.grab().save(str(compact), "PNG"):
|
||||
raise RuntimeError(f"failed to save {compact}")
|
||||
legacy = output.parent / "diagnosis_state_order_detail_640x540.png"
|
||||
if not drawer.grab().save(str(legacy), "PNG"):
|
||||
raise RuntimeError(f"failed to save {legacy}")
|
||||
drawer.close()
|
||||
host.close()
|
||||
app.processEvents()
|
||||
|
||||
|
||||
def render_video(app: QApplication, output: Path) -> None:
|
||||
dialog = DiagnosisDialog(RenderRepository(), permissions=["*"])
|
||||
dialog._editable = True
|
||||
dialog._can_video_upload = True
|
||||
dialog._diagnosis_id = 501
|
||||
dialog._tab_generations["video"] = 3
|
||||
dialog._fill_video(
|
||||
[
|
||||
{
|
||||
"id": 48,
|
||||
"recording_urls_list": [
|
||||
"https://media.example.invalid/consultation-48.mp4",
|
||||
"https://bucket.cos.ap-shanghai.myqcloud.com/consultation-48/index.m3u8",
|
||||
"https://media.example.invalid/consultation-48.webm",
|
||||
],
|
||||
"start_time_text": "2026-08-11 10:02:18",
|
||||
"end_time_text": "2026-08-11 10:26:43",
|
||||
"call_type": 2,
|
||||
"room_id": "room-501-20260811",
|
||||
"duration_text": "24分25秒",
|
||||
"status": 2,
|
||||
"recording_status_text": "录制完成",
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"recording_urls_list": [],
|
||||
"start_time_text": "2026-08-04 09:18:05",
|
||||
"end_time_text": "2026-08-04 09:23:17",
|
||||
"call_type": 1,
|
||||
"room_id": "room-501-20260804",
|
||||
"duration_text": "5分12秒",
|
||||
"status": 3,
|
||||
"recording_status_text": "暂无录制",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
preview = QFrame()
|
||||
preview.setObjectName("DiagnosisVideoRender")
|
||||
preview.setStyleSheet(
|
||||
DIAGNOSIS_QSS
|
||||
+ "QFrame#DiagnosisVideoRender{background:#F6F8FB;}"
|
||||
+ "QLabel#DiagnosisVideoRenderTitle{color:#1F2937;font-size:20px;font-weight:650;}"
|
||||
)
|
||||
layout = QVBoxLayout(preview)
|
||||
layout.setContentsMargins(22, 18, 22, 22)
|
||||
layout.setSpacing(12)
|
||||
title = QLabel("视频录制回放")
|
||||
title.setObjectName("DiagnosisVideoRenderTitle")
|
||||
title.setFixedHeight(32)
|
||||
title.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
|
||||
layout.addWidget(title)
|
||||
page = dialog._tab_pages["video"]
|
||||
page.setParent(preview)
|
||||
page.show()
|
||||
dialog.video_upload_button.show()
|
||||
layout.addWidget(page, 1)
|
||||
preview.resize(1200, 560)
|
||||
preview.show()
|
||||
app.processEvents()
|
||||
table = dialog._table_registry["video"][1]
|
||||
playback = table.cellWidget(0, 0)
|
||||
if not isinstance(playback, RecordingPlaybackCell):
|
||||
raise RuntimeError("video render is missing the inline playback cell")
|
||||
player = playback.findChild(InlineRecordingPlayer)
|
||||
if (
|
||||
player is None
|
||||
or playback.height() < playback.minimumSizeHint().height()
|
||||
or not 158 <= player.height() <= 180
|
||||
or table.rowHeight(0) < playback.required_table_row_height()
|
||||
):
|
||||
raise RuntimeError("video render clipped the inline playback geometry")
|
||||
image = preview.grab()
|
||||
if not image.save(str(output), "PNG"):
|
||||
raise RuntimeError(f"failed to save {output}")
|
||||
preview.resize(1024, 640)
|
||||
app.processEvents()
|
||||
replay_state = output.parent / "diagnosis_state_video_replay_1024x640.png"
|
||||
if not preview.grab().save(str(replay_state), "PNG"):
|
||||
raise RuntimeError(f"failed to save {replay_state}")
|
||||
table.horizontalScrollBar().setValue(table.horizontalScrollBar().maximum())
|
||||
app.processEvents()
|
||||
upload_state = output.parent / "diagnosis_state_video_upload_action_1024x640.png"
|
||||
if not preview.grab().save(str(upload_state), "PNG"):
|
||||
raise RuntimeError(f"failed to save {upload_state}")
|
||||
preview.close()
|
||||
dialog.close()
|
||||
app.processEvents()
|
||||
|
||||
|
||||
def render_order_offset(app: QApplication, output: Path) -> None:
|
||||
dialog = DiagnosisDialog(RenderRepository(), permissions=["*"])
|
||||
dialog._editable = True
|
||||
dialog._can_offset = True
|
||||
dialog._can_order_detail = True
|
||||
dialog._diagnosis_id = 501
|
||||
dialog._saved_order_offset = 0
|
||||
dialog.order_offset.setVisible(True)
|
||||
dialog.order_offset_save.setVisible(True)
|
||||
dialog.order_offset.setValue(2)
|
||||
dialog._fill_orders(
|
||||
[
|
||||
{
|
||||
"id": 801,
|
||||
"order_no": "RX-20260811-0801",
|
||||
"global_visit_seq": 3,
|
||||
"counts_for_revisit_rate": 1,
|
||||
"amount": 428.5,
|
||||
"doctor_name": "陈医生",
|
||||
"assistant_name": "赵医助",
|
||||
"fulfillment_status": 5,
|
||||
"create_time": "2026-08-11 09:26",
|
||||
},
|
||||
{
|
||||
"id": 794,
|
||||
"order_no": "RX-20260724-0794",
|
||||
"global_visit_seq": 2,
|
||||
"counts_for_revisit_rate": 1,
|
||||
"amount": 386,
|
||||
"doctor_name": "陈医生",
|
||||
"assistant_name": "赵医助",
|
||||
"fulfillment_status": 6,
|
||||
"create_time": "2026-07-24 10:18",
|
||||
},
|
||||
]
|
||||
)
|
||||
dialog._orders_total = 2
|
||||
dialog._update_orders_pager()
|
||||
|
||||
preview = QFrame()
|
||||
preview.setObjectName("DiagnosisOrderRender")
|
||||
preview.setStyleSheet(
|
||||
DIAGNOSIS_QSS
|
||||
+ "QFrame#DiagnosisOrderRender{background:#F6F8FB;}"
|
||||
+ "QLabel#DiagnosisOrderRenderTitle{color:#1F2937;font-size:20px;font-weight:650;}"
|
||||
)
|
||||
layout = QVBoxLayout(preview)
|
||||
layout.setContentsMargins(22, 18, 22, 22)
|
||||
layout.setSpacing(12)
|
||||
title = QLabel("业务订单")
|
||||
title.setObjectName("DiagnosisOrderRenderTitle")
|
||||
title.setFixedHeight(32)
|
||||
layout.addWidget(title)
|
||||
page = dialog._tab_pages["orders"]
|
||||
page.setParent(preview)
|
||||
page.show()
|
||||
layout.addWidget(page, 1)
|
||||
preview.resize(1024, 640)
|
||||
preview.show()
|
||||
app.processEvents()
|
||||
if not preview.grab().save(str(output), "PNG"):
|
||||
raise RuntimeError(f"failed to save {output}")
|
||||
preview.close()
|
||||
dialog.close()
|
||||
app.processEvents()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
output_dir = ROOT / "artifacts" / "diagnosis_visual"
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
app = QApplication.instance() or QApplication([])
|
||||
font_path = Path("C:/Windows/Fonts/msyh.ttc")
|
||||
if font_path.is_file():
|
||||
font_id = QFontDatabase.addApplicationFont(str(font_path))
|
||||
families = QFontDatabase.applicationFontFamilies(font_id)
|
||||
if families:
|
||||
app.setFont(QFont(families[0], 9))
|
||||
order_output = output_dir / "diagnosis_order_detail_drawer_1440x900.png"
|
||||
video_output = output_dir / "diagnosis_video_inline_player_1200x560.png"
|
||||
offset_output = output_dir / "diagnosis_state_order_offset_1024x640.png"
|
||||
render_order(app, order_output)
|
||||
render_video(app, video_output)
|
||||
render_order_offset(app, offset_output)
|
||||
print(order_output)
|
||||
print(video_output)
|
||||
print(offset_output)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user