金融业务可视化管理如何实现?

一说到银行业务保密性就会加强,所以以往我们的银行案例就不在这里给大家具体介绍,今天只讲金融业务可视化管理如何实现?对网点、金库、ATM等银行设备设施及运维、现金库存、金库调缴等业务进行可视化,在立体视角下掌控全局,为银行设备运维、现金服务及客户服务的状态监控提供三维可视化管理工具。脑补即可~运维场景可在thingjs平台查看哦~

金融业务可视化管理如何实现?

基本概念

对象的定义

ThingJS 平台的对象是指一个使用 ThingJS 提供的各种类创建的物体实例,不同类的对象实例具有不同接口和功能,比如我们在场景里创建一个园区,园区就是一个对象,园区里的建筑和物体都是对象。

模型的定义

ThingJS 平台的模型是指可复用的 3D 资源包,有些对象实例创建时指定模型资源的路径。

ThingJS 提供了具有丰富资源的模型库(ThingDepot)。

场景的定义

启动 ThingJS 后,ThingJS 就会创建一个三维空间,整个三维空间我们称之为“场景”(scene),在场景内我们可以创建对象,比如园区,楼宇,车辆,传感器等等。

园区的定义

通过 CamBuilder 可编辑并输出一个园区,该园区可在 ThingJS 场景中加载。

项目的定义

ThingJS 平台的项目是指一个场景加上一个交互脚本。脚本使用 JavaScript 语言开发。例如 Demo 里的粮仓管理,交互功能包括点击仓库可以显示信息牌,点击屋顶可以开盖。

坐标系

坐标系概念

以场景原点为中心的直角坐标系称为世界坐标。

在 ThingJS 中所有的物体的 position 值均为世界坐标,排列为 [x,y,z] 。

世界坐标系

当在场景中创建了园区,在园区下我们放置一个模型,模型是园区的子物体,我们想在园区的坐标系下,设置模型的位置,这时使用的园区的坐标系,就是模型的父物体坐标系。

父物体坐标系

启动 ThingJS 后,ThingJS 就会创建一个三维空间,整个三维空间我们称之为“场景”(scene),在场景内我们可以创建对象,比如园区,楼宇,车辆,传感器等等。

自身坐标系

某对象向前移动 2 米,就是在自身坐标系下设置坐标 [0,0,2](Z轴正向朝向我们的方向)。

配置和部署

系统运行硬件的要求

ThingJS 的 3D 可视化应用是 B/S 架构的,3D 场景是运行在客户端的浏览器中。3D 场景渲染展示对客户端设备要求较高,特别是显卡,一般必须是独立显卡

推荐使用 Chrome 浏览器进行开发和演示。

客户端:

系统:Windows 7 及以上

CPU:双核 CPU2.8GHz及以上

内存:8G 及以上

显卡:最低 GTX650,推荐 GTX960 及以上,显存 2G 及以上

硬盘:300GB 及以上

ThingJS 若是离线部署,需要部署到服务器端,ThingJS 对服务器端的要求并不高

服务器端:

系统:Windows Server 2003 及以上

CPU:双核 CPU2.8GHz 及以上

内存:8G 及以上

硬盘:500GB及以上

软件环境:JDK 1.6 及以上

部署方式

支持项目 托管部署 和 离线部包部署 两种方式。

收费方式

开发者收费方式

个人开发者免费,适用于验证 3D 开发流程,制作 Demo 项目。

商业开发者按年收费,商业开发者适用于开发/测试物联网 3D 项目。

项目收费方式

ThingJS 平台按项目数量计费。

托管项目按一个项目一年授权的方式收费。

离线部署包按项目收费。

具体详情可点击 此处 进行了解查看。

项目托管

开发者使用项目托管,通过在线开发调试代码,在测试完成后,可一键发布,并且在有效期内可随时更新。

离线部署包

开发者在开发完成后可申请离线部署包一个月试用。试用期内可随时更新场景和代码。 测试完成后,购买永久授权码。使用永久授权码最终交付项目。而且永久授权脚本可以随时更新,更新后不需要新授权码。但是永久授权更新场景需提交审核,变动不超过 50%,1工作日内发放新授权码。

数据对接

对接的数据不用经过 ThingJS 平台,可以通过 Ajax 请求或者 WebSocket 方式获取服务器端的数据。

性能问题

网速问题

在开发过程中出现加载慢等问题时,用户可先自行检测自己的网络是否正常,我们将会提供测试页面供用户检测。如果用户在正常时间范围内未打开测试页面,那么可能是由于用户网络的问题。

场景过大

每个用户搭建的场景不同,场景内的的物体数量也不确定,当场景内物体过多时也有可能会导致场景加载缓慢,卡顿。建议采用分批次加载,分室内外加载,动态加载等方式。

运行卡

场景内物体数量过多、开启了屏幕后期特效、请求后台数据频繁都可能造成性能损耗;代码脚本出现逻辑问题、客户端机器配置低等情况也会造成场景运行卡顿。

代码逻辑问题可通过log或者debuger进行检查。

document.title = 'Demo-建筑监控';

// 创建App

var app = new THING.App({

    el: 'div3d',

    url: "models/uinnova",

    skyBox: 'BlueSky'

});

// 加载场景后执行

var building = null, mainPanel;

app.on('load', function () {

    building = app.buildings[0];

    mainPanle = new MainPanel(app);// 界面的类

    setupNavpanel();

    app.level.change(app.root.campuses[0]);

});

// 注册 进入室外 事件

app.on('afterEnterOutdoorsLevel', function (ev) {

    building.facades[0].visible = true;  // 显示外立面

    var pos = building.position;

    app.camera.flyTo({

        position: [pos[0] + 3, pos[1] + 43.21, pos[2] + 80],

        target: pos,

        time: 1200

    });

});

// 注册 进入建筑 事件

app.on('afterEnterBuildingLevel', function (ev) {

    building.facades[0].visible = false; // 隐藏外立面

});

// 注册 进入楼层 事件

app.on('afterEnterFloorLevel', function (ev) {

    building.facades[0].visible = false; // 隐藏外立面

    var num = ev.state.floor.indexOfBuilding;

    var pos = building.position;

    app.camera.flyTo({

        position: [pos[0] - 3, pos[1] + 20.28 + (num - 1) * 2.5, pos[2] + 56],

        target: [pos[0], pos[1] + (num - 1) * 6, pos[2] + 15.76],

        time: 1200

    });

});

function initCSS(url) {

    var link = document.createElement("link");

    link.setAttribute("rel", "stylesheet");

    link.setAttribute("type", "text/css");

    link.setAttribute("href", url);

    var heads = document.getElementsByTagName("head");

    if (heads.length)

        heads[0].appendChild(link);

    else

        document.documentElement.appendChild(link);

}

// 给导航面板添加点击事件

function setupNavpanel() {

    var navPanel = mainPanle.createNavPanel();

    navPanel.on('click', function (obj, target) { // 绑定 导航树 事件

        navPanel.highLight(target);

        if (obj == '全景') {

            app.level.change(app.root.campuses[0]);

        } else {

            if (obj.name.indexOf('层') > -1) {

                var num = obj.name.substring(0, 1);

                var floor = building.floors[num];

                // navPanel.pathHighLight('全景.建筑.' + num + '层');

                app.level.change(floor);

            } else {

                // navPanel.pathHighLight('全景.' + obj.name);

                app.level.change(app.root.campuses[0]);

            }

        }

    })

}

class MainPanel {

    constructor(app) {

        this.app = app;

        this.nav_tree = {  // 导航树对象

            buildings: [{ name: "建筑", floors: [{ name: "1层", }, { name: "2层", }, { name: "3层", }, { name: "4层", }, { name: "5层", }] }],

            outdoor: { name: '室外' }

        }

        this.panels_xfs = [];

        this.panels_xfsx = [];

        this.panels_pyfj = [];

        this.toolBar = null;

        this.toolImgs = {};

        this.isExpandBuilding = false;

        this.createUIOnObjs();        // 创建 gui 面板

        this.createToolsPanel();

        this.building = this.app.buildings[0];

    }

    // 创建导航面板

    createNavPanel() {

        var main_panel = new THING.widget.NavPanel();

        main_panel.setPosition(0, null, null, 0);  // 设置面板 位置 (left/bottom/right/top)

        main_panel.addAppTree('全景', this.nav_tree); // 创建导航树

        return main_panel;

    }

    // 创建工具面板

    createToolsPanel() {

        var that = this;

        var baseURL = "https://www.thingjs.com/static/images/uBuilding/";

        this.toolBar = THING.widget.ToolBar({ width:'164px',media: true });

        this.toolBar.data = { xfsx: false, pyfj: false, xfs: false, enterBuilding: false, expandBuilding: false };

        this.toolBar.setPosition({ right: 0, top: 60 });

        this.toolImgs.img0 = this.toolBar.addImageBoolean(this.toolBar.data, 'xfsx').name('消防水箱').imgUrl(baseURL + 'xfsx.png');

        this.toolImgs.img1 = this.toolBar.addImageBoolean(this.toolBar.data, 'pyfj').name('排烟风机').imgUrl(baseURL + 'pyfj.png');

        this.toolImgs.img2 = this.toolBar.addImageBoolean(this.toolBar.data, 'xfs').name('消防栓').imgUrl(baseURL + 'xfs.png');

        this.toolImgs.img3 = this.toolBar.addImageBoolean(this.toolBar.data, 'enterBuilding').name('进入建筑').imgUrl(baseURL + 'jz.png');

        this.toolImgs.img4 = this.toolBar.addImageBoolean(this.toolBar.data, 'expandBuilding').name('楼层展开').imgUrl(baseURL + 'zk.png');

        this.toolImgs.img0.on('change', function (boolValue) { that.onChangeImageButton('xfsx', boolValue); });

        this.toolImgs.img1.on('change', function (boolValue) { that.onChangeImageButton('pyfj', boolValue); });

        this.toolImgs.img2.on('change', function (boolValue) { that.onChangeImageButton('xfs', boolValue); });

        this.toolImgs.img3.on('change', function (boolValue) { that.onChangeImageButton('enterBuilding', boolValue); });

        this.toolImgs.img4.on('change', function (boolValue) { that.onChangeImageButton('expandBuilding', boolValue); });

    }

    // 处理工具条按钮

    onChangeImageButton(key, boolValue) {

        var that = this;

        if (key == "enterBuilding") { // 进入建筑/室外

            this.resetExpand();

            var name = boolValue ? '返回室外' : '进入建筑';

            this.toolImgs.img3.name(name);

            if (boolValue)

                this.app.level.change(app.buildings[0]);

            else

                this.app.level.change(app.root.campuses[0]);

        } else if (key == "expandBuilding") { // 楼层横向展开

            this.app.level.change(app.buildings[0]); // 进入建筑

            if (boolValue) {

                this.building.expandFloors({

                    'time': 1000,

                    'length': 10,

                    'horzMode': false,

                    'hideRoof': true,

                    'complete': function () { that.isExpandBuilding = true; }

                })

            } else {

                this.building.unexpandFloors({

                    'time': 500,

                    'complete': function () { that.isExpandBuilding = false; }

                })

            }

        } else {

            this.resetExpand();

            this.app.level.change(app.root.campuses[0]);// 进入室外

            if (key == "xfsx") { // 消防水箱

                this.panels_xfsx.forEach(function (panel) { panel.show(boolValue); });

            } else if (key == "pyfj") { // 排烟风机

                this.panels_pyfj.forEach(function (panel) { panel.show(boolValue); });

            } else if (key == "xfs") { // 消防栓

                this.panels_xfs.forEach(function (panel) { panel.show(boolValue); });

            }

        }

    }

    // 展开的楼层收回去

    resetExpand() {

        var that = this;

        if (this.isExpandBuilding) {

            this.toolBar.data.expandBuilding = false;

            this.building.unexpandFloors({

                'time': 500,

                'complete': function () { that.isExpandBuilding = false; }

            })

        }

    }

    // 根据不同类型创建样式

    createPanels(type) {

        var obj = {};

        var that = this;

        var gui = new THING.widget.Panel({ width: '120px', name: type, opacity: 0.8, cornerType: 's2c5', width: '150px', hasTitle: true});

        gui.remember(obj);

        gui.show(false);

        switch (type) {

            case "消防栓":

                obj = { hydraulicPressure: '0.14MPa' };

                gui.add(obj, 'hydraulicPressure').name('水压');

                that.panels_xfs.push(gui);

                break;

            case "消防水箱":

                obj = { waterlevel: '2.5米' };

                gui.add(obj, 'waterlevel').name('水位');

                that.panels_xfsx.push(gui);

                break;

            case "排烟风机":

                obj = { state: '开' };

                gui.add(obj, 'state').name('状态');

                that.panels_pyfj.push(gui);

                break;

        }

        return gui;

    }

    // 为3d物体添加面板

    createUIOnObj(objs) {

        var that = this;

        objs.forEach(function (obj) {

            that.app.create({

                type: 'UI',

                parent: obj,

                el: that.createPanels(obj.custom['物体类型']).domElement,

                offset: [0, 1, 0],

                pivot: [0.5, 1]

            })

        })

    }

    // 收集需要加面板的 obj 并为其添加面板

    createUIOnObjs() {

        this.createUIOnObj(app.query('[物体类型=消防栓]'));

        this.createUIOnObj(app.query('[物体类型=消防水箱]'));

        this.createUIOnObj(app.query('[物体类型=排烟风机]'));

    }

}