@tencent-rtc/trtc-agent-skills 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/README.zh.md +173 -0
  4. package/bin/cli.js +434 -0
  5. package/knowledge-base/index.yaml +454 -0
  6. package/knowledge-base/platform-slice-template.md +233 -0
  7. package/knowledge-base/scenario-spec.md +350 -0
  8. package/knowledge-base/scenarios/conference/base/general-conference.md +365 -0
  9. package/knowledge-base/scenarios/conference/base/webinar-conference.md +130 -0
  10. package/knowledge-base/scenarios/conference/medical/1v1-video-consultation.md +145 -0
  11. package/knowledge-base/scenarios/conference/medical/medical-multidoctor-consultation.md +113 -0
  12. package/knowledge-base/scenarios/live/entertainment-live-room.md +118 -0
  13. package/knowledge-base/slice-spec.md +546 -0
  14. package/knowledge-base/slices/conference/web/ai-tools.md +225 -0
  15. package/knowledge-base/slices/conference/web/beauty-effects.md +188 -0
  16. package/knowledge-base/slices/conference/web/device-control.md +338 -0
  17. package/knowledge-base/slices/conference/web/login-auth.md +261 -0
  18. package/knowledge-base/slices/conference/web/network-quality.md +190 -0
  19. package/knowledge-base/slices/conference/web/official-roomkit-api.md +298 -0
  20. package/knowledge-base/slices/conference/web/official-roomkit-login-ui.md +246 -0
  21. package/knowledge-base/slices/conference/web/participant-list.md +238 -0
  22. package/knowledge-base/slices/conference/web/participant-management.md +718 -0
  23. package/knowledge-base/slices/conference/web/prejoin-check.md +293 -0
  24. package/knowledge-base/slices/conference/web/room-call.md +213 -0
  25. package/knowledge-base/slices/conference/web/room-chat.md +426 -0
  26. package/knowledge-base/slices/conference/web/room-lifecycle.md +534 -0
  27. package/knowledge-base/slices/conference/web/room-schedule.md +281 -0
  28. package/knowledge-base/slices/conference/web/screen-share.md +211 -0
  29. package/knowledge-base/slices/conference/web/video-layout.md +675 -0
  30. package/knowledge-base/slices/conference/web/virtual-background.md +197 -0
  31. package/knowledge-base/slices/conference/web/webinar-interaction.md +206 -0
  32. package/knowledge-base/slices/live/anchor-lifecycle.md +122 -0
  33. package/knowledge-base/slices/live/anchor-preview.md +90 -0
  34. package/knowledge-base/slices/live/anchor-room-config.md +104 -0
  35. package/knowledge-base/slices/live/audience-list.md +86 -0
  36. package/knowledge-base/slices/live/audience-manage.md +92 -0
  37. package/knowledge-base/slices/live/audience-watch.md +85 -0
  38. package/knowledge-base/slices/live/audio.md +116 -0
  39. package/knowledge-base/slices/live/barrage.md +88 -0
  40. package/knowledge-base/slices/live/beauty.md +99 -0
  41. package/knowledge-base/slices/live/coguest-apply.md +105 -0
  42. package/knowledge-base/slices/live/device-control.md +91 -0
  43. package/knowledge-base/slices/live/error-codes.md +167 -0
  44. package/knowledge-base/slices/live/gift.md +84 -0
  45. package/knowledge-base/slices/live/ios/.gitkeep +0 -0
  46. package/knowledge-base/slices/live/ios/anchor-lifecycle.md +313 -0
  47. package/knowledge-base/slices/live/ios/anchor-preview.md +228 -0
  48. package/knowledge-base/slices/live/ios/anchor-room-config.md +257 -0
  49. package/knowledge-base/slices/live/ios/audience-list.md +353 -0
  50. package/knowledge-base/slices/live/ios/audience-manage.md +381 -0
  51. package/knowledge-base/slices/live/ios/audience-watch.md +286 -0
  52. package/knowledge-base/slices/live/ios/audio.md +373 -0
  53. package/knowledge-base/slices/live/ios/barrage.md +285 -0
  54. package/knowledge-base/slices/live/ios/beauty.md +323 -0
  55. package/knowledge-base/slices/live/ios/coguest-apply.md +506 -0
  56. package/knowledge-base/slices/live/ios/device-control.md +286 -0
  57. package/knowledge-base/slices/live/ios/error-codes.md +270 -0
  58. package/knowledge-base/slices/live/ios/gift.md +315 -0
  59. package/knowledge-base/slices/live/ios/live-list.md +269 -0
  60. package/knowledge-base/slices/live/ios/login-auth.md +247 -0
  61. package/knowledge-base/slices/live/live-list.md +82 -0
  62. package/knowledge-base/slices/live/login-auth.md +78 -0
  63. package/package.json +34 -0
  64. package/skills/trtc/SKILL.md +326 -0
  65. package/skills/trtc/room-builder/SKILL.md +138 -0
  66. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/README.md +108 -0
  67. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/backend-contract.zh-CN.md +162 -0
  68. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/integration.zh-CN.md +154 -0
  69. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/theme.zh-CN.md +78 -0
  70. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/index.html +12 -0
  71. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/package.json +28 -0
  72. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/postcss.config.js +5 -0
  73. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/App.vue +25 -0
  74. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/ConsultationManagePanel.vue +838 -0
  75. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LanguageSwitch.vue +102 -0
  76. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LoadingSpinner.vue +6 -0
  77. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalAlert.vue +34 -0
  78. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalBusinessPanel.vue +148 -0
  79. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalButton.vue +49 -0
  80. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalConfirmDialog.vue +68 -0
  81. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalDataPanel.vue +196 -0
  82. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalRecordPanel.vue +270 -0
  83. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/PrescriptionPanel.vue +363 -0
  84. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/basic-info-config.ts +29 -0
  85. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.d.ts +4 -0
  86. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.js +2 -0
  87. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/runtime-config.ts +12 -0
  88. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/env.d.ts +32 -0
  89. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationChatPanel.vue +123 -0
  90. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationMembersPanel.vue +230 -0
  91. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationTranscriptionPanel.vue +135 -0
  92. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationVideoStage.vue +113 -0
  93. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/InviteDoctorDialog.vue +132 -0
  94. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/KickMemberConfirmDialog.vue +50 -0
  95. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/types.ts +77 -0
  96. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationChat.ts +97 -0
  97. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationDevices.ts +48 -0
  98. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationParticipants.ts +121 -0
  99. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationPermissions.ts +25 -0
  100. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/utils.ts +70 -0
  101. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/en-US/index.ts +553 -0
  102. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/index.ts +25 -0
  103. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/medicalTranslate.ts +85 -0
  104. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/state.ts +49 -0
  105. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/zh-CN/index.ts +463 -0
  106. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/main.ts +12 -0
  107. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/appointments.ts +96 -0
  108. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/users.ts +79 -0
  109. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/router/index.ts +63 -0
  110. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/index.ts +25 -0
  111. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/appointmentService.ts +77 -0
  112. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/authService.ts +38 -0
  113. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/launchContext.ts +31 -0
  114. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/userService.ts +35 -0
  115. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/appointmentService.ts +43 -0
  116. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/authService.ts +33 -0
  117. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/userService.ts +43 -0
  118. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/types.ts +135 -0
  119. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/shared/icons.ts +53 -0
  120. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/index.css +106 -0
  121. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/tailwind.css +3 -0
  122. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/theme.css +209 -0
  123. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/auth.ts +50 -0
  124. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/format.ts +24 -0
  125. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/navigation.ts +12 -0
  126. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/session.ts +28 -0
  127. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorConsultationView.vue +777 -0
  128. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorDashboardView.vue +678 -0
  129. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/LoginView.vue +441 -0
  130. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationFinishedView.vue +185 -0
  131. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationView.vue +1003 -0
  132. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientSelectDoctorView.vue +317 -0
  133. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientWaitingView.vue +454 -0
  134. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.json +21 -0
  135. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.node.json +8 -0
  136. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/vite.config.ts +17 -0
  137. package/skills/trtc/room-builder/templates/scenarios/medical-consultation//346/216/245/345/205/245/350/257/264/346/230/216.md +6 -0
  138. package/skills/trtc/room-builder/tools/render_ai_instructions.py +226 -0
  139. package/skills/trtc-apply/SKILL.md +97 -0
  140. package/skills/trtc-apply/guardrails/apply_lib/__init__.py +0 -0
  141. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/__init__.cpython-313.pyc +0 -0
  142. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/rule_parser.cpython-313.pyc +0 -0
  143. package/skills/trtc-apply/guardrails/apply_lib/rule_parser.py +268 -0
  144. package/skills/trtc-docs/SKILL.md +207 -0
  145. package/skills/trtc-onboarding/SKILL.md +839 -0
  146. package/skills/trtc-onboarding/reference/path-a1-demo.md +103 -0
  147. package/skills/trtc-onboarding/reference/path-a2-integrate.md +693 -0
  148. package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +115 -0
  149. package/skills/trtc-onboarding/reference/path-c-expand.md +43 -0
  150. package/skills/trtc-onboarding/reference/reporting-protocol.md +174 -0
  151. package/skills/trtc-onboarding/reference/supported-matrix.md +100 -0
  152. package/skills/trtc-onboarding/reference/usersig-handling.md +140 -0
  153. package/skills/trtc-search/SKILL.md +221 -0
  154. package/skills/trtc-topic/SKILL.md +638 -0
  155. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_read.cpython-313.pyc +0 -0
  156. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_write.cpython-313.pyc +0 -0
  157. package/skills/trtc-topic/guardrails/__pycache__/stop_require_apply_evidence.cpython-313.pyc +0 -0
  158. package/skills/trtc-topic/guardrails/gate_slice_read.py +133 -0
  159. package/skills/trtc-topic/guardrails/gate_slice_write.py +169 -0
  160. package/skills/trtc-topic/guardrails/stop_require_apply_evidence.py +97 -0
  161. package/skills/trtc-topic/references/execution-units.yaml +58 -0
  162. package/skills/trtc-topic/runtime/README.md +50 -0
  163. package/skills/trtc-topic/runtime/RUNTIME.md +128 -0
  164. package/skills/trtc-topic/runtime/lib/__init__.py +0 -0
  165. package/skills/trtc-topic/runtime/lib/platforms.py +194 -0
  166. package/skills/trtc-topic/runtime/package-lock.json +1211 -0
  167. package/skills/trtc-topic/runtime/package.json +13 -0
  168. package/skills/trtc-topic/runtime/telemetry-bridge.mjs +339 -0
  169. package/skills/trtc-topic/runtime/telemetry_collector.py +293 -0
  170. package/skills/trtc-topic/scripts/STATE-MACHINE-GUIDE.md +186 -0
  171. package/skills/trtc-topic/scripts/__pycache__/apply.cpython-313.pyc +0 -0
  172. package/skills/trtc-topic/scripts/apply.py +581 -0
  173. package/skills/trtc-topic/scripts/finalize_session.py +113 -0
  174. package/skills/trtc-topic/scripts/init_slice_queue.py +96 -0
  175. package/skills/trtc-topic/scripts/lib/__pycache__/state_machine.cpython-313.pyc +0 -0
  176. package/skills/trtc-topic/scripts/lib/state_machine.py +328 -0
  177. package/skills/trtc-topic/scripts/next_slice.py +137 -0
  178. package/skills/trtc-topic/tests/README.md +70 -0
  179. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
  180. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  181. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.2.pyc +0 -0
  182. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  183. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.2.pyc +0 -0
  184. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.3.pyc +0 -0
  185. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.2.pyc +0 -0
  186. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.3.pyc +0 -0
  187. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.2.pyc +0 -0
  188. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.3.pyc +0 -0
  189. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.2.pyc +0 -0
  190. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.3.pyc +0 -0
  191. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.2.pyc +0 -0
  192. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.3.pyc +0 -0
  193. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.2.pyc +0 -0
  194. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.3.pyc +0 -0
  195. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.2.pyc +0 -0
  196. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.3.pyc +0 -0
  197. package/skills/trtc-topic/tests/conftest.py +72 -0
  198. package/skills/trtc-topic/tests/test_apply_cli.py +480 -0
  199. package/skills/trtc-topic/tests/test_end_to_end.py +305 -0
  200. package/skills/trtc-topic/tests/test_finalize_session.py +51 -0
  201. package/skills/trtc-topic/tests/test_gates.py +316 -0
  202. package/skills/trtc-topic/tests/test_session_resolver.py +260 -0
  203. package/skills/trtc-topic/tests/test_state_machine.py +414 -0
  204. package/skills/trtc-topic/tests/test_stop_require_apply.py +99 -0
  205. package/skills/trtc-topic/tests/test_topic_skill_invariants.py +130 -0
@@ -0,0 +1,135 @@
1
+ export type UserRole = 'doctor' | 'patient';
2
+ export type DoctorStatus = 'online' | 'busy';
3
+ export type LaunchMode = 'mock' | 'integration';
4
+ export type BusinessPanelMode = 'demo' | 'slot';
5
+
6
+ export interface MedicalUser {
7
+ userId: string;
8
+ userName: string;
9
+ avatarUrl: string;
10
+ role: UserRole;
11
+ title?: string;
12
+ department?: string;
13
+ hospital?: string;
14
+ experience?: string;
15
+ rating?: string;
16
+ consultations?: string;
17
+ price?: string;
18
+ tags?: string[];
19
+ specialty?: string;
20
+ status?: DoctorStatus;
21
+ }
22
+
23
+ export interface MedicalAppointment {
24
+ id: string;
25
+ roomId: string;
26
+ doctorId: string;
27
+ patientId: string;
28
+ scheduleStartTime: number;
29
+ scheduleEndTime: number;
30
+ chiefComplaint: string;
31
+ allergyHistory: string;
32
+ medicalHistory: string;
33
+ patientAge: number;
34
+ patientGender: string;
35
+ patientPhone: string;
36
+ }
37
+
38
+ export interface BackendMedicalUserDTO {
39
+ userId: string;
40
+ userName: string;
41
+ avatarUrl?: string;
42
+ role: UserRole;
43
+ title?: string;
44
+ department?: string;
45
+ hospital?: string;
46
+ }
47
+
48
+ export interface BackendMedicalAppointmentDTO {
49
+ appointmentId: string;
50
+ roomId?: string;
51
+ doctorId: string;
52
+ patientId: string;
53
+ scheduleStartTime: number;
54
+ scheduleEndTime: number;
55
+ chiefComplaint?: string;
56
+ allergyHistory?: string;
57
+ medicalHistory?: string;
58
+ patientAge?: number;
59
+ patientGender?: string;
60
+ patientPhone?: string;
61
+ }
62
+
63
+ export interface BackendLaunchContextDTO {
64
+ role: UserRole;
65
+ userId: string;
66
+ appointmentId?: string;
67
+ token?: string;
68
+ doctorId?: string;
69
+ patientId?: string;
70
+ userName?: string;
71
+ avatarUrl?: string;
72
+ }
73
+
74
+ export interface MedicalBackendAdapter {
75
+ getLaunchContext(): Promise<BackendLaunchContextDTO | null>;
76
+ getCurrentUser(context: BackendLaunchContextDTO): Promise<BackendMedicalUserDTO>;
77
+ getAppointment(
78
+ context: BackendLaunchContextDTO
79
+ ): Promise<BackendMedicalAppointmentDTO | null>;
80
+ listDoctors(context: BackendLaunchContextDTO): Promise<BackendMedicalUserDTO[]>;
81
+ }
82
+
83
+ export interface SessionData {
84
+ role: UserRole;
85
+ userId: string;
86
+ appointmentId?: string;
87
+ token?: string;
88
+ launchMode?: LaunchMode;
89
+ user?: MedicalUser;
90
+ }
91
+
92
+ export interface LaunchContext {
93
+ role: UserRole;
94
+ userId: string;
95
+ appointmentId?: string;
96
+ token?: string;
97
+ doctorId?: string;
98
+ patientId?: string;
99
+ userName?: string;
100
+ avatarUrl?: string;
101
+ }
102
+
103
+ /**
104
+ * View-facing service contract used by the demo pages.
105
+ *
106
+ * Customer integration should map backend DTOs into these view models inside
107
+ * `services/adapters/integration/*`, keeping API/auth/field differences away
108
+ * from Vue pages.
109
+ */
110
+ export interface AuthService {
111
+ getLaunchContext(): LaunchContext | null;
112
+ login(context: LaunchContext): Promise<SessionData>;
113
+ logout(): Promise<void>;
114
+ }
115
+
116
+ export interface UserService {
117
+ listDoctors(): MedicalUser[];
118
+ listPatients(): MedicalUser[];
119
+ getUserById(userId: string): MedicalUser | null;
120
+ getDoctorById(userId: string): MedicalUser | null;
121
+ getPatientById(userId: string): MedicalUser | null;
122
+ }
123
+
124
+ export interface AppointmentService {
125
+ getAppointmentById(appointmentId: string): MedicalAppointment | null;
126
+ getAppointmentByRoomId(roomId: string): MedicalAppointment | null;
127
+ getAppointmentsByDoctor(doctorId: string): MedicalAppointment[];
128
+ getAppointmentsByPatient(patientId: string): MedicalAppointment[];
129
+ }
130
+
131
+ export interface MedicalServiceAdapter {
132
+ auth: AuthService;
133
+ user: UserService;
134
+ appointment: AppointmentService;
135
+ }
@@ -0,0 +1,53 @@
1
+ export {
2
+ Activity,
3
+ AlertCircle,
4
+ Award,
5
+ Bell,
6
+ Camera,
7
+ CameraOff,
8
+ CheckCircle,
9
+ CheckCircle2,
10
+ ChevronDown,
11
+ ChevronLeft,
12
+ Clock,
13
+ Copy,
14
+ Download,
15
+ Eye,
16
+ FileText,
17
+ FolderOpen,
18
+ House,
19
+ ImageIcon,
20
+ LayoutPanelLeft,
21
+ Lock,
22
+ LogOut,
23
+ MessageCircle,
24
+ MessageSquare,
25
+ Mic,
26
+ MicOff,
27
+ MoreVertical,
28
+ PenLine,
29
+ Phone,
30
+ PhoneOff,
31
+ Pill,
32
+ Plus,
33
+ Save,
34
+ Search,
35
+ Send,
36
+ Settings,
37
+ Shield,
38
+ ShieldAlert,
39
+ Star,
40
+ Stethoscope,
41
+ ThumbsUp,
42
+ TrendingUp,
43
+ Trash2,
44
+ Upload,
45
+ User,
46
+ UserPlus,
47
+ Users,
48
+ UserX,
49
+ Video,
50
+ Volume2,
51
+ VolumeX,
52
+ X,
53
+ } from 'lucide-vue-next';
@@ -0,0 +1,106 @@
1
+ @import './tailwind.css';
2
+
3
+ .medical-language-selector {
4
+ position: relative;
5
+ z-index: 30;
6
+ display: inline-flex;
7
+ flex-shrink: 0;
8
+ }
9
+
10
+ .medical-language-trigger {
11
+ display: inline-flex;
12
+ align-items: center;
13
+ justify-content: center;
14
+ gap: 7px;
15
+ height: 34px;
16
+ min-width: 94px;
17
+ padding: 0 10px;
18
+ border: 1px solid rgba(15, 23, 42, 0.12);
19
+ border-radius: 999px;
20
+ color: #334155;
21
+ background: rgba(255, 255, 255, 0.82);
22
+ box-shadow: 0 8px 20px rgba(15, 23, 42, 0.08);
23
+ font-size: 12px;
24
+ font-weight: 600;
25
+ line-height: 1;
26
+ backdrop-filter: blur(10px);
27
+ transition:
28
+ background-color 0.2s ease,
29
+ border-color 0.2s ease,
30
+ box-shadow 0.2s ease;
31
+ }
32
+
33
+ .medical-language-trigger:hover {
34
+ border-color: rgba(15, 23, 42, 0.18);
35
+ background: rgba(255, 255, 255, 0.96);
36
+ box-shadow: 0 10px 24px rgba(15, 23, 42, 0.12);
37
+ }
38
+
39
+ .medical-language-trigger:focus-visible,
40
+ .medical-language-option:focus-visible {
41
+ outline: 2px solid rgba(13, 148, 136, 0.36);
42
+ outline-offset: 2px;
43
+ }
44
+
45
+ .medical-language-current {
46
+ min-width: 42px;
47
+ text-align: left;
48
+ }
49
+
50
+ .medical-language-chevron {
51
+ color: #64748b;
52
+ transition: transform 0.2s ease;
53
+ }
54
+
55
+ .medical-language-chevron-open {
56
+ transform: rotate(180deg);
57
+ }
58
+
59
+ .medical-language-menu {
60
+ position: absolute;
61
+ top: calc(100% + 8px);
62
+ right: 0;
63
+ z-index: 50;
64
+ width: 148px;
65
+ padding: 6px;
66
+ border: 1px solid rgba(15, 23, 42, 0.1);
67
+ border-radius: 14px;
68
+ background: rgba(255, 255, 255, 0.98);
69
+ box-shadow: 0 18px 40px rgba(15, 23, 42, 0.16);
70
+ }
71
+
72
+ .medical-language-option {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 8px;
76
+ width: 100%;
77
+ height: 36px;
78
+ padding: 0 8px;
79
+ border-radius: 10px;
80
+ color: #334155;
81
+ font-size: 13px;
82
+ font-weight: 600;
83
+ text-align: left;
84
+ transition: background-color 0.2s ease, color 0.2s ease;
85
+ }
86
+
87
+ .medical-language-option:hover {
88
+ background: #f1f5f9;
89
+ }
90
+
91
+ .medical-language-option-badge {
92
+ display: inline-flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ width: 24px;
96
+ height: 22px;
97
+ border-radius: 7px;
98
+ background: #e2e8f0;
99
+ color: #475569;
100
+ font-size: 11px;
101
+ }
102
+
103
+ .medical-language-check {
104
+ margin-left: auto;
105
+ color: #0d9488;
106
+ }
@@ -0,0 +1,3 @@
1
+ @import 'tailwindcss';
2
+ @import 'tw-animate-css';
3
+ @import './theme.css';
@@ -0,0 +1,209 @@
1
+ @custom-variant dark (&:is(.dark *));
2
+
3
+ :root {
4
+ --font-size: 16px;
5
+ --background: #f8fafb;
6
+ --foreground: #1f2937;
7
+ --card: #ffffff;
8
+ --card-foreground: #1f2937;
9
+ --popover: #ffffff;
10
+ --popover-foreground: #1f2937;
11
+ --primary: #0d9488;
12
+ --primary-foreground: #ffffff;
13
+ --primary-hover: #0f766e;
14
+ --secondary: #475569;
15
+ --secondary-foreground: #ffffff;
16
+ --muted: #e2e8f0;
17
+ --muted-foreground: #64748b;
18
+ --accent: #f1f5f9;
19
+ --accent-foreground: #334155;
20
+ --destructive: #ef4444;
21
+ --destructive-foreground: #ffffff;
22
+ --medical-success: #10b981;
23
+ --medical-warning: #f59e0b;
24
+ --medical-info: #3b82f6;
25
+ --medical-urgent: #dc2626;
26
+ --border: #e2e8f0;
27
+ --input: transparent;
28
+ --input-background: #f8fafc;
29
+ --switch-background: #cbd5e1;
30
+ --font-weight-medium: 500;
31
+ --font-weight-normal: 400;
32
+ --ring: #0d9488;
33
+ --chart-1: #0d9488;
34
+ --chart-2: #3b82f6;
35
+ --chart-3: #8b5cf6;
36
+ --chart-4: #f59e0b;
37
+ --chart-5: #ef4444;
38
+ --radius: 1rem;
39
+ --sidebar: #ffffff;
40
+ --sidebar-foreground: #1f2937;
41
+ --sidebar-primary: #0d9488;
42
+ --sidebar-primary-foreground: #ffffff;
43
+ --sidebar-accent: #f1f5f9;
44
+ --sidebar-accent-foreground: #1f2937;
45
+ --sidebar-border: #e2e8f0;
46
+ --sidebar-ring: #0d9488;
47
+ }
48
+
49
+ .dark {
50
+ --background: oklch(0.145 0 0);
51
+ --foreground: oklch(0.985 0 0);
52
+ --card: oklch(0.145 0 0);
53
+ --card-foreground: oklch(0.985 0 0);
54
+ --popover: oklch(0.145 0 0);
55
+ --popover-foreground: oklch(0.985 0 0);
56
+ --primary: oklch(0.985 0 0);
57
+ --primary-foreground: oklch(0.205 0 0);
58
+ --secondary: oklch(0.269 0 0);
59
+ --secondary-foreground: oklch(0.985 0 0);
60
+ --muted: oklch(0.269 0 0);
61
+ --muted-foreground: oklch(0.708 0 0);
62
+ --accent: oklch(0.269 0 0);
63
+ --accent-foreground: oklch(0.985 0 0);
64
+ --destructive: oklch(0.396 0.141 25.723);
65
+ --destructive-foreground: oklch(0.637 0.237 25.331);
66
+ --border: oklch(0.269 0 0);
67
+ --input: oklch(0.269 0 0);
68
+ --ring: oklch(0.439 0 0);
69
+ --font-weight-medium: 500;
70
+ --font-weight-normal: 400;
71
+ --chart-1: oklch(0.488 0.243 264.376);
72
+ --chart-2: oklch(0.696 0.17 162.48);
73
+ --chart-3: oklch(0.769 0.188 70.08);
74
+ --chart-4: oklch(0.627 0.265 303.9);
75
+ --chart-5: oklch(0.645 0.246 16.439);
76
+ --sidebar: oklch(0.205 0 0);
77
+ --sidebar-foreground: oklch(0.985 0 0);
78
+ --sidebar-primary: oklch(0.488 0.243 264.376);
79
+ --sidebar-primary-foreground: oklch(0.985 0 0);
80
+ --sidebar-accent: oklch(0.269 0 0);
81
+ --sidebar-accent-foreground: oklch(0.985 0 0);
82
+ --sidebar-border: oklch(0.269 0 0);
83
+ --sidebar-ring: oklch(0.439 0 0);
84
+ }
85
+
86
+ @theme inline {
87
+ --color-background: var(--background);
88
+ --color-foreground: var(--foreground);
89
+ --color-card: var(--card);
90
+ --color-card-foreground: var(--card-foreground);
91
+ --color-popover: var(--popover);
92
+ --color-popover-foreground: var(--popover-foreground);
93
+ --color-primary: var(--primary);
94
+ --color-primary-foreground: var(--primary-foreground);
95
+ --color-secondary: var(--secondary);
96
+ --color-secondary-foreground: var(--secondary-foreground);
97
+ --color-muted: var(--muted);
98
+ --color-muted-foreground: var(--muted-foreground);
99
+ --color-accent: var(--accent);
100
+ --color-accent-foreground: var(--accent-foreground);
101
+ --color-destructive: var(--destructive);
102
+ --color-destructive-foreground: var(--destructive-foreground);
103
+ --color-border: var(--border);
104
+ --color-input: var(--input);
105
+ --color-input-background: var(--input-background);
106
+ --color-switch-background: var(--switch-background);
107
+ --color-ring: var(--ring);
108
+ --color-chart-1: var(--chart-1);
109
+ --color-chart-2: var(--chart-2);
110
+ --color-chart-3: var(--chart-3);
111
+ --color-chart-4: var(--chart-4);
112
+ --color-chart-5: var(--chart-5);
113
+ --color-medical-success: var(--medical-success);
114
+ --color-medical-warning: var(--medical-warning);
115
+ --color-medical-info: var(--medical-info);
116
+ --color-medical-urgent: var(--medical-urgent);
117
+ --color-primary-hover: var(--primary-hover);
118
+ --radius-sm: calc(var(--radius) - 4px);
119
+ --radius-md: calc(var(--radius) - 2px);
120
+ --radius-lg: var(--radius);
121
+ --radius-xl: calc(var(--radius) + 4px);
122
+ --color-sidebar: var(--sidebar);
123
+ --color-sidebar-foreground: var(--sidebar-foreground);
124
+ --color-sidebar-primary: var(--sidebar-primary);
125
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
126
+ --color-sidebar-accent: var(--sidebar-accent);
127
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
128
+ --color-sidebar-border: var(--sidebar-border);
129
+ --color-sidebar-ring: var(--sidebar-ring);
130
+ }
131
+
132
+ @layer base {
133
+ * {
134
+ @apply border-border outline-ring/50;
135
+ }
136
+
137
+ body {
138
+ @apply bg-background text-foreground;
139
+ }
140
+
141
+ html {
142
+ font-size: var(--font-size);
143
+ }
144
+
145
+ h1 {
146
+ font-size: var(--text-2xl);
147
+ font-weight: var(--font-weight-medium);
148
+ line-height: 1.5;
149
+ }
150
+
151
+ h2 {
152
+ font-size: var(--text-xl);
153
+ font-weight: var(--font-weight-medium);
154
+ line-height: 1.5;
155
+ }
156
+
157
+ h3 {
158
+ font-size: var(--text-lg);
159
+ font-weight: var(--font-weight-medium);
160
+ line-height: 1.5;
161
+ }
162
+
163
+ h4 {
164
+ font-size: var(--text-base);
165
+ font-weight: var(--font-weight-medium);
166
+ line-height: 1.5;
167
+ }
168
+
169
+ label {
170
+ font-size: var(--text-base);
171
+ font-weight: var(--font-weight-medium);
172
+ line-height: 1.5;
173
+ }
174
+
175
+ button {
176
+ font-size: var(--text-base);
177
+ font-weight: var(--font-weight-medium);
178
+ line-height: 1.5;
179
+ }
180
+
181
+ input {
182
+ font-size: var(--text-base);
183
+ font-weight: var(--font-weight-normal);
184
+ line-height: 1.5;
185
+ }
186
+
187
+ .custom-scrollbar {
188
+ scrollbar-width: thin;
189
+ scrollbar-color: #cbd5e1 transparent;
190
+ }
191
+
192
+ .custom-scrollbar::-webkit-scrollbar {
193
+ width: 6px;
194
+ height: 6px;
195
+ }
196
+
197
+ .custom-scrollbar::-webkit-scrollbar-track {
198
+ background: transparent;
199
+ }
200
+
201
+ .custom-scrollbar::-webkit-scrollbar-thumb {
202
+ background-color: #cbd5e1;
203
+ border-radius: 3px;
204
+ }
205
+
206
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
207
+ background-color: #94a3b8;
208
+ }
209
+ }
@@ -0,0 +1,50 @@
1
+ import { useLoginState } from 'tuikit-atomicx-vue3';
2
+ import { getBasicInfo } from '@/config/basic-info-config';
3
+ import { clearSession, getSession, getSessionUser } from '@/utils/session';
4
+
5
+ let restorePromise: Promise<boolean> | null = null;
6
+
7
+ export async function bootstrapSession() {
8
+ const session = getSession();
9
+ if (!session) {
10
+ return false;
11
+ }
12
+ return restoreLoginBySession();
13
+ }
14
+
15
+ export async function restoreLoginBySession(): Promise<boolean> {
16
+ const session = getSession();
17
+ const sessionUser = getSessionUser();
18
+
19
+ if (!session || !sessionUser) {
20
+ clearSession();
21
+ return false;
22
+ }
23
+
24
+ const { loginUserInfo, login, setSelfInfo } = useLoginState();
25
+ if (loginUserInfo.value?.userId === session.userId) {
26
+ return true;
27
+ }
28
+
29
+ if (restorePromise) {
30
+ return restorePromise;
31
+ }
32
+
33
+ restorePromise = (async () => {
34
+ try {
35
+ await login(getBasicInfo(session.userId));
36
+ await setSelfInfo({
37
+ userName: sessionUser?.userName || session.userId,
38
+ avatarUrl: sessionUser?.avatarUrl || '',
39
+ });
40
+ return true;
41
+ } catch {
42
+ clearSession();
43
+ return false;
44
+ } finally {
45
+ restorePromise = null;
46
+ }
47
+ })();
48
+
49
+ return restorePromise;
50
+ }
@@ -0,0 +1,24 @@
1
+ function normalizeToMs(timestamp: number) {
2
+ return timestamp < 1_000_000_000_000 ? timestamp * 1000 : timestamp;
3
+ }
4
+
5
+ export function formatTimeRange(start: number, end: number) {
6
+ const startValue = new Date(normalizeToMs(start));
7
+ const endValue = new Date(normalizeToMs(end));
8
+ const date = `${startValue.getFullYear()}-${String(startValue.getMonth() + 1).padStart(2, '0')}-${String(startValue.getDate()).padStart(2, '0')}`;
9
+ const startLabel = `${String(startValue.getHours()).padStart(2, '0')}:${String(startValue.getMinutes()).padStart(2, '0')}`;
10
+ const endLabel = `${String(endValue.getHours()).padStart(2, '0')}:${String(endValue.getMinutes()).padStart(2, '0')}`;
11
+ return `${date} ${startLabel} - ${endLabel}`;
12
+ }
13
+
14
+ export function formatDuration(seconds: number) {
15
+ const minutes = Math.floor(seconds / 60);
16
+ const remain = seconds % 60;
17
+ return `${String(minutes).padStart(2, '0')}:${String(remain).padStart(2, '0')}`;
18
+ }
19
+
20
+ export function formatWaiting(seconds: number) {
21
+ const minutes = Math.floor(seconds / 60);
22
+ const remain = seconds % 60;
23
+ return `${minutes}:${String(remain).padStart(2, '0')}`;
24
+ }
@@ -0,0 +1,12 @@
1
+ import type { UserRole } from '@/services/adapters';
2
+
3
+ export function getDefaultRoute(role: UserRole, appointmentId?: string) {
4
+ if (role === 'doctor') {
5
+ return appointmentId
6
+ ? `/doctor/consultation/${appointmentId}`
7
+ : '/doctor/dashboard';
8
+ }
9
+ return appointmentId
10
+ ? `/patient/waiting/${appointmentId}`
11
+ : '/patient/select-doctor';
12
+ }
@@ -0,0 +1,28 @@
1
+ import type { MedicalUser, SessionData } from '@/services/adapters';
2
+
3
+ const STORAGE_KEY = 'medical-demo-session';
4
+
5
+ export function saveSession(session: SessionData) {
6
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(session));
7
+ }
8
+
9
+ export function clearSession() {
10
+ localStorage.removeItem(STORAGE_KEY);
11
+ }
12
+
13
+ export function getSession(): SessionData | null {
14
+ const value = localStorage.getItem(STORAGE_KEY);
15
+ if (!value) {
16
+ return null;
17
+ }
18
+ try {
19
+ return JSON.parse(value) as SessionData;
20
+ } catch {
21
+ clearSession();
22
+ return null;
23
+ }
24
+ }
25
+
26
+ export function getSessionUser(): MedicalUser | null {
27
+ return getSession()?.user ?? null;
28
+ }