view.dart 6.1 KB

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