Browse Source

新增窗口行为

loki.wu 1 year ago
parent
commit
992b5fc944

+ 28 - 0
lib/pages/home/controller.dart

@@ -1,5 +1,6 @@
 import 'dart:async';
 
+import 'package:fis_common/js_plateform/js_platform.dart';
 import 'package:fis_jsonrpc/rpc.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
@@ -21,6 +22,8 @@ import 'package:vnote_device_plugin/consts/types.dart';
 import 'state.dart';
 
 class HomeController extends FControllerBase with HomeNavMixin {
+  static const String _windowName = "Main";
+
   /// 仅支持在线模式的菜单路由
   static final _onlineOnlyMenuRouteNames = <String>[
     "/contract/package_list",
@@ -488,6 +491,31 @@ class HomeController extends FControllerBase with HomeNavMixin {
   Widget _buildContent() {
     return const TwelveHeartRate();
   }
+
+  ///开启拖拽
+  Future<void> onStartDrag() async {
+    JSPlateForm.beginWindowDrag(_windowName);
+  }
+
+  ///结束拖拽
+  Future<void> onEndDrag() async {
+    JSPlateForm.endWindowDrag(_windowName);
+  }
+
+  ///最小化
+  Future<void> onMinimize() async {
+    JSPlateForm.minimizeWindow(_windowName);
+  }
+
+  ///最大化
+  Future<void> onMaximize() async {
+    JSPlateForm.maximizeWindow(_windowName);
+  }
+
+  ///关闭
+  Future<void> onWindowClose() async {
+    JSPlateForm.closeWindow(_windowName);
+  }
 }
 
 class _PatientAddIconProxyWidget extends StatelessWidget {

+ 5 - 0
lib/pages/home/state.dart

@@ -8,6 +8,7 @@ class HomeState {
   final RxList<HomeMenuItem> _menuItems = RxList.empty();
   final RxString _currentSelectMenu = RxString('/medical');
   final RxBool _isOnline = RxBool(true);
+  final Rx<bool> _isMaximized = Rx(false);
 
   /// 版本号
   String get version => "1.0.0.100";
@@ -26,6 +27,10 @@ class HomeState {
   set menuItems(Iterable<HomeMenuItem> val) =>
       _menuItems.value = List<HomeMenuItem>.from(val).obs;
 
+  ///窗口是否最大化
+  bool get isMaximized => _isMaximized.value;
+  set isMaximized(bool v) => _isMaximized.value = v;
+
   /// 当前选中菜单
   String get currentSelectMenu => _currentSelectMenu.value;
   set currentSelectMenu(String val) => _currentSelectMenu.value = val;

+ 94 - 27
lib/pages/home/view.dart

@@ -1,3 +1,4 @@
+import 'package:fis_theme/theme.dart';
 import 'package:fis_ui/values/icons.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
@@ -17,6 +18,7 @@ import 'widgets/menus.dart';
 import 'widgets/navigator.dart';
 import 'widgets/patient.dart';
 import 'widgets/status_bar.dart';
+import 'widgets/title_bar_buttons.dart';
 
 class HomePage extends GetView<HomeController> {
   const HomePage({super.key});
@@ -209,33 +211,23 @@ class HomePage extends GetView<HomeController> {
         ),
       ),
       child: Center(
-        child: Row(
-          mainAxisSize: MainAxisSize.max,
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          children: [
-            Expanded(
-              flex: 4,
-              child: Align(
-                alignment: Alignment.centerLeft,
-                child: _buildHeaderLeft(),
-              ),
-            ),
-            Flexible(
-              flex: 4,
-              child: Align(
-                alignment: Alignment.center,
-                child: _buildHeaderCenter(),
-              ),
-            ),
-            Expanded(
-              flex: 6,
-              child: Align(
-                alignment: Alignment.centerRight,
-                child: _buildHeaderRight(context),
-              ),
-            ),
-          ],
-        ),
+        child: kIsWeb
+            ? GestureDetector(
+                onPanStart: (event) {
+                  controller.onStartDrag();
+                },
+                onPanEnd: (e) {
+                  controller.onEndDrag();
+                },
+                onDoubleTap: () {
+                  controller.onMaximize();
+                },
+                onPanCancel: () {
+                  controller.onEndDrag();
+                },
+                child: _buildWindowTitle(context),
+              )
+            : _buildWindowTitle(context),
       ),
     );
   }
@@ -257,6 +249,13 @@ class HomePage extends GetView<HomeController> {
             ),
           ),
         ),
+        if (kIsWeb)
+          Expanded(
+            child: Container(
+              color: Colors.transparent,
+              height: 60,
+            ),
+          ),
       ],
     );
   }
@@ -268,6 +267,13 @@ class HomePage extends GetView<HomeController> {
       crossAxisAlignment: CrossAxisAlignment.center,
       children: [
         const SizedBox(width: 10),
+        if (kIsWeb)
+          Expanded(
+            child: Container(
+              color: Colors.transparent,
+              height: 60,
+            ),
+          ),
         Column(
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
@@ -294,6 +300,13 @@ class HomePage extends GetView<HomeController> {
             ),
           ],
         ),
+        if (kIsWeb)
+          Expanded(
+            child: Container(
+              color: Colors.transparent,
+              height: 60,
+            ),
+          ),
       ],
     );
   }
@@ -304,6 +317,13 @@ class HomePage extends GetView<HomeController> {
       mainAxisAlignment: MainAxisAlignment.center,
       crossAxisAlignment: CrossAxisAlignment.center,
       children: [
+        if (kIsWeb)
+          Expanded(
+            child: Container(
+              color: Colors.transparent,
+              height: 60,
+            ),
+          ),
         if (!kIsWeb && Store.user.kIsVitalStation)
           IconButton(
             onPressed: () {
@@ -350,6 +370,53 @@ class HomePage extends GetView<HomeController> {
             ),
           ),
         ),
+        if (kIsWeb) ...[
+          Padding(
+            padding: EdgeInsets.symmetric(horizontal: 8),
+            child: VerticalDivider(
+              indent: 12,
+              endIndent: 12,
+              color: Colors.white,
+            ),
+          ),
+          TitleBarButtons(
+            controller.onMinimize,
+            controller.onWindowClose,
+            controller.onMaximize,
+            Colors.white,
+            Colors.transparent,
+          ),
+        ],
+      ],
+    );
+  }
+
+  Widget _buildWindowTitle(BuildContext context) {
+    return Row(
+      mainAxisSize: MainAxisSize.max,
+      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+      children: [
+        Expanded(
+          flex: 4,
+          child: Align(
+            alignment: Alignment.centerLeft,
+            child: _buildHeaderLeft(),
+          ),
+        ),
+        Flexible(
+          flex: 4,
+          child: Align(
+            alignment: Alignment.center,
+            child: _buildHeaderCenter(),
+          ),
+        ),
+        Expanded(
+          flex: 6,
+          child: Align(
+            alignment: Alignment.centerRight,
+            child: _buildHeaderRight(context),
+          ),
+        ),
       ],
     );
   }

+ 174 - 0
lib/pages/home/widgets/title_bar_buttons.dart

@@ -0,0 +1,174 @@
+import 'package:fis_theme/theme.dart';
+import 'package:fis_ui/index.dart';
+import 'package:fis_ui/interface/interactive_container.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:vitalapp/pages/home/controller.dart';
+
+class TitleBarButtons extends StatefulWidget {
+  final VoidCallback onMinimize;
+  final VoidCallback onWindowClose;
+  final VoidCallback? onMaximize;
+  final Color iconColor;
+  final Color backgroundColor;
+  late final Color? hoverColor;
+  late final Color? hoverIconColor;
+
+  TitleBarButtons(
+    this.onMinimize,
+    this.onWindowClose,
+    this.onMaximize,
+    this.iconColor,
+    this.backgroundColor, {
+    Color? hoverColor,
+    Color? hoverIconColor,
+  }) {
+    if (hoverColor == null) {
+      this.hoverColor = FTheme.ins.colorScheme.secondary;
+    } else {
+      this.hoverColor = hoverColor;
+    }
+    if (hoverIconColor == null) {
+      this.hoverIconColor = iconColor;
+    } else {
+      this.hoverIconColor = hoverIconColor;
+    }
+  }
+
+  @override
+  State<StatefulWidget> createState() {
+    return _TitleBarButtonsState();
+  }
+}
+
+class _TitleBarButtonsState extends State<TitleBarButtons> {
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      height: 40,
+      child: Row(
+        crossAxisAlignment: CrossAxisAlignment.center,
+        mainAxisAlignment: MainAxisAlignment.end,
+        children: [
+          HoverIconButton(
+            widget.iconColor,
+            widget.onMinimize,
+            FIcon(Icons.remove),
+            widget.backgroundColor,
+            hoverColor: widget.hoverColor,
+            hoverIconColor: widget.hoverIconColor,
+          ),
+          if (widget.onMaximize != null) ...[
+            HoverIconButton(
+              widget.iconColor,
+              widget.onMaximize!,
+              Obx(() {
+                var controller = Get.find<HomeController>();
+                if (!controller.state.isMaximized) {
+                  return FIcon(Icons.crop_square);
+                } else {
+                  return FIcon(Icons.filter_none);
+                }
+              }),
+              widget.backgroundColor,
+              hoverColor: widget.hoverColor,
+              hoverIconColor: widget.hoverIconColor,
+            ),
+          ],
+          HoverIconButton(
+            widget.iconColor,
+            widget.onWindowClose,
+            FIcon(Icons.close),
+            widget.backgroundColor,
+            hoverColor: Colors.red,
+            hoverIconColor: widget.hoverIconColor,
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class HoverIconButton extends StatefulWidget {
+  final Color iconColor;
+  final Color backgroundColor;
+  final VoidCallback onPressed;
+  final Widget icon;
+
+  late final Color? hoverColor;
+  late final Color? hoverIconColor;
+  late final double? width;
+  late final double? height;
+
+  HoverIconButton(
+    this.iconColor,
+    this.onPressed,
+    this.icon,
+    this.backgroundColor, {
+    Color? hoverColor,
+    Color? hoverIconColor,
+    double? height,
+    double? width,
+  }) {
+    if (hoverColor == null) {
+      this.hoverColor = backgroundColor;
+    } else {
+      this.hoverColor = hoverColor;
+    }
+    this.height = height;
+    this.width = width;
+    if (hoverIconColor == null) {
+      this.hoverIconColor = iconColor;
+    } else {
+      this.hoverIconColor = hoverIconColor;
+    }
+  }
+  @override
+  State<StatefulWidget> createState() {
+    return HoverIconButtonState();
+  }
+}
+
+class HoverIconButtonState extends State<HoverIconButton> {
+  Color _backgroundColor = Colors.transparent;
+  late Color _iconColor;
+  late final Color hoverColor;
+  late final Color hoverIconColor;
+  @override
+  void initState() {
+    _iconColor = widget.iconColor;
+    hoverColor = widget.hoverColor ?? widget.backgroundColor;
+    hoverIconColor = widget.hoverIconColor ?? _iconColor;
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return MouseRegion(
+      onEnter: (event) {
+        setState(() {
+          _iconColor = hoverIconColor;
+          _backgroundColor = hoverColor;
+        });
+      },
+      onExit: (event) {
+        setState(() {
+          _iconColor = widget.iconColor;
+          _backgroundColor = widget.backgroundColor;
+        });
+      },
+      child: Container(
+        width: widget.width,
+        height: widget.height,
+        color: _backgroundColor,
+        child: IconButton(
+          color: _iconColor,
+          onPressed: () {
+            widget.onPressed.call();
+          },
+          icon: widget.icon,
+        ),
+      ),
+    );
+  }
+}

+ 42 - 0
web/js/index.js

@@ -27,6 +27,48 @@ function externalNotification(a, b) {
     window.invokeJs(a, b);
 }
 
+function closeSlaveWindow() {
+    var shell = window["FisShellApi"];
+    if (shell) {
+        shell.closeSlaveWindow();
+    }
+}
+
+function beginWindowDrag(name) {
+    var shell = window["FisShellApi"];
+    if (shell) {
+        shell.beginWindowDrag(name);
+    }
+}
+
+function endWindowDrag(name) {
+    var shell = window["FisShellApi"];
+    if (shell) {
+        shell.endWindowDrag(name);
+    }
+}
+
+function closeWindow(name) {
+    var shell = window["FisShellApi"];
+    if (shell) {
+        shell.closeWindow(name);
+    }
+}
+
+function maximizeWindow(name) {
+    var shell = window["FisShellApi"];
+    if (shell) {
+        shell.maximizeWindow(name);
+    }
+}
+
+function minimizeWindow(name) {
+    var shell = window["FisShellApi"];
+    if (shell) {
+        shell.minimizeWindow(name);
+    }
+}
+
 ///打印pdf
 function printPdfByBase64(base64) {
     printJS({