Răsfoiți Sursa

1、登录新版云服务上传FISIMPL的版本号,2、部分中英文翻译修正3、配置页新增图像采集设置4、排版调整5、修复云服务列表没有翻译的问题,6、更新最新WingDll

felix 1 an în urmă
părinte
comite
a60363e7fd
24 a modificat fișierele cu 608 adăugiri și 91 ștergeri
  1. 2 0
      FISSDK/FISIMPL/ConnectionService.cs
  2. 17 1
      Vinno.FIS.Sonopost/Assets/wwwroot/components/NetworkSettingForm.html
  3. 10 5
      Vinno.FIS.Sonopost/Assets/wwwroot/js/index.js
  4. 22 11
      Vinno.FIS.Sonopost/Assets/wwwroot/lang/en-us.json
  5. 17 6
      Vinno.FIS.Sonopost/Assets/wwwroot/lang/zh-cn.json
  6. 269 0
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/dicom/capture.html
  7. 7 4
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/dicom/sono.html
  8. 9 1
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/dicom/station.html
  9. 0 1
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/live/camera01.html
  10. 1 3
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/live/sono.html
  11. 34 28
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/server/login.html
  12. 3 1
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/system/recover.html
  13. 4 2
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/system/restart.html
  14. 1 1
      Vinno.FIS.Sonopost/Assets/wwwroot/pages/system/version.html
  15. 24 0
      Vinno.FIS.Sonopost/Common/EnumKey.cs
  16. 1 1
      Vinno.FIS.Sonopost/Common/SonopostConstants.cs
  17. 30 0
      Vinno.FIS.Sonopost/Features/Config/CaptureSetting.cs
  18. 71 24
      Vinno.FIS.Sonopost/Features/Config/SonopostUserDefinedSettingInfo.cs
  19. 6 0
      Vinno.FIS.Sonopost/Vinno.FIS.Sonopost.csproj
  20. 43 0
      Vinno.FIS.Sonopost/WebApi/Controllers/DicomController.cs
  21. 28 0
      Vinno.FIS.Sonopost/WebApi/Models/CaptureSettingRequest.cs
  22. 8 2
      Vinno.vCloud.Common.FIS/ConnectionInfo.cs
  23. 1 0
      Vinno.vCloud.Common.FIS/vCloudTerminalV2.cs
  24. BIN
      packages/WingInterfaceLibrary.dll

+ 2 - 0
FISSDK/FISIMPL/ConnectionService.cs

@@ -161,6 +161,7 @@ namespace FISIMPL
                 FISFolder = FISIMPL.UltrasoundMachineInfo.FISFolder,
                 USScreenHeight = FISIMPL.UltrasoundMachineInfo.USScreenHeight,
                 USScreenWidth = FISIMPL.UltrasoundMachineInfo.USScreenWidth,
+                FISIMPLVersion = Assembly.GetExecutingAssembly().GetName().Version,
                 IsOnlyUsedToRegister = false,
             };
             if (_vCloudTerminal != null)
@@ -242,6 +243,7 @@ namespace FISIMPL
                 FISFolder = FISIMPL.UltrasoundMachineInfo.FISFolder,
                 USScreenHeight = FISIMPL.UltrasoundMachineInfo.USScreenHeight,
                 USScreenWidth = FISIMPL.UltrasoundMachineInfo.USScreenWidth,
+                FISIMPLVersion = Assembly.GetExecutingAssembly().GetName().Version,
                 IsOnlyUsedToRegister = false,
             };
             if (_vCloudTerminal != null)

+ 17 - 1
Vinno.FIS.Sonopost/Assets/wwwroot/components/NetworkSettingForm.html

@@ -1,7 +1,7 @@
 <component name="NetworkSettingForm">
     <style>
         .netsetform-com {
-            width: 650px;
+            width: 550px;
         }
 
             .netsetform-com .device-name {
@@ -16,6 +16,22 @@
             .netsetform-com input::placeholder {
                 color: #ccc;
             }
+
+        .lang-cn .netsetform-com .layui-form-item .layui-form-label {
+            width: 70px;
+        }
+
+        .lang-en .netsetform-com .layui-form-item .layui-form-label {
+            width: 105px;
+        }
+
+        .lang-cn .netsetform-com .layui-form-item .layui-input-block {
+            margin-left: 105px;
+        }
+
+        .lang-en .netsetform-com .layui-form-item .layui-input-block {
+            margin-left: 140px;
+        }
     </style>
     <script type="text/html" id="tplNetworkSettingForm">
         <div class="netsetform-com sonopost-card layui-form page-form">

+ 10 - 5
Vinno.FIS.Sonopost/Assets/wwwroot/js/index.js

@@ -708,16 +708,21 @@ $(async function () {
                 title: "PageTitle4DicomSono",
                 path: "sono"
             },
-            {
-                name: "DicomFailList",
-                title: "PageTitle4DicomFailList",
-                path: "faillist"
-            },
             {
                 name: "DicomStation",
                 title: "PageTitle4DicomStation",
                 path: "station"
             },
+            {
+                name: "CaptureSetting",
+                title: "PageTitle4CaptureSetting",
+                path: "capture"
+            },
+            {
+                name: "DicomFailList",
+                title: "PageTitle4DicomFailList",
+                path: "faillist"
+            },
             ]
         }, {
             name: "NewworkManager",

+ 22 - 11
Vinno.FIS.Sonopost/Assets/wwwroot/lang/en-us.json

@@ -21,21 +21,21 @@
   "PageTitle4NetworkAdvance": "Advanced setting",
   "PageTitle4SystemReboot": "Reboot",
   "PageTitle4SystemRecover": "Recover",
-  "PageTitle4SystemOledLang": "Mini oled language",
+  "PageTitle4SystemOledLang": "Mini oled language setting",
   "PageTitle4SystemLog": "System log",
-  "PageTitle4SystemVersion": "Version",
-  "PageTitle4RainbowImage": "Rainbow Image Detect",
-  "PageTitle4VCloudLogin": "VCloud Login",
-  "PageDesc4ServerLogin": "You need to select the vCloud server of the sonopost box to successfully log in the cloud service. After the QR code appears in the ultrasonic box, indicating that the cloud service has been logged in successfully",
-  "PageDesc4ServerRegister": "You need to create a new account for the box when the first time to install it",
-  "PageDesc4ServerNetCheck": "When the ultrasonic magic box fails to log in due to various reasons, the network detection and troubleshooting can be carried out",
+  "PageTitle4SystemVersion": "Version info",
+  "PageTitle4RainbowImage": "Rainbow Image Detect setting",
+  "PageTitle4VCloudLogin": "VCloud login setting",
+  "PageDesc4ServerLogin": "You need to select the vCloud server of sonopost to successfully log in the cloud service. After the QR code appears in sonopost, indicating that the cloud service has been logged in successfully",
+  "PageDesc4ServerRegister": "You need to create a new account for sonopost when the first time to install it",
+  "PageDesc4ServerNetCheck": "When sonopost fails to log in due to various reasons, the network detection and troubleshooting can be carried out",
   "PageDesc4LiveSono": "Enable the live broadcast of the ultrasonic machine, select the appropriate resolution and save it, then you can watch the real-time live broadcast of the ultrasonic machine",
   "PageDesc4LiveCamera01": "Enable camera live broadcast, select the appropriate resolution and save it, then you can watch the scanning image",
   "PageDesc4LiveCamera02": "Enable camera 2 live broadcast, select the appropriate resolution and save it, then you can watch the scanning image",
   "PageDesc4LiveMic": "Enable mic live broadcast,you can save it, then it can acquire sound",
-  "PageDesc4DicomSono": "Enable DICOM connection and relevant Settings are completed in DICOM setting of ultrasonic machine,then you can transmit the images or videos stored in the ultrasonic machine to the time-sharing diagnosis list",
+  "PageDesc4DicomSono": "Enable DICOM connection,The image or video stored in the ultrasound machine can be transferred to the time-sharing diagnostic list of the vCloud service",
   "PageDesc4DicomFailList": "Time-sharing diagnosis may have transmission failure due to network fluctuations. Relevant cases can be selected from this list and retransmitted",
-  "PageDesc4DicomStation": "Enabled the DICOM connection of workstation, then the images or videos transmitted by the ultrasonic machine can be forwarded to the DICOM workstation through the ultrasonic magic box",
+  "PageDesc4DicomStation": "Enabled the DICOM connection of vStation, then The image or video transmitted by the ultrasound machine can be forwarded to the vStation through sonopost",
   "PageDesc4NetworkWifi": "In a WIFI environment, the WIFI network can be searched and connected",
   "PageDesc4NetworkAdvance": "If the Sonopost is connected to the external network and the internal network at the same time, the external network is connected to the cloud service, and the internal network is connected to the DICOM storage, this setting shall be enabled",
   "DeviceBindingQrCodeGuide": "Use Flyinsono scan or manually enter a unique code to bind the device",
@@ -92,7 +92,7 @@
   "NetworkStatus": "Network status",
   "CloudServerConnection": "Cloud server connection",
   "LiveService": "Live service",
-  "TimeSharedDiagnosisService": "Time-shared diagnosis service",
+  "TimeSharedDiagnosisService": "Time-sharing diagnosis service",
   "FirmwareVersion": "Firmware version",
   "SaveSetting": "Save setting",
   "SaveConfig": "Save config",
@@ -217,5 +217,16 @@
   "LogOffError": "Log Off Error",
   "Offline": "Offline",
   "Online": "Online",
-  "Logoning": "Logoning"
+  "Logoning": "Logoning",
+  "PageTitle4CaptureSetting": "Image capture setting",
+  "PageDesc4CaptureSetting": "Enable image capture, a single frame image/video can be captured by configuring the foot toggle and transmitted to the time-sharing diagnostic list of the vCloud service",
+  "SingleFrameImageCaptureSwitch": "Single Frame Image Capture Toggle Shortcut",
+  "VideoCaptureSwitch": "Video Capture Toggle Shortcut",
+  "LeftKeySetting": "Foot Toggle Left Key Keyboard Shortcut",
+  "RightKeySetting": "Foot Toggle Right Key Keyboard Shortcut",
+  "EnableCaptureSetting": "Enable Image Capture",
+  "FootSwitchConflict": "Foot toggle setting is conflict,please reset.",
+  "KeyBoardKeyConflict": "Keyboard key setting is conflict,please reset.",
+  "FootSwitchLeftKey": "Foot toggle left key",
+  "FootSwitchRightKey": "Foot toggle right key"
 }

+ 17 - 6
Vinno.FIS.Sonopost/Assets/wwwroot/lang/zh-cn.json

@@ -12,8 +12,8 @@
   "PageTitle4LiveCamera01": "摄像机直播设置",
   "PageTitle4LiveCamera02": "摄像机2直播设置",
   "PageTitle4LiveMic": "麦克风直播设置",
-  "PageTitle4DicomSono": "超声机DICOM连接",
-  "PageTitle4DicomStation": "工作站DICOM连接",
+  "PageTitle4DicomSono": "超声机DICOM连接设置",
+  "PageTitle4DicomStation": "工作站DICOM连接设置",
   "PageTitle4DicomFailList": "传输失败列表",
   "PageTitle4NetworkWire": "有线网络连接设置",
   "PageTitle4NetworkWifi": "无线网络连接设置",
@@ -23,7 +23,7 @@
   "PageTitle4SystemRecover": "恢复魔盒出厂设置",
   "PageTitle4SystemOledLang": "迷你屏幕语言设置",
   "PageTitle4SystemLog": "系统日志",
-  "PageTitle4SystemVersion": "版本信息查看",
+  "PageTitle4SystemVersion": "版本信息",
   "PageTitle4RainbowImage": "彩虹图监测设置",
   "PageTitle4VCloudLogin": "云服务登录设置",
   "PageDesc4ServerLogin": "请选择云服务器方可成功登录云服务,二维码出现后,意味着超声魔盒成功登录至云服务",
@@ -33,9 +33,9 @@
   "PageDesc4LiveCamera01": "启用摄像机直播,选择合适的分辨率并保存,可观看扫查手法画面",
   "PageDesc4LiveCamera02": "启用摄像机2直播,选择合适的分辨率并保存,可观看扫查手法画面",
   "PageDesc4LiveMic": "启用麦克风,直播时可采集音频。",
-  "PageDesc4DicomSono": "启用DICOM连接,在超声机DICOM设置中完成相关设置,可将超声机内存储的图像或视频传输至分时诊断列表",
+  "PageDesc4DicomSono": "启用DICOM连接,可将超声机内存储的图像或视频传输至云服务的分时诊断列表",
   "PageDesc4DicomFailList": "分时诊断可能存在因网络波动而传输失败的情况,可在此列表中选择相关病例并重传",
-  "PageDesc4DicomStation": "启用工作站DICOM连接,可通过超声魔盒将超声机上传的图像或视频转发至DICOM工作站",
+  "PageDesc4DicomStation": "启用工作站DICOM连接,可将超声机上传的图像或视频通过超声魔盒转发至工作站",
   "PageDesc4NetworkWifi": "在Wifi环境中,可搜索Wifi网络并连接",
   "PageDesc4NetworkAdvance": "如超声魔盒同时连接外网和内网,外网连接云服务,内网连接超声机DICOM存储,则需开启此设置",
   "DeviceBindingQrCodeGuide": "使用杏聆荟扫一扫或手动输入唯一码可绑定该设备",
@@ -217,5 +217,16 @@
   "LogOffError": "注销失败",
   "Offline": "离线状态",
   "Online": "在线状态",
-  "Logoning": "正在登录"
+  "Logoning": "正在登录",
+  "PageTitle4CaptureSetting": "图像采集设置",
+  "PageDesc4CaptureSetting": "启用图像采集功能,可通过配置脚踏开关采集单帧图/视频,并传输到云服务的分时诊断列表",
+  "SingleFrameImageCaptureSwitch": "单帧图采集开关快捷键",
+  "VideoCaptureSwitch": "视频采集开关快捷键",
+  "LeftKeySetting": "脚踏开关左键键盘快捷键",
+  "RightKeySetting": "脚踏开关右键键盘快捷键",
+  "EnableCaptureSetting": "启用图像采集功能",
+  "FootSwitchConflict": "脚踏开关按键冲突,请重新设置",
+  "KeyBoardKeyConflict": "键盘按键冲突,请重新设置",
+  "FootSwitchLeftKey": "脚踏开关左键",
+  "FootSwitchRightKey": "脚踏开关右键"
 }

+ 269 - 0
Vinno.FIS.Sonopost/Assets/wwwroot/pages/dicom/capture.html

@@ -0,0 +1,269 @@
+<style>
+    .lang-en .layui-form-item .layui-form-label {
+        width: 300px;
+    }
+
+    .lang-en .layui-form-item .layui-input-block {
+        margin-left: 330px;
+    }
+
+    .lang-cn .layui-form-item .layui-form-label {
+        width: 160px;
+    }
+
+    .lang-cn .layui-form-item .layui-input-block {
+        margin-left: 190px;
+    }
+</style>
+<div>
+    <div class="page-title" data-content="PageTitle4CaptureSetting"></div>
+    <div class="page-desc" data-content="PageDesc4CaptureSetting"></div>
+    <div class="layui-form page-form" lay-filter="FormCaptureSetting">
+        <div class="layui-form-item">
+            <div class="layui-inline">
+                <input type="checkbox"
+                       name="EnableCaptureSetting"
+                       id="EnableCaptureSetting"
+                       lay-filter="EnableCaptureSetting"
+                       lay-skin="switch" />
+                <label class="layui-form-label"
+                       style="float: right;"
+                       data-content="EnableCaptureSetting"></label>
+            </div>
+        </div>
+        <div id="captureSettingContainer">
+            <div class="layui-form-item">
+                <label class="layui-form-label" data-content="SingleFrameImageCaptureSwitch"></label>
+                <div class="layui-input-block">
+                    <select name="SingleFrameImageCaptureSwitch" lay-filter="SingleFrameImageCaptureSwitch">
+                    </select>
+                </div>
+            </div>
+            <div class="layui-form-item">
+                <label class="layui-form-label" data-content="VideoCaptureSwitch"></label>
+                <div class="layui-input-block">
+                    <select name="VideoCaptureSwitch" lay-filter="VideoCaptureSwitch"></select>
+                </div>
+            </div>
+            <div class="layui-form-item">
+                <label class="layui-form-label" data-content="LeftKeySetting"></label>
+                <div class="layui-input-block">
+                    <select name="LeftKeySetting" lay-filter="LeftKeySetting"></select>
+                </div>
+            </div>
+            <div class="layui-form-item">
+                <label class="layui-form-label" data-content="RightKeySetting"></label>
+                <div class="layui-input-block">
+                    <select name="RightKeySetting" lay-filter="RightKeySetting">
+                    </select>
+                </div>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <button class="layui-btn layui-btn-normal"
+                    lay-submit
+                    lay-filter="BtnSave"
+                    data-content="SaveConfig"></button>
+        </div>
+    </div>
+</div>
+<script>
+    function Page(app, runtime) {
+        const { $api, $t, $c, $loading } = runtime;
+        const { form, layer } = layui;
+        const formFilter = "FormCaptureSetting";
+        this.onload = async function () {
+            let loadingIndex = $loading();
+            try {
+                let res = await $api("dicom", "GetCaptureSetting");
+                if (!res.IsSuccess) {
+                    layer.msg.error($t(res.Code));
+                }
+                $("#EnableCaptureSetting").prop("checked", res.Data.CaptureEnabled);
+                if (!res.Data.CaptureEnabled) {
+                    $("#captureSettingContainer").hide();
+                }
+                let options = [];
+                options.push(`<option value="0" data-content="FootSwitchLeftKey">${$t("FootSwitchLeftKey")}</option>`);
+                options.push(`<option value="1" data-content="FootSwitchRightKey">${$t("FootSwitchRightKey")}</option>`);
+                form.find(formFilter, "SingleFrameImageCaptureSwitch").empty().append(options);
+                form.find(formFilter, "VideoCaptureSwitch").empty().append(options);
+                let el = form.find(formFilter, "SingleFrameImageCaptureSwitch");
+                el.val(res.Data.ImageCaptureForFootSwitchKey);
+                el = form.find(formFilter, "VideoCaptureSwitch");
+                el.val(res.Data.VideoCaptureForFootSwitchKey);
+                options = [];
+                options.push(`<option value="0">F1</option>`);
+                options.push(`<option value="1">F2</option>`);
+                options.push(`<option value="2">F3</option>`);
+                options.push(`<option value="3">F4</option>`);
+                options.push(`<option value="4">F5</option>`);
+                options.push(`<option value="5">F6</option>`);
+                options.push(`<option value="6">F7</option>`);
+                options.push(`<option value="7">F8</option>`);
+                options.push(`<option value="8">F9</option>`);
+                options.push(`<option value="9">F10</option>`);
+                options.push(`<option value="10">F11</option>`);
+                options.push(`<option value="11">F12</option>`);
+                try {
+                    let index = parseInt(res.Data.VideoCaptureForKeyBoardKey);
+                    if (index >= 0 && index <= 11) {
+                        options.splice(index, 1);
+                    }
+                } catch {
+                    console.log("ParseInt Error");
+                }
+                form.find(formFilter, "LeftKeySetting").empty().append(options);
+                options = [];
+                options.push(`<option value="0">F1</option>`);
+                options.push(`<option value="1">F2</option>`);
+                options.push(`<option value="2">F3</option>`);
+                options.push(`<option value="3">F4</option>`);
+                options.push(`<option value="4">F5</option>`);
+                options.push(`<option value="5">F6</option>`);
+                options.push(`<option value="6">F7</option>`);
+                options.push(`<option value="7">F8</option>`);
+                options.push(`<option value="8">F9</option>`);
+                options.push(`<option value="9">F10</option>`);
+                options.push(`<option value="10">F11</option>`);
+                options.push(`<option value="11">F12</option>`);
+                try {
+                    let index = parseInt(res.Data.ImageCaptureForKeyBoardKey);
+                    if (index >= 0 && index <= 11) {
+                        options.splice(index, 1);
+                    }
+                } catch {
+                    console.log("ParseInt Error");
+                }
+                form.find(formFilter, "RightKeySetting").empty().append(options);
+                el = form.find(formFilter, "LeftKeySetting");
+                el.val(res.Data.ImageCaptureForKeyBoardKey);
+                el = form.find(formFilter, "RightKeySetting");
+                el.val(res.Data.VideoCaptureForKeyBoardKey);
+                form.render(null, formFilter);
+            } finally {
+                layer.close(loadingIndex);
+            }
+        }
+
+        form.on("select(SingleFrameImageCaptureSwitch)", function (data) {
+            let value = data.value;
+            if (value === "1") {
+                let el = form.find(formFilter, "VideoCaptureSwitch");
+                el.val("0");
+            }
+            else if (value == "0") {
+                let el = form.find(formFilter, "VideoCaptureSwitch");
+                el.val("1");
+            }
+            form.render("select", formFilter);
+        });
+
+        form.on("select(VideoCaptureSwitch)", function (data) {
+            let value = data.value;
+            if (value === "1") {
+                let el = form.find(formFilter, "SingleFrameImageCaptureSwitch");
+                el.val("0");
+            }
+            else if (value == "0") {
+                let el = form.find(formFilter, "SingleFrameImageCaptureSwitch");
+                el.val("1");
+            }
+            form.render("select", formFilter);
+        });
+
+        form.on("select(LeftKeySetting)", function (data) {
+            let options = [];
+            options.push(`<option value="0">F1</option>`);
+            options.push(`<option value="1">F2</option>`);
+            options.push(`<option value="2">F3</option>`);
+            options.push(`<option value="3">F4</option>`);
+            options.push(`<option value="4">F5</option>`);
+            options.push(`<option value="5">F6</option>`);
+            options.push(`<option value="6">F7</option>`);
+            options.push(`<option value="7">F8</option>`);
+            options.push(`<option value="8">F9</option>`);
+            options.push(`<option value="9">F10</option>`);
+            options.push(`<option value="10">F11</option>`);
+            options.push(`<option value="11">F12</option>`);
+            try {
+                let index = parseInt(data.value);
+                if (index >= 0 && index <= 11) {
+                    options.splice(index, 1);
+                }
+            } catch {
+                console.log("ParseInt Error");
+            }
+            let el = form.find(formFilter, "RightKeySetting");
+            let oldValue = el.val();
+            form.find(formFilter, "RightKeySetting").empty().append(options);
+            el.val(oldValue);
+            form.render("select", formFilter);
+        });
+
+        form.on("select(RightKeySetting)", function (data) {
+            let options = [];
+            options.push(`<option value="0">F1</option>`);
+            options.push(`<option value="1">F2</option>`);
+            options.push(`<option value="2">F3</option>`);
+            options.push(`<option value="3">F4</option>`);
+            options.push(`<option value="4">F5</option>`);
+            options.push(`<option value="5">F6</option>`);
+            options.push(`<option value="6">F7</option>`);
+            options.push(`<option value="7">F8</option>`);
+            options.push(`<option value="8">F9</option>`);
+            options.push(`<option value="9">F10</option>`);
+            options.push(`<option value="10">F11</option>`);
+            options.push(`<option value="11">F12</option>`);
+            try {
+                let index = parseInt(data.value);
+                if (index >= 0 && index <= 11) {
+                    options.splice(index, 1);
+                }
+            } catch {
+                console.log("ParseInt Error");
+            }
+            let el = form.find(formFilter, "LeftKeySetting");
+            let oldValue = el.val();
+            form.find(formFilter, "LeftKeySetting").empty().append(options);
+            el.val(oldValue);
+            form.render("select", formFilter);
+        });
+
+        form.on("switch(EnableCaptureSetting)", async function (data) {
+            let checked = data.elem.checked;
+            if (checked) {
+                $("#captureSettingContainer").show();
+            } else {
+                $("#captureSettingContainer").hide();
+            }
+        });
+
+        form.on("submit(BtnSave)", async function (data) {
+            await handleSave(this, data.field);
+        });
+
+        async function handleSave(e, data) {
+            let loadingIndex = $loading();
+            try {
+                data.EnableCaptureSetting = data.EnableCaptureSetting === "on";
+                let request = {
+                    CaptureEnabled: data.EnableCaptureSetting,
+                    ImageCaptureForFootSwitchKey: data.SingleFrameImageCaptureSwitch,
+                    VideoCaptureForFootSwitchKey: data.VideoCaptureSwitch,
+                    ImageCaptureForKeyBoardKey: data.LeftKeySetting,
+                    VideoCaptureForKeyBoardKey: data.RightKeySetting,
+                };
+                let res = await $api("dicom", "SaveCaptureSetting", request);
+                if (!res.IsSuccess) {
+                    layer.msg.error($t(res.Code));
+                }
+                else {
+                    layer.msg.success($t("SaveSuccess"));
+                }
+            } finally {
+                layer.close(loadingIndex);
+            }
+        }
+    }
+</script>

+ 7 - 4
Vinno.FIS.Sonopost/Assets/wwwroot/pages/dicom/sono.html

@@ -1,10 +1,14 @@
 <style>
+    .lang-en .layui-form-item .layui-form-label {
+        width: 135px;
+    }
+
     .lang-en .layui-form-item .layui-input-block {
         margin-left: 165px;
     }
 
-    .lang-en .layui-form-item .layui-form-label {
-        width: 135px;
+    .lang-cn .layui-form-item .layui-form-label {
+        width: 100px;
     }
 </style>
 <div id="pageDicomSono">
@@ -86,7 +90,6 @@
         }
 
         async function CheckInput(data) {
-            console.log("1");
             var regexPort = new RegExp(/^-?\d+$/);
             if (data.IsEnable) {
                 if (data.Title == "" || data.Title == null || data.Title == undefined) {
@@ -144,4 +147,4 @@
             }
         }
     }
-</script>
+</script>

+ 9 - 1
Vinno.FIS.Sonopost/Assets/wwwroot/pages/dicom/station.html

@@ -1,4 +1,12 @@
-<style></style>
+<style>
+    .lang-en .layui-form-item .layui-form-label {
+        width: 135px;
+    }
+
+    .lang-cn .layui-form-item .layui-form-label {
+        width: 100px;
+    }
+</style>
 <div id="pageCameraLive">
     <div class="page-title" data-content="PageTitle4DicomStation"></div>
     <div class="page-desc" data-content="PageDesc4DicomStation"></div>

+ 0 - 1
Vinno.FIS.Sonopost/Assets/wwwroot/pages/live/camera01.html

@@ -188,7 +188,6 @@
 
         async function saveCameraInfo(data) {
             data.IsEnable = data.IsEnable === "on";
-            console.log("tttt");
             if (data.IsEnable) {
                 if (data.Id == null || data.Id == "" || data.Id == undefined) {
                     layer.msg.error($t("DeviceSelectTips"));

+ 1 - 3
Vinno.FIS.Sonopost/Assets/wwwroot/pages/live/sono.html

@@ -26,7 +26,7 @@
             <label class="layui-form-label" data-content="Brand"></label>
             <div class="layui-input-block">
                 <select name="Brand"
-                        lay-filter="Brand" ></select>
+                        lay-filter="Brand"></select>
             </div>
         </div>
         <div class="layui-form-item">
@@ -186,7 +186,6 @@
         async function loadBrandSeclect(brand, model) {
             let loadingIndex = $loading();
             try {
-                console.log("444");
                 let res = await $api("live", "GetBrandList");
                 if (res.IsSuccess && res.Data.length) {
                     brandArray = res.Data;
@@ -230,7 +229,6 @@
                 let res = await $api("live", "GetModelList", {
                     Brand: brand
                 });
-                console.log("111");
                 if (res.IsSuccess && res.Data.length) {
                     renderSelect(
                         "Model",

+ 34 - 28
Vinno.FIS.Sonopost/Assets/wwwroot/pages/server/login.html

@@ -152,12 +152,11 @@
             let loadingIndex = $loading();
             try {
                 await initServerNodeSelect();
-                form.on("submit(BtnLogin)", function (data) {
-                    handleLogin(this, data.field);
-                    return false;
+                form.on("submit(BtnLogin)", async function (data) {
+                    await handleLogin(this, data.field);
                 });
-                form.on("submit(BtnDisconnect)", function () {
-                    handleLogout(this);
+                form.on("submit(BtnDisconnect)", async function () {
+                    await handleLogout(this);
                 });
                 let accountInput = form.find(formFilter, "AccountInput");
                 let passwordInput = form.find(formFilter, "PasswordInput");
@@ -223,26 +222,33 @@
         }
 
         async function initServerNodeSelect() {
-            console.log("initServerNodeSelect");
             let res = await $api("server", "GetServerList");
             if (!res.IsSuccess) return;
             let options = [];
             res.Data.forEach((x) => {
-                options.push(`<option value="${x.Host}:${x.Port}@${x.DisplayName}">${$t(x.DisplayName)}</option>`);
-
+                if (x.DisplayName === "FlyinsonoServer") {
+                    options.push(`<option value="${x.Host}:${x.Port}@${x.DisplayName}" data-content="FlyinsonoServer">${$t(x.DisplayName)}</option>`);
+                }
+                else if (x.DisplayName === "CloudServerInChina") {
+                    options.push(`<option value="${x.Host}:${x.Port}@${x.DisplayName}" data-content="CloudServerInChina">${$t(x.DisplayName)}</option>`);
+                }
+                else if (x.DisplayName === "CloudServerInGermany") {
+                    options.push(`<option value="${x.Host}:${x.Port}@${x.DisplayName}" data-content="CloudServerInGermany">${$t(x.DisplayName)}</option>`);
+                }
+                else if (x.DisplayName === "CloudServerInHongKong") {
+                    options.push(`<option value="${x.Host}:${x.Port}@${x.DisplayName}" data-content="CloudServerInHongKong">${$t(x.DisplayName)}</option>`);
+                }
+                else {
+                    options.push(`<option value="${x.Host}:${x.Port}@${x.DisplayName}">${$t(x.DisplayName)}</option>`);
+                }
             });
-            options.push(
-                `<option value="custom" data-content="CloudServerByCustom">${$t(
-                    "CloudServerByCustom"
-                )}</option>`
-            );
+            options.push(`<option value="custom" data-content="CloudServerByCustom">${$t("CloudServerByCustom")}</option>`);
             form.find(formFilter, "ServerNode").empty().append(options);
             form.render("select", formFilter);
             initServerNodeEvent();
         }
         function initServerNodeEvent() {
             form.on("select(ServerNode)", function (data) {
-                console.log("initServerNodeEvent");
                 let ip = data.value;
                 let port = 9096;
                 let serverName = "";
@@ -277,19 +283,18 @@
 
         async function handleLogin(e, data) {
             let loadingIndex = $loading();
-            if (data.ServerName == "") {
-                data.ServerName = data.ServerAddress + ":" + data.ServerPort;
-            }
-            let request = {
-                Ipv4: data.ServerAddress,
-                Port: data.ServerPort,
-                Account: data.Account,
-                Password: data.Password,
-                HospitalName: data.HospitalName,
-                ServerName: data.ServerName,
-            };
-
             try {
+                if (data.ServerName == "") {
+                    data.ServerName = data.ServerAddress + ":" + data.ServerPort;
+                }
+                let request = {
+                    Ipv4: data.ServerAddress,
+                    Port: data.ServerPort,
+                    Account: data.Account,
+                    Password: data.Password,
+                    HospitalName: data.HospitalName,
+                    ServerName: data.ServerName,
+                };
                 var res = await $api("server", "login", request);
                 let organization = form.find(formFilter, "Organization");
                 let hospitalNameInput = form.find(formFilter, "HospitalNameInput");
@@ -325,12 +330,13 @@
         function addNewServerNode(ip, port) {
             let option = $("<option></option>");
             let address = ip + ":" + port;
-            option.val(address);
+            let value = ip + ":" + port + "@" + ip + ":" + port;
+            option.val(value);
             option.text(address);
             let el = form.find(formFilter, "ServerNode");
             let customOption = el.children("option").last();
             option.insertBefore(customOption);
-            el.val(address);
+            el.val(value);
         }
 
         async function handleLogout(e) {

+ 3 - 1
Vinno.FIS.Sonopost/Assets/wwwroot/pages/system/recover.html

@@ -1,5 +1,7 @@
 <div>
-    <button class="layui-btn layui-btn-normal" id="btnRecover" data-content="RecoverSonopost"></button>
+    <div class="layui-form-item">
+        <button class="layui-btn layui-btn-normal" id="btnRecover" data-content="RecoverSonopost"></button>
+    </div>
 </div>
 <script>
     function Page(app, runtime) {

+ 4 - 2
Vinno.FIS.Sonopost/Assets/wwwroot/pages/system/restart.html

@@ -1,11 +1,13 @@
 <div>
-    <button class="layui-btn layui-btn-normal" id="btnRestart" data-content="RestartSonopost"></button>
+    <div class="layui-form-item">
+        <button class="layui-btn layui-btn-normal" id="btnRestart" data-content="RestartSonopost"></button>
+    </div>
 </div>
 <script>
     function Page(app, runtime) {
         const { $api, $t } = runtime;
         const { layer } = layui;
-        
+
         this.onload = function () {
             $("#btnRestart").on('click', function () {
                 $api("system", "Reboot").then(res => {

+ 1 - 1
Vinno.FIS.Sonopost/Assets/wwwroot/pages/system/version.html

@@ -6,7 +6,7 @@
         const { $api, $t } = runtime;
         const { form, layer } = layui;
         let version = '';
-        
+
         this.onload = function () {
             let el = $("#lineVersion");
             el.empty();

+ 24 - 0
Vinno.FIS.Sonopost/Common/EnumKey.cs

@@ -0,0 +1,24 @@
+namespace Vinno.FIS.Sonopost.Common
+{
+    internal enum EnumKeyboardKey
+    {
+        F1Key,
+        F2Key,
+        F3Key,
+        F4Key,
+        F5Key,
+        F6Key,
+        F7Key,
+        F8Key,
+        F9Key,
+        F10Key,
+        F11Key,
+        F12Key,
+    }
+
+    internal enum EnumFootSwitchKey
+    {
+        LeftKey,
+        RightKey,
+    }
+}

+ 1 - 1
Vinno.FIS.Sonopost/Common/SonopostConstants.cs

@@ -28,6 +28,6 @@
         public const string HongkongServer = "s01.flyinsono.com:9096";
         public const string HongkongServerHost = "s01.flyinsono.com";
 
-        public const int CurrentSonopostUserDefinedSettingVersion = 1;
+        public const int CurrentSonopostUserDefinedSettingVersion = 2;
     }
 }

+ 30 - 0
Vinno.FIS.Sonopost/Features/Config/CaptureSetting.cs

@@ -0,0 +1,30 @@
+using Vinno.FIS.Sonopost.Common;
+
+namespace Vinno.FIS.Sonopost.Features.Config
+{
+    internal class CaptureSetting
+    {
+        public bool CaptureEnabled { get; set; }
+
+        /// <summary>
+        /// 截图对应的脚踏开关键(左或右),与录屏键互斥
+        /// </summary>
+        public EnumFootSwitchKey ImageCaptureForFootSwitchKey { get; set; }
+
+        /// <summary>
+        /// 录制视频对应的脚踏开关键(左或右),与截图键互斥
+        /// </summary>
+        public EnumFootSwitchKey VideoCaptureForFootSwitchKey { get; set; }
+
+        /// <summary>
+        /// 截图对应的键盘按键(F1-F12),与录屏键互斥
+        /// </summary>
+
+        public EnumKeyboardKey ImageCaptureForKeyBoardKey { get; set; }
+
+        /// <summary>
+        /// 录制视频对应的键盘按键0(F1-F12),与截图键互斥
+        /// </summary>
+        public EnumKeyboardKey VideoCaptureForKeyBoardKey { get; set; }
+    }
+}

+ 71 - 24
Vinno.FIS.Sonopost/Features/Config/SonopostUserDefinedSettingInfo.cs

@@ -22,6 +22,8 @@ namespace Vinno.FIS.Sonopost.Features.Config
         public OledSetting OledSetting { get; set; }
         public PageSetting PageSetting { get; set; }
 
+        public CaptureSetting CaptureSetting { get; set; }
+
         public int Version { get; set; }
     }
 
@@ -74,6 +76,14 @@ namespace Vinno.FIS.Sonopost.Features.Config
                     {
                         Language = Language.Chinese,
                     },
+                    CaptureSetting = new CaptureSetting
+                    {
+                        CaptureEnabled = false,
+                        ImageCaptureForFootSwitchKey = EnumFootSwitchKey.LeftKey,
+                        VideoCaptureForFootSwitchKey = EnumFootSwitchKey.RightKey,
+                        ImageCaptureForKeyBoardKey = EnumKeyboardKey.F1Key,
+                        VideoCaptureForKeyBoardKey = EnumKeyboardKey.F2Key,
+                    },
                     Version = SonopostConstants.CurrentSonopostUserDefinedSettingVersion,
                 };
                 Instance.Save();
@@ -101,30 +111,8 @@ namespace Vinno.FIS.Sonopost.Features.Config
                 }
                 if (Instance.Version < SonopostConstants.CurrentSonopostUserDefinedSettingVersion)
                 {
-                    if (Instance.Version == 0)
-                    {
-                        if (Instance.PageSetting == null)//老版的配置文件可能为空,
-                        {
-                            Instance.PageSetting = new PageSetting
-                            {
-                                Language = Language.Chinese,
-                            };
-                        }
-                        if (!Instance.ServerSetting.Servers.Any(x => x.DisplayName == SonopostConstants.ChinaServerName && x.IsDefault))
-                        {
-                            Instance.ServerSetting.Servers.Insert(1, new ServerInfoSetting(SonopostConstants.ChinaServerHost, 9096, true, ""));
-                        }
-                        if (!Instance.ServerSetting.Servers.Any(x => x.DisplayName == SonopostConstants.GermanyServerName && x.IsDefault))
-                        {
-                            Instance.ServerSetting.Servers.Insert(2, new ServerInfoSetting(SonopostConstants.GermanyServerHost, 9096, true, ""));
-                        }
-                        if (!Instance.ServerSetting.Servers.Any(x => x.DisplayName == SonopostConstants.HongkongServerName && x.IsDefault))
-                        {
-                            Instance.ServerSetting.Servers.Insert(3, new ServerInfoSetting(SonopostConstants.HongkongServerHost, 9096, true, ""));
-                        }
-                        Instance.Version = SonopostConstants.CurrentSonopostUserDefinedSettingVersion;
-                        Instance.Save();
-                    }
+                    UpdateVersionFrom0To1();
+                    UpdateVersionFrom1To2();
                 }
                 return true;
             }
@@ -134,6 +122,65 @@ namespace Vinno.FIS.Sonopost.Features.Config
             return false;
         }
 
+        private static void UpdateVersionFrom0To1()
+        {
+            if (Instance.Version == 0)
+            {
+                if (Instance.PageSetting == null)//老版的配置文件可能为空,
+                {
+                    Instance.PageSetting = new PageSetting
+                    {
+                        Language = Language.Chinese,
+                    };
+                }
+                if (!Instance.ServerSetting.Servers.Any(x => x.DisplayName == SonopostConstants.ChinaServerName && x.IsDefault))
+                {
+                    Instance.ServerSetting.Servers.Insert(1, new ServerInfoSetting(SonopostConstants.ChinaServerHost, 9096, true, ""));
+                }
+                if (!Instance.ServerSetting.Servers.Any(x => x.DisplayName == SonopostConstants.GermanyServerName && x.IsDefault))
+                {
+                    Instance.ServerSetting.Servers.Insert(2, new ServerInfoSetting(SonopostConstants.GermanyServerHost, 9096, true, ""));
+                }
+                if (!Instance.ServerSetting.Servers.Any(x => x.DisplayName == SonopostConstants.HongkongServerName && x.IsDefault))
+                {
+                    Instance.ServerSetting.Servers.Insert(3, new ServerInfoSetting(SonopostConstants.HongkongServerHost, 9096, true, ""));
+                }
+                if (Instance.CaptureSetting == null || Instance.CaptureSetting.ImageCaptureForFootSwitchKey == Instance.CaptureSetting.VideoCaptureForFootSwitchKey || Instance.CaptureSetting.ImageCaptureForKeyBoardKey == Instance.CaptureSetting.VideoCaptureForKeyBoardKey)
+                {
+                    Instance.CaptureSetting = new CaptureSetting
+                    {
+                        CaptureEnabled = false,
+                        ImageCaptureForFootSwitchKey = EnumFootSwitchKey.LeftKey,
+                        VideoCaptureForFootSwitchKey = EnumFootSwitchKey.RightKey,
+                        ImageCaptureForKeyBoardKey = EnumKeyboardKey.F1Key,
+                        VideoCaptureForKeyBoardKey = EnumKeyboardKey.F2Key,
+                    };
+                }
+                Instance.Version = 1;
+                Instance.Save();
+            }
+        }
+
+        private static void UpdateVersionFrom1To2()
+        {
+            if (Instance.Version == 1)
+            {
+                if (Instance.CaptureSetting == null)
+                {
+                    Instance.CaptureSetting = new CaptureSetting
+                    {
+                        CaptureEnabled = false,
+                        ImageCaptureForFootSwitchKey = EnumFootSwitchKey.LeftKey,
+                        VideoCaptureForFootSwitchKey = EnumFootSwitchKey.RightKey,
+                        ImageCaptureForKeyBoardKey = EnumKeyboardKey.F1Key,
+                        VideoCaptureForKeyBoardKey = EnumKeyboardKey.F2Key,
+                    };
+                }
+                Instance.Version = 2;
+                Instance.Save();
+            }
+        }
+
         /// <summary>
         /// Save settings.
         /// </summary>

+ 6 - 0
Vinno.FIS.Sonopost/Vinno.FIS.Sonopost.csproj

@@ -77,6 +77,8 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </ApplicationDefinition>
+    <Compile Include="Common\EnumKey.cs" />
+    <Compile Include="Features\Config\CaptureSetting.cs" />
     <Compile Include="Features\Config\PageSetting.cs" />
     <Compile Include="Features\Config\ServerInfoSetting.cs" />
     <Compile Include="Managers\Interfaces\IKeyBoardListenManager.cs" />
@@ -87,6 +89,7 @@
     <Compile Include="WebApi\Controllers\NetworkController.cs" />
     <Compile Include="WebApi\Controllers\ServerController.cs" />
     <Compile Include="WebApi\Controllers\SystemController.cs" />
+    <Compile Include="WebApi\Models\CaptureSettingRequest.cs" />
     <Compile Include="WebApi\Models\DicomFailActionRequest.cs" />
     <Compile Include="WebApi\Models\DicomFailListRequest.cs" />
     <Compile Include="WebApi\Models\DicomSonoSettingModel.cs" />
@@ -332,6 +335,9 @@
       <Name>Vinno.vCloud.FIS.CrossPlatform.Windows</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Assets\wwwroot\pages\dicom\capture.html" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
     <PostBuildEvent>if not exist "$(TargetDir)x64" mkdir "$(TargetDir)x64"

+ 43 - 0
Vinno.FIS.Sonopost/WebApi/Controllers/DicomController.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using Vinno.FIS.Sonopost.Common;
 using Vinno.FIS.Sonopost.Features.Config;
 using Vinno.FIS.Sonopost.Features.Dicom;
 using Vinno.FIS.Sonopost.Helpers;
@@ -160,5 +161,47 @@ namespace Vinno.FIS.Sonopost.WebApi.Controllers
             };
             return Result.Success(response);
         }
+
+        /// <summary>
+        /// 获取图像采集设定
+        /// </summary>
+        /// <returns></returns>
+        [WebApiAction]
+        public Result GetCaptureSetting()
+        {
+            CaptureSettingModel captureSettingMode = new CaptureSettingModel
+            {
+                CaptureEnabled = SonopostUserDefinedSettings.Instance.CaptureSetting.CaptureEnabled,
+                ImageCaptureForFootSwitchKey = (int)SonopostUserDefinedSettings.Instance.CaptureSetting.ImageCaptureForFootSwitchKey,
+                VideoCaptureForFootSwitchKey = (int)SonopostUserDefinedSettings.Instance.CaptureSetting.VideoCaptureForFootSwitchKey,
+                ImageCaptureForKeyBoardKey = (int)SonopostUserDefinedSettings.Instance.CaptureSetting.ImageCaptureForKeyBoardKey,
+                VideoCaptureForKeyBoardKey = (int)SonopostUserDefinedSettings.Instance.CaptureSetting.VideoCaptureForKeyBoardKey,
+            };
+            return Result.Success(captureSettingMode);
+        }
+
+        /// <summary>
+        /// 保存图像采集设定
+        /// </summary>
+        /// <returns></returns>
+        [WebApiAction]
+        public Result SaveCaptureSetting(CaptureSettingModel captureSettingModel)
+        {
+            if (captureSettingModel.ImageCaptureForFootSwitchKey == captureSettingModel.VideoCaptureForFootSwitchKey)
+            {
+                return Result.Fail("FootSwitchConflict");
+            }
+            if (captureSettingModel.ImageCaptureForKeyBoardKey == captureSettingModel.VideoCaptureForKeyBoardKey)
+            {
+                return Result.Fail("KeyBoardKeyConflict");
+            }
+            SonopostUserDefinedSettings.Instance.CaptureSetting.CaptureEnabled = captureSettingModel.CaptureEnabled;
+            SonopostUserDefinedSettings.Instance.CaptureSetting.ImageCaptureForFootSwitchKey = (EnumFootSwitchKey)captureSettingModel.ImageCaptureForFootSwitchKey;
+            SonopostUserDefinedSettings.Instance.CaptureSetting.VideoCaptureForFootSwitchKey = (EnumFootSwitchKey)captureSettingModel.VideoCaptureForFootSwitchKey;
+            SonopostUserDefinedSettings.Instance.CaptureSetting.ImageCaptureForKeyBoardKey = (EnumKeyboardKey)captureSettingModel.ImageCaptureForKeyBoardKey;
+            SonopostUserDefinedSettings.Instance.CaptureSetting.VideoCaptureForKeyBoardKey = (EnumKeyboardKey)captureSettingModel.VideoCaptureForKeyBoardKey;
+            ConfigManager.Save();
+            return Result.Success();
+        }
     }
 }

+ 28 - 0
Vinno.FIS.Sonopost/WebApi/Models/CaptureSettingRequest.cs

@@ -0,0 +1,28 @@
+namespace Vinno.FIS.Sonopost.WebApi.Models
+{
+    internal class CaptureSettingModel
+    {
+        public bool CaptureEnabled { get; set; }
+
+        /// <summary>
+        /// 截图对应的脚踏开关键(左或右),与录屏键互斥
+        /// </summary>
+        public int ImageCaptureForFootSwitchKey { get; set; }
+
+        /// <summary>
+        /// 录制视频对应的脚踏开关键(左或右),与截图键互斥
+        /// </summary>
+        public int VideoCaptureForFootSwitchKey { get; set; }
+
+        /// <summary>
+        /// 截图对应的键盘按键(F1-F12),与录屏键互斥
+        /// </summary>
+
+        public int ImageCaptureForKeyBoardKey { get; set; }
+
+        /// <summary>
+        /// 录制视频对应的键盘按键0(F1-F12),与截图键互斥
+        /// </summary>
+        public int VideoCaptureForKeyBoardKey { get; set; }
+    }
+}

+ 8 - 2
Vinno.vCloud.Common.FIS/ConnectionInfo.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using WingInterfaceLibrary.Enum;
 
 namespace Vinno.vCloud.Common.FIS
@@ -92,6 +93,11 @@ namespace Vinno.vCloud.Common.FIS
         /// Language Name
         /// </summary>
         public string LanguageName { get; set; }
+
+        /// <summary>
+        /// FISIMPL Version
+        /// </summary>
+        public Version FISIMPLVersion { get; set; }
     }
 
     /// <summary>
@@ -114,4 +120,4 @@ namespace Vinno.vCloud.Common.FIS
         /// </summary>
         public bool IsUserDefined { get; set; }
     }
-}
+}

+ 1 - 0
Vinno.vCloud.Common.FIS/vCloudTerminalV2.cs

@@ -171,6 +171,7 @@ namespace Vinno.vCloud.Common.FIS
                     DepartmentCode = "",
                     LoginSource = _connectionInfo.LoginSource,
                     Platform = _connectionInfo.Platform,
+                    InstallVersion=_connectionInfo.FISIMPLVersion?.ToString(),
                 };
                 ConnectResult result = JsonRpcHelper.Connect(_connectService, connectRequest);
                 if (result == null)

BIN
packages/WingInterfaceLibrary.dll