measure_images_bar.dart 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. import 'package:fis_jsonrpc/rpc.dart';
  2. import 'package:fis_measure/interfaces/process/workspace/exam_info.dart';
  3. import 'package:fis_measure/process/workspace/measure_controller.dart';
  4. import 'package:fis_measure/process/workspace/measure_data_controller.dart';
  5. import 'package:fis_measure/process/workspace/measure_handler.dart';
  6. import 'package:fis_measure/view/measure/measure_images_bar.dart';
  7. export 'package:fis_lib_business_components/index.dart';
  8. import 'package:fis_ui/index.dart';
  9. import 'package:flutter/material.dart';
  10. import 'package:get/get.dart';
  11. class MeasureImagesBar extends StatefulWidget implements FWidget {
  12. const MeasureImagesBar({Key? key}) : super(key: key);
  13. @override
  14. State<MeasureImagesBar> createState() => _MeasureImagesBarState();
  15. }
  16. class _MeasureImagesBarState extends State<MeasureImagesBar> {
  17. /// 图片滑动控制器
  18. ScrollController scrollController = ScrollController();
  19. /// 数据
  20. final measureData = Get.find<MeasureDataController>();
  21. /// 全部图片list
  22. final measureController = Get.find<MeasureController>();
  23. /// 当前可滑动的范围宽度
  24. late double width = 0;
  25. /// 是否滑到最后
  26. bool _isEnd = false;
  27. /// 计算下标
  28. int _currentIndex = 0;
  29. /// 左边能否滑动
  30. bool get isLeftCanScroll => _currentIndex <= 0;
  31. /// 右边能否滑动
  32. bool get isRightCanScroll => _isEnd;
  33. /// 滑动区域的key值
  34. final GlobalKey globalKey = GlobalKey();
  35. /// 图片左划事件
  36. void onLeftMoveImage() async {
  37. if (_currentIndex > 0) {
  38. _currentIndex--;
  39. await scrollController.animateTo(
  40. (160 * _currentIndex).toDouble(),
  41. duration: const Duration(milliseconds: 300),
  42. curve: Curves.linear,
  43. );
  44. }
  45. }
  46. /// 图片右划事件
  47. void onRightMoveImage() async {
  48. if (!isRightCanScroll) {
  49. _currentIndex++;
  50. await scrollController.animateTo(
  51. (160 * _currentIndex).toDouble(),
  52. duration: const Duration(milliseconds: 300),
  53. curve: Curves.linear,
  54. );
  55. }
  56. }
  57. @override
  58. Widget build(BuildContext context) {
  59. return FContainer(
  60. height: 120,
  61. margin: const EdgeInsets.symmetric(
  62. vertical: 15,
  63. ),
  64. child: FRow(
  65. children: [
  66. _buildImageListIcon(
  67. FIcons.fis_left_arrow,
  68. isLeftCanScroll,
  69. onLeftMoveImage,
  70. ),
  71. FExpanded(
  72. child: ScrollableImageList(
  73. scrollController: scrollController,
  74. globalKey: globalKey,
  75. remedicalList: measureData.remedicalList,
  76. ),
  77. ),
  78. _buildImageListIcon(
  79. FIcons.fis_right_arrow,
  80. isRightCanScroll,
  81. onRightMoveImage,
  82. ),
  83. ],
  84. ),
  85. );
  86. }
  87. @override
  88. void initState() {
  89. scrollController.addListener(
  90. () async {
  91. // 如果滑动到最右边
  92. if (scrollController.position.pixels ==
  93. scrollController.position.maxScrollExtent) {
  94. setState(() {
  95. _isEnd = true;
  96. });
  97. } else {
  98. setState(
  99. () {
  100. _isEnd = false;
  101. },
  102. );
  103. }
  104. },
  105. );
  106. super.initState();
  107. }
  108. @override
  109. void didChangeDependencies() {
  110. super.didChangeDependencies();
  111. WidgetsBinding.instance.addPostFrameCallback(
  112. (mag) {
  113. width = globalKey.currentContext!.size!.width;
  114. setState(
  115. () {
  116. _isEnd = width >= measureData.remedicalList.length * 160;
  117. _currentIndex = measureController.examInfo.selectedImageIndex;
  118. if (_currentIndex * 160 >
  119. scrollController.position.maxScrollExtent) {
  120. _currentIndex = scrollController.position.maxScrollExtent ~/ 160;
  121. }
  122. scrollController.animateTo(
  123. (160 * _currentIndex).toDouble(),
  124. duration: const Duration(milliseconds: 300),
  125. curve: Curves.linear,
  126. );
  127. },
  128. );
  129. },
  130. );
  131. }
  132. @override
  133. void dispose() {
  134. super.dispose();
  135. }
  136. FWidget _buildImageListIcon(
  137. IconData iconsData, bool isCanClick, Function onIconTap) {
  138. return FInkWell(
  139. onTap: () => onIconTap.call(),
  140. child: FContainer(
  141. width: 100,
  142. child: FIcon(
  143. iconsData,
  144. color: isCanClick ? Colors.grey : Colors.white,
  145. size: 30,
  146. ),
  147. ),
  148. );
  149. }
  150. }
  151. /// 可滑动的图片组,显示当前测量组的所有图片
  152. class ScrollableImageList extends StatefulWidget implements FWidget {
  153. const ScrollableImageList({
  154. required this.scrollController,
  155. required this.globalKey,
  156. required this.remedicalList,
  157. Key? key,
  158. }) : super(key: key);
  159. /// 图片滑动控制器
  160. final ScrollController scrollController;
  161. final GlobalKey globalKey;
  162. final List<RemedicalInfoDTO> remedicalList;
  163. @override
  164. State<ScrollableImageList> createState() => _ScrollableImageListState();
  165. }
  166. class _ScrollableImageListState extends State<ScrollableImageList> {
  167. /// 当前测量的图片
  168. // final measureCurrentImage = Get.put(MeasureGetCurrentImage());
  169. /// 测量AI数据
  170. final measureData = Get.find<MeasureDataController>();
  171. MeasureController measureController = Get.find<MeasureController>();
  172. late final measureHandler = Get.put(MeasureHandler());
  173. /// 图像数据列表
  174. List<RemedicalInfoDTO> remedicalList = [];
  175. /// 当前选中的图像下标
  176. int selectedImageIndex = -1;
  177. /// 获取图片地址
  178. void onChangeImage(
  179. String imageUrl,
  180. String remedicalCode,
  181. ) async {
  182. if (measureData.itemCurrentImage == imageUrl) {
  183. return;
  184. }
  185. measureHandler.changeImageLoaded = true;
  186. measureHandler.imageChanged = ChangeImageInfo(
  187. imageUrl,
  188. remedicalCode,
  189. );
  190. ExamImageInfo selectedImage = measureController.examInfo.images.firstWhere(
  191. (element) => element.url == imageUrl,
  192. );
  193. selectedImageIndex =
  194. measureController.examInfo.images.indexOf(selectedImage);
  195. measureData.itemCurrentImage = imageUrl;
  196. measureController.examInfo.selectedImageIndex = selectedImageIndex;
  197. setState(() {});
  198. }
  199. /// 获取图像Code来更新图像
  200. void onChangeImageByRemedicalCode(_, e) {
  201. onChangeImage(findImageUrlByRemedicalCode(e), e);
  202. }
  203. /// 更新图像集合
  204. void onChangeImageList(_, e) {
  205. measureController = Get.find<MeasureController>();
  206. setState(() {
  207. remedicalList = e;
  208. });
  209. }
  210. String findImageUrlByRemedicalCode(String remedicalCode) {
  211. String imageUrl = '';
  212. for (var i = 0; i < measureController.examInfo.images.length; i++) {
  213. if (remedicalList[i].remedicalCode! == remedicalCode) {
  214. imageUrl = remedicalList[i].terminalImages!.imageUrl!;
  215. break;
  216. }
  217. }
  218. return imageUrl;
  219. }
  220. @override
  221. void initState() {
  222. remedicalList = widget.remedicalList;
  223. measureHandler.changeImageByRemedicalCode
  224. .addListener(onChangeImageByRemedicalCode);
  225. measureHandler.changeImageList.addListener(onChangeImageList);
  226. super.initState();
  227. }
  228. @override
  229. void dispose() {
  230. measureHandler.changeImageByRemedicalCode
  231. .removeListener(onChangeImageByRemedicalCode);
  232. measureHandler.changeImageList.removeListener(onChangeImageList);
  233. super.dispose();
  234. }
  235. @override
  236. FWidget build(BuildContext context) {
  237. return FContainer(
  238. key: ValueKey(measureData.itemCurrentImage),
  239. alignment: Alignment.topCenter,
  240. child: _buildImageList(remedicalList),
  241. );
  242. }
  243. FWidget _buildImageList(List<RemedicalInfoDTO> remedicalItemList) {
  244. return FContainer(
  245. key: widget.globalKey,
  246. child: FListView.builder(
  247. scrollDirection: Axis.horizontal,
  248. shrinkWrap: true,
  249. controller: widget.scrollController,
  250. itemCount: remedicalItemList.toList().length,
  251. itemBuilder: (BuildContext context, int index) {
  252. final FWidget image = ContentImage(
  253. remedicalInfo: remedicalItemList[index],
  254. fileDataType: remedicalItemList[index].fileDataType,
  255. terminalImage: TerminalImage(
  256. previewUrl: remedicalItemList[index].terminalImages!.previewUrl,
  257. ),
  258. isMeasure: true,
  259. application: remedicalItemList[index].application ?? '',
  260. onTap: () => onChangeImage(
  261. remedicalItemList[index].terminalImages!.imageUrl!,
  262. remedicalItemList[index].remedicalCode!,
  263. ),
  264. );
  265. return FContainer(
  266. key: ValueKey(measureData.itemCurrentImage),
  267. width: 160,
  268. alignment: Alignment.center,
  269. decoration: BoxDecoration(
  270. border: Border.all(
  271. width: 3,
  272. color: remedicalItemList[index].terminalImages!.imageUrl! !=
  273. measureData.itemCurrentImage
  274. ? Colors.grey
  275. : Colors.blue,
  276. ),
  277. ),
  278. child: image,
  279. );
  280. },
  281. ),
  282. );
  283. }
  284. }