V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GrapeCityChina
V2EX  ›  推广

如何在 30 分钟完成表格增删改查的前后端框架搭建

  •  
  •   GrapeCityChina · 2022-05-20 13:56:47 +08:00 · 643 次点击
    这是一个创建于 920 天前的主题,其中的信息可能已经有所发展或是发生改变。

    30 分钟,你可以做什么? 可以风卷残云的饱餐一顿;可以简单地打扫一下房间;或者可以跳 10 十遍刘畊宏《本草纲目》毽子操。 而今天,本葡萄要带你在 30 分钟内完成一套拥有增删改查表格系统的前后端搭建!

    在日常的系统开发中,表格( Grid )是最常见的数据表达形式,而表格中“增删改查”又是最常见的功能之一。所以在日常开发过程中,快速构建表格增删改查的框架将会成为影响开发效率最重要的部分之一。 为了实现本次 30 分钟快速构建表格系统的目标,我们需要回顾年初的文章中,我们介绍的集算表的相关内容。

    什么是集算表?

    为了让前端的表格不但具备类 Excel 的公式计算能力,同时还拥有传统表格控件的高性能,我们希望将传统的高性能结构化表格 (Grid) 与公式计算引擎 (CalcEngine)结合在一起。 为了实现这样的设计,我们首次提出了数据管理容器 (DataManager) 的概念,将原有在后端才具备的关系数据引擎,完全在前端实现,从而实现了在大量数据(百万行)的环境下,实现秒级的加载、排序、筛选,而这所有的操作,都能够完全在前端浏览器中,通过 JavaScript 代码实现。 数据管理容器 (DataManager)不仅承担了数据存储与索引的功能,同时还实现了多数据表关系、视图、CRUD 等功能。 集算表( TableSheet )则负责将数据管理容器 (DataManager)中整理好的数据、视图、关系,通过 SpreadJS 本身的"Canvas 画布"呈现在网页中。

    在集算表的帮助下,电子表格中的数据管理器具备了直连数据源、数据关系(外键)管理和异步操作更新等功能,产品数据处理分析能力得到进一步提升。

    综合集算表的功能特性,以下问题使用集算表将会变得很容易:

    • 加载后端数据到表格中,并进行分析、处理
    • 需要整合来自多个数据表(源)的数据并进行分析
    • 对后端提供的原始数据进行再加工(修改、计算等)和回写

    实战开始

    了解了集算表,接下来我们就正式开始内容搭建。

    首先,我们对问题进行步骤拆解: 1 、后端使用 Spring Boot 做快速搭建,创建一个 spring boot web 工程,下面是大致用到的 dependencies

    基本除了 springboot 自带的之外,额外引用了 fastjson 用于对一些复杂 json 格式进行处理。

    2 、构建前后台,可以选择前后端分离,或者结合的方式(例子中选中了前后端结合的方式),大致工程结构如下:

    3 、构建前端页面,前端页面的可以选择适合的框架( VUE ,React ,Angular ,例子中使用源生 JS 进行构建),在页面中引入 SpreadJS TableSheet (集算表)中的相关依赖

    需在原本 SpreadJS 的依赖基础上引入 gc.spread.sheets.tablesheet 这个依赖。

    4 、构建前端集算表配置配置集算表的功能操作

    var myTable = dataManager.addTable("myTable", {
                            remote: {
                                read: {
                                    url: "initDataManager"
                                },
                                            batch: {
                                                    url: "batchUpdateDataManager"
                                            }
                            },
                                    batch: true,
                                    autoSync: false
                        });
    
    

    上述配置了读取和批量两个操作,读取设置是在指定地址下读取数据。而批量操作包含对数据的批量增删改。从而覆盖到整个增删改查逻辑。

    var rowActions = GC.Spread.Sheets.TableSheet.BuiltInRowActions;
                        var options = sheet.rowActionOptions();
                        options.push(
                            rowActions.removeRow,
                            rowActions.saveRow,
                            rowActions.resetRow,
                        );
                        sheet.rowActionOptions(options);
    
    

    上述代码设置了页面上供用户进行操作的对应按钮(删除行,保存行,重置行)

    myTable.fetch().then(function() {
                            var view = myTable.addView("myView", [
                                { value: "id", caption:"编号", width: 80 },
                                { value: "firstname", caption:"姓", width: 100 },
                                { value: "lastname", caption:"名", width: 100 },
                                { value: "homephone", caption:"电话", width: 100 }
                                   ]); 
                         sheet.setDataView(view);
                            });
    
    
    

    上述代码设置了表格的结构,对每一列进行了设置

    var submitButton = document.getElementById('submit');
                        submitButton.addEventListener('click', function() {
                            sheet.submitChanges();
                        });
    
    

    通过设置一个提交的按钮,用于将批量的修改进行一次性提交。 5 、后端构建对应的数据增删改查逻辑(实例中通过一个假数据构建一个 list 进行模拟,实际情况可以扩展持久层与真实的数据库进行交互)。

    private static List<Employee> list = new ArrayList<Employee>();
            static {
                    for(int i=0;i<10;i++) {
                            Employee employee = new Employee();
                            employee.setId(i);
                            employee.setFirstname("FirstName"+i);
                            employee.setLastname("LastName"+i);
                            employee.setHomephone("HomePhone"+i);
                            list.add(employee);
                    }
            }
            
            @RequestMapping(value = "/initDataManager", method = RequestMethod.GET)
            @ResponseBody
            public List<Employee> initWorkBook() {
                    return list;
            }
            
            @RequestMapping(value = "/batchUpdateDataManager", method = RequestMethod.POST)
            @ResponseBody
            public List<Map<String,Object>> batchUpdateDataManager(@RequestBody List<BatchManager> batchManagerList) {
                    List<Map<String,Object>> reutrnList = new ArrayList<Map<String,Object>>();
                    for (BatchManager batchManager : batchManagerList){
                            Map<String,Object> returnMap = new HashMap<String,Object>();
                            String type = batchManager.getType().toString();
                            try{
                                    if (type.equals("update"))
                        {
                            Employee employee = batchManager.getDataItem();
                            int index = batchManager.getSourceIndex();
                            Employee employeeSource = list.get(index);
                            employeeSource.setId(employee.getId());
                            employeeSource.setFirstname(employee.getFirstname());
                            employeeSource.setLastname(employee.getLastname());
                            employeeSource.setHomephone(employee.getHomephone());
                            list.remove(index);
                            list.add(index, employeeSource);
                            returnMap.put("succeed", true);
                        }else if (type.equals("insert"))
                        {
                                Employee employee = batchManager.getDataItem();
                                list.add(employee);
                                returnMap.put("succeed", true);
                                employee.setId(employee.getId()+10000);
                                returnMap.put("data", employee);
                        }else if (type.equals("delete"))
                        {
                                int index = batchManager.getSourceIndex();
                                list.remove(index);
                                returnMap.put("succeed", true);
                        }
                                    
                            }catch(Exception e) {
                                    returnMap.put("succeed", false);
                            }
                            reutrnList.add(returnMap);
                    }
                    return reutrnList;
            }
    
    

    这样,我们的框架就算搭建完成了。后面可以根据情况再做细微的调整和优化。总共耗时 30 分钟左右。 实例的代码可以参考附件,有兴趣的朋友可以下载自行参考搭建

    关注葡萄城社区,回复“增删改查”,即可免费获取文内 demo 。

    更多纯前端表格 demo 在线体验: https://demo.grapecity.com.cn/spreadjs/gc-sjs-samples/index.html

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5891 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 01:54 · PVG 09:54 · LAX 17:54 · JFK 20:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.