main.dart 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. import 'dart:async';
  2. import 'dart:math';
  3. import 'package:fis_lib_basictest/hardware_detection/index.dart';
  4. import 'package:fis_ui/index.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:get/get.dart';
  7. void main() {
  8. runApp(const MyApp());
  9. }
  10. class MyApp extends StatelessWidget {
  11. const MyApp({super.key});
  12. // This widget is the root of your application.
  13. @override
  14. Widget build(BuildContext context) {
  15. return GetMaterialApp(
  16. theme: ThemeData(
  17. primarySwatch: Colors.blue,
  18. ),
  19. initialRoute: '/',
  20. getPages: [
  21. GetPage(
  22. name: '/',
  23. page: () => HardwareDetectionPage(),
  24. binding: HardwareDetectionBinding(),
  25. ),
  26. GetPage(name: '/old', page: () => DrawWidgetStep2()),
  27. ],
  28. );
  29. }
  30. }
  31. class DrawWidgetStep2 extends StatefulWidget {
  32. const DrawWidgetStep2({Key? key}) : super(key: key);
  33. @override
  34. State<StatefulWidget> createState() => DrawWidgetStep2State();
  35. }
  36. class DrawWidgetStep2State extends State<DrawWidgetStep2>
  37. with TickerProviderStateMixin {
  38. late Timer timer;
  39. AnimationController? controller;
  40. late Animation<double> strokePercentAnimation;
  41. late Animation<double> labelPercentAnimation;
  42. late Animation<Color?> strokeColorAnimation;
  43. late double beginPercentValue;
  44. late double endPercentValue;
  45. late Color beginColor;
  46. late Color endColor;
  47. late double speechSliderValue = 0;
  48. late double microPhoneSliderValue = 0;
  49. late String speechSliderText = "0";
  50. late String microphoneSliderText = "0";
  51. @override
  52. void initState() {
  53. super.initState();
  54. // 设置初始值结束值
  55. beginPercentValue = 0;
  56. endPercentValue = 0;
  57. beginColor = Colors.black;
  58. endColor = ([...Colors.primaries]..shuffle()).first;
  59. // 动画控制器初始化
  60. controller = AnimationController(
  61. vsync: this, duration: const Duration(milliseconds: 1000));
  62. // 添加监听
  63. controller?.addListener(() => setState(() {}));
  64. // 开始执行动画
  65. startAnimation();
  66. // 设置定时器
  67. timer = Timer.periodic(const Duration(milliseconds: 300), (timer) {
  68. startAnimation();
  69. });
  70. }
  71. void startAnimation() {
  72. // 进度条动画
  73. strokePercentAnimation =
  74. Tween<double>(begin: beginPercentValue, end: endPercentValue).animate(
  75. CurvedAnimation(parent: controller!, curve: Curves.elasticOut));
  76. // text动画
  77. labelPercentAnimation =
  78. Tween<double>(begin: beginPercentValue, end: endPercentValue).animate(
  79. CurvedAnimation(parent: controller!, curve: Curves.easeInOutCubic));
  80. // 进度条颜色动画
  81. strokeColorAnimation = ColorTween(begin: beginColor, end: endColor).animate(
  82. CurvedAnimation(parent: controller!, curve: Curves.easeInOutCubic));
  83. beginPercentValue = endPercentValue;
  84. endPercentValue = Random().nextDouble();
  85. beginColor = endColor;
  86. endColor = ([...Colors.primaries]..shuffle()).first;
  87. controller?.forward(from: 1);
  88. }
  89. @override
  90. void dispose() {
  91. controller?.dispose();
  92. timer.cancel();
  93. super.dispose();
  94. }
  95. @override
  96. Widget build(BuildContext context) {
  97. return Scaffold(
  98. body: FPadding(
  99. padding: const EdgeInsets.symmetric(vertical: 10),
  100. child: FSingleChildScrollView(
  101. child: FColumn(
  102. mainAxisAlignment: MainAxisAlignment.start,
  103. crossAxisAlignment: CrossAxisAlignment.start,
  104. children: [
  105. _buildNetworkTest(),
  106. _buildSpeechTest(),
  107. _buildMicroPhoneTest(),
  108. _buildCameraTest(),
  109. ],
  110. ),
  111. ),
  112. ));
  113. }
  114. _buildNetworkTest() {
  115. var title = _bildTestTitle("网络检测");
  116. var testButton = _buildTestButton("网络检测");
  117. var networkTestItems = _buildNetworkTestItems();
  118. var divider = _buildDevider();
  119. return FColumn(
  120. crossAxisAlignment: CrossAxisAlignment.start,
  121. children: [
  122. title,
  123. testButton,
  124. ...networkTestItems,
  125. divider,
  126. ],
  127. );
  128. }
  129. _buildSpeechTest() {
  130. var title = _bildTestTitle("扬声器检测");
  131. var divider = _buildDevider();
  132. var speechSelections = _buildSpeechSelections();
  133. var speechResult = _buildTestItem(
  134. title: "扬声器状态",
  135. value: -1,
  136. valueUnit: "",
  137. testResult: "满足要求",
  138. isTestPass: true,
  139. );
  140. var speechButton = _buildTestButton("扬声器检测");
  141. var volumeSlider = _buildVolumSlider("扬声器音量", true);
  142. var mediaWave = _buildMediaWaves(false);
  143. var testResultActionButtonGroup = FContainer(
  144. padding: EdgeInsets.fromLTRB(0, 10, 10, 10),
  145. width: 250,
  146. child: FRow(
  147. children: [
  148. FContainer(
  149. width: 100,
  150. child: _buildTestButton("听到了"),
  151. ),
  152. FContainer(
  153. width: 100,
  154. child: _buildTestButton("没听到"),
  155. )
  156. ],
  157. ),
  158. );
  159. return FColumn(
  160. crossAxisAlignment: CrossAxisAlignment.start,
  161. children: [
  162. title,
  163. speechSelections,
  164. volumeSlider,
  165. speechButton,
  166. mediaWave,
  167. testResultActionButtonGroup,
  168. speechResult,
  169. divider,
  170. ],
  171. );
  172. }
  173. FWidget _buildVolumSlider(String title, bool isSpeechSlider) {
  174. return FContainer(
  175. width: 500,
  176. padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
  177. child: FRow(
  178. children: [
  179. FContainer(
  180. width: 140,
  181. child: FText(
  182. title,
  183. style: TextStyle(
  184. fontWeight: FontWeight.bold,
  185. ),
  186. ),
  187. ),
  188. FContainer(
  189. width: 310,
  190. child: _buidSlider(isSpeechSlider),
  191. ),
  192. FText(
  193. isSpeechSlider ? speechSliderText : microphoneSliderText,
  194. ),
  195. ],
  196. ),
  197. );
  198. }
  199. void updateSlider(value, text, isSpeech) {
  200. if (isSpeech) {
  201. speechSliderValue = value;
  202. speechSliderText = text;
  203. } else {
  204. microPhoneSliderValue = value;
  205. microphoneSliderText = text;
  206. }
  207. setState(() {});
  208. }
  209. _buildMicroPhoneTest() {
  210. var title = _bildTestTitle("麦克风检测");
  211. var divider = _buildDevider();
  212. var mediaWave = _buildMediaWaves(true);
  213. var microPhoneResult = _buildTestItem(
  214. title: "麦克风状态",
  215. value: -1,
  216. valueUnit: "",
  217. testResult: "满足要求",
  218. isTestPass: true,
  219. );
  220. var microphpneButton = _buildTestButton("麦克风测试");
  221. var volumeSlider = _buildVolumSlider("麦克风音量", false);
  222. var microphoneSelection = _buildMicrophoneSelections();
  223. return FColumn(
  224. crossAxisAlignment: CrossAxisAlignment.start,
  225. children: [
  226. title,
  227. microphoneSelection,
  228. volumeSlider,
  229. microphpneButton,
  230. mediaWave,
  231. microPhoneResult,
  232. divider,
  233. ],
  234. );
  235. }
  236. _buildMediaWaves(bool isMicrophone) {
  237. var mediaWave = FContainer(
  238. padding: EdgeInsets.fromLTRB(13, 10, 10, 10),
  239. child: FSizedBox(
  240. width: 100,
  241. height: 10,
  242. child: FCustomPaint(
  243. painter: DrawPainter(
  244. strokeBackgroundColor: Colors.grey.withOpacity(0.1),
  245. strokeColor: Colors.red,
  246. startAngle: -pi * 0.5,
  247. percent: 0,
  248. percentLabel: "0",
  249. strokeWidth: 1,
  250. fontSize: 2,
  251. ),
  252. ),
  253. ),
  254. );
  255. return mediaWave;
  256. }
  257. _buildCameraTest() {
  258. var title = _bildTestTitle("摄像头检测");
  259. var cameraSelection = _buildCameraSelections();
  260. var devider = _buildDevider();
  261. var cameraResult = _buildTestItem(
  262. title: "摄像头状态",
  263. value: -1,
  264. valueUnit: "",
  265. testResult: "满足要求",
  266. isTestPass: true,
  267. );
  268. var testResultActionButtonGroup = FContainer(
  269. padding: EdgeInsets.fromLTRB(0, 10, 10, 10),
  270. width: 250,
  271. child: FRow(
  272. children: [
  273. FContainer(
  274. width: 100,
  275. child: _buildTestButton("看到了"),
  276. ),
  277. FContainer(
  278. width: 100,
  279. child: _buildTestButton("没看到"),
  280. )
  281. ],
  282. ),
  283. );
  284. var image = FContainer(
  285. margin: EdgeInsets.fromLTRB(8, 10, 10, 10),
  286. width: 640,
  287. height: 480,
  288. color: Colors.black,
  289. );
  290. var cameraStatement = FContainer(
  291. padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
  292. child: FText("该摄像头用于会诊时采集本地画面,请确认是否成功看到画面。"),
  293. );
  294. return FColumn(
  295. crossAxisAlignment: CrossAxisAlignment.start,
  296. children: [
  297. title,
  298. cameraSelection,
  299. image,
  300. cameraStatement,
  301. testResultActionButtonGroup,
  302. cameraResult,
  303. devider,
  304. ],
  305. );
  306. }
  307. FWidget _buidSlider(bool isSpeechSlider) {
  308. return FSlider(
  309. value: isSpeechSlider ? speechSliderValue : microPhoneSliderValue,
  310. max: 100,
  311. onChanged: (value) {
  312. var intValue = value.toInt();
  313. updateSlider(value, "$intValue", isSpeechSlider);
  314. },
  315. onChangeStart: (value) {
  316. var intValue = value.toInt();
  317. updateSlider(value, "$intValue", isSpeechSlider);
  318. },
  319. onChangeEnd: (value) {
  320. var intValue = value.toInt();
  321. updateSlider(value, " $intValue", isSpeechSlider);
  322. },
  323. );
  324. }
  325. _bildTestTitle(String title) {
  326. return FContainer(
  327. padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
  328. child: FText(
  329. title,
  330. style: TextStyle(
  331. fontSize: 18,
  332. fontWeight: FontWeight.bold,
  333. ),
  334. ),
  335. );
  336. }
  337. FWidget _buildTestButton(String content) {
  338. return FContainer(
  339. padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
  340. child: FInkWell(
  341. child: FText(content),
  342. onTap: () => {},
  343. ),
  344. );
  345. }
  346. List<FWidget> _buildNetworkTestItems() {
  347. var testItems = <FWidget>[];
  348. testItems.add(_buildTestItem(
  349. title: "网络延迟",
  350. value: 1,
  351. valueUnit: "ms",
  352. testResult: "满足要求",
  353. isTestPass: true,
  354. ));
  355. testItems.add(_buildTestItem(
  356. title: "上传速度",
  357. value: 342,
  358. valueUnit: "Mbps",
  359. testResult: "满足要求",
  360. isTestPass: true,
  361. ));
  362. testItems.add(_buildTestItem(
  363. title: "下载速度",
  364. value: 350,
  365. valueUnit: "Mbps",
  366. testResult: "满足要求",
  367. isTestPass: true,
  368. ));
  369. testItems.add(_buildTestItem(
  370. title: "视频服务质量",
  371. value: 20,
  372. valueUnit: "ms",
  373. testResult: "不满足要求",
  374. isTestPass: false,
  375. ));
  376. testItems.add(_buildTestItem(
  377. title: "网络质量",
  378. value: -1,
  379. valueUnit: "",
  380. testResult: "一般",
  381. isTestPass: false,
  382. ));
  383. return testItems;
  384. }
  385. FWidget _buildTestItem({
  386. required String title,
  387. required int value,
  388. required String valueUnit,
  389. required String testResult,
  390. required bool isTestPass,
  391. }) {
  392. var color = isTestPass ? Colors.green : Colors.red;
  393. return FContainer(
  394. padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
  395. width: 500,
  396. child: FRow(
  397. mainAxisAlignment: MainAxisAlignment.start,
  398. children: [
  399. FContainer(
  400. width: 125,
  401. margin: EdgeInsets.fromLTRB(0, 0, 0, 0),
  402. child: FText(
  403. title,
  404. style: TextStyle(
  405. fontWeight: FontWeight.bold,
  406. ),
  407. ),
  408. ),
  409. FContainer(
  410. width: 125,
  411. child: FText(value == -1 ? "" : value.toString() + valueUnit),
  412. ),
  413. FContainer(
  414. width: 125,
  415. child: FText(
  416. testResult,
  417. style: TextStyle(
  418. color: color,
  419. ),
  420. ),
  421. ),
  422. FContainer(
  423. width: 60,
  424. child: isTestPass
  425. ? FIcon(
  426. Icons.check_circle_outline,
  427. color: color,
  428. )
  429. : FIcon(
  430. Icons.highlight_off_rounded,
  431. color: color,
  432. ),
  433. ),
  434. ],
  435. ),
  436. );
  437. }
  438. FWidget _buildDevider() {
  439. return FDivider(
  440. height: 15,
  441. thickness: 1,
  442. color: Colors.black,
  443. indent: 10,
  444. );
  445. }
  446. FWidget _buildSpeechSelections() {
  447. var devices = <DeviceModel>[];
  448. devices.add(DeviceModel(name: "扬声器1", id: "1"));
  449. devices.add(DeviceModel(name: "扬声器2", id: "2"));
  450. devices.add(DeviceModel(name: "扬声器3", id: "3"));
  451. return _buildDeviceSelections(devices);
  452. }
  453. FWidget _buildMicrophoneSelections() {
  454. var devices = <DeviceModel>[];
  455. devices.add(DeviceModel(name: "麦克风1", id: "1"));
  456. devices.add(DeviceModel(name: "麦克风2", id: "2"));
  457. devices.add(DeviceModel(name: "麦克风3", id: "3"));
  458. return _buildDeviceSelections(devices);
  459. }
  460. FWidget _buildCameraSelections() {
  461. var devices = <DeviceModel>[];
  462. devices.add(DeviceModel(name: "摄像头1", id: "1"));
  463. devices.add(DeviceModel(name: "摄像头2", id: "2"));
  464. devices.add(DeviceModel(name: "摄像头3", id: "3"));
  465. return _buildDeviceSelections(devices);
  466. }
  467. FWidget _buildDeviceSelections(List<DeviceModel> source) {
  468. return FContainer(
  469. margin: EdgeInsets.fromLTRB(10, 10, 10, 10),
  470. child: FSelect<DeviceModel, String>(
  471. source: source,
  472. height: 33,
  473. width: 250,
  474. value: "1",
  475. optionValueExtractor: (value) {
  476. return value.id;
  477. },
  478. optionLabelExtractor: (value) {
  479. return value.name;
  480. },
  481. onSelectChanged: (value, index) {
  482. ;
  483. },
  484. fontSize: 14,
  485. ),
  486. );
  487. }
  488. }
  489. class DeviceModel {
  490. DeviceModel({
  491. required this.name,
  492. required this.id,
  493. });
  494. final String name;
  495. final String id;
  496. }
  497. class DrawPainter extends CustomPainter {
  498. final double strokeWidth;
  499. final Color strokeColor;
  500. final Color strokeBackgroundColor;
  501. final double startAngle;
  502. final double percent;
  503. final double fontSize;
  504. final Color textColor;
  505. final String? percentLabel;
  506. DrawPainter({
  507. this.strokeWidth = 10,
  508. this.strokeColor = Colors.black,
  509. this.strokeBackgroundColor = Colors.grey,
  510. this.startAngle = 0,
  511. this.percent = 0,
  512. this.fontSize = 20,
  513. this.textColor = Colors.black,
  514. this.percentLabel,
  515. });
  516. @override
  517. void paint(Canvas canvas, Size size) {
  518. //backgroud
  519. for (var i = 0; i < 15; i++) {
  520. var scolor = Colors.grey;
  521. var paint = Paint()
  522. ..style = PaintingStyle.stroke
  523. ..color = scolor
  524. ..strokeWidth = 3;
  525. var left = i * 10.0;
  526. var rect = Rect.fromLTWH(left, 2, 3, 20);
  527. canvas.drawRect(rect, paint);
  528. }
  529. var random = Random().nextInt(15);
  530. for (var i = 0; i < random; i++) {
  531. var scolor = Colors.blue;
  532. var paint = Paint()
  533. ..style = PaintingStyle.stroke
  534. ..color = scolor
  535. ..strokeWidth = 4;
  536. var left = i * 10.0;
  537. var rect = Rect.fromLTWH(left, 2, 3, 20);
  538. canvas.drawRect(rect, paint);
  539. }
  540. }
  541. @override
  542. bool shouldRepaint(CustomPainter oldDelegate) {
  543. return oldDelegate != this;
  544. }
  545. }