数据库动态视图和存储过程报表数据管理功能设计

news2024/11/16 11:47:06

需求:需要将ERP的报表数据挪到OA中,但是OA表单设计不支持存储过程动态传参,所以需要设计一个系统,可以手动配置,动态显示原本ERP的报表数据,ERP报表是存在数据库的视图和存储过程中

思路:因为ERP数据库只有一个,所以不需要考虑多数据源问题(当然这个也很好解决),动态sql拼接,存储过程原本想用临时表的方式解决结果集字段查询和分页问题,但是后来觉得太麻烦了,选择程序中解决,毕竟数据量最多的也就一两万条,使用list的截取实现分页

后端:spring
前端:element

效果截图:
管理界面:
在这里插入图片描述
新增界面:
在这里插入图片描述
修改界面:
视图没有必要参数,因为视图可以通过where查询,默认都是结果集筛选参数
在这里插入图片描述
展示页面效果(用于外挂在OA系统里):
(展示页面只有一个文件,动态展示数据,根据管理页面中注释字段区分)
在这里插入图片描述
所有筛选参数和展示字段也都是动态显示
在这里插入图片描述

针对不同字段的动态处理:
日期:
在这里插入图片描述
客户和供应商,采购员,员工,销售员都是对应数据的下拉带搜索:
在这里插入图片描述
在这里插入图片描述
后台配置筛选参数的时候,字段名叫日期会去调用日期选择,字段叫客户会调用所有客户信息选择,字段名叫供应商会去调用所有供应商信息,字段名带员的(人员,员工,采购员,销售员)会去调用员工信息选择(这些都是前端设置的,不想后端在加一个类型字段来区分了,直接用名字区分)

数据库表结构:
主表:
在这里插入图片描述
从表(用于筛选字段):
在这里插入图片描述
部分代码:
页面获取参数信息(根据展示页面url的参数):

@RequestMapping("/getcanshu")
    public R getcanshu(@RequestParam("name") String zhushi){
        QueryWrapper<XinxiShituzhuEntity> query = new QueryWrapper();
        query.eq("zhushi", zhushi);
        XinxiShituzhuEntity zhudata = xinxiShituzhuService.getOne(query);
        Integer zhuid = zhudata.getId();
        QueryWrapper<XinxiShitucongEntity> congquery = new QueryWrapper();
        congquery.eq("fatherid", zhuid);
        List<XinxiShitucongEntity> congdata = xinxiShitucongService.list(congquery);
        zhudata.setCanshu(congdata);
        return R.ok().put("data", zhudata);
    }

获取展示页面查询数据:

@RequestMapping("/getalldatas")
    public R getalldatas(@RequestBody XinxiShituzhuEntity xinxiShituzhu){
        // 视图
        if(xinxiShituzhu.getBtype()==1){
            // 拼接sql
            String querySql = "SELECT * FROM "+xinxiShituzhu.getName() +" WHERE 1=1 ";
            String countsql = "SELECT COUNT(1) FROM "+xinxiShituzhu.getName() +" WHERE 1=1 ";
            List<XinxiShitucongEntity> congdatas = xinxiShituzhu.getCanshu();
            for(XinxiShitucongEntity data: congdatas){
                if(!Objects.equals(data.getZdzhi(), "")&& data.getZdzhi()!=null){
                    querySql = querySql + " AND ["+data.getName()+"]= '"+data.getZdzhi()+"'";
                    countsql = countsql + " AND ["+data.getName()+"]= '"+data.getZdzhi()+"'";
                }
            }

            // 添加分页
            querySql = querySql + " order by ["+ xinxiShituzhu.getPaixuzd() +"] offset "+(xinxiShituzhu.getPageNum()-1)*xinxiShituzhu.getPageSize()+" row fetch next "+xinxiShituzhu.getPageSize()+" row only;";

            List<Map<String, Object>> zhudatas = xinxiShituzhuService.getAllShituDatas(querySql);

            // 总数
            Integer zhucount = xinxiShituzhuService.getAllShituCount(countsql);

            // 获取所有表头,用于展示页表头信息
            List<Map<String, Object>> newdatas = new ArrayList<>();

            for(Map<String, Object> data : zhudatas){
                for(String key: data.keySet()){
                    Map<String, Object> newmapdata = new LinkedHashMap<>();
                    newmapdata.put("key", key);
                    newdatas.add(newmapdata);
                }
//                Collections.reverse(newdatas);
                break;
            }

            return R.ok().put("count", zhucount).put("data", zhudatas).put("headdata", newdatas);
        }
        // 存储过程
        else{
            // 拼接sql
            String querySql = "EXEC ["+xinxiShituzhu.getName()+"]";
            List<XinxiShitucongEntity> congdatas = xinxiShituzhu.getCanshu();
            // 遍历所有参数
            for(XinxiShitucongEntity data: congdatas){
                // 视图必要参数添加
                if(Objects.equals(data.getZdtype(), "1")){
                    if(!Objects.equals(data.getZdzhi(), "")&& data.getZdzhi()!=null){
                        querySql = querySql + " @"+data.getName()+"= '"+data.getZdzhi()+"'";
                    }else{
                        return R.error("必要参数不能为空");
                    }
                }
            }
            // 获取所有数据
            List<Map<String, Object>> zhudatas = xinxiShituzhuService.getAllShituDatas(querySql);

            List<Map<String, Object>> newdatas = new ArrayList<>();

            // 遍历结果集,用于结果集的字段筛选
            for(Map<String, Object> dataxx: zhudatas){
                // 用于标记筛选字段有效性
                List<Boolean> biaojis = new ArrayList<>();
                for(XinxiShitucongEntity data: congdatas){
                    if(Objects.equals(data.getZdtype(), "2")){
                        if(!Objects.equals(data.getZdzhi(), "")&& data.getZdzhi()!=null){
                            if(ObjectUtil.isNotNull(dataxx.get(data.getName())) && dataxx.get(data.getName()).equals(data.getZdzhi())){
                                // 如果被其中一个条件筛选出来就给整条数据标记true
                                biaojis.add(true);
                            }else{
                                // 如果被其中一个条件没有筛选出来就给整条数据标记false
                                biaojis.add(false);
                            }
                        }else{
                            // 筛选条件没有填的是都要筛选的
                            biaojis.add(true);
                        }
                    }
                }
                // 只有没有false标记的数据才是被筛选出来的
                if(!biaojis.contains(false)){
                    newdatas.add(dataxx);
                }
            }

            // 总数
            Integer zhucount = newdatas.size();

            int pagenum = (xinxiShituzhu.getPageNum()-1)*xinxiShituzhu.getPageSize();
            int pagesize = pagenum + xinxiShituzhu.getPageSize();

            // list截取
            List<Map<String, Object>> newzhudatas = CollectionUtil.sub(newdatas, pagenum, pagesize);

            List<Map<String, Object>> newheaddatas = new ArrayList<>();

            // 获取表头信息
            for(Map<String, Object> data : newzhudatas){
                for(String key: data.keySet()){
                    Map<String, Object> newmapdata = new LinkedHashMap<>();
                    newmapdata.put("key", key);
                    newheaddatas.add(newmapdata);
                }
                break;
            }

            return R.ok().put("count", zhucount).put("data", newzhudatas).put("headdata", newheaddatas);
        }
    }

sql拼接xml(要用LinkedHashMap类型,不然字段顺序不固定,数据展示就很难看):

 <select id="getAllShituDatas" resultType="java.util.LinkedHashMap">
        ${shitusql}
    </select>

    <select id="getAllShituCount" resultType="java.lang.Integer">
        ${shitusql}
    </select>

主Entity:
在这里插入图片描述
从Entity:
在这里插入图片描述

展示页面的vue代码:

<template>
    <div class="sanfangcangkuliang-main">
        <el-form :model="form" :inline="true" >
            <el-form-item :label="item.zdname" v-for="item of canshulist" :key="item.name" >
                <el-input v-model="item.zdzhi" v-if="item.zdname!='供应商' && item.zdname!='客户' && item.zdname.indexOf('员')==-1 && item.zdname!='日期'" :placeholder="item.zdtype==1?'必填':'选填'"></el-input>
                <!-- <el-input v-model="item.zdzhi" v-if="item.zdtype==2" placeholder="选填"></el-input> -->

                <el-select v-model="item.zdzhi" filterable clearable :placeholder="item.zdtype==1?'必填':'选填'" v-if="item.zdname=='供应商'">
                  <el-option
                    v-for="item in gongyingshanglist"
                    :key="item.gys"
                    :label="item.gys"
                    :value="item.gys">
                  </el-option>
                </el-select>

                <el-select v-model="item.zdzhi" filterable clearable :placeholder="item.zdtype==1?'必填':'选填'" v-if="item.zdname=='客户'">
                  <el-option
                    v-for="item in kehulist"
                    :key="item.kh"
                    :label="item.kh"
                    :value="item.kh">
                  </el-option>
                </el-select>

                <el-select v-model="item.zdzhi" filterable clearable :placeholder="item.zdtype==1?'必填':'选填'" v-if="item.zdname.indexOf('员')!=-1">
                  <el-option
                    v-for="item in renyuanlist"
                    :key="item.yg"
                    :label="item.yg"
                    :value="item.yg">
                  </el-option>
                </el-select>

                <el-date-picker
                  v-model="item.zdzhi"
                  type="date"
                  value-format="yyyy-MM-dd"
                  :placeholder="item.zdtype==1?'必填':'选填'"
                  v-if="item.zdname=='日期'"
                  >
                </el-date-picker>

            </el-form-item>

            <el-form-item>
                <el-button type="primary" style="display:inline-block; width: 80px;height: 40px;" @click="getList(1)">搜索</el-button>
                <el-button style="display:inline-block; width: 80px;height: 40px;" @click="chongzhi()">重置</el-button>
                
                <!-- <el-button type="success" style="display:inline-block; width: 100px;height: 40px;" @click="gengxin()">批量更新</el-button> -->
            </el-form-item>
        </el-form>
        
        <el-pagination
        style="margin:30px"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="mapdatas.pageNum"
        :page-sizes="[50, 100, 200, 500, 1000, 2000, 5000]"
        :page-size="mapdatas.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total=total>
        </el-pagination>

        <el-table style="width: 100%; margin-left:40px" :data="tableData">
            <template v-for="(item,index) in maphead">
                <el-table-column :prop="item.key" :label="item.key" :key="index"></el-table-column>
            </template>
        </el-table>

        <el-pagination
        style="margin:30px"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="mapdatas.pageNum"
        :page-sizes="[50, 100, 200, 500, 1000, 2000, 5000]"
        :page-size="mapdatas.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total=total>
        </el-pagination>
        
    </div>
</template>
<script>

export default {
    data () {
        return {
          renyuanlist:[],
          gongyingshanglist:[],
          kehulist:[],
            form:{},
            maphead:[],
            mapdatas:{
                pageNum:1,
                pageSize:100,
            },
            canshulist:[],
            pageSize:100,
            currentPage:1,
            total:0,
            tableData: [],
            xiangqingshow:false,
            xiangqingdatas:[],
            tableDatazong:[],
            ckmclist: [],
            ywymc:""
        }
    },
    mounted(){
        this.getTableCanshu();
        this.getRenyuanDatas();
        this.getGyingshangDatas();
        this.getKehuDatas();
    },
    methods: {
        handleSizeChange(val) {
        this.mapdatas.pageSize = val
        this.getList(2);
      },
      handleCurrentChange(val) {
        this.mapdatas.pageNum = val
        this.getList(2);
      },

      getList(type){
        if(type==1){
          this.mapdatas.pageNum = 1
          this.mapdatas.pageSize = 100;
        }

        this.mapdatas['canshu'] = this.canshulist
        
        this.$axios({
          method:'post',
          url:"/renren-fast/xinxi/xinxishituzhu/getalldatas",
          data:JSON.stringify(this.mapdatas),
          headers:{"Content-Type": "application/json"}
        }).then((response) =>{          //这里使用了ES6的语法
          if(response.data.code==0 || response.data.code=='0'){
            this.tableData = response.data.data;
            this.total = response.data.count;
            this.maphead = response.data.headdata;
          }else{
            this.$message.error(response.data.msg);
            this.total = 0
            this.mapdatas.pageNum = 1
            this.mapdatas.pageSize = 100;
          }
        }).catch((error) =>{
          console.log(error)       //请求失败返回的数据
          
        })
      },
      chongzhi(){
        for(let data of this.canshulist){
            data.zdzhi=""
        }

        this.mapdatas.pageNum = 1
        this.mapdatas.pageSize = 100;
        this.tableData = []
        this.getList(1)
      },
  
      // 获取表的参数
      getTableCanshu(){
        this.$axios({
            url: '/xinxi/xinxishituzhu/getcanshu',
            method: 'GET',
            params: {
                name: this.$route.query.name
            }
            }).then((res) => {
                if(res.data.code==0 || res.data.code=='0'){

                    this.mapdatas = {
                        btype: res.data.data.btype,
                        deleted: res.data.data.deleted,
                        id: res.data.data.id,
                        name: res.data.data.name,
                        pageNum: res.data.data.pageNum || 1,
                        pageSize: res.data.data.pageSize || 100,
                        paixuzd: res.data.data.paixuzd,
                        reationtime: res.data.data.reationtime,
                        updatetime: res.data.data.updatetime,
                        zhushi: res.data.data.zhushi
                    }
                    
                    this.canshulist = res.data.data.canshu

                    if(res.data.data.btype==1){
                        this.getList(1);
                    }
                }
            })
      },
      // 获取人员
      getRenyuanDatas(){
        this.$axios({
            url: '/xinxi/xinxishituzhu/getyuangongdatas',
            method: 'GET',
            // params: {
            //     name: this.$route.query.name
            // }
            }).then((res) => {
                if(res.data.code==0 || res.data.code=='0'){
                    this.renyuanlist = res.data.data;
                }
            })
      },

      // 获取供应商
      getGyingshangDatas(){
        this.$axios({
            url: '/xinxi/xinxishituzhu/getgongyingshangdatas',
            method: 'GET',
            // params: {
            //     name: this.$route.query.name
            // }
            }).then((res) => {
                if(res.data.code==0 || res.data.code=='0'){
                    this.gongyingshanglist = res.data.data;
                }
            })
      },

      // 获取客户
      getKehuDatas(){
        this.$axios({
            url: '/xinxi/xinxishituzhu/getkehudatas',
            method: 'GET',
            // params: {
            //     name: this.$route.query.name
            // }
            }).then((res) => {
                if(res.data.code==0 || res.data.code=='0'){
                    this.kehulist = res.data.data;
                }
            })
      },
    }
}
</script>
<style scoped>
*{
    margin: 0;
    padding: 0;
}
</style>

因为ERP有几十个报表要迁移,之前领导都是上级领导想看报表但是他们不使用ERP只使用OA,就会我们做进OA报表,只有OA实现不了的我才自己写后台接口和前端页面,这次说要全部迁移,我看一下几十个报表,如果像原来那样一个个写后台接口和前端页面的话不知道要写到什么时候,于是花了两天写了这个功能出来,目前正常使用没问题(因为存储过程必须要填参数才可以出数据,所以存储过程的展示页面需要输入必填参数以后点查询出数据,视图则是可以直接出数据)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1310204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法复习——6种排序方法的简单回顾

算法复习——6种排序方法的简单回顾 常见排序方法&#xff1a;冒泡排序、选择排序、插入排序、堆排序、归并排序、快速排序的简单回顾 冒泡排序 重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置” 在冒泡排序中&#xff0c;第 1 轮需要比较 n - 1…

整理b站黑马程序员C++课程中对于计算机视觉学习有所帮助的知识点。(重点用*标出)

文章目录 1、注释2、变量3、常量4、标识符5、整型 浮点型 字符型 字符串 布尔6、输入 输出7、逻辑运算法8、 程序流程结构9、三目运算符10、switch语句11、循环语句12、跳转语句13、*数组13.1一维数组名 14、二维数组15、**函数15.1、函数的调用15.2、函数的声明15.3、函数份文…

Android camera的metadata

一、实现 先看一下metadata内部是什么样子&#xff1a; 可以看出&#xff0c;metadata 内部是一块连续的内存空间。 其内存分布大致可概括为&#xff1a; 区域一 &#xff1a;存 camera_metadata_t 结构体定义&#xff0c;占用内存 96 Byte 区域二 &#xff1a;保留区&#x…

HarmonyOS--基础组件TextInput

TextInput 官方文档 TextInput组件https://developer.harmonyos.com/cn/docs/documentation/doc-references-V3/ts-basic-components-textinput-0000001427584864-V3#ZH-CN_TOPIC_0000001523968610__%E5%AD%90%E7%BB%84%E4%BB%B6 文本输入框组件 接口 TextInput(value?:…

【Python】用Python发邮件

准备工作 以新浪邮箱为例&#xff0c;进入账号管理&#xff0c;打开授权码并保存下来 用到的包 import smtplib from email.header import Header from email.mime.text import MIMEText 账号授权码准备 这里用的是前面记录的授权码&#xff0c;不是登录密码哦 email_hostsm…

40G AOC线缆全系列产品知识详解

40G AOC&#xff08;Active Optical Cable&#xff09;线缆作为高速数据传输的重要组成部分&#xff0c;在现代通信和数据中心应用中扮演着重要角色。本期文章我们将从其基本原理、应用领域、优势特点等方面对ETU-LINK 40G AOC全系列产品进行解析。 一、40G AOC全系列产品解析…

Facebook广告投放常见错误

在进行Facebook广告投放时&#xff0c;很容易犯一些常见的错误。这些错误可能导致广告投资的浪费&#xff0c;影响广告效果并降低回报。本文小编讲一些常见的Facebook广告投放错误&#xff0c;以及如何避免它们。 1、不明确目标受众 广告的成功与否很大程度上取决于你选择的目…

基于Java+Swing+mysql学生选课成绩信息管理系统

基于JavaSwingmysql学生选课成绩信息管理系统 一、系统介绍二、功能展示三、项目相关3.1 乱码问题3.2 如何将GBK编码系统修改为UTF-8编码的系统&#xff1f; 四、其它1.其他系统实现 五、源码下载 一、系统介绍 学生教师信息管理、年级班级信息管理、课程信息管理、选课、成绩…

怎么制作一个微信小程序商城

随着移动互联网的普及&#xff0c;越来越多的商家开始关注线上销售。微信小程序商城作为一种便捷、实用的线上销售平台&#xff0c;受到了广大商家的青睐。本文将详细介绍如何制作一个微信小程序商城。 一、登录乔拓云平台进入后台 首先&#xff0c;我们需要登录乔拓云平台&am…

亚信科技AntDB数据库——深入了解AntDB-M元数据锁的相关概念

AntDB-M在架构上分为两层&#xff0c;服务层和存储引擎层。元数据的并发管理集中在服务层&#xff0c;数据的存储访问在存储引擎层。为了保证DDL操作与DML操作之间的一致性&#xff0c;引入了元数据锁&#xff08;MDL&#xff09;。 AntDB-M提供了丰富的元数据锁功能&#xff…

服务器感染了.DevicData-D-XXXXXXXX勒索病毒,如何确保数据文件完整恢复?

引言&#xff1a; 勒索病毒成为网络安全的严峻挑战&#xff0c;而最新的.DevicData-D-XXXXXXXX勒索病毒更是引起广泛关注。本文将深入介绍.DevicData-D-XXXXXXXX勒索病毒的特征&#xff0c;提供恢复被其加密的数据文件的方法&#xff0c;并分享预防措施&#xff0c;以确保您的数…

【算法题】打印任务排序(js)

输入: 1,2,2 输出&#xff1a;2,0,1 说明:队列头部任务的优先级为1&#xff0c;被移到队列尾部&#xff1b;接着顺序打印两个优先级为2的任务&#xff0c;故其序号分别为0和1&#xff1b;最后打印剩下的优先级为1的任务&#xff0c;其序号为2 解法&#xff1a; const str &q…

_pickle.PicklingError: Can‘t pickle : import of module failed

有问题 没问题的 python - pickle cant import a module that exists? - Stack Overflow

1311:【例2.5】求逆序对 归并排序

1311&#xff1a;【例2.5】求逆序对 【题目描述】 给定一个序列a1,a2,…,an&#xff0c;如果存在i<j并且ai>aj&#xff0c;那么我们称之为逆序对&#xff0c;求逆序对的数目。 【输入】 第一行为n,表示序列长度&#xff0c;接下来的n行&#xff0c;第i1行表示序列中的第…

idea中定时+多数据源配置

因项目要求,需要定时从达梦数据库中取数据,并插入或更新到ORACLE数据库中 1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-…

01读《物联网安全研究综述:威胁、检测与防御》随笔

01读《物联网安全研究综述&#xff1a;威胁、检测与防御》随笔 摘要3 研究现状3.1 安全威胁3.1.1 云平台访问控制缺陷3.1.2 云平台恶意应用3.1.3 云平台实体和应用交互漏洞3.1.4 通信协议漏洞3.1.5 通信流量侧信道信息泄露3.1.6 设备固件漏洞3.1.7 基于语音信道的攻击3.1.8 基于…

SpringBoot核心功能-temp

yml&类配置 Configuration-processor

软文写作需要避免的四大误区,媒介盒子分享

有不少企业在做软文推广时在文案上容易踩坑&#xff0c;导致推广不起效。今天媒介盒子就来和大家聊聊软文写作中需要避免的四大类型&#xff0c;帮助企业提高软文推广效率。 一、 文案没有核心点 一篇软文的价值在于软文阐述的核心点&#xff0c;若没有一个核心点加以细化撰写…

2023年【A特种设备相关管理(锅炉压力容器压力管道)】考试题及A特种设备相关管理(锅炉压力容器压力管道)考试内容

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;考试题是安全生产模拟考试一点通总题库中生成的一套A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;考试内容&#xff0c;安全生产模…

保姆级 Keras 实现 YOLO v3 三

保姆级 Keras 实现 YOLO v3 三 一. 分配 anchor box二. 正负样本匹配规则三. 为每一个 anchor box 打标签3.1 anchor box 长什么样?3.2 每一个 anchor box 标签需要填充的信息有哪些?3.3 ( Δ x , Δ y , Δ w , Δ h ) (\Delta x, \Delta y, \Delta w, \Delta h) (Δx,Δy,…