• 如何用jxTMS开发一个功能(三)


    本文是讲解如何用jxTMS来开发jxTMS示例之故障排查的系列文章中的一篇。整个系列的文章请查看:如何用jxTMS开发一个功能

    故障维护的管理与衍生动作

    任何一个业务点,都包括三个基本的动作:创建、列表并带条件查询、查看详情。然后再通过查看详情衍生出相应的业务管理动作。

    其中的列表查询主要为业务管理提供概览、归集、汇总、统计、分析等综合功能。既是最基础的管理切入点,也是高级管理功能的出发点。

    所以,本场景属于补完整个故障排查功能的最后一个环节,也是非常基础的业务管理点。即,前两篇文章所讲述的是业务操作范畴,而本文则属于业务管理范畴,任何管理都包括计划、组织、领导、控制。而作为切入点和最基础的管理行为,一般的列表查询主要是提供业务操作的基础性控制信息。

    这些信息包括:

    • 时间信息:该业务什么时候创建的、什么时候结束的、预计还需多长时间、和标准用时的偏差

    • 状态信息:当前状态、当前动作、当前问题、当前占用的资源等

    • 基本情况:名称、概要说明、创建人、执行人、关系人、责任人等

    • 资源开销:预算、决算、所需关键资源、【和其它事项的】资源冲突等

    概要的说,任何业务都需要人财物事的支撑才能完成,所以管理者需要这些基本信息来了解业务整体的概貌、资源能否支撑、业务风险大小等。

    但是,上面所列的信息项太多,列表中的一行根本显示不下、看起来很吃力;而且信息太多,要全面理解所消耗的精力也会非常大。所以一般都是根据业务特点来列出这些信息那些对各层级的管理者更重要,然后针对不同层级的管理者提供相应的信息供给。

    也就是说,随着系统的进化,最后很大可能是一人一表,即针对性提供其高效工作的信息攻击。

    通过上述讨论,本场景主要有三个动作:

    • 对所有故障Case的列表查询

    • 用户可以查看各故障的详情,包括维护处置动作的记录

    • 通过查看具体的故障详情,可将典型案例其加工为知识产品

    列表查询故障Case

    1、入口

    列表查询一般和创建都定义在快捷栏中:

    #由于列表查询的重要性与常用性,所以jxTMS对列表查询做了深入的优化,需要多个参数来控制
    @biz.Demand('disp','listCase')
    @biz.OPDescr
    def op1(json):
        json.setShortcut('维修管理'.decode('utf-8'),'故障查询'.decode('utf-8'))
        #指示listCase是一个数据表的查询功能,请求系统自动介入
        json.setParam('dispType','list')
        #指示从数据库中查询出来的结果是一个json数组
        json.setParam('resultType','json')
        #将上述的json数组发送到web中的哪个数据表
        json.setParam('listTable','listCaset2')
        #为本次查询指定数据源,即使用那个sql语句从数据库中查询数据
        json.setParam('dataSource','bugCase.listBugCase')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    热机刷新后,该入口就会在快捷栏中显示出来:【维修管理->故障查询】。所有人都能看到,但由于快捷栏是用户登录时一次性生成的,所以需要用户登出后再次登录才能在快捷栏中看到。

    2、web界面设计

    点击该入口,就会向jxTMS请求显示同名【listCase】的界面。

    在web文件中,我们定义了该界面:

    web listCase type div;
    //先是一个查询条件的容器表
    web listCaset1 parent listCase type table title="查询条件",width=900,alone=true;
    with listCaset1 row 0 col c0 web n type text text='关键字:',width=150;
    with listCaset1 row 0 col c1 web n bind bugName type input width=150,placeholder="故障名称中的关键字...";
    with listCaset1 row 0 col c2 web n type text text='维修人:',width=150;
    with listCaset1 row 0 col c3 web n bind bugRepairor type input width=150;
    with listCaset1 row 1 col c0 web n type text text='客户:',width=150;
    with listCaset1 row 1 col c1 web n bind customName type input width=150;
    with listCaset1 row 1 col c2 web n type text text='状态:',width=150;
    with listCaset1 row 1 col c3 web n bind bugState type combobox width=150,useText=true,
    	values=[{'text':'未修复'},{'text':'新故障现象'},{'text':'部分修复'},{'text':'已修复'}];
    
    with listCaset1 row 2 col c0 web n type text text="查询时间段起点:",width=120;
    with listCaset1 row 2 col c1 web n bind startDate type dtpicker width=120,initDisp=false;
    with listCaset1 row 2 col c2 web n type text text="查询时间段终点:",width=120;
    with listCaset1 row 2 col c3 web n bind endDate type dtpicker width=120,time=false,initDisp=false;
    
    with listCaset1 row 3 col c0 web n type button width=80,motion=cmd,demand=reSearch,text='搜索',onlyOnce=false;
    
    //再是一个查询结果的分页数据表
    web listCaset2 bind tableTotalCount parent listCase type table title="案例列表",width=900,pagination=true,query=search;
    with listCaset2 col joID head joID hide=true;
    with listCaset2 col caseTime head 日期 width=100;
    with listCaset2 col caseName head 简述 width=200;
    with listCaset2 col customName head 客户 width=90;
    with listCaset2 col customPlace head 位置 width=90;
    with listCaset2 col caseExecor head 处理人 width=90;
    with listCaset2 col caseState head 状态 width=90;
    with listCaset2 col customSignImg head 客户签名 web n type img width=100,height=300;
    with listCaset2 col readed head 已读 width=90;
    //会自动为每行故障添加一个名为【查看】的工具条,点击就会以require来准备参数去调用dispCase
    //primary指示显示到一个新的主界面中,ignoreCapaid=true配合capaname,只是新开一个bugCaseMain实例
    //因为故障查询和查看故障详情,都是bugCaseMain中的函数,现在要开一个新的主界面,如果不ignoreCapaid
    //就会导致两个主界面共用同一个bugCaseMain,导致相互干扰,甚至数据都会乱串!
    with listCaset2 col op1 head 操作 web n type a width=80,text='查看',ignoreCapaid=true,primary=true,
        capaname='bugCase.main',motion=disp,demand=dispCase,require=[{"paramName":"joID"}];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    该界面的显示效果如下:

    列表故障

    其中的客户签名是用户手写签名的故障排查信息的截屏图片,显示效果如下:

    新故障

    由于web界面的设计是一行一个控件,都是用文本进行的定义,也非常简单,大家对照着定义和显示效果就好。

    3、数据

    jxTMS对列表查询做了针对性的优化,所以整个查询过程已经自动化了。列表查询的数据准备是通过数据源方式提供的。

    sql文件中定义了入口中指定的故障查询的数据源:listBugCase。其定义如下:

    sql listBugCase
        from task as ta,fulltextTag as tc
        select ta.ID as joID,ta.CreateTime as caseTime,
        tc.Name as customName,tc.ObjType as customPlace,tc.Descr as customSignImg,
        ta.Name as caseName,ta.Purpose as caseExecor,
        ta.State as caseState,ta.Info
        where ta.Type=='bug' and tc.ObjID==ta.ID and tc.Type=='custom'
        orderBy ta.CreateTime DESC;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    相关语法,可参考jxTMS在线编程手册中的数据源部分

    4、业务逻辑

    jxTMS对列表查询做了针对性的优化,所以列表查询有完整的业务逻辑:

    • 指定参数:op.py中的入口或界面打开的事件响应函数中编程指定

    • 设计数据源:在sql文件中定义

    • 界面设计:在web文件中设计条件查询表和数据表,数据表如需分页则添加相应的设计

    • 设置查询条件:在capa.py文件中继承setSearchCondition和setSearchConditionVarValue来设置查询条件

    • 进行数据转换或增加额外的显示信息:数据转换,如状态,在数据库中可能是标志位的整数型,但显示给用户则需要翻译成【紧急,重要】这样人可阅读的信息;增加额外信息,如流程,可能需要添加当前正在执行的节点和相应的人员

    我们用这5点来看故障查询,其参数在op.py文件的入口中进行定义,数据源listBugCase中没有变量,而且信息都保存在数据库中,不需要转换与额外的添加信息。所以只需要重载setSearchCondition函数就可实现条件查询了。

    故障查询的条件查询部分,有六个查询条件,只要针对这六个条件分别添加查询时的where子句就好:

    def setSearchCondition(self, db, ctx):
        if self.dataSource == 'bugCase.sqlwxListMyBugCase':
            return
        cn = self.getInputString('bugName')
        if utils.valid(cn):
            #用户输入了故障名,Match是全文搜索。全文索引不是所有字段都设了的,请先查看编程手册
            self.sql.addContion('task', self.trans2Field('bugName'), jxCompare.Match,cn)
        cn = self.getInputString('bugRepairor')
        if utils.valid(cn):
            #trans2Field函数是将语义翻译成实际的字段
            self.sql.addContion('task', self.trans2Field('bugRepairor'), jxCompare.Equal,cn)
        cn = self.getInputString('bugState')
        if utils.valid(cn):
            self.sql.addContion('task', self.trans2Field('bugState'), jxCompare.Equal,cn)
        cn = self.getInputString('customName')
        if utils.valid(cn):
            #客户名也是全文搜索。需要注意的是mysql规定一个sql查询只能使用一个全文索引
            #所以customName和bugName不能同时出现,否则会导致查询失败,我这里没有做检测
            self.sql.addContion('fulltextTag', self.trans2Field('customName'), jxCompare.Match,cn)
        ds = self.getInputDate('startDate')
        if not utils.isNone(ds):
            self.sql.addContion('task', 'CreateTime',jxCompare.GreatEqual, ds)
        de = self.getInputDate('endDate')
        if not utils.isNone(de):
            #我们一般说截止某天都是到当天的最后一秒,所以不能直接用,而是用utils.getDateEndBefore来获取
            self.sql.addContion('task', 'CreateTime', jxCompare.Less, utils.getDateEndBefore(de))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    由此,我们就完成了故障查询的功能设计。

  • 相关阅读:
    final跟finally和finalize有什么区别
    Elasticsearch:使用不同的 CA 更新安全证书 (二)
    Polygon Miden交易模型:Actor模式 + ZKP => 并行 + 隐私
    【今日文章】:Web端常用的Observer监听器
    Webpack十大缺点:当过度工程化遇上简单的静态页面
    Flink Table&SQL的底层原理和企业应用
    试图带你一文搞懂transformer注意力机制(Self-Attention)的本质
    电脑软件:推荐一款非常实用的固态硬盘优化工具
    08.23类属性和实例属性
    高斯推断推导
  • 原文地址:https://blog.csdn.net/jxandrew/article/details/126028947