mine.dart 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. import 'dart:io';
  2. import 'package:dio/dio.dart';
  3. import 'package:eitc_erm_app/bean/normal_response.dart';
  4. import 'package:eitc_erm_app/my_doctor.dart';
  5. import 'package:eitc_erm_app/patient_list.dart';
  6. import 'package:eitc_erm_app/patient_talk_list.dart';
  7. import 'package:eitc_erm_app/record_registration.dart';
  8. import 'package:eitc_erm_app/utils/Component.dart';
  9. import 'package:eitc_erm_app/utils/Constants.dart';
  10. import 'package:eitc_erm_app/utils/Utils.dart';
  11. import 'package:eitc_erm_app/utils/logger.dart';
  12. import 'package:eitc_erm_app/widget/image_error.dart';
  13. import 'package:eitc_erm_app/widget/user_header.dart';
  14. import 'package:file_picker/file_picker.dart';
  15. import 'package:flutter/material.dart';
  16. import 'package:flutter/services.dart';
  17. import 'package:http/http.dart' as http;
  18. import 'package:package_info_plus/package_info_plus.dart';
  19. import 'package:permission_handler/permission_handler.dart';
  20. import 'bean/upload_entity.dart';
  21. import 'bean/user_list.dart';
  22. import 'change_password.dart';
  23. import 'change_phoneno.dart';
  24. import 'login.dart';
  25. void main() {
  26. WidgetsFlutterBinding.ensureInitialized();
  27. runApp(Mine());
  28. }
  29. class Mine extends StatefulWidget {
  30. @override
  31. State<StatefulWidget> createState() => MineState();
  32. }
  33. class MineState extends State<Mine> {
  34. late Future<UserListEntity?> _future;
  35. @override
  36. void initState() {
  37. super.initState();
  38. _future = fetchData();
  39. }
  40. MethodChannel _channel = MethodChannel('channel_name');
  41. Future<String?> get platformVersion async {
  42. final String? version = await _channel.invokeMethod('getPlatformVersion');
  43. return version;
  44. }
  45. Future<UserListEntity?> fetchData() async {
  46. Map<String, String> headers = {
  47. 'token': Global.token,
  48. };
  49. final response =
  50. await http.get(Uri.parse('${Global.BaseUrl}user/list'), headers: jsonHeaders(withToken: true));
  51. if (response.statusCode == 200) {
  52. final json = decodeBodyToJson(response.bodyBytes);
  53. logd("就诊人列表=$json");
  54. UserListEntity mUserListEntity = new UserListEntity.fromJson(json);
  55. for (int i = 0; i < mUserListEntity.data!.length; i++) {
  56. logd("=================${mUserListEntity.data![i].isDefault}");
  57. if (mUserListEntity.data?[i].isDefault == 1 &&
  58. Global.selectPatient == -1) {
  59. Global.appointmentPersonId = mUserListEntity.data![i].patientId!;
  60. Global.selectPatient = i;
  61. Global.patient = mUserListEntity;
  62. }
  63. }
  64. return mUserListEntity;
  65. } else {
  66. Component.toast("出错了,请稍后再试!", 0);
  67. }
  68. }
  69. Future<void> initPlatformState() async {
  70. //相机权限
  71. if (await requestCameraPermission() == false) {
  72. return;
  73. }
  74. //录音权限
  75. if (await requestMicrophonePermission() == false) {
  76. return;
  77. }
  78. }
  79. Future<bool> requestCameraPermission() async {
  80. var status = await Permission.camera.status;
  81. if (status == PermissionStatus.granted) {
  82. return true;
  83. } else {
  84. status = await Permission.camera.request();
  85. if (status == PermissionStatus.granted) {
  86. return true;
  87. } else {
  88. return false;
  89. }
  90. }
  91. }
  92. Future<bool> requestMicrophonePermission() async {
  93. //获取当前的权限
  94. var status = await Permission.microphone.status;
  95. if (status == PermissionStatus.granted) {
  96. //已经授权
  97. return true;
  98. } else {
  99. //未授权则发起一次申请
  100. status = await Permission.microphone.request();
  101. if (status == PermissionStatus.granted) {
  102. return true;
  103. } else {
  104. return false;
  105. }
  106. }
  107. }
  108. @override
  109. Widget build(BuildContext context) {
  110. return Scaffold(
  111. appBar: AppBar(
  112. title: const Text('个人中心',
  113. style: TextStyle(
  114. color: Colors.white,
  115. )),
  116. centerTitle: true,
  117. elevation: 0.5,
  118. backgroundColor: Global.StatusBarColor,
  119. ),
  120. body: SingleChildScrollView(
  121. child: Column(
  122. mainAxisSize: MainAxisSize.min,
  123. crossAxisAlignment: CrossAxisAlignment.start,
  124. children: <Widget>[
  125. Container(
  126. decoration: const BoxDecoration(
  127. color: Global.StatusBarColor,
  128. ),
  129. child: Padding(
  130. padding: const EdgeInsets.all(20),
  131. child: Row(
  132. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  133. children: [
  134. Row(
  135. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  136. children: [
  137. GestureDetector(
  138. onTap: () {
  139. uploadFile();
  140. },
  141. child: FutureBuilder(
  142. future: Utils.readData("userAvatar"),
  143. builder: (ctx, shot) {
  144. Widget imageError = const ImageError(
  145. icon: Icons.account_circle,
  146. size: 60,
  147. color: Colors.white,
  148. );
  149. if (shot.connectionState !=
  150. ConnectionState.done) {
  151. return imageError;
  152. } else {
  153. if (shot.hasError ||
  154. !shot.hasData ||
  155. shot.data == null ||
  156. shot.data!.isEmpty) {
  157. return imageError;
  158. }
  159. return UserHeader(
  160. url:
  161. "${Global.ImageUrl}${shot.data!}",
  162. placeHolder: imageError,
  163. );
  164. }
  165. }),
  166. ),
  167. Text(
  168. ' ${Global.loginPhoneNo}',
  169. style: const TextStyle(
  170. fontSize: 18, color: Colors.white),
  171. ),
  172. ]),
  173. GestureDetector(
  174. onTap: () {
  175. Navigator.push(
  176. context,
  177. MaterialPageRoute(
  178. builder: (context) => PatientTalkList()),
  179. );
  180. },
  181. child: const Icon(
  182. Icons.message,
  183. color: Colors.white,
  184. ),
  185. ),
  186. ]),
  187. ),
  188. ),
  189. Container(
  190. width: double.infinity,
  191. height: 100,
  192. decoration: const BoxDecoration(
  193. image: DecorationImage(
  194. image: AssetImage('assets/images/mine_bg.png'),
  195. fit: BoxFit.cover,
  196. ),
  197. ),
  198. child: Row(
  199. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  200. children: [
  201. GestureDetector(
  202. onTap: () {
  203. Navigator.push(
  204. context,
  205. MaterialPageRoute(
  206. builder: (context) => PatientList()),
  207. );
  208. },
  209. child: const Column(
  210. mainAxisAlignment: MainAxisAlignment.center,
  211. mainAxisSize: MainAxisSize.max,
  212. children: [
  213. Icon(
  214. Icons.person,
  215. color: Colors.orange,
  216. ),
  217. Text(
  218. '就诊人管理',
  219. style: TextStyle(
  220. fontSize: 14,
  221. color: Colors.orange,
  222. ),
  223. )
  224. ])),
  225. GestureDetector(
  226. onTap: () {
  227. Navigator.push(
  228. context,
  229. MaterialPageRoute(
  230. builder: (context) => MyDoctor()),
  231. );
  232. },
  233. child: const Column(
  234. mainAxisAlignment: MainAxisAlignment.center,
  235. mainAxisSize: MainAxisSize.max,
  236. children: [
  237. Icon(
  238. Icons.data_saver_on_outlined,
  239. color: Colors.green,
  240. ),
  241. Text(
  242. '收藏的医生',
  243. style: TextStyle(
  244. fontSize: 14,
  245. color: Colors.green,
  246. ),
  247. )
  248. ])),
  249. ]),
  250. ),
  251. GestureDetector(
  252. behavior: HitTestBehavior.opaque,
  253. onTap: () {
  254. Navigator.push(
  255. context,
  256. MaterialPageRoute(
  257. builder: (context) => RecordRegistration()),
  258. );
  259. },
  260. child: const Row(
  261. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  262. children: [
  263. Row(
  264. mainAxisAlignment: MainAxisAlignment.center,
  265. children: [
  266. Padding(
  267. padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
  268. child: Icon(
  269. Icons.receipt_long,
  270. color: Colors.green,
  271. )),
  272. Text(
  273. '预约挂号记录',
  274. style: TextStyle(fontSize: 18),
  275. ),
  276. ]),
  277. Padding(
  278. padding: EdgeInsets.fromLTRB(10, 20, 20, 20),
  279. child: Icon(
  280. Icons.keyboard_double_arrow_right,
  281. color: Colors.grey,
  282. ),
  283. ),
  284. ]),
  285. ),
  286. Padding(
  287. padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
  288. child: Container(
  289. width: double.infinity,
  290. height: 1.0,
  291. padding: const EdgeInsets.all(50),
  292. decoration: const BoxDecoration(
  293. gradient: LinearGradient(
  294. colors: [Colors.black, Colors.white],
  295. begin: Alignment.center,
  296. end: Alignment.centerRight,
  297. tileMode: TileMode.mirror,
  298. ),
  299. ),
  300. child: const Image(
  301. image: AssetImage('assets/images/line.png'),
  302. ),
  303. ),
  304. ),
  305. /*GestureDetector(
  306. onTap: () {
  307. */ /*Navigator.push(
  308. context,
  309. MaterialPageRoute(
  310. builder: (context) => MyApp()),
  311. );*/ /*
  312. if (Platform.isIOS) {
  313. platformVersion;
  314. } else if (Platform.isAndroid) {
  315. launchAndroid();
  316. }
  317. },
  318. child: Row(
  319. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  320. children: [
  321. Row(
  322. mainAxisAlignment: MainAxisAlignment.center,
  323. children: [
  324. Padding(
  325. padding: const EdgeInsets.fromLTRB(
  326. 20, 20, 20, 20),
  327. child: Icon(
  328. Icons.phone_android_sharp,
  329. color: Colors.lightBlueAccent,
  330. )),
  331. Text(
  332. '我的设备',
  333. style: const TextStyle(fontSize: 18),
  334. ),
  335. ]),
  336. Padding(
  337. padding:
  338. const EdgeInsets.fromLTRB(10, 20, 20, 20),
  339. child: Icon(
  340. Icons.keyboard_double_arrow_right,
  341. color: Colors.grey,
  342. ),
  343. ),
  344. ]),
  345. ),
  346. Padding(
  347. padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
  348. child: Container(
  349. width: double.infinity,
  350. height: 1.0,
  351. padding: const EdgeInsets.all(50),
  352. decoration: BoxDecoration(
  353. gradient: LinearGradient(
  354. colors: [Colors.black, Colors.white],
  355. begin: Alignment.center,
  356. end: Alignment.centerRight,
  357. tileMode: TileMode.mirror,
  358. ),
  359. ),
  360. child: Image(
  361. image: AssetImage('assets/images/line.png'),
  362. ),
  363. ),
  364. ),*/
  365. GestureDetector(
  366. behavior: HitTestBehavior.opaque,
  367. onTap: () {
  368. Navigator.push(
  369. context,
  370. MaterialPageRoute(
  371. builder: (context) => ChangePasswordPage()),
  372. );
  373. },
  374. child: const Row(
  375. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  376. children: [
  377. Row(
  378. mainAxisAlignment: MainAxisAlignment.center,
  379. children: [
  380. Padding(
  381. padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
  382. child: Icon(
  383. Icons.password_outlined,
  384. color: Colors.deepPurple,
  385. )),
  386. Text(
  387. '修改密码',
  388. style: TextStyle(fontSize: 18),
  389. ),
  390. ]),
  391. Padding(
  392. padding: EdgeInsets.fromLTRB(10, 20, 20, 20),
  393. child: Icon(
  394. Icons.keyboard_double_arrow_right,
  395. color: Colors.grey,
  396. ),
  397. ),
  398. ]),
  399. ),
  400. Padding(
  401. padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
  402. child: Container(
  403. width: double.infinity,
  404. height: 1.0,
  405. padding: const EdgeInsets.all(50),
  406. decoration: const BoxDecoration(
  407. gradient: LinearGradient(
  408. colors: [Colors.black, Colors.white],
  409. begin: Alignment.center,
  410. end: Alignment.centerRight,
  411. tileMode: TileMode.mirror,
  412. ),
  413. ),
  414. child: const Image(
  415. image: AssetImage('assets/images/line.png'),
  416. ),
  417. ),
  418. ),
  419. GestureDetector(
  420. behavior: HitTestBehavior.opaque,
  421. onTap: () {
  422. Navigator.push(
  423. context,
  424. MaterialPageRoute(builder: (context) => ChangePhoneNo()),
  425. );
  426. },
  427. child: const Row(
  428. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  429. children: [
  430. Row(
  431. mainAxisAlignment: MainAxisAlignment.center,
  432. children: [
  433. Padding(
  434. padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
  435. child: Icon(
  436. Icons.mobile_screen_share,
  437. color: Colors.red,
  438. )),
  439. Text(
  440. '修改手机号',
  441. style: TextStyle(fontSize: 18),
  442. ),
  443. ]),
  444. Padding(
  445. padding: EdgeInsets.fromLTRB(10, 20, 20, 20),
  446. child: Icon(
  447. Icons.keyboard_double_arrow_right,
  448. color: Colors.grey,
  449. ),
  450. ),
  451. ]),
  452. ),
  453. Padding(
  454. padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
  455. child: Container(
  456. width: double.infinity,
  457. height: 1.0,
  458. padding: const EdgeInsets.all(50),
  459. decoration: const BoxDecoration(
  460. gradient: LinearGradient(
  461. colors: [Colors.black, Colors.white],
  462. begin: Alignment.center,
  463. end: Alignment.centerRight,
  464. tileMode: TileMode.mirror,
  465. ),
  466. ),
  467. child: const Image(
  468. image: AssetImage('assets/images/line.png'),
  469. ),
  470. ),
  471. ),
  472. GestureDetector(
  473. behavior: HitTestBehavior.opaque,
  474. onTap: () async {
  475. PackageInfo packageInfo = await PackageInfo.fromPlatform();
  476. showDialog(
  477. context: context,
  478. builder: (ctx) {
  479. return AlertDialog(
  480. title: Text(packageInfo.appName),
  481. content: Text("版本:${packageInfo.version}"),
  482. actions: [
  483. TextButton(
  484. onPressed: () => Navigator.pop(ctx),
  485. child: const Text("关闭"))
  486. ],
  487. );
  488. });
  489. },
  490. child: const Row(
  491. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  492. children: [
  493. Row(
  494. mainAxisAlignment: MainAxisAlignment.center,
  495. children: [
  496. Padding(
  497. padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
  498. child: Icon(
  499. Icons.info_outline,
  500. color: Colors.red,
  501. )),
  502. Text(
  503. '关于',
  504. style: TextStyle(fontSize: 18),
  505. ),
  506. ]),
  507. Padding(
  508. padding: EdgeInsets.fromLTRB(10, 20, 20, 20),
  509. child: Icon(
  510. Icons.keyboard_double_arrow_right,
  511. color: Colors.grey,
  512. ),
  513. ),
  514. ]),
  515. ),
  516. Padding(
  517. padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
  518. child: Container(
  519. width: double.infinity,
  520. height: 1.0,
  521. padding: const EdgeInsets.all(50),
  522. decoration: const BoxDecoration(
  523. gradient: LinearGradient(
  524. colors: [Colors.black, Colors.white],
  525. begin: Alignment.center,
  526. end: Alignment.centerRight,
  527. tileMode: TileMode.mirror,
  528. ),
  529. ),
  530. child: const Image(
  531. image: AssetImage('assets/images/line.png'),
  532. ),
  533. ),
  534. ),
  535. Container(
  536. width: double.infinity,
  537. padding: const EdgeInsets.fromLTRB(20, 50, 20, 0),
  538. child: ElevatedButton(
  539. style: ButtonStyle(
  540. backgroundColor:
  541. WidgetStateProperty.resolveWith<Color>((states) {
  542. return Colors.blue; // Regular color
  543. }),
  544. ),
  545. onPressed: () {
  546. logout();
  547. },
  548. child: const Text("退出",
  549. style: TextStyle(color: Colors.white, fontSize: 15)),
  550. ),
  551. )
  552. ]),
  553. ));
  554. }
  555. Future<String?> logout() async {
  556. Utils.saveData("token", "");
  557. Utils.saveData("userId", "");
  558. Utils.saveData("userAvatar", "");
  559. Map<String, String> headers = {
  560. 'token': Global.token,
  561. };
  562. var response =
  563. await http.get(Uri.parse('${Global.BaseUrl}logout'), headers: headers);
  564. if (response.statusCode == 200) {
  565. final json = decodeBodyToJson(response.bodyBytes);
  566. logd("登出结果=$json");
  567. NormalResponse mNormalResponse = new NormalResponse.fromJson(json);
  568. if (mNormalResponse.code == Global.responseSuccessCode) {
  569. } else {
  570. Component.toast(mNormalResponse.msg.toString(), 0);
  571. }
  572. Navigator.pushReplacement(
  573. context,
  574. MaterialPageRoute(builder: (context) => Login()),
  575. );
  576. return response.toString();
  577. } else {
  578. Navigator.pushReplacement(
  579. context,
  580. MaterialPageRoute(builder: (context) => Login()),
  581. );
  582. return null;
  583. }
  584. }
  585. void uploadFile() async {
  586. FilePickerResult? result =
  587. await FilePicker.platform.pickFiles(type: FileType.image);
  588. if (result != null) {
  589. String fileName = result.files.single.name;
  590. String? filePath = result.files.single.path;
  591. FormData formData = FormData.fromMap({
  592. "file": await MultipartFile.fromFile(filePath!, filename: fileName),
  593. });
  594. Component.toast("正在上传头像,请稍后", 2);
  595. try {
  596. Map<String, String> headers = {
  597. 'token': Global.token,
  598. };
  599. Response response = await Dio().post('${Global.BaseUrl}common/upload',
  600. data: formData, options: Options(headers: headers));
  601. if (response.statusCode == 200) {
  602. var json = decodeBodyToJson(response.data);
  603. logd("上传头像文件结果=$json");
  604. UploadEntity mUploadEntity = UploadEntity.fromJson(json);
  605. if (mUploadEntity.code == Global.responseSuccessCode) {
  606. logd("uploaded=${mUploadEntity.toJson()}");
  607. //保存头像
  608. bool result = await _saveAvatar(mUploadEntity.fileName ?? "");
  609. if (result) {
  610. setState(() {
  611. Component.toast("上传成功!", 2);
  612. });
  613. return;
  614. }
  615. Component.toast("出错了,请稍后再试!", 0);
  616. } else {
  617. Component.toast(mUploadEntity.msg.toString(), 0);
  618. }
  619. } else {
  620. Component.toast("出错了,请稍后再试!", 0);
  621. return null;
  622. }
  623. } catch (e) {
  624. logd(e);
  625. }
  626. }
  627. }
  628. Future<bool> _saveAvatar(String path) async {
  629. if (path.isEmpty) {
  630. return Future.value(false);
  631. }
  632. Map<String, dynamic> params = {"id": Global.userId, "avatar": path};
  633. try {
  634. var response = await http.post(Uri.parse("${Global.BaseUrl}user/edit"),
  635. body: encodeBody(params), headers: jsonHeaders(withToken: true));
  636. if (response.statusCode == 200) {
  637. final json = decodeBodyToJson(response.bodyBytes);
  638. logd("保存头像结果=$json");
  639. if (json["code"] != 200) {
  640. return Future.value(false);
  641. }
  642. await Utils.saveData("userAvatar", path);
  643. return Future.value(true);
  644. } else {
  645. return Future.value(false);
  646. }
  647. } catch (e) {
  648. logd("更新头像异常,e=$e");
  649. }
  650. return Future.value(false);
  651. }
  652. Future<void> launchAndroid() async {
  653. const platform = MethodChannel('com.example.xcx_dashan_app/channel');
  654. try {
  655. var result = await platform.invokeMethod('launchApp');
  656. // var result = await platform.invokeMethod('launchAppOne',{'param1': "这是一个参数"});
  657. // var result = await platform.invokeMethod('launchAppOne',{'param1': "这是一个参数",'param2': "这是一个参数"});
  658. logd("结果$result");
  659. } on PlatformException catch (e) {
  660. logd("Failed to invoke method: '${e.message}'.");
  661. }
  662. }
  663. }