jeecg后端审核完整

弄(抄)了近乎一个星期,终于把完整流程走通了,记下来,之后还要做好几个

controller层

controller层主要是产生对象,是前端传数据的接口,我把功能单独列出来方便看(抄)
提交审核,权限路径为monthlyPlan:monthlyPlan:verify,前端通用请求为“/verify”,通用结构都是一样的,
屌用service层的verify方法来进行结果判定,成功提交审核失败是捕获异常、打印异常堆栈跟踪信息,并将异常消息作为错误结果返回给调用方

 /**
    *  提交审核
    *
    * @param id
    * @return
    */
   @AutoLog(value = "月度计划产值-编辑")
   @ApiOperation(value="月度计划产值-编辑", notes="月度计划产值-编辑")
   @RequiresPermissions("monthlyPlan:monthlyPlan:verify")
   @GetMapping(value = "/verify")
   public Result<String> verify(@RequestParam("id") String id) {
     try {
       monthlyPlanService.verify(id);
       return Result.OK("已提交审核!");

     } catch (Exception e) {
       e.printStackTrace();
       return Result.error(e.getMessage());
     }
   }

该结构用list封装了想要查询的几个值,其中有默认值,初始化一个querywapper对象,构建查询条件,然后创建page对象指定当前页码和每页数量,调用service和调取项目和用户信息的方法进行分页查询,用page和querywarapper进行传参

   /**
    * 月度计划产值查询
    *
    * @param monthlyPlan
    * @param pageNo
    * @param pageSize
    * @param req
    * @return
    */

   @ApiOperation(value="月度计划产值-分页列表查询", notes="月度计划产值-分页列表查询")
   @GetMapping(value = "/monthlyPlan/list")
//   @RequiresPermissions("warehosueMgr:warehosue:audit")
   public Result<IPage<MonthlyPlanVO>> monthlyPlanList(MonthlyPlanVO monthlyPlan,
                           @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                           @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                           HttpServletRequest req) {
     QueryWrapper<MonthlyPlanVO> queryWrapper = QueryGenerator.initQueryWrapper(monthlyPlan, req.getParameterMap());
     Page<MonthlyPlanVO> page = new Page<>(pageNo, pageSize);
     IPage<MonthlyPlanVO> pageList = monthlyPlanService.pageVerifyWithProjectAndSysuser(page, queryWrapper);
     return Result.OK(pageList);
   }
   /**
    * 月度计划审核
    *
    * @param vo
    */
   @AutoLog(value = "月度计划产值-审核")
   @ApiOperation(value="月度计划产值-审核", notes="月度计划产值-审核")
   @RequiresPermissions("monthlyPlan:monthPlan:audit") //月度产值审核
   @PostMapping(value = "/monthlyPlan/audit")
   public Result<String> monthlyPlanAudit(@RequestBody AuditVO<MonthlyPlan> vo) {
     monthlyPlanService.verifyStep(vo);
     return Result.OK("入库审批完成!");
   }
   /**
    * 月度计划审核详情
    * @param   id
    */
   @AutoLog(value = "月度计划产值-审核详情")
   @ApiOperation(value="月度计划产值-审核详情", notes="月度计划产值-审核详情")
   @GetMapping(value = "/monthlyPlan/verifyQuery")
   public Result<AuditVO> monthlyPlanVerifyQuery(@RequestParam("id") String id) {
     AuditVO  vo = monthlyPlanService.monthlyPlanVerifyQuery(id);
     return Result.OK(vo);
   }

构造一个list对象来传递service中过程密钥的,这里面分别有id,字符串类型,index,整形,和type,字符转类型,如果
list的长度小于等于0,那么结果返回error,没有审批历史,
在ipage中构造page对象,page进行记录,将查询到信息写入list’中,同时记录list的长度

   /**
    * 流程审批节点历史信息详情列表
    *
    * @param   id
    */
   @AutoLog(value = "月度计划产值管理-审核")
   @ApiOperation(value="月度计划产值管理-审核", notes="月度计划产值管理-入库审核")
   @GetMapping(value = "/monthlyPlan/verify/historyQuery")
   public Result<IPage<AuditHistroyVO>> monthlyPlanVerifyHistoryQuery(@RequestParam("id") String id, @RequestParam("index") Integer index, @RequestParam("type") String type) {
     List<AuditHistroyVO> list = monthlyPlanService.auditHistoryListByProcessKey(id,index,type);
     if(list.size() <=0){
       return Result.error(1001,"该节点没有审批历史!");
     }

     IPage<AuditHistroyVO> page = new Page<>();
     page.setRecords(list);
     page.setTotal(list.size());
     return Result.OK(page);
   }

同上,当时这里查询的是queryhistorulist中的id返回数量和信息

   /**
    * 流程审批全流程详情
    * @param id
    */
   @AutoLog(value = "月度计划产值-审核")
   @ApiOperation(value="月度计划产值-审核", notes="月度计划产值-审核")
   @GetMapping(value = "/monthlyPlan/verify/historyList")
   public Result<IPage<AuditHistroyVO>> historyList(@RequestParam("id") String id) {
     List<AuditHistroyVO> list = monthlyPlanService.queryhistoryList(id);
     if(list.size() <=0){
       return Result.error(1001,"没有审批历史!");
     }

     IPage<AuditHistroyVO> page = new Page<>();
     page.setRecords(list);
     page.setTotal(list.size());
     return Result.OK(page);
   }

service&implements层

这个地方是对象和方法实现类,尽可能讲清楚,方便回来看,
先说一下我们审核的逻辑,是从表单开始,表单有项目经历提交审核,然就发油经营部审核,然后经营部副总进行总审批,然后总经理审批,这样流程结束,每个环节出现驳回都将返回到最开始的一级,即由项目经理填写

 private String[] monthlyPlanAuditTasks= {"start","form","step1","step2","step3","end"};
private String[] taskNodeNames = {"流程开始","项目经理提审","经营部审核","经营部副总审批","总经理审核","审批结束"};

以上两个一个审核任务节点,下面的是节点名称

 @Override
    public IPage<MonthlyPlanVO> pageVerifyWithProjectAndSysuser(Page<MonthlyPlanVO> page, QueryWrapper<MonthlyPlanVO> queryWrapper) {
        System.out.println(monthlyPlanEndListener);

        //获取登录用户信息
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //获取用户角色
        List<String> userRoles = iSysBaseAPI.getRolesByUsername(sysUser.getUsername());

        //获取用户拥有的项目部权限
          //List<ProjectMgr> projects = this.getBaseMapper().queryProjectByTeamUserId(sysUser.getId());
          //List<String> projectIds = projects.stream().map(ProjectMgr::getId).collect(Collectors.toList());
          List<String> insIds = new ArrayList<>();
        // step1审核权限角色(部门负责人)
        if(userRoles.indexOf("monthlyPlan_step1")!=-1){
            List<String> insId1 = taskService.createTaskQuery()
                    .processDefinitionKey("monthlyPlan")
                    .taskName("step1")
                    .list()//这个地方不要分页
                    .stream()
                    .map(Task::getProcessInstanceId)
                    .collect(Collectors.toList());

            insIds.addAll(insId1);
        }

        // step2审核权限角色(副总经理)
        if(userRoles.indexOf("monthlyPlan_step2")!=-1){
            List<String> insId2 = taskService.createTaskQuery()
                    .processDefinitionKey("monthlyPlan")
                    .taskName("step2")
                    .list()  //这个地方不要分页
                    .stream()
                    .map(Task::getProcessInstanceId)
                    .collect(Collectors.toList());

            insIds.addAll(insId2);
        }

        // step3审核权限角色(总经理)
        if(userRoles.indexOf("monthlyPlan_step3")!=-1){
            List<String> insId2 = taskService.createTaskQuery()
                    .processDefinitionKey("monthlyPlan")
                    .taskName("step3")
                    .list()  //这个地方不要分页
                    .stream()
                    .map(Task::getProcessInstanceId)
                    .collect(Collectors.toList());

            insIds.addAll(insId2);
        }

        //必须满足 审核中的流程 && 且项目是当前用户所在项目组
        if(insIds.size()>=1 /**&& projectIds.size()>=1*/){
            queryWrapper.lambda()
                    .in(MonthlyPlanVO::getActInstanceId,insIds); //符合条件的流程Id
//                    .in(WarehosueVO::getProjectId,projectIds); //所在项目部

            queryWrapper
                    .orderByDesc("verify_status") //根据出入库状态排序
                    .orderByDesc("create_time"); //根据时间排序

            IPage<MonthlyPlanVO> pageList = this.getBaseMapper().pageVerifyWithProjectAndSysuser(page,queryWrapper);
            return pageList;
        }

        //如果没有流程则返回空对象
        return new Page<>(page.getCurrent(), page.getSize(), 0);
    }

这个地方就是之前审核要进行调用的实现类,构造一个monthlyPlan的对象,这个对象是一个查取的方法,利用id去查取数据库的对象,如果其中monthlyPlan这个对象查到的状态等于1或者状态等于二,相当于审核未通过
如果查到的这个叫审核状态等于0,相当于第一次提交被驳回了们开始重新提交,verifyStart就是审核流程开始的方法,方法的参数为该对象,每当流程重新开始就更新数据库更逊查询结果
如果违背驳回,那么就钩爪一个审核信息对象,该对象可以对mongthlyPlan这个对象写入记录,获取登录用户的信息了解其权限然后得到结果,完成结点

//提交审核
    @Override
    public void verify(String id) throws Exception {
        MonthlyPlan monthlyPlan = this.getBaseMapper().selectById(id);
        if (monthlyPlan.getVerifyStatus() == 1 || monthlyPlan.getVerifyStatus() == 2) {
            //当前状态为审核中或审核通过,不允许提交流程
            log.error("当前状态为审核中或审核通过,不允许提交流程, id={}", monthlyPlan.getId());
            return;
        }
        //入库审核

            //判断时第一次提交还是驳回后再次提交
            if(monthlyPlan.getVerifyStatus() == 0){
                //第一次提交
                verifyStart(monthlyPlan);  //开启一个新流程
                this.getBaseMapper().updateById(monthlyPlan); //更新数据库
            }else {
                //再次提交

                //构造一个审核信息对象
                AuditVO<MonthlyPlan> vo = new AuditVO<>();
                vo.setRecord(monthlyPlan);

                //获取登录用户信息
                LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                vo.setAuditUserId(sysUser.getId());

                vo.setAuditResult(2);

                //完成节点
                verifyStep(vo);
            }
    }

这就是流程开始方法,首先获取登录着的信息
根据提供的代码片段,这段代码的作用是查询定义为 “monthlyPlan” 的流程定义,并获取最新版本的流程定义对象。

首先,通过 repositoryService(流程存储服务)调用 createProcessDefinitionQuery() 方法创建一个流程定义查询对象。然后使用 processDefinitionKey(“monthlyPlan”) 方法设置查询条件,筛选出流程定义的 key 为 “monthlyPlan” 的流程。

接下来,使用 orderByProcessDefinitionVersion().desc() 方法按照流程定义版本进行降序排列,以确保获取最新的版本。

然后,通过 list() 方法获取查询结果列表,并使用 get(0) 获取列表中的第一个流程定义对象,即最新版本的流程定义对象。

最终,将获取到的流程定义赋值给 processDefinition 变量,以便后续使用。

这段代码的目的是获取指定 key 的流程定义中最新的版本流程定义对象,以便使用该对象执行后续的流程操作。
之后在注释写的很清楚了

 private void verifyStart(MonthlyPlan monthlyPlan) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //获取流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("monthlyPlan")
                .orderByProcessDefinitionVersion().desc()   //如果多次部署时要获取最新的版本
                .list().get(0);

        //获取流程实例(启动新流程)通过id进行绑定,绑定流程图和表
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(),monthlyPlan.getId());  //流程定义ID,业务ID

        //设置任务完成 (从from变成step1了)
        Task task =  taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();   //form
        //System.out.println("当前任务节点:"+task.getName()); //form
        //form直接在这里完成
        taskService.complete(task.getId());
        //System.out.println("当前任务节点(完成后):"+taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult().getName());// step1


        //流程全局属性,用于存放每个节点的审批信息
        {
            List<AuditHistroyVO> formVariables = new ArrayList<AuditHistroyVO>();
            AuditHistroyVO vo = new AuditHistroyVO()
                    .setAuditType("月度计划审核")
                    .setTaskId(task.getId())
                    .setAuditCreateTime( new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(task.getCreateTime()))
                    .setAuditEndTime(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()))
                    .setTaskName("form")
                    .setTaskDescr("项目经理填写表单")
                    .setAuditUserId(sysUser.getId()); //审批人,这里表示提交人
            formVariables.add(vo);
            runtimeService.setVariable(processInstance.getId(),"form",formVariables);


            List<AuditHistroyVO> step1Variables = new ArrayList<AuditHistroyVO>();
            runtimeService.setVariable(processInstance.getId(),"step1",step1Variables);

            List<AuditHistroyVO> step2Variables = new ArrayList<AuditHistroyVO>();
            runtimeService.setVariable(processInstance.getId(),"step2",step2Variables);

            List<AuditHistroyVO> step3Variables = new ArrayList<AuditHistroyVO>();
            runtimeService.setVariable(processInstance.getId(),"step3",step3Variables);
        }

        monthlyPlan.setVerifyStatus(1);//设置状态为提交审核
        monthlyPlan.setActInstanceId(processInstance.getId()); //记录入库流程ID
    }

太晚了,先弄到这里,剩下的明天再来

  @Override
    public void verifyStep(AuditVO<MonthlyPlan> auditVO) {
        MonthlyPlan monthlyPlan = auditVO.getRecord();
        String processInstanceId = monthlyPlan.getActInstanceId();
        ProcessInstance processInstance =  runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();

        Optional.of( taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult()).ifPresent(task->{

            String taskName = task.getName();
            List<AuditHistroyVO> stepVariable = (List<AuditHistroyVO>) runtimeService.getVariable(processInstanceId,taskName);

            Date createTime = task.getCreateTime();
            String createTimeString = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(createTime);

            Date endTime = new Date();
            String endTimeString = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(endTime);

            stepVariable.add(new AuditHistroyVO()
                    .setAuditCreateTime(createTimeString)
                    .setAuditEndTime(endTimeString)
                    .setAuditType("月度计划产值审核")
                    .setAuditUserId(auditVO.getAuditUserId())
                    .setAuditContent(auditVO.getAuditContent())
                    .setAuditResult(auditVO.getAuditResult())
                    .setTaskName(task.getName())
                    .setTaskDescr(task.getDescription())
                    .setTaskId(task.getId())
            );
            runtimeService.setVariable(processInstanceId,taskName,stepVariable); //重新set一遍更新属性

            //设置网关条件
            //是否驳回 true驳回,false通过   字典:2通过 3驳回
            runtimeService.setVariable(processInstanceId,"isReject",auditVO.getAuditResult() == 3);

            //更新业务审核状态
            this.getBaseMapper().updateById(
                    new MonthlyPlan()
                    .setId(monthlyPlan.getId())
                    .setVerifyStatus(
                            auditVO.getAuditResult() == 3 ?3:1  //如果是驳回设置3(已驳回) 否则设置1(审核中)
                    ));

            //任务完成
            taskService.complete(task.getId());
        });
    }
@Override
    public AuditVO monthlyPlanVerifyQuery(String id) {
        AuditVO vo = new AuditVO();

        //查询出实体类
        MonthlyPlanVO monthlyPlan = this.getBaseMapper().selectVOById(id);

        //根据流程id查询流程信息
        Optional.of(taskService.createTaskQuery().processInstanceId(monthlyPlan.getActInstanceId()).singleResult()).ifPresent(task->{
            //当前处于哪个节点
            int index = IntStream.range(0, monthlyPlanAuditTasks.length)
                    .filter(i -> monthlyPlanAuditTasks[i].equals(task.getName()))
                    .findFirst()
                    .orElse(-1);
            vo.setVerifyIndex(index);

            vo.setRecord(monthlyPlan);
            vo.setAuditType("月度计划产值审核");
            vo.setLastTaskNodeName(getLastTaskName(index));
            vo.setNextTaskNodeName(getNextTaskName(index));
            vo.setCurrTaskNodeName(getCurrTaskName(index));

            JSONObject json = new JSONObject();
            json.put("name",task.getName());
            json.put("id",task.getId());
            json.put("claimTime",task.getClaimTime());
            json.put("createTime",task.getCreateTime());
            json.put("taskDefinitionKey",task.getTaskDefinitionKey());
            json.put("processInstanceId",task.getProcessInstanceId());
            json.put("taskDefinitionKey",task.getTaskDefinitionKey());
            json.put("dueDate",task.getDueDate());

//            task.getId();
//            task.getCategory(); //命名空间、类别
//            task.getFormKey();
//            task.getClaimTime();//获取任务被签收的时间
//            task.getCreateTime();
//            task.getDescription();
//            task.getAssignee();  //受理人 (审批人)
//            task.getOwner();
//            task.getProcessDefinitionId();
//            task.getProcessInstanceId();
//            task.getTaskDefinitionKey();
//            task.getPriority();   //获取任务的优先级
//            task.getExecutionId();
//            task.getDueDate(); //获取任务的截止日期

            vo.setActiviti(json);

        });
        return vo;
    }

    private String getCurrTaskName(int index) {
        return taskNodeNames[index];
    }

    private String getNextTaskName(int index) {
        return taskNodeNames[index+1];
    }

    private String getLastTaskName(int index) {
        return taskNodeNames[index-1];
    }

    @Override
    public List<AuditHistroyVO> auditHistoryListByProcessKey(String id, Integer index, String type) {
        if(("monthlyPlan").equals(type)){
            //注意前端index =1,2
            String processKey = "monthlyPlan";              //前端传递的是,这里转换成流程定义KEY
            String taskKey = monthlyPlanAuditTasks[index+1];
            return auditMonthlyPlanHistoryListByProcessKey(id,processKey,taskKey);
        }

//        if(("outbound").equals(type)){
//            String processKey = "out_bound";//前端传递的是出入库类型,这里转换成流程定义KEY
//            String taskKey = outBoundAuditTasks[index];
//            return auditOutboundHistoryListByProcessKey(id,processKey,taskKey);
//        }

        log.error("错误的type或index,type={},index={}",type,index);
        return null;
    }

    private List<AuditHistroyVO> auditMonthlyPlanHistoryListByProcessKey(String id, String processKey, String taskKey) {
        MonthlyPlan monthlyPlan = this.getBaseMapper().selectById(id);
        List<AuditHistroyVO> stepVariable = (List<AuditHistroyVO>) runtimeService.getVariable(monthlyPlan.getActInstanceId(),taskKey);
        return stepVariable;
        //return null;
    }

    @Override
    public List<AuditHistroyVO> queryhistoryList(String id) {
        MonthlyPlan monthlyPlan = this.getBaseMapper().selectById(id);
        List<AuditHistroyVO> list = new ArrayList<>(); //返回结果
        List<HistoricTaskInstance> historyTaskList = new ArrayList<>(); //临时保存任务节点流
        Map<String,AuditHistroyVO> temp = new HashMap<>(); //临时保存vo对象,key为taskId

        //入库审核历史
        Optional.ofNullable(monthlyPlan.getActInstanceId()).ifPresent(processInstanceId->{
            if(oConvertUtils.isEmpty(processInstanceId)){
                return;
            }

            //已经结束的任务查不到task
//            List<Task> task = taskService.createTaskQuery()
//                    .processDefinitionKey("in_bound")
//                    .processDefinitionId(processInstanceId)
//                    .list();

            setKeyMapAuditHistroyVO(temp,processInstanceId,"form");//form数据
            setKeyMapAuditHistroyVO(temp,processInstanceId,"step1");//节点1数据
            setKeyMapAuditHistroyVO(temp,processInstanceId,"step2");//节点2数据
            setKeyMapAuditHistroyVO(temp,processInstanceId,"step3");//节点2数据

            //将流程任务顺序存入list中
            historyTaskList.addAll(historyService.createHistoricTaskInstanceQuery()
                    .processDefinitionKey("monthlyPlan")
                    .processInstanceId(processInstanceId)
                    .list());
        });

        //变量流程任务节点,按顺序存入list中,并匹配vo属性
        //@BUG 流程没结束时,最后一个任务没有vo,list添加了一个空元素
        historyTaskList.stream().forEach(htask->{
            AuditHistroyVO vo = temp.get(htask.getId());  //根据taskId 获取对应的vo
            if(vo != null && oConvertUtils.isNotEmpty(vo.getTaskId())){
                list.add(vo);
            }
        });

        return list;
    }

    @Override
    public void updateProcessResult(String processInstanceId, String processInstanceBusinessKey, int verifyStatus) {
        MonthlyPlan monthlyPlan = new MonthlyPlan();
        monthlyPlan.setId(processInstanceBusinessKey);
        monthlyPlan.setVerifyStatus(2);

        this.getBaseMapper().updateById(monthlyPlan); //更新审核状态
    }

    private void setKeyMapAuditHistroyVO(Map<String,AuditHistroyVO> temp, String processInstanceId, String taskKey){
        HistoricVariableInstance hisInstance =  historyService
                .createHistoricVariableInstanceQuery()
                .processInstanceId(processInstanceId)
                .variableName(taskKey)
                .singleResult();

        List<AuditHistroyVO> vo = (List<AuditHistroyVO>) hisInstance.getValue();
        vo.stream().forEach(v->{
            temp.put(v.getTaskId(),v);
        });
    }



}

注意流程图

流程图注意一个是每个节点的注释,和最后审批完成节点的监听器,当后端出现
在这里插入图片描述
这样的问题时去查看end节点的事件是否路径正确,路径是endlistenner的包路径

package org.jeecg.modules.demo.monthlyAchieve.listener;

更改完之后记得重新部署

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
授权方式: 开源软件 界面语言: 简体中文 文件大小: 45.6 MB 更新时间: 2020-08-12 资源类型: 国产软件 推荐等级: ★★★☆☆ 平台环境: JAVA 作者主页: 点击查看 演示地址: 点击查看 详细介绍 – [ JEECG快速开发平台 v4.0 ] JEECG (J2EE Code Generation)是一款基于代码生成器的智能开发平台。引领新的开发模式(Online Coding->代码生成器->手工MERGE智能开发),可以帮助解决Java项目90%的重复工作,让开发更多关注业务逻辑。既能快速提高开发效率,帮助公司节省人力成本,同时又不失灵活性。 JEECG宗旨是:简单功能由代Online Coding配置出功能;复杂功能由代码生成器生成进行手工Merge;复杂流程业务采用表单自定义,业务流程使用工作流来实现、扩展出任务接口,供开发编写业务逻辑。实现了流程任务节点和任务接口的灵活配置,既保证了公司流程的保密行,又减少了开发人员的工作量。 JEECG功能特点 1、采用SpringMVC+Hibernate+Minidao(类Mybatis)+Easyui(UI库)+Jquery+Boostrap+Ehcache+Redis+Ztree+Vue+Boostrap-table+ElementUI等基础架构 2、采用面向声明的开发模式,基于泛型编写极少代码即可实现复杂的数据展示、数据编辑、表单处理等功能,再配合Online Coding在线开发与代码生成器的使用,将J2EE的开发效率提高8倍以上,可以将代码减少90%以上。 3、JEECGV4.0,经过了专业压力测试,性能测试,保证后台数据的准确性和页面访问速度 4、支持多种浏览器:IE,火狐,Google等 5、支持数据库:Mysql,Oracle,Postgre,SqlServer等 6、基础权限:用户,角色,菜单权限,按钮权限,数据权限 7、智能报表集成:简易的图像报表工具和Excel导入导出 8、Web容器测试通过的有Jetty和Tomcat,Weblogic 9、亮点功能:分布式部署,云平台,移动平台开发,规则引擎 10、要求JDK1.6+ JEECG技术点总结 技术点一:代码生成器SPA单页面应用快速生成,采用VUE+ElementUI打造酷炫效果 技术点二:新一代代码生成器更灵活的代码生成器工厂,可灵活自定义生成的代码文件名称、路径等;根据模板结构生成代码文件 技术点三:新一代代码生成器支持Vue+ElementUI风格,Bootstrap表单+EasyUI原生态列表风格,ElementUI表单+EasyUI原生态列表风格 技术点四:Dategrid标签多列表风格快速切换,给用户提供多种选择 技术点五:Online Coding在线开发(通过在线配置实现一个表模型的增删改查功能,无需一行代码,支持用户自定义表单布局) 技术点六:代码生成器,支持多种数据模型,根据表生成对应的Entity,Service,Dao,Action,JSP等,增删改查功能生成直接使用 技术点七:UI快速开发库,针对WEBUI进行标准封装,页面统一采用UI标签实现功能:数据datagrid,表单校验,Popup,Tab等,实现JSP页面零JS,开发维护非常高效 技术点八:在线流程定义,采用开源Activiti流程引擎,实现在线画流程,自定义表单,表单挂接,业务流转,流程监控,流程跟踪,流程委托等 技术点九:自定义表单,支持用户自定义表单布局,支持单表、列表、Select\\Radio\\Checkbox\\PopUP\\Date等特殊控件 技术点十:查询过滤器:查询功能自动生成,后台动态拼SQL追加查询条件;支持多种匹配方式(全匹配/模糊查询/包含查询/不匹配查询) 技术点十一:移动平台支持,对Bootstrap(兼容Html5)进行标准封装 技术点十二:动态报表功能(用户输入一个sql,系统自动解析生成报表) 技术点十三:数据权限(精细化数据权限控制,控制到行级,列表级,表单字段级,实现不同人看不同数据,不同人对同一个页面操作不同字段) 技术点十四:国际化(支持多语言,国际化的封装为多语言做了便捷支持) 技术点十五:多数据源(在线配置数据源,数据源工作类封装) 技术点十六:多种首页风格切换,支持自定义首页风格。(经典风格、Shortcut风格、ACEbootstrap风格、云桌面风格) 技术点十七:在线配置报表(无需编码,通过在线配置方式,实现曲线图,柱状图,数据等报表) 技术点十八:简易Excel导入导出,支持单表导出和一对多表模式导出,生成的代码自带导入导出功能 技术点十九:移动OA,移动OA审批功能,采用H5技术,实现手机移动办公,无缝对接微信、钉钉、微信企业号
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值