view.dart 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:vnoteapp/components/appbar.dart';
  4. import 'package:vnoteapp/components/panel.dart';
  5. import 'controller.dart';
  6. class PatientDetailPage extends GetView<PatientDetailController> {
  7. const PatientDetailPage({super.key});
  8. @override
  9. Widget build(BuildContext context) {
  10. return Scaffold(
  11. backgroundColor: const Color.fromRGBO(238, 238, 238, 1),
  12. // appBar: VAppBar(titleText: "${controller.state.name}档案详情"),
  13. appBar: VAppBar(
  14. context: context,
  15. titleWidget: Obx(
  16. () => Text(
  17. "${controller.state.name}档案详情",
  18. style: const TextStyle(fontSize: 24),
  19. ),
  20. ),
  21. ),
  22. body: Padding(
  23. padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
  24. child: Column(
  25. children: [
  26. SizedBox(
  27. height: 220,
  28. child: Row(
  29. children: [
  30. VPanel(
  31. backgroundColor: const Color.fromRGBO(0, 152, 218, 1),
  32. child: SizedBox(
  33. width: 680,
  34. child: _buildPatientInfoChild(),
  35. ),
  36. ),
  37. const SizedBox(width: 16),
  38. Expanded(
  39. child: VPanel(
  40. backgroundColor: const Color.fromRGBO(249, 216, 69, 1),
  41. child: _buildFollowUpChild(),
  42. ),
  43. ),
  44. ],
  45. ),
  46. ),
  47. const SizedBox(height: 16),
  48. Expanded(
  49. child: VPanel(
  50. child: Padding(
  51. padding: const EdgeInsets.symmetric(horizontal: 30),
  52. child: _buildEntranceChild(),
  53. ),
  54. ),
  55. )
  56. ],
  57. ),
  58. ),
  59. );
  60. }
  61. Widget _buildPatientInfoChild() {
  62. const txtStyle = TextStyle(color: Colors.white, fontSize: 14);
  63. return Row(
  64. crossAxisAlignment: CrossAxisAlignment.start,
  65. children: [
  66. Container(
  67. width: 110,
  68. padding: const EdgeInsets.only(top: 8),
  69. child: CircleAvatar(
  70. radius: 50,
  71. child: Image.asset("assets/images/patient/avatar_girl.png"),
  72. ),
  73. ),
  74. const SizedBox(width: 8),
  75. Obx(
  76. () => Column(
  77. crossAxisAlignment: CrossAxisAlignment.start,
  78. children: [
  79. const SizedBox(height: 8),
  80. Text(controller.state.name,
  81. style: txtStyle.copyWith(fontSize: 18)),
  82. const SizedBox(height: 8),
  83. Text(
  84. "${controller.state.genderDesc} ${controller.state.age}岁 电话:${controller.state.phone}",
  85. style: txtStyle),
  86. const SizedBox(height: 2),
  87. Text("地址:${controller.state.address}", style: txtStyle),
  88. const SizedBox(height: 16),
  89. SizedBox(
  90. width: 380,
  91. child: Wrap(
  92. spacing: 20,
  93. runSpacing: 12,
  94. //TODO:
  95. children: ["一般人群", "高血压", "老年人", "儿童", "糖尿病", "冠心病", "残疾人"]
  96. .map((e) => _PatientClassTagWidget(
  97. label: e,
  98. ))
  99. .toList(),
  100. ),
  101. ),
  102. ],
  103. ),
  104. ),
  105. ],
  106. );
  107. }
  108. /// 构建功能页入口
  109. Widget _buildEntranceChild() {
  110. return Wrap(
  111. spacing: 110,
  112. runSpacing: 40,
  113. children: [
  114. _FunctionEntranceWidget(
  115. label: "健康档案",
  116. assetName: "档案.png",
  117. onTap: controller.gotoInfo,
  118. ),
  119. _FunctionEntranceWidget(
  120. label: "人群随访",
  121. assetName: "随访.png",
  122. onTap: () {},
  123. ),
  124. _FunctionEntranceWidget(
  125. label: "随访报告",
  126. assetName: "随访报告.png",
  127. onTap: () {},
  128. ),
  129. _FunctionEntranceWidget(
  130. label: "健康体检",
  131. assetName: "体检.png",
  132. onTap: () {},
  133. ),
  134. _FunctionEntranceWidget(
  135. label: "医生签约",
  136. assetName: "签约.png",
  137. onTap: () {
  138. Get.toNamed(
  139. "/contract/package_list",
  140. parameters: {"patientCode": controller.state.code},
  141. );
  142. },
  143. ),
  144. _FunctionEntranceWidget(
  145. label: "双向转诊",
  146. assetName: "转诊.png",
  147. onTap: () {},
  148. ),
  149. _FunctionEntranceWidget(
  150. label: "诊疗展示",
  151. assetName: "诊疗.png",
  152. onTap: () {},
  153. ),
  154. ],
  155. );
  156. }
  157. Widget _buildFollowUpChild() {
  158. return Padding(
  159. padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
  160. child: Column(
  161. crossAxisAlignment: CrossAxisAlignment.start,
  162. children: [
  163. _FollowUpTagWidget(),
  164. const SizedBox(height: 24),
  165. LayoutBuilder(builder: (context, c) {
  166. return Container(
  167. width: c.maxWidth,
  168. padding: const EdgeInsets.symmetric(horizontal: 8),
  169. child: Wrap(
  170. spacing: 20,
  171. runSpacing: 12,
  172. children: ["高血压", "儿童"]
  173. .map((e) => _PatientClassTagWidget(
  174. label: e,
  175. ))
  176. .toList(),
  177. ),
  178. );
  179. })
  180. ],
  181. ),
  182. );
  183. }
  184. }
  185. class _PatientClassTagWidget extends StatelessWidget {
  186. final String label;
  187. const _PatientClassTagWidget({required this.label});
  188. @override
  189. Widget build(BuildContext context) {
  190. return Container(
  191. width: 60,
  192. height: 24,
  193. alignment: Alignment.center,
  194. decoration: BoxDecoration(
  195. borderRadius: BorderRadius.circular(4),
  196. border: Border.all(color: Colors.white, width: 1),
  197. ),
  198. child: Text(
  199. label,
  200. style: const TextStyle(color: Colors.white, fontSize: 12),
  201. ),
  202. );
  203. }
  204. }
  205. class _FunctionEntranceWidget extends StatelessWidget {
  206. final String label;
  207. final String assetName;
  208. final VoidCallback? onTap;
  209. const _FunctionEntranceWidget({
  210. required this.label,
  211. required this.assetName,
  212. this.onTap,
  213. });
  214. @override
  215. Widget build(BuildContext context) {
  216. return Material(
  217. child: Ink(
  218. child: InkWell(
  219. borderRadius: BorderRadius.circular(8),
  220. onTap: () {
  221. onTap?.call();
  222. },
  223. child: Container(
  224. decoration: BoxDecoration(
  225. borderRadius: BorderRadius.circular(8),
  226. ),
  227. padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 14),
  228. child: Column(
  229. mainAxisSize: MainAxisSize.min,
  230. crossAxisAlignment: CrossAxisAlignment.center,
  231. children: [
  232. Image.asset(
  233. "assets/images/patient/$assetName",
  234. width: 70,
  235. height: 70,
  236. fit: BoxFit.contain,
  237. ),
  238. const SizedBox(height: 8),
  239. Text(
  240. label,
  241. style: const TextStyle(
  242. fontSize: 22,
  243. color: Colors.black,
  244. fontWeight: FontWeight.bold,
  245. ),
  246. ),
  247. ],
  248. ),
  249. ),
  250. ),
  251. ),
  252. );
  253. }
  254. }
  255. class _FollowUpTagWidget extends StatelessWidget {
  256. @override
  257. Widget build(BuildContext context) {
  258. return Container(
  259. width: 190,
  260. height: 60,
  261. alignment: Alignment.center,
  262. // padding: const EdgeInsets.symmetric(horizontal: 56 / 2),
  263. decoration: BoxDecoration(
  264. color: const Color.fromRGBO(240, 128, 0, 1),
  265. borderRadius: BorderRadius.circular(56 / 2),
  266. ),
  267. child: Row(
  268. crossAxisAlignment: CrossAxisAlignment.center,
  269. mainAxisAlignment: MainAxisAlignment.center,
  270. children: [
  271. Image.asset(
  272. "assets/images/icons/remind.png",
  273. width: 32,
  274. height: 32,
  275. fit: BoxFit.contain,
  276. ),
  277. const SizedBox(width: 4),
  278. const Text(
  279. "随访提醒",
  280. style: TextStyle(
  281. color: Colors.white,
  282. fontSize: 24,
  283. fontWeight: FontWeight.bold,
  284. ),
  285. ),
  286. ],
  287. ),
  288. );
  289. }
  290. }