"""Render the real native client with synthetic data for UI design review.""" from __future__ import annotations import argparse import html import json import os from pathlib import Path os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") os.environ.setdefault("DOCTOR_MOTION", "off") from PySide6.QtCore import QSettings, QThreadPool from PySide6.QtGui import QImage from PySide6.QtTest import QTest from PySide6.QtWidgets import QApplication from doctor_workstation.services import DemoDoctorRepository from doctor_workstation.ui import ShellWindow, apply_theme from doctor_workstation.ui.login import LoginWindow ROUTES = { "appointments": "挂号列表", "consultations": "问诊列表", "patients": "我的患者", "prescription_library": "我的处方库", "prescriptions": "已开处方", "reception": "接诊台", } def settle(app: QApplication) -> None: for _ in range(4): QThreadPool.globalInstance().waitForDone(3000) app.processEvents() QTest.qWait(75) def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--output", type=Path, default=Path("artifacts/client-design")) args = parser.parse_args() output = args.output.resolve() output.mkdir(parents=True, exist_ok=True) app = QApplication.instance() or QApplication([]) apply_theme(app) repo = DemoDoctorRepository() records = [] def capture(window, name: str, title: str) -> None: settle(app) filename = f"{name}.png" if not window.grab().save(str(output / filename)): raise RuntimeError(f"Could not save {filename}") records.append({ "title": title, "file": filename, "width": window.width(), "height": window.height(), }) # Isolate preview settings from the user's saved account and credentials. settings = QSettings(str(output / "preview-login.ini"), QSettings.Format.IniFormat) settings.clear() login = LoginWindow(repo, settings=settings) login.show() for width, height in ((1280, 800), (860, 640)): login.resize(width, height) capture(login, f"login-{width}", "登录工作站") login.close() session = repo.login(repo.DEMO_ACCOUNT, repo.DEMO_PASSWORD) shell = ShellWindow( repo, {"session": session, "demo_mode": True}, permissions=session.permissions, ) shell.show() try: for width, height in ((1440, 900), (1024, 640)): shell.resize(width, height) for route, title in ROUTES.items(): shell.navigate(route) capture(shell, f"{route}-{width}", title) finally: settle(app) shell.close() # Include independently rendered dialog/media fixtures when available. supplementary = [ ("patient_orders_1366x768.png", "患者业务订单"), ("patient_progress_1366x768.png", "患者进度"), ("clinical-after/appointment_drawer_1440x900.png", "预约编辑"), ("clinical-after/diagnosis_edit_1440x900.png", "诊单编辑"), ("clinical-after/diagnosis_edit_1024x640.png", "诊单编辑 · 紧凑窗口"), ("clinical-after/diagnosis_index_1440x900.png", "诊单列表"), ("assistant-1440.png", "AI 问诊"), ("assistant-1080.png", "AI 问诊 · 紧凑窗口"), ("../subwindow_exact/prescription_editor_860x900.png", "处方编辑"), ("../subwindow_exact/prescription_ai_report_920x760.png", "处方报告"), ("video-call-1120x760.png", "视频面诊"), ("video-call-440x300.png", "视频面诊 · 小窗"), ("video-chat-440x300.png", "视频聊天 · 小窗"), ("video-preview-1120x760.png", "视频截图确认"), ] for filename, title in supplementary: preview = QImage(str(output / filename)) if not preview.isNull(): records.append({ "title": title, "file": filename, "width": preview.width(), "height": preview.height(), }) (output / "gallery.json").write_text( json.dumps(records, ensure_ascii=False, indent=2), encoding="utf-8", ) cards = [] for record in records: filename = html.escape(record["file"]) title = html.escape(record["title"]) cards.append( f'

{title} {record["width"]} × {record["height"]}' f'

{title}' '
' ) (output / "index.html").write_text( '' '' '医生工作站 · 客户端设计验收

医生工作站 · 客户端设计验收

' '

使用演示数据渲染的真实客户端。点击图片查看原始尺寸。

' + "".join(cards) + '
', encoding="utf-8", ) print(output / "index.html") if __name__ == "__main__": main()