view.dart 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import 'package:flutter/foundation.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_inappwebview/flutter_inappwebview.dart';
  4. import 'package:get/get.dart';
  5. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  6. import 'package:vitalapp/components/appbar.dart';
  7. import 'package:vitalapp/components/button.dart';
  8. import 'package:webviewx/webviewx.dart';
  9. import 'controller.dart';
  10. // ignore: must_be_immutable
  11. class ContractTemplatePage extends GetView<ContractTemplateController> {
  12. ContractTemplatePage({super.key});
  13. late InAppWebViewController? _webViewAppController;
  14. late WebViewXController? _webViewWebController;
  15. @override
  16. Widget build(BuildContext context) {
  17. return Scaffold(
  18. // backgroundColor: const Color.fromRGBO(238, 238, 238, 1),
  19. appBar: VAppBar(
  20. titleWidget: const Text(
  21. "合同",
  22. style: TextStyle(fontSize: 24),
  23. ),
  24. ),
  25. body: Column(
  26. children: [
  27. Expanded(
  28. child: _buildWebView(context),
  29. ),
  30. Obx(
  31. () => Container(
  32. height: 100,
  33. padding: const EdgeInsets.symmetric(vertical: 20),
  34. child: Row(
  35. mainAxisAlignment: MainAxisAlignment.spaceAround,
  36. children: [
  37. VButton(
  38. label: "签字",
  39. onTap: () => gotoSignature(),
  40. ),
  41. if (controller.state.userSignature != '')
  42. VButton(
  43. label: "提交",
  44. onTap: () => controller.submitContract(),
  45. ),
  46. ],
  47. ),
  48. ),
  49. )
  50. ],
  51. ),
  52. );
  53. }
  54. Future<void> _scrollToBottom() async {
  55. if (_webViewAppController != null) {
  56. await _webViewAppController!.scrollTo(
  57. x: 0,
  58. y: 3000,
  59. animated: true,
  60. );
  61. }
  62. }
  63. Widget _buildAppWebView() {
  64. return FutureBuilder(
  65. future: controller.loadData(),
  66. builder: (context, snapshot) {
  67. if (snapshot.connectionState != ConnectionState.done) {
  68. return const Center(
  69. child: SizedBox(
  70. width: 20,
  71. height: 20,
  72. child: CircularProgressIndicator(),
  73. ),
  74. );
  75. } else {
  76. return InAppWebView(
  77. initialData: InAppWebViewInitialData(
  78. data:
  79. '<body style="padding: 100px;">${controller.state.templateContent}</body>',
  80. ),
  81. initialOptions: InAppWebViewGroupOptions(
  82. crossPlatform: InAppWebViewOptions(
  83. useShouldOverrideUrlLoading: false,
  84. mediaPlaybackRequiresUserGesture: false,
  85. cacheEnabled: true,
  86. ),
  87. android: AndroidInAppWebViewOptions(
  88. //设置为 true 以启用混合组合
  89. useHybridComposition: true,
  90. ),
  91. ),
  92. onLoadStart: (controller, url) {
  93. PromptBox.loading('加载合同中');
  94. // 显示加载指示器
  95. },
  96. onLoadStop: (controller, url) {
  97. PromptBox.dismiss();
  98. },
  99. onWebViewCreated: (InAppWebViewController controller) {
  100. _webViewAppController = controller;
  101. },
  102. );
  103. }
  104. },
  105. );
  106. }
  107. Widget _buildWebwebview(BuildContext context) {
  108. return FutureBuilder<String>(
  109. future: _loadLocalHtml(context,
  110. '<html><body style="padding: 100px 0px;">${controller.state.templateContent}</body></html>'),
  111. builder: (context, snapshot) {
  112. if (!snapshot.hasData) {
  113. return const Center(child: CircularProgressIndicator());
  114. // return FCenter(child: FText("${i18nBook.common.loading.t}..."));
  115. } else {
  116. return WebViewX(
  117. height: MediaQuery.of(Get.context!).size.height,
  118. width: MediaQuery.of(Get.context!).size.width,
  119. initialSourceType: SourceType.html,
  120. initialContent:
  121. '<html><body style="padding: 100px;">${controller.state.templateContent}</body></html>',
  122. javascriptMode: JavascriptMode.unrestricted,
  123. onWebResourceError: (p0) {},
  124. onWebViewCreated: (controller) {
  125. _webViewWebController = controller;
  126. },
  127. );
  128. }
  129. },
  130. );
  131. }
  132. Widget _buildWebView(BuildContext context) {
  133. if (kIsWeb) {
  134. return _buildWebwebview(context);
  135. } else {
  136. return _buildAppWebView();
  137. }
  138. }
  139. Future<String> _loadLocalHtml(BuildContext context, String assetKey) async {
  140. // await Future.delayed(const Duration(milliseconds: 200));
  141. // final start = DateTime.now();
  142. // final content = await DefaultAssetBundle.of(context).loadString(assetKey);
  143. // final end = DateTime.now();
  144. await controller.loadData();
  145. return assetKey;
  146. }
  147. Future<void> gotoSignature() async {
  148. final result = await Get.toNamed("/contract/signature");
  149. if (kDebugMode) {
  150. // TODO: 调试记录签名
  151. // await TextStorage(
  152. // fileName: "signature_${DateTime.now().millisecondsSinceEpoch}.txt",
  153. // directory: "debug",
  154. // ).save(result);
  155. }
  156. controller.state.userSignature = result;
  157. final dto = await controller.contractTemplateManager
  158. .getContractTemplateDetail(controller.state.templateCode);
  159. if (dto != null) {
  160. controller.state.templateContent = dto.templateContent ?? '';
  161. controller.getkey();
  162. }
  163. _scrollToBottom();
  164. if (kIsWeb) {
  165. _webViewWebController?.loadContent(
  166. '<body style="padding: 100px;">${controller.state.templateContent}</body>',
  167. SourceType.html,
  168. );
  169. } else {
  170. _webViewAppController?.loadData(
  171. data:
  172. '<body style="padding: 100px;">${controller.state.templateContent}</body>',
  173. mimeType: 'text/html',
  174. encoding: 'utf-8',
  175. );
  176. }
  177. }
  178. }