likes
comments
collection
share

《可视化搭建系统》“星空” nodejs server 端(三)

作者站长头像
站长
· 阅读数 14

前两篇说到了星空的大体架构以及 webcomponents 在星空中的作用,本篇说一下星空 server(eggjs) 端做得一些事情。

表结构设计

之前在创业公司那套搭建系统,一张表维护了所有的信息,也行,但后期维护与扩展困难。所以我们需要根据需求及后期扩展来设计一下。

回顾一下搭建主页面 👇🏻

《可视化搭建系统》“星空” nodejs server 端(三)

从上图可以看出,主要包含两大部分,页面跟物料。

简单分析下:

首先是页面,页面除了包含一些基本信息,比如页面发布状态、名称等以外,还涉及到页面跟物料的配置关系。涉及到发布,就有回滚,把回滚考虑进去,意味着页面配置存在多版本管理。

其次是物料,物料由前端开发,运营用来页面搭建。考虑物料更新(比如你这个物料有 bug,需要开发更新一版),那么物料也存在多版本管理。

具体如何来设计呢?

把 “page” “pageConfig” 分成两张表,“page”表管理基本数据,“pageConfig”管理页面配置数据及历史版本回滚。

把 “module” “module_version” 也分成两张表,“module” 管理基本数据,“module_version” 管理版本。

下面看下 4 张表的结构

page 表

CREATE TABLE IF NOT EXISTS `page` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '页面ID',
  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '页面名称',
  `owner` varchar(255) NOT NULL DEFAULT '' COMMENT '页面创建者',
  `is_delete` tinyint(1) DEFAULT '0' COMMENT '是否删除状态',
  `published_status` tinyint(1) DEFAULT '0' COMMENT '发布状态 0: 未发布; 1: 已发布线上; 2: 已下线;',
  `start_time` datetime DEFAULT NULL COMMENT '开始时间',
  `end_time` datetime DEFAULT NULL COMMENT '结束时间',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

一些页面级别的属性,放在 page 表中进行管理。

page_config 表

CREATE TABLE IF NOT EXISTS `page_config` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '配置ID',
  `page_id` bigint(20) unsigned NOT NULL COMMENT '关联的页面ID',
  `owner` varchar(255) NOT NULL DEFAULT '' COMMENT '操作者',
  `config` mediumtext COMMENT '页面配置的具体内容,JSON格式',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

其中 page_config 表通过 page_id 字段,跟 page 表进行关联。同一个 page_id 可以存在多条记录,也就可以用来管理页面历史记录、回滚等相关操作。

需要注意的是 config 字段, 在 page_config 中最为重要。

  • materialList 存储页面物料搭建顺序
    • props 存储物料的静态数据
    • schema 存储 formRender 的渲染数据结构
  • materialPageConfig 存储页面全局配置数据
{
    "materialList": [
        {
            "id": 1,
            "module_id": 1,
            "title": "物料",
            "version": 1,
            "props": {
                "desc": "物料静态配置数据"
            },
            "schema": {
                "type": "object",
                "properties": {
                    "desc": {
                        "title": "描述",
                        "type": "string",
                        "placeholder": "请输入",
                        "required": true
                    }
                }
            },
        }
    ],
    "materialPageConfig": {
        "title": "测试标题",
        "bgColor": "255,255,255,1"
    }
}

module 表

CREATE TABLE IF NOT EXISTS `module` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '模块ID',
  `owner` varchar(255) NOT NULL DEFAULT '' COMMENT '模块作者',
  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '模块名称',
  `desc` varchar(255) NOT NULL DEFAULT '' COMMENT '模块描述',
  `cover` varchar(255) DEFAULT NULL COMMENT '模块封面',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

物料相关属性,放到 module 表进行管理。

modele_version 表

CREATE TABLE `module_version` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '版本号 ID',
  `module_id` bigint(20) unsigned NOT NULL COMMENT '关联的模块ID',
  `config` mediumtext COMMENT '模块配置信息,JSON格式',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

其中 module_version 表通过 module_id 字段,跟 module 表进行关联。同一个 module_id 可以存在多条记录,也就可以用来管理物料的历史记录、回滚等相关操作。

需要注意的是 config 字段, 在 module_version 中最为重要。

  • props 存储物料的默认配置数据
  • schema 存储 formRender 的渲染数据结构
{
    "props": {
        "desc": "我是一个物料"
    },
    "schema": {
        "type": "object",
        "properties": {
            "desc": {
                "title": "描述",
                "type": "string",
                "placeholder": "请输入",
                "required": true
            }
        }
    }
}

通过上述4张表,基本上就可以对物料,以及页面进行管理。

且可以根据自己的业务场景,进行一定的扩展。比如物料可以按业务类型进行区分,直播、内容、促销等,那么就可以在 module 表中,加一个 type 字段,用来管理类型。

项目结构

项目基于 eggjs 开发,个人觉得 eggjs 的目录结构还是蛮清晰的。

《可视化搭建系统》“星空” nodejs server 端(三)

整体逻辑比较常规,围绕上述的4张表,进行增删改查。

基于 eggjs 的插件生态,一些基础功能,通过配置就可以快速完成。

  • egg-cors 处理跨域
  • egg-mysql 处理数据库
  • egg-jwt 实现登录管理
  • egg-validate 统一处理请求入参校验

基于 midlle 机制,自定义中间件处理业务逻辑。比如 response_handle 中间件,统一处理异常及接口请求数据结构。再比如 jwt 中间件,统一校验请求的登录态等。

预览、发布

server 端整体代码都不难,相对复杂一点的是预览跟发布接口,这里单独拿出来聊聊。

我们先来看下,预览跟发布的操作流程

《可视化搭建系统》“星空” nodejs server 端(三)

点进测试地址, 观察下网络请求

《可视化搭建系统》“星空” nodejs server 端(三)

观察上图,可以对请求分为 3 大类

  • 页面 document html 请求,返回测试页面
  • react/vue 物料运行时
  • 物料资源
    • 物料 js 资源
    • 物料 css 样式

点击线上地址,其实请求跟测试地址是类似的,只是 document html 页面来源不同。测试页面是 eggjs 动态返回的,线上页面是 nginx 代理返回的。

细说预览流程

直接上代码,再来分析

《可视化搭建系统》“星空” nodejs server 端(三)

可以看到,核心是 transformTemplate 方法,主要做了两件事

  • 将数据库中获取到的页面配置数据,写入 starry_template.html 中
  • 返回写入后的页面

如何将获取到的数据写入 starry_template.html 中呢?我们可以在模板中设置一个标志位,并将数据 JSON.stringify 一下后,替换掉标志位即可。也就是 transformTemplate 方法做的事情。

《可视化搭建系统》“星空” nodejs server 端(三) 《可视化搭建系统》“星空” nodejs server 端(三)

返回写入后的页面很简单,直接在 middle 中的 response_handle 中间件中支持一下 html 请求,改写一下 content-type 为 text/html 即可。

《可视化搭建系统》“星空” nodejs server 端(三)

starry_template.html

最后,返回的 html,客户端是如何渲染成页面的呢,我们来分析一下。

第一步,取数据

上面说到数据注入到了页面中,那我们先把数据取出来。

《可视化搭建系统》“星空” nodejs server 端(三)

  • materialPageConfig 存储一些页面级别的配置,比如页面标题、页面背景色等,通过 document 相关方法对页面整体进行设置即可
  • materialList 存储页面模块地址,以及模块的配置数据等,后面马上会用到
第二步,注册并渲染 webcomponents

《可视化搭建系统》“星空” nodejs server 端(三)

  • http://localhost:4000/static 是一个 nginx 的静态服务,用于存储开发好的 js 模块,这部分后续的系列会细讲,开发开发好的模块,打包后,通过 cli 会 upload 到对应的 nginx 服务
  • magic(webcomponentName, module, enhanceOptions) 这部分是在注册 webcomponents,这部分可以参考《可视化搭建系统》“星空” webcomponents 从0到1(二)
  • Promise.all 等待所有的 webcomponents 注册好之后,再根据 materialList 中的模块顺序,使用 document.createElement 创建 dom,append 至 body 下即可

发布流程

发布流程跟预览流程,基本一致。

只是说预览的 html 是根据预览数据实时生成,返回到客户端预览。而发布是将数据写入 html 后,将此 html 写入线上 nginx 服务,最后根据统一的线上域名/page_id.html 就可以访问到发布后的页面了。

小结

本文主要介绍了星空的 server 端的一些简单设计思想,主要是页面、模块管理以及模版 html 的应用。个人觉得,作为 nodejs 的简单入门实战项目,还是不错的。

“星空”已完成的历史系列

“星空”后续系列

  • 物料模板设计,脚手架实现(四)
  • “星空”搭建后台实现 (五)
  • docker、nginx 环境详解(六)
  • “星空”代码开源,本地启动流程详解(七)