base_info.dart 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import 'package:fis_jsonrpc/rpc.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. import 'package:vitalapp/architecture/values/features.dart';
  5. import 'package:vitalapp/components/button.dart';
  6. import 'package:vitalapp/consts/styles.dart';
  7. import 'package:vitalapp/store/store.dart';
  8. import '../controller.dart';
  9. /// 基本信息卡片
  10. class BaseInfoCard extends GetView<PatientDetailController> {
  11. const BaseInfoCard({super.key});
  12. @override
  13. Widget build(BuildContext context) {
  14. final state = controller.state;
  15. return _InfoCardContainer(
  16. child: Stack(
  17. children: [
  18. Padding(
  19. padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
  20. child: Obx(
  21. () {
  22. if (state.phone == "UNLOAD") {
  23. return Container(
  24. height: 30 * 6 + 18,
  25. alignment: Alignment.center,
  26. child: SizedBox(
  27. width: 20,
  28. height: 20,
  29. child: CircularProgressIndicator(),
  30. ),
  31. );
  32. }
  33. return Column(
  34. children: [
  35. const SizedBox(height: 18),
  36. _buildItem("姓名", state.name),
  37. _buildItem("性别", state.genderDesc),
  38. _buildItem("年龄", state.age.toString()),
  39. _buildItem("电话", state.phone, placeholder: "未填写"),
  40. _buildItem("身份证", state.cardNo),
  41. // const SizedBox(height: 8),
  42. _buildItem("地址", state.address, enableTooltip: true),
  43. ],
  44. );
  45. },
  46. ),
  47. ),
  48. Positioned(
  49. top: 2,
  50. right: 6,
  51. child: _buildAvatar(),
  52. ),
  53. ],
  54. ),
  55. );
  56. }
  57. Widget _buildItem(String label, String? content,
  58. {bool enableTooltip = false, String placeholder = ""}) {
  59. String displayContent;
  60. if (content == null || content.isEmpty) {
  61. displayContent = placeholder;
  62. } else {
  63. displayContent = content;
  64. }
  65. Widget contentWidget = Text(
  66. displayContent,
  67. style: const TextStyle(
  68. color: Colors.black,
  69. fontSize: 18,
  70. ),
  71. overflow: TextOverflow.ellipsis,
  72. );
  73. if (enableTooltip) {
  74. contentWidget = Tooltip(
  75. message: displayContent,
  76. padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
  77. textStyle: const TextStyle(fontSize: 18, color: Colors.white),
  78. triggerMode: TooltipTriggerMode.tap,
  79. child: contentWidget,
  80. );
  81. }
  82. return SizedBox(
  83. height: 30,
  84. child: Row(
  85. children: [
  86. SizedBox(
  87. width: 60,
  88. child: Text(
  89. label,
  90. style: const TextStyle(color: Colors.grey, fontSize: 18),
  91. ),
  92. ),
  93. const SizedBox(width: 12),
  94. Expanded(child: contentWidget),
  95. ],
  96. ),
  97. );
  98. }
  99. Widget _buildAvatar() {
  100. return Obx(() {
  101. if (controller.state.phone == "UNLOAD") {
  102. return SizedBox(width: 100, height: 150);
  103. }
  104. final url = controller.state.avatarUrl;
  105. Widget image;
  106. if (url != null && url.isNotEmpty) {
  107. image = Image.network(url, fit: BoxFit.cover);
  108. } else {
  109. if (controller.state.gender == GenderEnum.Male) {
  110. image = Image.asset("assets/images/avatar_man.png");
  111. } else {
  112. image = Image.asset("assets/images/avatar_women.png");
  113. }
  114. }
  115. return SizedBox(
  116. width: 100,
  117. height: 150,
  118. child: Column(
  119. children: [
  120. Expanded(
  121. child: ClipOval(
  122. child: image,
  123. ),
  124. ),
  125. const SizedBox(
  126. height: 10,
  127. ),
  128. SizedBox(
  129. height: 40,
  130. child: Obx(() {
  131. if (Store.user.hasFeature(FeatureKeys.FaceRecognition) &&
  132. controller.state.isOnline) {
  133. return VButton(
  134. label: '绑定人脸',
  135. onTap: controller.queryIsNeedFaceInput,
  136. );
  137. }
  138. return Container();
  139. }),
  140. ),
  141. ],
  142. ),
  143. );
  144. });
  145. }
  146. }
  147. class _InfoCardContainer extends StatelessWidget {
  148. final Widget child;
  149. const _InfoCardContainer({
  150. required this.child,
  151. });
  152. @override
  153. Widget build(BuildContext context) {
  154. return Container(
  155. alignment: Alignment.topLeft,
  156. padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
  157. decoration: BoxDecoration(
  158. color: Colors.white,
  159. borderRadius: GlobalStyles.borderRadius,
  160. ),
  161. child: child,
  162. );
  163. }
  164. }