【java爬虫】使用element-plus进行个股详细数据分页展示

前言

前面的文章我们讲述了获取详细个股数据的方法,并且使用echarts对个股的价格走势图进行了展示,本文将编写一个页面,对个股详细数据进行展示。别问涉及到了element-plus中分页的写法,对于这部分知识将会做重点讲解。

首先看一下效果

之前我一直认为前端分页很难写,不过今天写完这个页面之后我发现,有了element-plus这样的框架,前端真的变得非常简单。

获取所有有数据的股票代码

我们的页面主要分为两个部分,第一部分是获取所有有数据的股票代码,一旦选择了某一个股票代码,就会进行相对应数据的展示

本节我们先来说一下获取所有可展示的数据

和本页面相关的数据表一共有两张,一张是沪深300成分股表,表中记录了股票代码和股票名称

 

另一张表是个股详细数据表,就是我们在之前的文章介绍过的表

【java爬虫】基于springboot+jdbcTemplate+sqlite+OkHttp获取个股的详细数据-CSDN博客

这样表对应的详细信息如下图所示

我们要分页展示的也是这张表中的数据,之所以需要两张表联动,是因为这张表中没有股票名称,为了能够同时将股票代码和股票名称查出来,我们需要首先查询个股数据表,然后再从沪深300成分股表中查询出股票代码对应的股票名称

    public List<StockOptionVO> getAllCode() {List<StockEntity> stockEntities = sqLiteStockDao.queryAllCode();List<CSI300Entity> csi300Entities = sqlIteCSI300Dao.queryAllItems();List<StockOptionVO> stockOptionVOList = new ArrayList<>();for (int i=0; i<stockEntities.size(); i++) {StockOptionVO stockOptionVO = new StockOptionVO();stockOptionVO.setCode(stockEntities.get(i).getCode());for (int j=0; j<csi300Entities.size(); j++) {if (csi300Entities.get(j).getCode().equals(stockEntities.get(i).getCode())) {stockOptionVO.setName(csi300Entities.get(j).getName());break;}}stockOptionVOList.add(stockOptionVO);}return stockOptionVOList;}

 其中两个SQL语句都很简单,就是SELECT查询数据

    @Overridepublic List<StockEntity> queryAllCode() {String sql = "SELECT DISTINCT code FROM " + TABLE_NAME;log.info("执行sql:" + sql);List<StockEntity> stockEntities = jdbcTemplate.query(sql, new Object[]{}, new BeanPropertyRowMapper<>(StockEntity.class));return stockEntities;}
    @Overridepublic List<CSI300Entity> queryAllItems() {String sql = "SELECT * FROM " + tableName;List<CSI300Entity> csi300Entities = jdbcTemplate.query(sql, new Object[]{}, new BeanPropertyRowMapper<CSI300Entity>(CSI300Entity.class));return csi300Entities;}

控制层代码如下

    // 获取所有有详细数据的股票代码@RequestMapping("/queryCodeOptions")@ResponseBodypublic String queryCodeOptions() {List<StockOptionVO> stockOptionVOList = stockService.getAllCode();return JSON.toJSONString(stockOptionVOList);}

该接口调用的结果如下所示

[{"code":"000001","name":"平安银行"},{"code":"000063","name":"中兴通讯"},{"code":"000002","name":"万科A"},{"code":"688981","name":"中芯国际"},{"code":"000568","name":"泸州老窖"}]

然后我们回到前端,我们使用了<el-select>组件进行多个选项的选择,其中<el-option>是对应的选项,我们使用v-for将后端请求到的数据渲染成选项

     <el-card><el-form label-width="auto"><el-form-item label="选择要查询的股票"><el-select v-model="code" placeholder="请选择股票"><el-option@click="handleSelect(item)"v-for="item in options":label="item.code + ' ' + item.name":value="item.code":key="item.code"></el-option></el-select></el-form-item></el-form></el-card>

注意看,<el-option>中有一个@click选项,就是我们点击的时候会触发的相应操作,实际上这个函数的逻辑就是点击后就进行相对应股票数据的查询。

获取个股详细数据并分页展示

分页有非常多好处,在SQL端主要就是使用LIMIT和OFFSET这两个关键字来实现的

接口层面接收三个参数,分别是股票代码,每一页的数据量和当前页数

    // 分页查询某一只股票的详细数据@RequestMapping("/queryDataByPage/{code}/{pagesize}/{page}")@ResponseBodypublic String queryDataByPage(@PathVariable("code") String code,@PathVariable("pagesize") Integer pagesize,@PathVariable("page") Integer page) {List<StockEntity> stockEntities = stockService.queryDataByPage(code, pagesize, page);return JSON.toJSONString(stockEntities);}

在Service层将页数转换为SQL语句中的LIMIT和OFFSET,其中LIMIT是固定的,就是你的每一页的数据量,OFFSET的计算公式为(page - 1) * pagesize

    // 分页查询某一只股票的详细数据public List<StockEntity> queryDataByPage(String code, Integer pagesize, Integer page) {Integer limit = pagesize;Integer offset = (page - 1) * pagesize;List<StockEntity> stockEntities = sqLiteStockDao.queryDataByPage(code, limit, offset);return stockEntities;}

最后就是DAO层的代码

     @Overridepublic List<StockEntity> queryDataByPage(String code, Integer limit, Integer offset) {String sql = "SELECT * FROM " + TABLE_NAME +" WHERE code=? ORDER BY record_date DESC LIMIT ? OFFSET ?";log.info("执行sql:" + sql);List<StockEntity> stockEntities = jdbcTemplate.query(sql, new Object[]{code, limit, offset},new BeanPropertyRowMapper<>(StockEntity.class));return stockEntities;}

这样一来我们就编写好了分页查询的后端接口。

我们还需要一个获取数据总量的接口,从控制层到服务层再到Dao层的代码如下

    // 查询数据的总条数@RequestMapping("/queryNumByCode/{code}")@ResponseBodypublic Integer queryNumByCode(@PathVariable("code") String code) {int num = stockService.queryNumByCode(code);return num;}
    // 查询数据的总条数public int queryNumByCode(String code) {return sqLiteStockDao.queryNumByCode(code);}
    @Overridepublic int queryNumByCode(String code) {String sql = "SELECT COUNT(id) FROM " + TABLE_NAME + " WHERE code=?";log.info("执行sql:" + sql);int num = jdbcTemplate.queryForObject(sql, new Object[]{code},Integer.class);return num;}

下面来看一下前端的分页组件,element-plus提供了<el-pagintion>进行分页,我们拿一个官网的例子来讲解这个组件的用法

从上到下依次为:

  • current-page:表示当前页数,这是一个动态的值
  • page-size:表示每一页的数据量,这也是一个动态的值
  • small:是否采用小型分页样式
  • disabled:是否禁用分页
  • background:是否为分页按钮添加背景颜色(添加了背景颜色会更好看)
  • layout:组件的排版方式
  • total:总的数据量(这是需要提前获取的)
  • size-change:当每一页的数据量变化时触发的事件
  • current-change:当前页面变化时触发的事件

关于这个样式,我给大家举一个例子,比如我是这样写的

可以看到从左到右分别是sizes,prev,pager,next和total,那么对应的呈现的效果如下

这样子说不知道大家是否能更好地理解这个属性的用法。

那么有了基本的样式后,我们还需要编写当前页和每一页数据量这两个变量改变时的响应事件,其实逻辑都很简单,就是改变一下变量的值,然后再请求新的数据

    handleSizeChange(number) {this.current_size = number;var url ="http://localhost:9001/stock/queryDataByPage/" +this.current_code +"/" +this.current_size +"/" +this.current_page;this.loading = true;axios.get(url).then((response) => {this.table_data = response.data;console.log(response);this.loading = false;}).catch((error) => {console.log(error);this.loading = false;});},handleCurrentChange(number) {this.current_page = number;var url ="http://localhost:9001/stock/queryDataByPage/" +this.current_code +"/" +this.current_size +"/" +this.current_page;this.loading = true;axios.get(url).then((response) => {this.table_data = response.data;console.log(response);this.loading = false;}).catch((error) => {console.log(error);this.loading = false;});},

下面展示一下前端页面的完整代码

<template><el-container><el-main><el-card><el-form label-width="auto"><el-form-item label="选择要查询的股票"><el-select v-model="code" placeholder="请选择股票"><el-option@click="handleSelect(item)"v-for="item in options":label="item.code + ' ' + item.name":value="item.code":key="item.code"></el-option></el-select></el-form-item></el-form></el-card><el-card><template #header><div class="card-header"><span>{{ table_title }}</span></div></template><el-tablev-loading="loading":data="table_data":show-header="true":max-height="500"stripe><el-table-column prop="record_date" label="时间"></el-table-column><el-table-column prop="open_price" label="开盘价"></el-table-column><el-table-column prop="close_price" label="收盘价"></el-table-column><el-table-column prop="change_ament" label="涨跌额"></el-table-column><el-table-columnprop="change_range"label="涨跌幅":formatter="formatter1"></el-table-column><el-table-column prop="max_price" label="最高价格"></el-table-column><el-table-column prop="min_price" label="最低价格"></el-table-column><el-table-column prop="volume" label="成交量(手)"></el-table-column><el-table-columnprop="turnover"label="成交额(万)"></el-table-column><el-table-columnprop="turnover_rate"label="换手率":formatter="formatter2"></el-table-column></el-table><el-divider /><el-pagination:current-page="current_page":page-size="current_size":page-sizes="[10, 20, 30]":small="false":background="true"layout="sizes, prev, pager, next, total":total="total_num"@size-change="handleSizeChange"@current-change="handleCurrentChange"/></el-card></el-main></el-container>
</template><script>
import axios from "axios";
import { getCurrentInstance } from "vue";
export default {data() {return {update_status: "未开始",loading: false,// 当前选中的股票code: "",// 所有的选项options: [],table_title: "个股数据",// 个股详细信息table_data: [],// 分页相关选项// 当前查询的股票代码current_code: "",// 当前页current_page: 1,// 每一页的数量current_size: 10,// 数据总数total_num: 0,echarts: getCurrentInstance().appContext.config.globalProperties.$echarts,};},mounted() {this.init();},methods: {init() {var url = "http://localhost:9001/stock/queryCodeOptions";axios.get(url).then((response) => {this.options = response.data;console.log(response);}).catch((error) => {console.log(error);});},handleSelect(item) {this.current_code = item.code;this.current_page = 1;// 获取表格详细数据var url1 ="http://localhost:9001/stock/queryDataByPage/" +this.current_code +"/" +this.current_size +"/" +this.current_page;this.loading = true;this.table_title = item.code + " " + item.name;axios.get(url1).then((response) => {this.table_data = response.data;console.log(response);this.loading = false;}).catch((error) => {console.log(error);this.loading = false;});// 获取当前股票数据总数var url2 = "http://localhost:9001/stock/queryNumByCode/" + item.code;axios.get(url2).then((response) => {this.total_num = response.data;console.log(response);}).catch((error) => {console.log(error);});},formatter1(row) {return row.change_range + "%";},formatter2(row) {return row.turnover_rate + "%";},handleSizeChange(number) {this.current_size = number;var url ="http://localhost:9001/stock/queryDataByPage/" +this.current_code +"/" +this.current_size +"/" +this.current_page;this.loading = true;axios.get(url).then((response) => {this.table_data = response.data;console.log(response);this.loading = false;}).catch((error) => {console.log(error);this.loading = false;});},handleCurrentChange(number) {this.current_page = number;var url ="http://localhost:9001/stock/queryDataByPage/" +this.current_code +"/" +this.current_size +"/" +this.current_page;this.loading = true;axios.get(url).then((response) => {this.table_data = response.data;console.log(response);this.loading = false;}).catch((error) => {console.log(error);this.loading = false;});},},
};
</script><style scoped>
.card-header {display: flex;justify-content: space-between;align-items: center;
}
</style>

还有一点需要额外说一下,大家可以看一下我们表格中的数据

这两列是由百分号,但是数据库中存的数据是没有百分号的,我们选择在前端进行处理,在表格相应的列中添加一个formatter属性,属性的值是一个函数,函数返回值就是最后渲染到页面上的字符串。

这两个函数的具体实现如下

 

结语

本文介绍了后端分页接口以及基于element-plus的分页实现方法,希望对你有所帮助。

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

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

相关文章

Autosar MCAL-RH850P1HC Dio配置

文章目录 DioDioGeneralDioCriticalSectionProtectionDioDevErrorDetectDioDeviceNameDioFlipChannelApiDioMaskedWritePortApiDioUseWriteVerifyErrorInterfaceDioVersionCheckExternalModulesDioVersionInfoApiDioWriteVerifyDioWriteVerifyErrorInterface DioPortP0-P9DioPo…

管道进行进程间通信(上)

管道进行进程间通信 在posix和system V标准还没有出现的时候&#xff0c;进程间是如何进行通信的呢&#xff1f;这就要借助于我们今天学习的这个东西了。在进程间通信的标准没有出现之前&#xff0c;在os中就已经存在了文件了。而管道就是基于文件的一种进行进程间通信的方式。…

WorkPlus为企业打造私有化部署IM解决方案

在移动数字化时代&#xff0c;企业面临着如何全面掌控业务和生态的挑战。企业微信、钉钉、飞书、Teams等应用虽然提供了部分解决方案&#xff0c;但无法满足企业的私有化部署需求。此时&#xff0c;WorkPlus作为安全专属的移动数字化平台&#xff0c;被誉为移动应用的“航空母舰…

独热编码的两种实现形式

独热编码的两种实现形式&#xff1a; ​ OneHotEncoder和DictVectorizer是两种常用的特征向量化方法&#xff0c;用于将分类特征转换为数值特征。但还是有一定的区别不管是再输入格式还是在输出类型上都有一些不同。 区别&#xff1a; 输入格式要求&#xff1a; OneHotEncod…

小梅哥Xilinx FPGA学习笔记18——专用时钟电路 PLL与时钟向导 IP

目录 一&#xff1a;IP核简介&#xff08;具体可参考野火FPGA文档&#xff09; 二&#xff1a; 章节导读 三&#xff1a;PLL电路原理 3.1 PLL基本实现框图 3.2 PLL倍频实现 3.3 PLL分频实现 四: 基于 PLL 的多时钟 LED 驱动设计 4.1 配置 Clocking Wizard 核 4.2 led …

NXP实战笔记(二):S32K3xx基于RTD-SDK在S32DS上配置PIT与STM中断并反转IO

目录 1、PIT 1.1、PIT概述 1.2、PIT的配置 1.3、Dio配置 1.4、中断配置 1.5、测试代码 1.6、测试结果 2、STM 2.1、STM概述 2.2、STM的配置 2.3、测试代码 2.4、测试结果 1、PIT 1.1、PIT概述 PIT是一组定时器&#xff0c;可用于引发中断和触发器&#xff0c;包括一…

PyQt5-控件之QDialog(UI-业务分离搭建自定义xDialog)

1.继承QtWidgets.QWidget自定义对话框 继承于QtWidgets.QWidget自定义一个对话框类&#xff1a;SelectingDlg class SelectingDlg(QtWidgets.QWidget): def __init__(self): super(SelectingDlg, self).__init__() self.initUI() def initUI(self):s…

数据结构和算法-B+树(性质 查找)

文章目录 B树叶子节点B树的查找第一种查找方式第二种查找方式 小结 B树 B树节点的关键个数1B树该节点的子树个数 B树节点的关键字个数和节点的子树个数一样 叶子节点包含全部关键字&#xff0c;并且都相互链接了 叶子节点 根节点也能是叶子节点 B树的查找 第一种查找方式…

HTTP分数排行榜

HTTP分数排行榜 介绍一、创建数据库二、创建PHP脚本三、上传下载分数四、测试 介绍 Unity中向服务器发送用户名和得分&#xff0c;并存入数据库&#xff0c;再讲数据库中的得分按照降序的方式下载到Unity中。 一、创建数据库 首先&#xff0c;我们要在MySQL数据库中建立一个…

Adobe ColdFusion 文件读取漏洞(CVE-2010-2861)

漏洞原理 Adobe ColdFusion是美国Adobe公司的一款动态Web服务器产品&#xff0c;其运行的CFML&#xff08;ColdFusion Markup Language&#xff09;是针对Web应用的一种程序设计语言。由于AJP协议设计存在缺陷导致内部相关的属性可控&#xff0c;攻击者可以构造属性值&#xff…

.NET Core中灵活使用反射

前言 前段时间有朋友问道一个这样的问题&#xff0c;.NET Core中如何通过Attribute的元数据信息来调用标记的对应方法。我第一时间想到的就是通过C#反射获取带有Custom Attribute标记的类&#xff0c;然后通过依赖注入&#xff08;DI&#xff09;的方式获取对应服务的方法并通…

中小微医院机构云服务(云HIS)平台源码

云HIS&#xff08;Cloud-Based Healthcare Information System&#xff09;重新定义了HIS&#xff0c;目标是为中小型医疗卫生机构提供优质经济的医疗卫生信息化产品及服务&#xff1b;是以健康档案为主线、以电子病历为核心、以云计算技术为基础的医疗卫生系统。云HIS作为基于…

王道考研计算机组成原理——存储系统

存储系统的基础知识 微信打开的时候会有一个人站在地球上&#xff0c;这个过程就是把程序从辅存转移到主存&#xff0c;数据只有调入主存当中才可以被CPU访问 cache&#xff1a;主存速度还是慢&#xff0c;为了进一步缓解CPU和主存之间的速度矛盾 在微信打视频聊天的时候&am…

Git 常用命令(从远程gitee/GitCode/GitHub下载项目到本地仓库)

​分布式项目控制管理gitGit 分布式版本控制系统(序章1)windows和linux操作Git(序章2) git在windows和ubuntu操作命令无异。本次举例平台&#xff1a;ubuntu18.04 查看是否安装和查看版本号 git --version # 仓库 # 在当前目录新建一个Git代码库$ git init​# 新建一个目录…

约翰瑟尔的故事

约翰瑟尔的故事 你即将看到的是“瑟尔效能机”创始者&#xff0c;约翰瑟尔的故事 据瑟尔原话&#xff0c;该装置会是通向自由能源的关键 “他”拥有“会飞”等不可思议的特性相关说法还有待证实&#xff0c;此记录篇仅为告知观者 制片方对瑟尔技术持中立态度 以下是我们所搜集…

【兔子王赠书第14期】《YOLO目标检测》涵盖众多目标检测框架,附赠源代码和全书彩图!

文章目录 写在前面YOLO目标检测推荐图书本书特色内容简介作者简介 推荐理由粉丝福利写在后面 写在前面 小伙伴们好久不见吖&#xff0c;本期博主给大家推荐一本关于YOLO目标检测的图书&#xff0c;该书侧重目标检测的基础知识&#xff0c;包含丰富的实践内容&#xff0c;是目标…

python编程从入门到实践(1)

文章目录 2.2.1命名的说明2.3字符串2.3.1使用方法修改字符串的大小写2.3.2 在字符串中使用变量2.3.3 制表符 和 换行符2.5.4删除空白2.5.5 删除前缀&#xff0b;后缀 2.2.1命名的说明 只能包含&#xff1a;字母&#xff0c;下划线&#xff0c;数字 必须&#xff1a;字母&#…

【LeetCode:34. 在排序数组中查找元素的第一个和最后一个位置 | 二分】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Linux驱动学习—pinctl和gpio子系统

1、pinctl和gpio子系统&#xff08;一&#xff09; 1.1pinctrl 子系统主要工作内容 <1>获取设备树中 pin 信息&#xff0c;管理系统中所有的可以控制的 pin&#xff0c; 在系统初始化的时候&#xff0c; 枚举所有可以控制的 pin&#xff0c; 并标识这些 pin。 <2>…

【年度征文邀请,老题目新解法,描述我的一些编程心得】2023-12-30

缘由本论坛年度征文邀请 之前论坛给的一个笔耕不辍实体已经给后辈玩了&#xff0c;那波浪上的孙猴儿会随波逐流摇来晃去的&#xff0c;后辈挺喜欢的。 前几天回复了一个整数正序分解&#xff0c;虽说是老话题了&#xff0c;不过常有新想法&#xff0c;其实整数正序分解整合不…