图表管理功能(前后端实现增删改查)

图表管理功能(前后端实现增删改查)

后端

  1. 库表设计

    create table chart
    (id         bigint auto_increment comment 'id'primary key,goal       text                               null comment '分析目标',chartData  text                               null comment '图表信息',chartType  varchar(256)                       null comment '图表类型',genChart   text                               null comment '生成的图表信息',genResult  text                               null,userId     bigint                             null comment '创建图标用户 id',createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',isDelete   tinyint  default 0                 not null comment '是否删除',name       varchar(128)                       null comment '图表名称'
    )comment '图表信息表' collate = utf8mb4_unicode_ci;
    
  2. 增删改查代码自动生成工具生成:

    使用Mybatis-Generator自动代码生成工具生成实体类,mapper接口和实现类。

  3. controller层增删改查询接口实现

    /*** 接口**/
    @RestController
    @RequestMapping("/chart")
    @Slf4j
    public class ChartController {@Resourceprivate ChartService chartService;private final static Gson GSON = new Gson();// region 增删改查/*** 创建** @param chartAddRequest* @param request* @return*/@PostMapping("/add")public BaseResponse<Long> addChart(@RequestBody ChartAddRequest chartAddRequest, HttpServletRequest request) {if (chartAddRequest == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}Chart chart = new Chart();BeanUtils.copyProperties(chartAddRequest, chart);User loginUser = userService.getLoginUser(request);chart.setUserId(loginUser.getId());boolean result = chartService.save(chart);ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);long newChartId = chart.getId();return ResultUtils.success(newChartId);}/*** 删除** @param deleteRequest* @param request* @return*/@PostMapping("/delete")public BaseResponse<Boolean> deleteChart(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {if (deleteRequest == null || deleteRequest.getId() <= 0) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}User user = userService.getLoginUser(request);long id = deleteRequest.getId();// 判断是否存在Chart oldChart = chartService.getById(id);ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR);// 仅本人或管理员可删除if (!oldChart.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {throw new BusinessException(ErrorCode.NO_AUTH_ERROR);}boolean b = chartService.removeById(id);return ResultUtils.success(b);}/*** 更新(仅管理员)** @param chartUpdateRequest* @return*/@PostMapping("/update")@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)public BaseResponse<Boolean> updateChart(@RequestBody ChartUpdateRequest chartUpdateRequest) {if (chartUpdateRequest == null || chartUpdateRequest.getId() <= 0) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}Chart chart = new Chart();BeanUtils.copyProperties(chartUpdateRequest, chart);long id = chartUpdateRequest.getId();// 判断是否存在Chart oldChart = chartService.getById(id);ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR);boolean result = chartService.updateById(chart);return ResultUtils.success(result);}/*** 根据 id 获取** @param id* @return*/@GetMapping("/get")public BaseResponse<Chart> getChartById(long id, HttpServletRequest request) {if (id <= 0) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}Chart chart = chartService.getById(id);if (chart == null) {throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);}return ResultUtils.success(chart);}/*** 分页获取列表** @param chartQueryRequest* @param request* @return*/@PostMapping("/list/page")public BaseResponse<Page<Chart>> listChartByPage(@RequestBody ChartQueryRequest chartQueryRequest,HttpServletRequest request) {long current = chartQueryRequest.getCurrent();long size = chartQueryRequest.getPageSize();// 限制爬虫ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);Page<Chart> chartPage = chartService.page(new Page<>(current, size),getQueryWrapper(chartQueryRequest));return ResultUtils.success(chartPage);}/*** 分页获取当前用户创建的资源列表** @param chartQueryRequest* @param request* @return*/@PostMapping("/my/list/page")public BaseResponse<Page<Chart>> listMyChartByPage(@RequestBody ChartQueryRequest chartQueryRequest,HttpServletRequest request) {if (chartQueryRequest == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}User loginUser = userService.getLoginUser(request);chartQueryRequest.setUserId(loginUser.getId());long current = chartQueryRequest.getCurrent();long size = chartQueryRequest.getPageSize();// 限制爬虫ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);Page<Chart> chartPage = chartService.page(new Page<>(current, size),getQueryWrapper(chartQueryRequest));return ResultUtils.success(chartPage);}
    }

前端(antdesign组件库)

  1. 开发一个表展示页

    1. 新添加路由

        {path: '/my_chart',name: '我的图表',icon: 'pieChart',component: './MyChart',},
      
    2. 创建页面

    3. 填充内容

      1. 获取需要的数据

        • 定义一个获取数据的函数,调用接口(await把异步变成同步) listMyChartPageUsingPost和后端对应的查询接口由OpenApi工具根据Swagger接口自动生成,大幅提高开发效率。

          const loadData = async () => {try {const res = await listMyChartByPageUsingPost(searchParams);if (res.data) {setChartList(res.data.records ?? []);}} catch (e: any) {message.error('获取图表失败', e.message);}};
          
      2. 首次页面加载时触发时加载数据(钩子函数:页面首次渲染时以及数组中的变量发生变化时执行钩子函数中的方法)

          //钩子函数:页面首次渲染时以及数组中的变量发生变化时执行钩子函数中的方法useEffect(() => {loadData();}, [searchParams]);//搜索参数改变就会触发加载数据方法
        
      3. 引入Ant Design的List组件,https://ant.design/components/list-cn,复制示例代码

      4. 调整 List 组件中的内容为自己的(注意,获取用户头像可以从初始化状态中获取)

        const { initialState } = useModel('@@initialState');
        const { currentUser } = initialState || {};
        
      5. 针对样式,对数据做一些处理,比如统一隐藏图表自身的 title

  2. 实现分页展示表

    逻辑:当用户点击切换页面的时候,组件触发onChange方法,改变搜索条件,当所搜条件改变的时候又会触发数据的加载,后端返回新的数据 。

    • 使用AntDesign组件库中的分页组件
  3. 添加按表名称搜索表功能

    • 添加搜索组件框组件,当用户的搜索条件(初始化)改变时,要添加到原始的搜索条件
  4. (附)前端展示图表,页面,搜索源码

//前端分页查询图表展示预页面(源码)
const MyChartPage: React.FC = () => {/*** 初始值*/const initSearchParams = {current: 1,pageSize: 6,};const [searchParams, setSearchParams] = useState<API.ChartQueryRequest>({...initSearchParams,});// const [selectedChartId, setSelectedChartId] = useState<number | undefined>(undefined);/*** 分页获取图表*/const [chartList, setChartList] = useState<API.Chart[]>();const [chartTotal, setChartTotal] = useState<number>(0);const [loading, setLoading] = useState<boolean>(true);/*** 获取当前用户*/const { initialState } = useModel('@@initialState');const { currentUser } = initialState || {};/*** 删除图表* @param chartId*/const handleDelete = (chartId: any) => {Modal.confirm({title: '确认删除',icon: <ExclamationCircleOutlined />,content: '确定要删除这个图表吗?',okText: '确认',cancelText: '取消',onOk: async () => {try {const res = await deleteChartUsingPost({ id: chartId });// 后端返回 boolean值console.log('res:', res.data);if (res.data) {message.success('删除成功');// 删除成功后重新加载图表数据loadData();} else {message.error('删除失败');}} catch (e: any) {message.error('删除失败' + e.message);}},});};/*** 加载图表数据*/const loadData = async () => {setLoading(loading);try {let res = await listMyChartByPageUsingPost(searchParams);if (res.data) {setChartList(res.data.records ?? []);setChartTotal(res.data.total ?? 0);// 隐藏titleif (res.data.records) {res.data.records.forEach((data) => {const chartOption = JSON.parse(data.genChart ?? '{}');// 取出title并且设置为 undefinedchartOption.title = undefined;data.genChart = JSON.stringify(chartOption);});}} else {message.error('获取我的图表失败');}} catch (e: any) {message.error('获取我的图表失败' + e.message);}setLoading(false);};/*** 变化时执行此处*/useEffect(() => {loadData();}, [searchParams]);return (<div className="my-chart-page"><div className="margin-20"><Searchplaceholder="请输入图标名称搜索"loading={loading}enterButtononSearch={(value) => {setSearchParams({...initSearchParams,chartName: value,});}}/></div><Listgrid={{gutter: 16,xs: 1,sm: 1,md: 1,lg: 2,xl: 2,xxl: 2,}}pagination={{// 设置分页showTotal: () => `${chartTotal} 条记录`,showSizeChanger: true,showQuickJumper: true,pageSizeOptions: ['6', '10', '14', '20'],onChange: (page, pageSize) => {setSearchParams({...searchParams,current: page,pageSize,});},current: searchParams.current, // 当前页pageSize: searchParams.pageSize, // 每页条数total: chartTotal, // 总数}}loading={loading}dataSource={chartList}renderItem={(item) => (<List.Item key={item.id}><Card style={{ width: '100%' }}><List.Item.Metaavatar={<Avatar src={currentUser?.userAvatar} />}title={currentUser?.userName}/><pstyle={{textAlign: 'center',fontWeight: 'bold',color: 'black',fontSize: '16px',}}>{'分析目标:' + item.goal}</p><List.Item.Metastyle={{ textAlign: 'right' }}description={item.chartType ? '图表类型:' + item.chartType : undefined}/><ReactECharts option={item.genChart && JSON.parse(item.genChart)} /><pstyle={{textAlign: 'center',fontWeight: 'bold',color: '#e617ff',fontSize: '16px',}}>{'图表名称:' + item.name}</p><Divider style={{ fontWeight: 'bold', color: 'blue', fontSize: '16px' }}>智能分析结果</Divider><p style={{ fontWeight: 'bold', color: '#0b93a1' }}>{item.getResult}</p><Row justify="end"><Col><Button danger onClick={() => handleDelete(item.id)}>删除</Button></Col></Row></Card></List.Item>)}/></div>);
};
export default MyChartPage;

尚且不懂知识点记录

  1. react的数据状态:

    //定义了一个searchParams的变量
    const [searchParams,setSearchParams] = useState<Api.ChartQueryRequest>({...initSearchParams, //初始值设置,每页12条,...initSearchParams把此对象展开成新的对象,不会由对象污染});//定义变量存前端展示的数据,从数据返回值中取得数据
    const [chartList, setChartList] = useState<API.Chart[]>();//定义变量存储数据总数
    const [total,setTotal] = useState<number>(0);
  2. idea快捷键:

    • 快速生成try-catch的快捷键:ctrl+alt+t
    • 格式化代码:ctrl+alt+l
  3. 原子化css

    通过className组合出一套组件

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

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

相关文章

css弹窗动画效果,示例弹窗从底部弹出

从底部弹出来&#xff0c;有过渡动画效果 用max-height可以自适应内容的高度&#xff0c;当内容会超过最大高度时可以在弹窗里加个scroll-view 弹窗不能用v-if来隐藏&#xff0c;不然transition没效果&#xff0c;transition只能对已有dom元素起效果&#xff0c;所以用透明和v…

软件测试入门:静态测试

什么是静态测试 顾名思义&#xff0c;这里的静态是指程序的状态&#xff0c;即在不执行代码的情况下检查软件应用程序中的缺陷。进行静态测试是为了仅早在开发的早期阶段发现程序缺陷&#xff0c;因为这样可以更快速地识别缺陷并低成本解决缺陷&#xff0c;它还有助于查找动态测…

GO设计模式——11、装饰器模式(结构型)

目录 装饰器模式&#xff08;Decorator Pattern&#xff09; 装饰器模式的核心角色&#xff1a; 优缺点 使用场景 代码实现 装饰器模式&#xff08;Decorator Pattern&#xff09; 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功…

Elasticsearch从入门到精通

Elasticsearch简介 应用开发中一个比较常见的功能是搜索&#xff0c;传统应用的解决方案&#xff1a;数据库的模糊查询。 模糊查询存在的问题&#xff1a; 海量数据下效率低下功能不够丰富&#xff1a;不够智能、不能高亮 Elasticsearch 是一个分布式、RESTful 风格的搜索和数据…

鸿蒙原生应用/元服务开发-Stage模型能力接口(一)

ohos.app.ability.Ability (Ability基类)一、说明 UIAbility和ExtensionAbility的基类&#xff0c;提供系统配置更新回调和系统内存调整回调。本模块首批接口从API version 9 开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。本模块接口仅可在Stag…

flex布局的flex为1到底是什么

参考博客&#xff1a;flex:1什么意思_公孙元二的博客-CSDN博客 flex&#xff1a;1即为flex-grow&#xff1a;1&#xff0c;经常用作自适应布局&#xff0c;将父容器的display&#xff1a;flex&#xff0c;侧边栏大小固定后&#xff0c;将内容区flex&#xff1a;1&#xff0c;内…

华为数通---配置Smart Link负载分担案例

定义 Smart Link&#xff0c;又叫做备份链路。一个Smart Link由两个接口组成&#xff0c;其中一个接口作为另一个的备份。Smart Link常用于双上行组网&#xff0c;提供可靠高效的备份和快速的切换机制。 目的 下游设备连接到上游设备&#xff0c;当使用单上行方式时&#x…

KUKA机器人如何自定义数值型变量?

KUKA机器人如何自定义数值型变量? 在KUKA机器人系统中如何自定义数值型变量来实现工件计数、计时等功能? 具体方法可参考以下内容: 如下图所示,找到SYSTEM—CONFIG.DAT文件,进入(需要管理员权限), 如下图所示,在第10行自定义一个int型的变量a, 如下图所示,自定义完成…

Ribbon组件的负载均衡原理

原因背景 spring cloud的底层负载均衡是采用Ribbon组件&#xff0c;我们将user-service服务注册到eureka-server中&#xff0c;那么当我们在另一个服务的代码层面请求远程调用API接口http://user-service/users/5时&#xff0c;程序代码如何解析远程调用的user-service服务名转…

springboot集成cxf

<?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-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://ma…

Dockerfile介绍

1. DockerFile介绍 dockerfile是用来构建docker镜像的文件&#xff01;命令参数脚本&#xff01; 构建步骤&#xff1a; 1、编写一个dockerfile文件 2、docker build 构建成为一个镜像 3、docker run运行镜像 4、docker push发布镜像&#xff08;DockerHub、阿里云镜像仓库…

Django模板,Django中间件,ORM操作(pymysql + SQL语句),连接池,session和cookie, 缓存

day04 django进阶-知识点 今日概要&#xff1a; 模板中间件ORM操作&#xff08;pymysql SQL语句&#xff09;session和cookie缓存&#xff08;很多种方式&#xff09; 内容回顾 请求周期 路由系统 最基本路由关系动态路由&#xff08;含正则&#xff09;路由分发不同的app中…

《论文阅读》用于情绪回复生成的情绪正则化条件变分自动编码器 Affective Computing 2021

《论文阅读》用于情绪回复生成的情绪正则化条件变分自动编码器 前言简介模型结构实验结果总结前言 今天为大家带来的是《Emotion-Regularized Conditional Variational Autoencoder for Emotional Response Generation》 出版:IEEE Transactions on Affective Computing 时间…

ZKP Understanding Nova (2) Relaxed R1CS

Understanding Nova Kothapalli, Abhiram, Srinath Setty, and Ioanna Tzialla. “Nova: Recursive zero-knowledge arguments from folding schemes.” Annual International Cryptology Conference. Cham: Springer Nature Switzerland, 2022. Nova: Paper Code 2. Unders…

安装TensorFlow2.12.0

文章目录 一、安装Anaconda步骤 1: 下载Anaconda步骤 2: 运行安装程序步骤 3: 选择安装路径步骤 4: 完成安装步骤 5: 启动Anaconda Navigator步骤 6: 创建和管理环境二、安装TensorFlow​(一)Anaconda修改国内镜像源(二)安装CPU版TensorFlow2.12.0(三)查看TensorFlow版本…

openGauss学习笔记-147 openGauss 数据库运维-备份与恢复-逻辑备份与恢复之gs_dump

文章目录 openGauss学习笔记-147 openGauss 数据库运维-备份与恢复-逻辑备份与恢复之gs_dump147.1 背景信息147.2 注意事项147.3 语法147.4 参数说明147.4.1 通用参数&#xff1a;147.4.2 转储参数&#xff1a;147.4.3 连接参数&#xff1a; 147.5 说明147.6 示例 openGauss学习…

HTTP、HTTPS、SSL协议以及报文讲解

目录 HTTP/HTTPS介绍 HTTP/HTTPS基本信息 HTTP请求与应答报文 HTTP请求报文 HTTP响应报文 SSL协议 SSL单向认证 SSL双向认证 HTTP连接建立与传输步骤 HTTP访问全过程相关报文&#xff08;以访问www.download.cucdccom为例子&#xff09; DNS报文解析 TCP三次握手连…

【Flink系列六】Flink里面的状态一致性

状态一致性 有状态的流处理&#xff0c;内部每个算子任务都可以有自己的状态&#xff0c;对于流处理器内部来说&#xff0c;所谓的状态一致性&#xff0c;其实就是我们所说的计算结果要保证准确。一条数据不应该丢失&#xff0c;也不应该重复计算。再遇到有故障时可以恢复状态…

RabbitMQ 常见面试题

目录 1.前置知识1.1.什么是 MQ&#xff1f;它有什么作用&#xff1f;1.2.什么是消费者生产者模型&#xff1f;1.3.AMQP 是什么&#xff1f; 2.RabbitMQ 入门2.1.什么是 RabbitMQ&#xff1f;有什么特点&#xff1f;2.2.RabbitMQ 的核心概念有哪些&#xff1f;2.2.1.生产者 (Pro…

css 元素前后添加图标(::before 和 ::after 的妙用)

<template><div class"container"><div class"label">猜你喜欢</div></div> </template><style lang"scss" scoped> .label {display: flex;&::before,&::after {content: "";widt…