VUE实现简单留言板(Timeline+infinite scroll+Springboot+Hibernate)

先贴出效果图:

留言按照倒序排列。在底部的文本框内输入留言后,点击“留言”按钮,留言将保存至数据库中,同时刷新网页,新留言出现在顶部。

当滚动条到底部时,自动调用加载函数,显示更多早期留言。

前端代码index.vue:

<script setup lang="ts">import { useBoard } from "./utils/hook";
import { ref, markRaw } from "vue";const {boardInfo,dataList,onSubmit,onLazyLoad
} = useBoard();</script><template>
<div><el-card shadow="never"><div class="flex justify-between"><span class="text-md font-medium">留言区</span></div><!-- <el-scrollbar max-height="380" class="mt-3"> --><div><el-timeline v-infinite-scroll="onLazyLoad" style="overflow:auto" class="infinite-list"><el-timeline-item class="infinite-list-item"v-for="(item, index) in dataList":key="index"centerplacement="top":timestamp="item.date"><el-card><p>{{item.username}}</p><p class="text-text_color_regular text-sm">{{item.comments}}</p></el-card></el-timeline-item></el-timeline></div><!-- </el-scrollbar> --></el-card><el-card><el-inputv-model="boardInfo.comments"placeholder="请输入留言"type="textarea":autosize="{ minRows: 2, maxRows: 3 }"maxlength="256"show-word-limit      /><div><el-button type="primary" class="submit-btn" @click="onSubmit(boardInfo)">留言</el-button></div></el-card>
<div>
</template><style lang="scss" scoped>
.infinite-list {height: 440px;padding: 0;margin: 0;list-style: none;
}
.infinite-list .infinite-list-item {display: flex;align-items: center;justify-content: center;height: 110px;margin: 10px;
}.submit-btn{float: right;margin-top: 10px;
}</style>

hook.tsx,滚动条滚到底时自动调用onLazyLoad函数,提交留言调用onSubmit函数。


import { reactive, ref, toRaw, onMounted } from "vue";
import { http } from "@/utils/http";
import { baseUrlApi } from "../../../api/utils";export function useBoard() {type Result = {success: boolean;data?: Array<any>;}type ResultTable = {success: boolean;data?: {list: Array<any>;total?: number;pageSize?: number;currentPage?: number;};};const boardInfo = reactive({avatar: "",nickname: "",comments: "",username: "游客"});const dataList = ref([]);async function onSubmit(data) {const { success } = await addBoard(boardInfo);if (success) {reload();}}const count = ref(0);const currentPage = ref(-1);const pageSize = ref(-1);async function onLazyLoad() {count.value += 1;console.log("--------->lazyload----" + count.value);const param = {"currentPage": currentPage.value,"pageSize": pageSize.value,"total": dataList.value.length};const { success, data } = await lazyload(param);if (success) {dataList.value = dataList.value.concat(data.list);currentPage.value = data.currentPage;pageSize.value = data.pageSize;}}async function reload() {count.value += 1;const param = {"currentPage": 0,"pageSize": 4,"total": 0};const { success, data } = await lazyload(param);if (success) {dataList.value = data.list;currentPage.value = data.currentPage;pageSize.value = data.pageSize;}}onMounted(async () => {});const addBoard = (data?: object) => {return http.request<Result>("post", baseUrlApi("/board/addBoard"), { data });};const lazyload = (data?: object) => {return http.request<ResultTable>("post", baseUrlApi("/board/getBoard-lazyload"), { data });};return {boardInfo,dataList,onSubmit,onLazyLoad};}

后端代码BoardController.java:

package com.test.controller;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.test.Utils;
import com.test.entity.Board;
import com.test.service.BoardService;@Controller
@RequestMapping("/board")
public class BoardController {@Autowiredprivate BoardService boardService;@PostMapping("/getBoard-lazyload")@ResponseBodypublic Map getBoardLazyLoad(@RequestBody Map<String,Object> param) {Integer currentPage = Utils.parseInt(param, "currentPage");Integer pagesize = Utils.parseInt(param, "pageSize");Integer total = Utils.parseInt(param, "total");currentPage += 1;pagesize = 4;Map ret = new HashMap();System.out.print("++++++++++>" + currentPage);List<Board> list = boardService.getBoards(currentPage, pagesize,total);if(list.size()>0) {			Map map = new HashMap();map.put("list", list);map.put("total", list.size());map.put("pageSize", pagesize);map.put("currentPage", currentPage);ret.put("data", map);ret.put("success", true);}else {ret.put("data", null);ret.put("success", false);}return ret;}@PostMapping("/addBoard")@ResponseBody@Transactional(value = "primaryTransactionManager")public Map addBoard(@RequestBody Map<String, Object> param) {Map map = new HashMap();try {Board b = new Board();b.setComments(Utils.parseString(param, "comments"));b.setUsername(Utils.parseString(param, "username"));SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");long timestamp = System.currentTimeMillis();String dateString = sdf.format(new Date(timestamp));b.setDate(dateString);boardService.addBoard(b);		map.put("data", null);map.put("success", true);}catch(Exception e) {map.put("data", null);map.put("success", false);}return map;}}

Hibernate配置类PrimaryDbConfig:

package com.test.conf;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;/*** 数据库配置** basePackages:JPA扫描配置* entityManagerFactoryRef:实体扫描配置* transactionManagerRef:事务配置** */
@Configuration
@EnableJpaRepositories(basePackages = "com.test.dao", entityManagerFactoryRef = "primaryEntityManager", transactionManagerRef = "primaryTransactionManager")
public class PrimaryDbConfig {private final Logger log = LoggerFactory.getLogger(getClass());private DataSource dataSource;private LocalContainerEntityManagerFactoryBean entityManager;/** 创建数据库连接* @Primary 配置多个数据源时,用于标记主库* @ConfigurationProperties 指定配置文件中的属性前缀** */@Primary@ConfigurationProperties(prefix = "spring.datasource.primary")@Bean(name = "primaryDataSource")public DataSource primaryDataSource() {System.out.printf("++++++++++++++++++++++++++++++++++>");dataSource = DataSourceBuilder.create().build();log.info("正在连接数据库1...");return dataSource;}/** 实体扫描配置** 方法名与类注解中的entityManagerFactoryRef的值保持一致,配置多个数据源时方法名不能相同** */@Bean@PrimaryLocalContainerEntityManagerFactoryBean primaryEntityManager(EntityManagerFactoryBuilder builder) {log.info("正在扫描接数据库1的实体类...");entityManager = builder.dataSource(dataSource).packages("com.test.entity").persistenceUnit("primaryPersistenceUnit").build();return entityManager;}/** 事务配置** 方法名与类注解中的transactionManagerRef的值保持一致,配置多个数据源时方法名不能相同** */@Bean@PrimaryPlatformTransactionManager primaryTransactionManager(EntityManagerFactoryBuilder builder) {log.info("正在配置接数据库1的事务管理器...");return new JpaTransactionManager(entityManager.getObject());}
}

Hibernate配置文件application.properties:

server.port=5000
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/数据库名称
spring.datasource.primary.username=root
spring.datasource.primary.password=密码
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.show-sql=true
spring.jpa.open-in-view=false

BoardDaoImpl.java:

package com.test.dao;import java.util.List;import org.hibernate.HibernateException;
import org.springframework.stereotype.Repository;
import com.test.entity.Board;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;@Repository
public class BoardDaoImpl implements BoardDao {@PersistenceContext(unitName = "primaryEntityManager")private EntityManager entityManager;@Override/*** page:当前起始页,total:已查询的总数*/public List<Board> getBoards(int page, int pagesize, int total) {try {page = total / pagesize;String sql = "select * from board ORDER BY create_time DESC limit :start,:size ";Query query = entityManager.createNativeQuery(sql, Board.class);query.setParameter("start", total);query.setParameter("size", pagesize);List<Board> result = query.getResultList();return result;} catch (HibernateException e) {e.printStackTrace();}return null;}@Overridepublic Boolean addBoard(Board b) {try {entityManager.persist(b);return true;} catch (HibernateException e) {e.printStackTrace();}return false;}}

Board.java:

package com.test.entity;import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;@Entity
@Table(name = "board")
public class Board {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String createTime;private String comments;private String username;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getDate() {return createTime;}public void setDate(String createTime) {this.createTime = createTime;}public String getComments() {return comments;}public void setComments(String comments) {this.comments = comments;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}}

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

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

相关文章

Java基础(3)

Java 数据类型详解 九、运算符 1. 基本运算符 Java 提供了多种运算符来执行不同的操作&#xff1a; 算术运算符&#xff1a;&#xff08;加&#xff09;、-&#xff08;减&#xff09;、*&#xff08;乘&#xff09;、/&#xff08;除&#xff09;、%&#xff08;取模&…

电力场景红外测温图像绝缘套管分割数据集labelme格式2436张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2436 标注数量(json文件个数)&#xff1a;2436 标注类别数&#xff1a;1 标注类别名称:["arrester"] 每个类别标注的框数&am…

降维算法:主成分分析

主成分分析 一种常用的数据分析技术&#xff0c;主要用于数据降维&#xff0c;在众多领域如统计学、机器学习、信号处理等都有广泛应用。 主成分分析是一种通过正交变换将一组可能存在相关性的变量转换为一组线性不相关的变量&#xff08;即主成分&#xff09;的方法。这些主…

深入解析 C++17 中的 u8 字符字面量:提升 Unicode 处理能力

在现代软件开发中&#xff0c;处理多语言文本是一个常见需求&#xff0c;特别是在全球化的应用场景下。C17 标准引入的 u8 字符字面量为开发者提供了一个强大的工具&#xff0c;以更有效地处理和表示 UTF-8 编码的字符串。本文将详细探讨 u8 字符字面量的技术细节、实际应用&am…

ElasticSearch索引别名的应用

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview Elasticsearch 索引别名是一种极为灵活且强大的功能&#xff0c;它允许用户为一个或多个索引创建逻辑上…

Java高频面试之SE-15

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; String 怎么转成 Integer 的&#xff1f;它的原理是&#xff1f; 在 Java 中&#xff0c;要将 String 转换为 Integer 类型&#xff0c;可…

2024又是一年的CSDN之旅-总结过去展望未来

一、前言 一年就这样在忙忙碌碌的工作和生活中一晃而过&#xff0c;总结今年在CSDN上发表的博客&#xff0c;也有上百篇之多&#xff0c;首先感谢CSDN这个平台&#xff0c;能让我有一个地方记录工作中的点点滴滴&#xff0c;也在上面学到了不少知识&#xff0c;解决了工作中遇到…

c86机器安装nvaid显卡驱动报错:ERROR:Unable to load the kernel module ‘nvidia.ko‘.

背景&#xff1a; 最近小伙伴要去北京甲方现场搭建我们的AI编码服务&#xff0c;需要使用GPU机器跑大模型&#xff0c;根据现场提供的信息是2台C86的机器&#xff0c;显卡够够的&#xff0c;但是现场是内网环境&#xff0c;因此&#xff0c;需要先准备好需要的安装包&#xff…

LeetCode 热题 100_实现 Trie (前缀树)(54_208_中等_C++)(图;前缀树;字典树)

[TOC](LeetCode 热题 100_实现 Trie (前缀树)&#xff08;54_208&#xff09;) 题目描述&#xff1a; Trie&#xff08;发音类似 “try”&#xff09;或者说 前缀树 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&…

【Maui】视图界面与数据模型绑定

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 创建模型3.2 视图界面3.3 控制器逻辑层 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创建本机移动和桌面应用。 使用 .NET MAUI&…

从 Spark 到 StarRocks:实现58同城湖仓一体架构的高效转型

作者&#xff1a;王世发&#xff0c;吴艳兴等&#xff0c;58同城数据架构部 导读&#xff1a; 本文介绍了58同城在其数据探查平台中引入StarRocks的实践&#xff0c;旨在提升实时查询性能。在面对传统Spark和Hive架构的性能瓶颈时&#xff0c;58同城选择StarRocks作为加速引擎&…

探秘 Linux 进程状态:解锁系统运行的密码

&#x1f31f; 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。&#x1f31f; &#x1f6a9;用通俗易懂且不失专业性的文字&#xff0c;讲解计算机领域那些看似枯燥的知识点&#x1f6a9; 在 Linux 系统…

深度学习-89-大语言模型LLM之AI应用开发的基本概念

文章目录 1 什么是智能体(Agent)2 什么是大语言模型(LLM)2.1 LLM的训练及使用2.2 Transformer架构2.3 基于LLM的Agent框架3 什么是检索增强生成(RAG)3.1 RAG是什么3.2 生成式AI应用开发3.3 RAG的整体流程3.4 RAG技术3.4.1 简单RAG(Simple RAG)3.4.2 校正RAG(Corrective RAG)3.4…

鸿蒙产业学院正式揭牌!软通动力与深信息签署校企合作框架协议

12月27日&#xff0c;深圳信息职业技术学院&#xff08;简称“深信息”&#xff09;与软通动力信息技术&#xff08;集团&#xff09;股份有限公司&#xff08;简称“软通动力”&#xff09;正式签署校企合作框架协议&#xff0c;并共同揭牌成立鸿蒙产业学院。深信息校长王晖&a…

python轻量级框架-flask

简述 Flask 是 Python 生态圈中一个基于 Python 的Web 框架。其轻量、模块化和易于扩展的特点导致其被广泛使用&#xff0c;适合快速开发 Web 应用以及构建小型到中型项目。它提供了开发 Web 应用最基础的工具和组件。之所以称为微框架&#xff0c;是因为它与一些大型 Web 框架…

2024年河北省职业院校技能大赛 “信息技术应用创新赛项”(高职组)样题解法

​有问题请留言或主页私信咨询 2024年河北省职业院校技能大赛 “信息技术应用创新赛项”&#xff08;高职组&#xff09;样题 一、初始化环境 1.账号及默认密码如表1所示。 表1 账号及密码规划表 账 号密 码root&#xff08;服务端&#xff09;kylin2024!desk&#xff08…

gozero获取数据库内容报错解决方案与实践

这个错误通常出现在 Go 语言的数据库查询中&#xff0c;表示你尝试将一个不支持的数据类型&#xff08;[]uint8&#xff0c;即字节切片&#xff09;存储到一个 Go 类型&#xff08;*time.Time&#xff09;中。具体来说&#xff0c;create_time 列的类型可能是 DATETIME 或 TIME…

【学习笔记15】如何在非root服务器中,安装属于自己的redis

一、下载安装包 官网下载黑马程序员给的安装包&#xff08;redis-6.2.6&#xff09; 二、将安装包上传至服务器 我将安装包上传在我的文件夹/home/XXX&#xff0c;指定路径中/src/local/redis/&#xff0c;绝对路径为/home/XXX/src/local/redis/解压安装包 XXXomega:~$ cd …

PotPlayer 配置安装

文章目录 一、下载1、官网链接2、微软商店 Microsoft Store 二、安装1、双击安装包2、选择字体3、安装向导下一步4、接收许可协议5、选择组件及关联6、选择安装位置7、硬解选项 三、设置1、关闭自动更新2、左键单双击设置3、视频下自动隐藏3.1、效果对比 4、播放信息显示设置4.…

【PCIe 总线及设备入门学习专栏 2 -- PCIe 的 LTSSM 和 Enumeration】

文章目录 OverviewLTSSM StatesDetect StatesDETECT_QUIETDETECT_ACTDETECT_WAITPolling StatesPOLL_ACTIVEPOLL_CONFIGPOLL_COMPLIANCEConfiguration StatesCONFIG_LINKWD_STARTCONFIG_LINKWD_ACCEPTCONFIG_LANENUM_WAITCONFIG_LANENUM_ACCEPTCONFIG_COMPLETECONFIG_IDLERecov…