felix da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
..
components da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
css da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
images da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
js da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
lang da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
libs da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
pages da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
README.md da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
favicon.ico da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois
index.html da9b902bb6 Revert "尝试修复拉取失败2" il y a 9 mois

README.md

Windows魔盒Web管理工具项目说明

项目目录

Vinno.FIS.Sonopost
├───Assets      Web前端
│   ├───wwwroot     前端项目代码
│   │   ├───components     组件目录
│   │   ├───css            样式目录
│   │   ├───images         图片目录
│   │   ├───js             脚本目录
│   │   ├───lang           翻译文件目录
│   │   ├───libs           第三方库目录
│   │   ├───pages          页面目录
│   │   ├───favicon.ico
│   │   ├───index.html
│   │   └───README.md      /* Current Document */
│   └───ViewEngine.cs    前端资源引擎
├───Features
│    └───Web
│        └───WebPreviewHandler.cs     基于Websocket的设备采集画面预览服务
├───WebApi      Web后端
│   ├───Controllers      业务Controller目录
│   │   ├───DicomController.cs
│   │   ├───LiveController.cs
│   │   ├───NetworkController.cs
│   │   ├───ServerController.cs
│   │   ├───SystemController.cs
│   ├───Models      实体目录
│   ├───BaseController.cs       Controller基类
│   ├───WebApiAttribute.cs      WebAPI实体目录
│   └───WebApiEngine.cs       WebAPI处理引擎
└───WebHost.cs      Web宿主

Web 后端

采用魔盒启动时,开启自宿主Http服务来承载Web管理工具的页面和服务,在App.xmal.cs的OnStartup()最后调用`new WebHost().Start()`开启Web功能(端口设置在Setting文件的Web节点下)。

`Start()`运行后开启两个HttpListener监听Web请求:
1. Http
    此Listener会同时监听80端口和8080端口(备用),监听处理Get和Post请求
    其中Get请求交由ViewEngine.cs查找并输出web静态资源,Post请求交由WebApiEngine.cs处理WebAPI接口请求

2. WebSocket
    此Listener会监听50012端口,负责基于WebSocket的采集画面预览请求,建立与浏览器的长连接

前端资源引擎


Web 前端

浏览器支持

    为了高效开发和代码整洁,使用了现代浏览器支持的 Map、Array.map、Array.filter、Promise、async/await 等 ES6~ES8 特性和语法,所以放弃支持老旧的IE等浏览器。

    针对非现代浏览器访问本工具的处理办法:
1. 检测浏览器版本
    在加载应用和运行时(index.js)之前,会先加载执行prepare.js脚本,通过封装的isBrowserSupport() 检测

2. 页面提示
    页面展示提示用户当前浏览器不被支持,并提供MicroSoft Edge下载地址

3. 移动端处理
    与1、2点类似,检测为移动端环境时,页面展示提示用户仅在PC上访问


自建运行时

本项目模拟 App 设计了一套包含 App 单例和公共 Runtime 能力支持的开发方案。

项目设计为 单页应用 ,通过切换内容区域的`HTML`和`function Page()`实现页面的切换,`HTML`和`function Page()`及页面样式统一写在`pages`目录下单个`.html`文件中。

`function Page()` 默认支持两个入参:`app` 和 `runtime`,这两个入参都是对象类型,各自包含如下属性:

1. app 参数

属性 描述
el 应用实例 JQuery Dom
currentPage 当前内容页面function Page()实例
store 状态管理,支持通过defineProp定义带有get(),set的属性
router 路由 (注: 在 index.js 的generateRoutes()内注册页面路由)


1.1 router 属性明细
属性 描述
current 当前页面路由
getByPath() 根据 hash 路由 path 获取路由信息
goto(name,isManual) 切换页面
routes 路由注册表


2. runtime 参数

属性 描述
locale 本地化(翻译)功能实例
componentLoader 组件管理功能实例: install()uninstall()
$api(controller,action,request,timeout=5000) WebAPI 请求方法
$t(code) locale.translate()的缩写代理
$c(...componentNames) componentLoader.install()的代理和扩展
$loading() 全局 Loading


2.1 locale 属性明细
属性 描述
currentLanguage() 获取当前语言
isCurrentChinese() 当前语言是否中文
translate(code) 根据 code 获取翻译文字
translatePage(page) 整页翻译
changeLanguage(lang) 全局切换语言


页面生命周期

回调方法 描述
onload() 页面加载
beforeDestroy() 页面销毁前
onLanguageChanged(lang) 全局语言切换后
onResize() 全局尺寸变化


关于组件

由于新增组件的场景少,且设计较为简单,不多说明。如有需要,请翻看源码,谢谢!


简单示例

<style>
    #pageDemo {
        /* ... */
    }
    #page .layui-form-item {
        padding-bottom: 5px;
    }
</style>

<div id="pageDemo">
    <div class="layui-form page-form" lay-filter="FormDemo">
        <div class="layui-form-item">
            <label class="layui-form-label" data-content="Name"></label>
            <div class="layui-input-block">
                <input
                    type="text"
                    class="layui-input"
                    name="Name"
                    lay-filter="Name"
                />
            </div>
        </div>
        <div>
            <button
                class="layui-btn layui-btn-normal"
                lay-submit
                lay-filter="Save"
                data-content="Save"
            ></button>
        </div>
        <div id="cc"></div>
    </div>
</div>

<script>
    function Page(app, runtime) {
        const { store, router } = app;
        const { $api, $t, $c, $loading } = runtime;
        const { form, layer } = layui;
        const formFilter = "FormDemo";

        this.onload = async function () {
            initForm();
            // 引入组件
            await $c("Component01", "Component02");
            let c01 = new Component01();
            let c02 = new Component02();
            c01.addTo("#cc");
            c02.addTo("#cc");
            form.on("submit(Save)",async function(data){
                let index = $loading();
                // 请求WebAPI
                let res = await $api("Demo", "Test", data.field);
                layer.close(index);
                if(res.IsSuccess){
                    store.uniqueId = res.Data.UniqueId;
                    layer.msg.success($t("Success"));
                    // 通过路由跳转页面
                    router.goto("Page02", true);
                }else{
                    layer.msg.error($t(res.Code));
                }
            });
        };
        this.beforeDestroy = function () {
            console.log("Page demo closing...");
            // await runtime.componentLoader.uninstall("Component01"); // 卸载组件
        };
        this.onLanguageChanged(lang){
            layer.msg(`${$t("CurrentLanguage")}: ${lang}`);
        }

        // 页面私有方法必须定义在Page方法体内!
        function initForm(){
            form.val(formFilter, {
                Name: "Test"
            });
        }
    }
</script>