h5-Dooring Documentation

H5 Page Maker, H5 Editor, LowCode. Make H5 as easy as building blocks. | 让H5制作像搭积木一样简单, 轻松搭建H5页面, H5网站, PC端网站,LowCode平台.

10,005 stars JavaScript JavaScript 24 files · ~8,738 tokens #antd#drag-and-drop#h5#h5-builder#h5-dooring#h5-editor#javascript#low-code
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy h5-Dooring on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name h5-dooring --restart always mrxujiang/h5-dooring:latest

File: readme.md

Make H5 as easy as building blocks!

Welcome to H5-Dooring 👋

H5-Dooring is a powerful, open source, free H5 visual page configuration solution dedicated to providing a simple, convenient, professional and reliable, unlimited set of H5 landing page best practices. The technology stack is mainly react, developed in the background using nodejs.

home🏠 demo✨ doc📦 tutorial wiki
website Demo Document 视频&Video wiki

✨ note: If the official visit is too slow, visit the H5-Dooring for Singapore

English | 简体中文

new doc: private deployment process

website: H5-Dooring

tech blog: sharing of technology

Related products:

Author

👤 alex_xu

🤝 Contributing and support

Contributions, issues and feature requests are welcome!Feel free to check issues page.

Give a ⭐️ if this project helped you!

Privatization Deployment documentation

Features

  1. editor
    • Guides
    • The underlying component
    • Visual components
    • Media components
    • Product components
    • Dragper
    • Configure the panel
    • Form designer
    • (Multi) Page management (copy, edit, delete, new)
    • Component animation
    • Component interaction
    • Data source management
    • Quick preview
    • Real machine preview
    • Undo and redo
    • WeChat shares
    • shortcut key
    • The template library
    • Desktop software, Dooring-electron, supports offline use
  1. Enhanced features

    • Upload json, convert to H5 with one click
    • Photo gallery
    • Code capability (download source, download dis package)
  2. backend API

    • Create, save, and update your work
    • User management, rights management
    • One-click intelligent analysis
    • Data look
    • Form data collection
    • Form data presentation
    • Form data analysis, one-click export excel, form multi-condition search
    • Preview online
    • QR code preview
    • Template management
    • Code interface

Update the log

  1. Whether the video component adds a full-screen configuration item when playing
  2. Fixes a click failure of the icon component
  3. The editor supports multi-size switching and canvas size customization
  4. Fix multilingual issues with background management analytics forms
  5. The component library supports user-defined selection

Technology Sharing

The back-end section

The back-end part because of the knowledge points involved is more, is not the focus of this article, so here is a few points, you can use completely different technology to achieve back-office services, such as PHP, Java, Python or Egg. The author here is using the "koa" .

Specific code can refer to the full stack development article:

Install

  1. Download the code
sh
git clone https://github.com/MrXujiang/h5-Dooring.git
  1. Go to the project catalog
sh
cd ./h5-Dooring
  1. Install the dependency package
sh
yarn pkg

Usage

Launch the app locally

sh
yarn start
or
cnpm run start

local visit:

text
http://localhost:port/h5_plus

注意: 如果 window 系统下无法启动, 请移步 dooring-electron

How to run the downloaded code ?

  1. The compression package can be unzipped directly to the server root, and access to the root address is sufficient
  2. 'vscode' installs the Live Server plug-in, unzips the downloaded compression package into a folder, opens with 'vscode', clicks on Live Server, and notes that to remove the 'index .html' of the startup path, change it to '/'

If you find that the local boot component drag and drop encountered strange errors, is the third-party component in the development environment bug, you can take a step to solve:

If you find that the local start-up component drag encountered strange errors, is a bug that should be a third-party component in the development environment, can be resolved in a way:

sh
yarn dev
or
cnpm run dev

The premise is to install the http-server module first.

Browsers support

Modern browsers does not support IE browser

IEdge Firefox Chrome Safari
Edge last 2 versions last 2 versions last 2 versions

Contact us

Twitter Account:@H5Dooring

Partner project

Technical feedback and communication

wechat:beautifulFront


File: CHANGELOG.md

[Binary file]


File: package.json

{
"name": "h5-dooring",
"version": "1.3.0",
"description": "H5-Dooring是一款功能强大,开源免费的H5可视化页面配置解决方案,致力于提供一套简单方便、专业可靠、无限可能的H5落地页最佳实践。技术栈以react为主, 后台采用nodejs开发。",
"private": false,
"author": {
"name": "徐小夕",
"email": "[email protected]",
"url": "http://h5.dooring.cn/h5_visible"
},
"keywords": [
"h5 editor",
"h5",
"react",
"antd",
"react-dnd",
"web visible"
],
"contributors": [
"徐小夕 [email protected] (https://github.com/MrXujiang))",
"mokinzhao [email protected] (https://github.com/mokinzhao))",
"yehuozhili [email protected] (https://github.com/yehuozhili))"
],
"scripts": {
"start": "export NODE_OPTIONS=--openssl-legacy-provider && umi dev -- editor",
"start:win": "set NODE_OPTIONS=--openssl-legacy-provider && umi dev -- editor",
"build": "export NODE_OPTIONS=--openssl-legacy-provider && umi build",
"build:win": "set NODE_OPTIONS=--openssl-legacy-provider && umi build",
"server": "node server.js",
"dev": "http-server dist",
"docs:dev": "vuepress dev doc",
"docs:build": "vuepress build doc",
"test-demo": "http-server dist",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage",
"nocompress": "cross-env RM_TMPDIR=none COMPRESS=none umi build"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"
.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"homepage": "http://h5.dooring.cn",
"repository": {
"type": "git",
"url": "git+https://github.com/MrXujiang/h5-Dooring.git"
},
"bugs": {
"url": "https://github.com/MrXujiang/h5-Dooring/issues"
},
"dependencies": {
"@ant-design/icons": "^4.2.1",
"@antv/f2": "^3.7.7",
"@visactor/vchart": "^1.12.1",
"@uiw/react-baidu-map": "^1.17.3",
"@umijs/plugin-esbuild": "^1.0.1",
"@umijs/plugin-sass": "^1.1.1",
"@umijs/preset-react": "1.x",
"@umijs/test": "^3.2.19",
"antd": "^4.7.0",
"antd-img-crop": "^3.10.0",
"axios": "^0.19.2",
"braft-editor": "^2.3.9",
"chatbot-antd": "^0.6.0",
"codemirror": "^5.57.0",
"dom-to-image": "^2.6.0",
"file-saver": "^2.0.2",
"http-server": "^0.12.3",
"keymaster": "^1.6.2",
"qrcode.react": "^1.0.0",
"react": "^16.12.0",
"react-audio-player": "^0.14.0",
"react-codemirror2": "^7.2.1",
"react-color": "^2.18.1",
"react-contexify": "^4.1.1",
"react-dnd": "^11.1.3",
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "^16.12.0",
"react-draggable": "^4.4.3",
"react-draggable-ball": "^0.1.0",
"react-grid-layout": "^1.0.0",
"react-hotkeys-hook": "^2.3.1",
"react-text-loop": "^2.3.0",
"redux-undo": "^1.0.1",
"socket.io-client": "^2.3.0",
"umi": "^3.2.19",
"video-react": "^0.14.1",
"xlsx": "^0.16.7",
"yh-react-popover": "^0.3.0",
"yorkie": "^2.0.0",
"zarm": "^2.5.1"
},
"license": "GPL-3.0",
"devDependencies": {
"@types/classnames": "^2.2.10",
"@types/codemirror": "^0.0.98",
"@types/events": "^3.0.0",
"@types/file-saver": "^2.0.1",
"@types/node": "^14.6.2",
"@types/qrcode.react": "^1.0.1",
"@types/react-color": "^3.0.4",
"@types/react-grid-layout": "^1.1.0",
"@types/redux-logger": "^3.0.8",
"@types/xlsx": "^0.0.36",
"@typescript-eslint/eslint-plugin": "4.1.1",
"@typescript-eslint/parser": "4.1.1",
"babel-eslint": "10.x",
"babel-plugin-import": "^1.13.0",
"cross-env": "^7.0.2",
"eslint": "6.x",
"eslint-config-react-app": "^5.2.1",
"eslint-plugin-flowtype": "4.x",
"eslint-plugin-import": "2.x",
"eslint-plugin-jsx-a11y": "6.x",
"eslint-plugin-react": "7.x",
"eslint-plugin-react-hooks": "2.x",
"koa": "^2.13.0",
"koa-body": "^4.2.0",
"koa-logger": "^3.2.1",
"koa-static": "^5.0.0",
"koa2-cors": "^2.0.6",
"lint-staged": "^10.0.7",
"prettier": "^1.19.1",
"redux-logger": "^3.0.6",
"sass-loader": "^9.0.3",
"typescript": "^4.0.2",
"vuepress": "^1.8.0"
}
}


File: SECURITY.md

Security Policy

Supported Versions

Use this section to tell people about which versions of your project are
currently being supported with security updates.

Version Supported
5.1.x :white_check_mark:
5.0.x :x:
4.0.x :white_check_mark:
< 4.0 :x:

Reporting a Vulnerability

Use this section to tell people how to report a vulnerability.

Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.


File: tsconfig.json

{
"compilerOptions": {
"target": "es5",
"module": "ESNext",
"moduleResolution": "node",
"jsx": "react",
"baseUrl": ".",
"strict": true,
"importHelpers": true,
"sourceMap": true,
"lib": ["dom", "dom.iterable", "esnext"],
"paths": {
"@/": ["src/"],
"@@/": ["src/.umi/"],
"components/": ["src/components/"],
"utils/": ["src/utils/"],
"assets/": ["src/assets/"]
},
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"noEmit": true,
"skipLibCheck": true
}
}


File: zh.md

[Binary file]


File: doc/README.md


content: Home
home: true
#heroImage: ../imgs/common/logo.svg
heroText: 一款所见即所得的H5编辑器
features:

  • title: 简洁方便
    details: 任何人只需傻瓜式拖拽或进行简单编辑即可生成精美的H5页面
  • title: 插拔式体验
    details: 产品以GPL协议开源, 授权后可植入任何系统,并支持二次开发
  • title: 持续迭代,无限可能
    details: 目前正在持续迭代中,后续可根据需求开发功能更强大的可视化系统
    actionText: 快速上手 →
    actionLink: /zh/guide/
    footer: GPL Licensed | Copyright © 2020-present H5-Dooring


File: doc/zh/guide/README.md

[Binary file]


File: doc/zh/guide/building.md

正在建设中...


File: doc/zh/guide/directoryStructure.md

[Binary file]


File: doc/zh/guide/introduced.md

注:灰色部分还未实现,正在更新中...


File: doc/zh/guide/startedQuickly.md

[Binary file]


File: doc/zh/guide/componentDev/componentStructure.md

组件结构

dooring 的组件设计包含以下 3 个部分组件:

1、component 组件主体

2、schema 组件的 DSL,结构协议层

3、template 定义了组件的类型、外观、从属关系,后期考虑纳入 schema

接下来我会介绍一个基本的组件主体设计,以为 template 设计,在下一章会具体介绍 schema 部分。

组件设计

我们这里拿基本的 header 组件来举例,如下是 header 组件的代码:

jsx
interface HeaderPropTypes extends IHeaderConfig {
  isTpl: boolean;
}

const Header = memo((props: HeaderPropTypes) => {
  const { bgColor, logo, logoText, fontSize, color } = props;
  return props.isTpl ? (
    <div>
      <img style={{ width: "100%" }} src={logos} alt="" />
    </div>
  ) : (
    <header className={styles.header} style={{ backgroundColor: bgColor }}>
      <div className={styles.logo}>
        <img src={logo && logo[0].url} alt={logoText} />
      </div>
      <div className={styles.title} style={{ fontSize, color }}>
        {logoText}
      </div>
    </header>
  );
});

我们只需要按照上面的方式编写组件即可,props 是 DSL 定义的数据层,用来控制组件的 shape,也就是组件的表现。我们看看 header 对应的 template。

template 设计

js
const template = {
  type: "Header",
  h: 28,
  displayName: "页头组件"
};
export default template;

以上就是我们 template 的结构,type 用来定义组件的类型,方便渲染器动态查找,h 代表组件的初始化高度,我们可以自由设置。displayName 是组件的中文名,用来在左侧组件面板中展示,方便用户理解,我们可以在 template 中自定义更多辅助信息,方便使用者更高效的使用我们的编辑器。

schema 设计

开发一个自定义组件需要包含 3 部分, Component, Schema 和 Template. 接下来我们看一下 Header 组件的 Schema.

js
import {
  IColorConfigType,
  INumberConfigType,
  ITextConfigType,
  IUploadConfigType,
  TColorDefaultType,
  TNumberDefaultType,
  TTextDefaultType,
  TUploadDefaultType
} from "@/components/FormComponents/types";
import { baseConfig, baseDefault, ICommonBaseType } from "../../common";

export type THeaderEditData = Array<
  IColorConfigType | INumberConfigType | IUploadConfigType | ITextConfigType
>;
export interface IHeaderConfig extends ICommonBaseType {
  bgColor: TColorDefaultType;
  logo: TUploadDefaultType;
  logoText: TTextDefaultType;
  fontSize: TNumberDefaultType;
  color: TColorDefaultType;
  height: TNumberDefaultType;
}

export interface IHeaderSchema {
  editData: THeaderEditData;
  config: IHeaderConfig;
}

const Header: IHeaderSchema = {
  editData: [
    ...baseConfig,
    {
      key: "bgColor",
      name: "背景色",
      type: "Color"
    },
    {
      key: "height",
      name: "高度",
      type: "Number"
    },
    {
      key: "logo",
      name: "logo",
      type: "Upload",
      isCrop: true,
      cropRate: 1000 / 618
    },
    {
      key: "logoText",
      name: "logo文字",
      type: "Text"
    },
    {
      key: "color",
      name: "文字颜色",
      type: "Color"
    },
    {
      key: "fontSize",
      name: "文字大小",
      type: "Number"
    }
  ],
  config: {
    bgColor: "rgba(0,0,0,1)",
    logo: [
      {
        uid: "001",
        name: "image.png",
        status: "done",
        url: "http://49.234.61.19/uploads/3_1740be8a482.png"
      }
    ],
    logoText: "页头Header",
    fontSize: 20,
    color: "rgba(255,255,255,1)",
    height: 50,
    ...baseDefault
  }
};

export default Header;

editData表示组件的可编辑属性, 我们可以自定义哪些组件可编辑. config为组件接收的属性, 和editData数组项中的key一一对应.

组件编辑区属性类型

Dooring组件编辑面板有如下对应编辑类型:

  • Upload 上传组件
  • Text 文本框
  • RichText 富文本
  • TextArea 多行文本
  • Number 数字输入框
  • DataList 列表编辑器
  • FileList 文件列表编辑器
  • InteractionData 交互设置
  • Color 颜色面板
  • MutiText 多文本
  • Select 选择下拉框
  • Radio 单选框
  • Switch 开关切换
  • CardPicker 卡片面板
  • Table 表格编辑器
  • Pos 坐标编辑器
  • FormItems 表单设计器

File: doc/zh/guide/componentDev/DSLAnalysis.md

DSL 设计

DSL 层主要约定了 Dooring 组件的数据协议,包括组件的可编辑属性、编辑类型、初始值等,之所以定义一致的协议层,主要是方便后期的组件扩展,配置后移,有助于不同后端语言开发和数据存储,接下来我们看看 header 组件的 schema。

1.editData 可编辑的属性类型 DSL

2.config 可编辑组件的默认属性

js
const Header: IHeaderSchema = {
  editData: [
    {
      key: "bgColor",
      name: "背景色",
      type: "Color"
    },
    {
      key: "height",
      name: "高度",
      type: "Number"
    },
    {
      key: "logo",
      name: "logo",
      type: "Upload",
      isCrop: true,
      cropRate: 1000 / 618
    },
    {
      key: "logoText",
      name: "logo文字",
      type: "Text"
    },
    {
      key: "color",
      name: "文字颜色",
      type: "Color"
    },
    {
      key: "fontSize",
      name: "文字大小",
      type: "Number"
    }
  ],
  config: {
    bgColor: "rgba(245,245,245,1)",
    logo: [
      {
        uid: "001",
        name: "image.png",
        status: "done",
        url: `${serverUrl}/uploads/3_1740be8a482.png`
      }
    ],
    logoText: "页头Header",
    fontSize: 20,
    color: "rgba(47,84,235,1)",
    height: 50
  }
};

由以上代码可知,我们可以在 editData 属性中给组件添加可编辑的属性,比如背景图,然后再 component 中接受属性从而设置样式。

在 config 属性中,我们可以设置组件默认属性值,和 editData 中每一项的 key 一一对应。


File: doc/zh/guide/componentDev/dynamicLoading.md

组件动态加载

目前 H5-Dooring 的组件都是通过动态加载的方式引入,好处是我们在页面中只会加载我们需要的组件,不需要的组件不会被加载,这样可以提高页面加载的速度,这样做也会出现一些问题,比如一个长页面,配置了很多组件,那么一个页面加载过程可以会触发多次请求,目前还没有遇到性能问题,但后续会逐渐优化这个问题。

umi3 提供的 dynamic

目前组件的动态加载我们采用的 umi 的 dynamic 方案,基于它我们上层封装了一个组件动态加载器,原理如下:

具体代码可以参考 Dooring 的 Github 地址:https://github.com/MrXujiang/h5-Dooring


File: doc/zh/guide/deployDev/api.md

[Binary file]


File: doc/zh/guide/deployDev/deploy.md

私有化部署需要获取 4 个核心项目包, 包括

  • H5 编辑器(h5_plus)
  • H5 基座(h5)
  • Dooring 管理后台(Dooring-Admin)
  • 服务端项目(Server)

获取以上四个核心源码工程需要满足商业授权协议, 具体可联系作者徐小夕

部署架构图

部署流程如下:

  1. 下载 4 个源码工程, 安装依赖(npm install 或 yarn)
  2. 打包 3 个前端工程至server的 static 目录下
  3. 在server下本地运行 yarn start 或 npm start 启动服务端进行本地测试
  4. 打包服务端代码, yarn build 生成 dist 目录, 建议使用 pm2 做nodejs服务的负载均衡, 运行 pm2 start dist/index.js启动生产环境代码

也可以将以上步骤集成到 gitlab 等 CI, CD 服务中, 进行自动化打包发布, 或者采用docker进行容器化部署.

步骤 3.4 详细流程

1. 安装项目环境

服务器需提前安装 node 和 pm2, 将本项目上传至服务器指定的目录(如/www/activity), 进入项目目录, 执行:

text
npm install

2. 修改项目域名

进入./src/config/index.js, 修改staticPath变量为当前服务器域名/ip, 如http://xxx.com或http://xxx.com:8080(如非 80 端口)

3. 编译项目

执行npm run build编译项目, 生成dist目录

4. 运行项目

在项目根目录执行 pm2 start dist/index.js启动项目


File: doc/zh/guide/deployDev/deploy_v6.md

私有化部署需要获取 3 个核心项目包, 包括

  • 可视化大屏编辑器(v6.dooring/)
  • v6 管理后台(v6.dooring/manage)
  • 服务端项目(v6.dooring/server)

获取以上三个核心源码工程需要满足商业授权协议, 具体可参考商业授权方案

部署架构图

部署流程如下:

  1. 下载 3 个源码工程, 安装依赖(npm install 或 yarn)
  2. 打包 2 个前端工程至server的 static 目录下
  3. 在server下本地运行 yarn start 或 npm start 启动服务端进行本地测试
  4. 打包服务端代码, yarn build 生成 dist 目录, 建议使用 pm2 做nodejs服务的负载均衡, 运行 pm2 start dist/index.js启动生产环境代码

也可以将以上步骤集成到 gitlab 等 CI, CD 服务中, 进行自动化打包发布, 或者采用docker进行容器化部署.

步骤 3.4 详细流程

1. 安装项目环境

服务器需提前安装 node 和 pm2, 将本项目上传至服务器指定的目录(如/www/activity), 进入项目目录, 执行:

text
npm install

2. 修改项目域名

进入./src/config/index.js, 修改staticPath变量为当前服务器域名/ip, 如http://xxx.com或http://xxx.com:8080(如非 80 端口)

3. 编译项目

执行npm run build编译项目, 生成dist目录

4. 运行项目

在项目根目录执行 pm2 start dist/index.js启动项目


File: doc/zh/guide/deployDev/dir.md

[Binary file]


File: doc/zh/guide/deployDev/form.md

获取 Form 组件的值数据

Form 表单组件在editor目录下src/components/BasicShop/BasicComponents位置.

Form 组件是Dooring的核心组件之一, 内部的值通过 Form 组件内部收集, 当然我们也可以暴露出来让其他交互或者组件消费(需要一定的二次开发), 关键代码如下:

js
req
  .post(`/vip/h5/form/post${location.search}`, { ...fields, ...formData })
  .then(res => {
    if (type === "link") {
      // 解析参数
      let isPre = content.indexOf("?") < 0;
      let query = { dr: Date.now(), from: urlParmas.tid };
      try {
        query = params ? { ...JSON.parse(params), ...query } : query;
      } catch (err) {
        console.log(err);
      }

      // 跳转
      if (content.indexOf("http") > -1) {
        window.location.href = content + urlencode(query, isPre);
        return;
      }

      history.push(`/m?tid=${content}&${urlencode(query)}`);
    } else if (type === "modal") {
      setVisible(true);
    } else if (type === "code") {
      eval(content);
    }
  });

数据收集提交的核心代码在 Form 组件的第 56-149 行, 也就是submit方法. 表单组件收集到的数据统一存放在代码中的formData字段, 所以要想在其他地方获取用户表单填写的值, 我们只需要手动将formData传递出去, 或者挂载到全局(如 window 对象, localStorage, indexedDB 等).


File: doc/zh/guide/deployDev/https.md

目前H5-Dooring全面支持 https 部署, 具体方式方案如下.

前端工程

我们需要在前端工程中的src/pages/document.ejs中的head中添加如下代码:

html
<meta
  http-equiv="Content-Security-Policy"
  content="upgrade-insecure-requests"
/>

目的是强制将页面中 HTTP 请求转换为 HTTPS.

服务器工程

1. 申请 SSL 证书

2. 生成 server.csr+server.key

3. 通过证书链生成.pem 文件

在`server`中的`src/index.js`按如下方式修改

js
// 忽略部分无影响代码
import https from "https";

// 你的ssl存放路径, 建议直接放在server目录下
const filePath = path.join(__dirname, "../ssl");

// 启动逻辑
async function start() {
  // https配置
  const httpsOptions = {
    key: fs.readFileSync(path.join(filePath, "3536084__doctopia.com.cn.key")), //ssl文件路径
    cert: fs.readFileSync(path.join(filePath, "3536084__doctopia.com.cn.pem")) //ssl文件路径
  };

  // https服务
  const server = https.createServer(httpsOptions, app.callback());

  const io = require("socket.io")(server);

  // 忽略其他无影响代码

  // https默认443, 这里我们可以走公共配置
  server.listen(443, () => {
    console.log(`服务器地址:${config.staticPath}`);
  });
}

start();

File: doc/zh/guide/deployDev/log.md

[Binary file]


File: doc/zh/guide/deployDev/oss.md

H5-Dooring全面支持第三方对象存储服务, 我们以七牛云对象存储为例.

前端上传文件到 oss

首先我们需要在第三方对象储存服务中配置对应的服务和域名. 其次安装对应的 sdk, 如七牛云 sdk:

js
import * as qiniu from "qiniu-js";

其次我们修改h5_plus工程的Upload组件, 详细地址为src/core/FormComponents/Upload.

修改内容如下:

js
const fileName = file.name;
const suffix = "自定义文件后缀";
const putExtra = {
  fname: fileName,
  params: {}
};
const uid = +new Date() + uuid(16, 8) + suffix;
// 使用七牛云上传api, 前提是提前在前端拿到对应的ticket, 可以通过请求的方式获取
const observe = qiniu.upload(
  file,
  uid,
  this.state.qnToken.ticket,
  putExtra,
  {}
);
observe.subscribe(
  () => {},
  null,
  res => {
    // 拼接路径
    const url = `${this.state.qnToken.domain}/${res.key}`;
    // 存库
    const fileList = [{ uid, name: fileName, status: "done", url }];
    this.setState({
      curImgUrl: url,
      fileList
    });
    this.props.onChange && this.props.onChange(fileList);
  }
);

其他 oss 服务类似, 如果不清楚如何配置, 可以在H5-Dooring 官网中找到我们.

如何接入任何第三方上传服务

首先我们的上传组件Upload使用内部的服务接口来实现上传功能, 所以需要给组件的action赋值, 如下:

jsx
<Upload
  fileList={fileList}
  onPreview={this.handlePreview}
  onChange={this.handleChange}
  onRemove={this.handleRemove}
  name="file"
  listType="picture-card"
  className={styles.avatarUploader}
  action={sdk_upload_api || action}
  withCredentials={withCredentials}
  headers={{
    "x-requested-with": localStorage.getItem("user") || "",
    authorization: localStorage.getItem("token") || "",
    ...headers
  }}
  beforeUpload={this.handleBeforeUpload}
>
  {fileList.length >= maxLen ? null : uploadButton}
</Upload>

如果需要集成第三方 oss, 如七牛云, 阿里 oss 等, 我们需要将Upload组件的action属性设置为空字符串, 其次删除onChange属性, 上传操作统一在beforeUpload中进行. 案例如下:

jsx
<Upload
  fileList={fileList}
  action=""
  onPreview={this.handlePreview}
  onRemove={this.onRemove}
  name="file"
  listType="picture-card"
  className={styles.avatarUploader}
  headers={{ ...headers }}
  beforeUpload={this.handleBeforeUpload}
>
  {fileList.length >= maxLen ? null : uploadButton}
</Upload>

自定义上传的核心逻辑放在了beforeUpload上. 我们具体看看beforeUpload这个方法如何实现.

js
handleBeforeUpload = (file: RcFile) => {
  // 1. 限制图片类型
  const isJpgOrPng =
    file.type === "image/jpeg" ||
    file.type === "image/png" ||
    file.type === "image/jpg" ||
    file.type === "image/gif";
  if (!isJpgOrPng) {
    message.error("只能上传格式为jpeg/png/gif的图片");
  }
  // 限制上传文件大小
  const isLt3M = file.size / 1024 / 1024 < 3;
  if (!isLt3M) {
    message.error("图片必须小于3MB!");
  }
  if (isJpgOrPng && isLt3M) {
    // 3. 正常上传逻辑
    const fileName = file.name;
    // 3.1 调用oss接口, 将图片上传oss
    // 3.2 将接口返回的url信息, 组装成fileList数据结构, 并更新state
    const fileList = [{ uid, name: fileName, status: "done", url }];
    this.setState({
      curImgUrl: url,
      fileList
    });
    // 3.3 将数据传给上层保存
    this.props.onChange && this.props.onChange(fileList);
  }
  return isJpgOrPng && isLt3M;
};

File: doc/zh/guide/functionRealization/download.md

下载源码

目前 Dooring 已支持下载源码功能, 我们可以使用编辑器页面头部的下载按钮来实现下载用户搭建的 H5 源码.

源码下载之后是完整的 React 项目源代码, 开发人员可以直接根据自己的业务需求来二次编写代码来满足不同的业务需求.

在拿到源码之后, 我们需要进入项目, 使用 npm 或者 yarn 安装项目依赖, 如下:

bash
npm install
// 或者
yarn

之后我们就可以本地运行项目了:

bash
npm start
// 或者
yarn start

因为源码工程采用umi3.0搭建, 所以代码配置可以参考umi3.0规范, 比如路由配置, history模式, 打包路径等, 二次开发完成之后, 我们可以执行:

bash
npm run build
// 或者
yarn build

将项目打包成 html, 以便部署到任何服务器中.


File: doc/zh/guide/functionRealization/machinePreview.md

真机预览

真机预览和网页预览的流程类似,工作流程如下:

由于不同机型预览的效果有些许不同,最终效果以实际看到的为主。


File: doc/zh/guide/functionRealization/pagePreview.md

网页预览

我们看看网页预览的工作流程:

前端预览界面:


File: doc/zh/guide/functionRealization/revocation.md

撤销/重做

撤销重做我们主要使用了 redux-undo 这个库,配合 Dva 使用,具体使用方法参考如下操作:

js
import { createLogger } from "redux-logger";
import { message } from "antd";
import undoable, { StateWithHistory } from "redux-undo";
import { Reducer, AnyAction } from "redux";

export const dva = {
  config: {
    onAction: createLogger(),
    onError(e: Error) {
      message.error(e.message, 3);
    },
    onReducer: (reducer: Reducer<any, AnyAction>) => {
      let undoReducer = undoable(reducer);
      return function(state: StateWithHistory<any>, action: AnyAction) {
        let newState = undoReducer(state, action);
        let router = newState.present.router
          ? newState.present.router
          : newState.present.routing;
        return { ...newState, router: router };
      };
    }
  }
};

以上我们就实现了全局配置 redux-undo,在撤销重做按钮中我们就可以触发对应的方法来实现撤销重做的功能,其次我们还使用了 redux-logger 来实现 redux 的日志输出。


File: doc/zh/guide/functionRealization/saveJson.md

保存 json

我们配置好 H5 页面之后,如果希望其他人观看,我们可以保存页面并发送链接。但是如果有多人协作的需求,比如一个 H5 页面可能由多个人完成,这个时候该怎么实现呢?基于已有的方案,我们可以采用 socket 实现多人协同编辑,但是成本比较大,所有这里我们提供了保存 json 的功能。

我们可以将配置好的页面导出为 json,发送给另一个人,这样另一个人通过导入该 json 文件可以实时看到当前的页面,这里还是依靠我们的页面渲染引擎 viewEngine。实现思路也很简单,可以在 github[https://github.com/MrXujiang/h5-Dooring]上参考体验。


File: doc/zh/guide/functionRealization/screenshot.md

截图功能

截图功能这里我们主要使用了 dom-to-image 这个库,来将 html 转化为图片,并进行分享。


File: doc/zh/guide/functionRealization/templateLibrary.md

模板库实现思路

我们目前开放了模板库功能,一方面我们会定期配置行业模板,另一个方面 Dooring 还支持用户自己配置模板,可以一键保存到云端供用户使用。我们也可以将模板变成自己的页面共享给其他人。实现方式本质上是保存用户的配置信息,上传到服务器中做存储,在后台提供了管理模板的模块,可以修改,删除模板。如下图所示:

模板前台展示:

模板后台展示:


File: .github/FUNDING.yml

These are supported funding model platforms

support simple dooring !

weclome to try this repo.

open_collective: h5-dooring


File: .github/ISSUE_TEMPLATE/custom.md


name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''