+// 布局
+
+ // 页面
+
+ // 栅格
+
+ // 区块,以表格为例
+
+ // 配置工具栏
+
+ // 操作栏
+
+ // 操作
+
+
+
+ // 内容区
+
+
+ // 表格列的字段
+
+
+
+
+
+
+
+
+
+
+
+
+
+注:以上例子只为表达组件树的结构和组件之间的关系,实际代码并不如此。
+
+接下来,我们来详细的介绍各部分的概念。
+
+## 布局和页面
+
+页面是可以通过地址访问的网页,不同页面之间可能具有相同的页眉、页脚和导航,通常我们会把这些公共的内容放在布局组件里。例如,初始化的 NocoBase 提供了两个布局组件,如图所示:
+
+图
+
+- AuthLayout:无需登录就能访问,一般用于嵌入登录、注册、忘记密码等页面。
+- AdminLayout:需要登录,管理后台的所有页面。
+
+布局和页面组件通过 createRouteSwitch 注册,更多扩展内容点此查看。
+
+## 页面内容排版
+
+对开发者来说,页面内容的编写是自由的,不过为了方便对页面内容进行排版,提供了两种排版方式:
+
+### 简易的上下结构
+
+
+
+
+
+
+
+
+
+例子如下:
+
+```js
+// 示例
+```
+
+### 可拖拽的栅格
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+栅格组件 Grid 基于行(Grid.Row)和列(Grid.Col)来定义区块的外部框架。例子如下:
+
+```js
+// 示例
+```
+
+## AddNew
+
+AddNew 是页面可视化配置最重要的操作按钮,更多关于 AddNew 的内容点此查看
+
+## 区块 - Block
+
+区块一般放在页面里,可以是任意东西,包括文字、附件、表格、表单、日历、看板等等。一个完整的区块由三部分组成:
+
+- 内容区 Content,区块的主体
+- 操作栏 ActionBar,可以放置各种操作按钮,用于操作区块数据(可选)
+- 配置工具栏 DesignableBar,操作区块配置的按钮(可选)
+
+以表格区块为例,组件结构如下:
+
+
+
+
+
+
+大部分的操作指令需要用户提供参数,如新增数据操作,需要用户填写数据,填写数据一般需要弹出表单,用户填写完数据,点击提交,才触发操作指令。组件结构如下:
+
+
+
+ {/* 这是个弹窗表单,内置提交按钮,点击提交触发操作指令,具体代码省略 */}
+
+
+
+
+一个完整的操作大概分为两步:
+
+- 为 Action 绑定一段指令
+- 如果指令需要用户提供参数,需要提供交互界面,目前内置的有:
+ - Action.Drawer:抽屉
+ - Action.Modal:对话框
+ - Action.Popover:气泡
+
+操作是 NocoBase 里非常重要的一个概念,更多详情点此查看
+
+## 配置工具栏 - DesignableBar
+
+所有的 Schema Component 都可以绑定自己的配置工具栏(DesignableBar),用于修改当前组件的 Schema。
+
+
+**什么是 Schema Component?**
+通过 Schema 协议编写的类 JSON Schema 格式的组件,如:
+
+```js
+{
+ type: 'void',
+ 'x-Component': 'Hello',
+ 'x-designable-bar': 'Hello.DesignableBar',
+ 'x-dect': 'CardItem',
+}
+```
+
+举几个例子,如:
+
+表单字段的 JSON Schema
+
+```js
+const schema = {
+ type: 'string',
+ 'x-component': 'Input',
+ 'x-decorator': 'FormItem',
+ 'x-designable-bar': 'Form.Field.DesignableBar',
+};
+```
+
+表单项的配置工具栏 `Form.Field.DesignableBar` 的效果
+
+
+
+表格的 JSON Schema
+
+```js
+const schema = {
+ type: 'array',
+ 'x-component': 'Table',
+ 'x-decorator': 'CardItem',
+ 'x-designable-bar': 'Table.DesignableBar',
+};
+```
+
+表格配置工具栏 `Table.DesignableBar` 的效果
+
+
+
+菜单项的 JSON Schema:
+
+```js
+const schema = {
+ type: 'array',
+ 'x-component': 'Menu.Item',
+ 'x-designable-bar': 'Menu.Item.DesignableBar',
+};
+```
+
+菜单项配置工具栏 `Menu.Item.DesignableBar` 的效果
+
+
+
+更多配置工具栏详情点此查看
+
+## 字段组件 - CollectionField
+
+字段组件的配置参数可能非常多,在不同数据区块里也可能用到同一个字段组件,为了减少代码重复,NocoBase 里,将字段组件的配置交由数据表统一管理。一处配置,多处使用。数据区块里直接引用字段组件,如果有其他不同参数再另行扩展。
+
+
+
+// 布局
+
+ // 页面
+
+ // 栅格
+
+ // 区块,以表格为例
+
+ // 配置工具栏
+
+ // 操作栏
+
+ // 操作
+
+
+
+ // 内容区
+
+
+ // 表格列的字段
+
+
+
+
+
+
+
+
+
+
+
+
+
+注:以上例子只为表达组件树的结构和组件之间的关系,实际代码并不如此。
+
+接下来,我们来详细的介绍各部分的概念。
+
+## 布局和页面
+
+页面是可以通过地址访问的网页,不同页面之间可能具有相同的页眉、页脚和导航,通常我们会把这些公共的内容放在布局组件里。例如,初始化的 NocoBase 提供了两个布局组件,如图所示:
+
+图
+
+- AuthLayout:无需登录就能访问,一般用于嵌入登录、注册、忘记密码等页面。
+- AdminLayout:需要登录,管理后台的所有页面。
+
+布局和页面组件通过 createRouteSwitch 注册,更多扩展内容点此查看。
+
+## 页面内容排版
+
+对开发者来说,页面内容的编写是自由的,不过为了方便对页面内容进行排版,提供了两种排版方式:
+
+### 简易的上下结构
+
+
+
+
+
+
+
+
+
+例子如下:
+
+```js
+// 示例
+```
+
+### 可拖拽的栅格
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+栅格组件 Grid 基于行(Grid.Row)和列(Grid.Col)来定义区块的外部框架。例子如下:
+
+```js
+// 示例
+```
+
+## AddNew
+
+AddNew 是页面可视化配置最重要的操作按钮,更多关于 AddNew 的内容点此查看
+
+## 区块 - Block
+
+区块一般放在页面里,可以是任意东西,包括文字、附件、表格、表单、日历、看板等等。一个完整的区块由三部分组成:
+
+- 内容区 Content,区块的主体
+- 操作栏 ActionBar,可以放置各种操作按钮,用于操作区块数据(可选)
+- 配置工具栏 DesignableBar,操作区块配置的按钮(可选)
+
+以表格区块为例,组件结构如下:
+
+
+
+
+
+
+大部分的操作指令需要用户提供参数,如新增数据操作,需要用户填写数据,填写数据一般需要弹出表单,用户填写完数据,点击提交,才触发操作指令。组件结构如下:
+
+
+
+ {/* 这是个弹窗表单,内置提交按钮,点击提交触发操作指令,具体代码省略 */}
+
+
+
+
+一个完整的操作大概分为两步:
+
+- 为 Action 绑定一段指令
+- 如果指令需要用户提供参数,需要提供交互界面,目前内置的有:
+ - Action.Drawer:抽屉
+ - Action.Modal:对话框
+ - Action.Popover:气泡
+
+操作是 NocoBase 里非常重要的一个概念,更多详情点此查看
+
+## 配置工具栏 - DesignableBar
+
+所有的 Schema Component 都可以绑定自己的配置工具栏(DesignableBar),用于修改当前组件的 Schema。
+
+
+**什么是 Schema Component?**
+通过 Schema 协议编写的类 JSON Schema 格式的组件,如:
+
+```js
+{
+ type: 'void',
+ 'x-Component': 'Hello',
+ 'x-designable-bar': 'Hello.DesignableBar',
+ 'x-dect': 'CardItem',
+}
+```
+
+举几个例子,如:
+
+表单字段的 JSON Schema
+
+```js
+const schema = {
+ type: 'string',
+ 'x-component': 'Input',
+ 'x-decorator': 'FormItem',
+ 'x-designable-bar': 'Form.Field.DesignableBar',
+};
+```
+
+表单项的配置工具栏 `Form.Field.DesignableBar` 的效果
+
+
+
+表格的 JSON Schema
+
+```js
+const schema = {
+ type: 'array',
+ 'x-component': 'Table',
+ 'x-decorator': 'CardItem',
+ 'x-designable-bar': 'Table.DesignableBar',
+};
+```
+
+表格配置工具栏 `Table.DesignableBar` 的效果
+
+
+
+菜单项的 JSON Schema:
+
+```js
+const schema = {
+ type: 'array',
+ 'x-component': 'Menu.Item',
+ 'x-designable-bar': 'Menu.Item.DesignableBar',
+};
+```
+
+菜单项配置工具栏 `Menu.Item.DesignableBar` 的效果
+
+
+
+更多配置工具栏详情点此查看
+
+## 字段组件 - CollectionField
+
+字段组件的配置参数可能非常多,在不同数据区块里也可能用到同一个字段组件,为了减少代码重复,NocoBase 里,将字段组件的配置交由数据表统一管理。一处配置,多处使用。数据区块里直接引用字段组件,如果有其他不同参数再另行扩展。
+
+
+
+import { I18nextProvider } from 'react-i18next';
+import { createRouteSwitch, APIClient } from '@nocobase/client';
+
+const apiClient = new APIClient();
+const i18n = i18next.createInstance();
+
+const Hello = () => {
+ return Hello;
+}
+
+const SchemaComponent = createSchemaComponent({
+ components: {
+ Hello,
+ },
+});
+
+const PageTemplate = () => {
+ const schema = {
+ type: 'void',
+ 'x-component': 'Hello',
+ };
+ return (
+
+ );
+}
+
+const RouteSwitch = createRouteSwitch({
+ components: {
+ PageTemplate,
+ },
+});
+
+const routes = [
+ { path: '/hello', component: 'Hello' },
+];
+
+function AntdProvider(props) {
+ // 可以根据 i18next 的情况动态处理这里的 locale
+ return (
+ {props.children}
+ );
+}
+
+const App = () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
+
+
+- APIClientProvider:提供 APIClient
+- I18nextProvider:国际化
+- AntdProvider:处理 antd 组件的国际化,需要放在 I18nextProvider 里
+- Router:路由驱动
+- RouteSwitch:路由分发
+
+上面代码看似有些啰嗦,实际各部分的功能和作用并不一样,不适合过度封装。如果需要可以根据实际情况,再进一步封装。
\ No newline at end of file
diff --git a/docs/guide/kernel-principle/client-side-kernel.zh-CN.md b/docs/guide/kernel-principle/client-side-kernel.zh-CN.md
new file mode 100644
index 0000000000..847d05fca3
--- /dev/null
+++ b/docs/guide/kernel-principle/client-side-kernel.zh-CN.md
@@ -0,0 +1,158 @@
+---
+order: 2
+---
+
+# 客户端内核
+
+为了让更多非开发人员也能参与进来,NocoBase 提供了配套的客户端插件 —— 无代码的可视化配置界面。这部分的核心就是 @nocobase/client,理想状态可以用在任意前端构建工具或框架内,如:
+
+- umijs
+- create-react-app
+- icejs
+- vite
+- snowpack
+- nextjs
+- 其他
+
+暂时只支持 umijs(打包编译还有些问题),未来会逐步支持以上罗列的各个框架。
+
+客户端主要的组成部分包括:
+
+## 请求
+
+- API Client
+- Request Hook
+
+```ts
+const api = new APIClient({
+ request,
+});
+
+api.auth();
+api.get();
+api.post();
+api.resource('collections').create();
+api.resource('collections').findOne({});
+api.resource('collections').findMany({});
+api.resource('collections').relation('fields').of(1).create();
+```
+
+以下细节待定,特殊的资源
+
+```js
+api.collections.create();
+api.uiSchemas.create();
+```
+
+Request Hook
+
+[https://www.npmjs.com/package/@ahooksjs/use-request](https://www.npmjs.com/package/@ahooksjs/use-request)
+
+```js
+const { data } = useRequest(() => api.resource('users').findMany());
+```
+
+## 路由
+
+- createRouteSwitch
+
+```js
+const RouteSwitch = createRouteSwitch({
+ components: {},
+});
+
+
+import { I18nextProvider } from 'react-i18next';
+import { createRouteSwitch, APIClient } from '@nocobase/client';
+
+const apiClient = new APIClient();
+const i18n = i18next.createInstance();
+
+const Hello = () => {
+ return Hello;
+}
+
+const SchemaComponent = createSchemaComponent({
+ components: {
+ Hello,
+ },
+});
+
+const PageTemplate = () => {
+ const schema = {
+ type: 'void',
+ 'x-component': 'Hello',
+ };
+ return (
+
+ );
+}
+
+const RouteSwitch = createRouteSwitch({
+ components: {
+ PageTemplate,
+ },
+});
+
+const routes = [
+ { path: '/hello', component: 'Hello' },
+];
+
+function AntdProvider(props) {
+ // 可以根据 i18next 的情况动态处理这里的 locale
+ return (
+ {props.children}
+ );
+}
+
+const App = () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
+
+
+- APIClientProvider:提供 APIClient
+- I18nextProvider:国际化
+- AntdProvider:处理 antd 组件的国际化,需要放在 I18nextProvider 里
+- Router:路由驱动
+- RouteSwitch:路由分发
+
+上面代码看似有些啰嗦,实际各部分的功能和作用并不一样,不适合过度封装。如果需要可以根据实际情况,再进一步封装。
\ No newline at end of file
diff --git a/docs/guide/kernel-principle/installation-startup.md b/docs/guide/kernel-principle/installation-startup.md
new file mode 100644
index 0000000000..edd085b5b9
--- /dev/null
+++ b/docs/guide/kernel-principle/installation-startup.md
@@ -0,0 +1,73 @@
+---
+order: 3
+---
+
+# Installation and Startup Process
+
+## 项目安装
+
+```bash
+yarn nocobase init
+```
+
+- app.constructor()
+- app.parse()
+ - yarn nocobase init
+ 初始化安装
+ - app.load()
+ 加载配置
+ - app.emitAsync('beforeLoad')
+ 所有配置加载之前的钩子
+ - app.pluginManager.load()
+ 按顺序载入所有激活的插件的配置
+ - 加载 plugin-collections 的配置
+ - 添加 app.on('init') 监听
+ - db.getModel('collections').load()
+ 把 collections 表的配置都导入 db.table()
+ - app.db.sync({force: false})
+ 再执行 sync,创建 collections 表里配置的数据表
+ - app.emitAsync('afterLoad')
+ 所有配置加载之后的钩子
+ - app.db.sync({force: true})
+ 根据配置生成数据表、字段、索引等
+ - app.emitAsync('init')
+ 执行所有 init listeners,一般是初始化的数据操作
+ - 触发 plugin-collections 的 init 事件,数据表就创建好了
+ - app.stop()
+ 结束
+
+## 项目启动
+
+```bash
+yarn nocobase start --init --sync
+# --init 用于启动时快捷安装
+# --sync 开发环境时,当 app.collection() 有更新时快速建表或更新表
+```
+
+
+
+- app.constructor()
+- app.parse()
+ - yarn nocobase start
+ 初始化安装
+ - app.load()
+ 加载配置
+ - app.emitAsync('beforeLoad')
+ 所有配置加载之前的钩子
+ - app.pluginManager.load()
+ 按顺序载入所有激活的插件的配置
+ - 加载 plugin-collections 的配置
+ - 添加 app.on('start') 监听
+ - db.getModel('collections').load()
+ 把 collections 表的配置都导入 db.table(),在 start 流程里不需要再 db.sync
+ - app.emitAsync('afterLoad')
+ 所有配置加载之后的钩子
+ - app.db.sync({force: false})
+ yarn nocobase start --sync 有更新时快速建表或更新表
+ yarn nocobase start --init 快捷 init
+ - app.emitAsync('init')
+ yarn nocobase start --init 快捷 init
+ - app.emitAsync('start')
+ 执行所有 start listeners,一般是从数据表里读取一些必要的数据
+ - app.listen()
+ 启动 http server
diff --git a/docs/guide/kernel-principle/installation-startup.zh-CN.md b/docs/guide/kernel-principle/installation-startup.zh-CN.md
new file mode 100644
index 0000000000..f7027f630b
--- /dev/null
+++ b/docs/guide/kernel-principle/installation-startup.zh-CN.md
@@ -0,0 +1,73 @@
+---
+order: 3
+---
+
+# 项目安装和启动流程
+
+## 项目安装
+
+```bash
+yarn nocobase init
+```
+
+- app.constructor()
+- app.parse()
+ - yarn nocobase init
+ 初始化安装
+ - app.load()
+ 加载配置
+ - app.emitAsync('beforeLoad')
+ 所有配置加载之前的钩子
+ - app.pluginManager.load()
+ 按顺序载入所有激活的插件的配置
+ - 加载 plugin-collections 的配置
+ - 添加 app.on('init') 监听
+ - db.getModel('collections').load()
+ 把 collections 表的配置都导入 db.table()
+ - app.db.sync({force: false})
+ 再执行 sync,创建 collections 表里配置的数据表
+ - app.emitAsync('afterLoad')
+ 所有配置加载之后的钩子
+ - app.db.sync({force: true})
+ 根据配置生成数据表、字段、索引等
+ - app.emitAsync('init')
+ 执行所有 init listeners,一般是初始化的数据操作
+ - 触发 plugin-collections 的 init 事件,数据表就创建好了
+ - app.stop()
+ 结束
+
+## 项目启动
+
+```bash
+yarn nocobase start --init --sync
+# --init 用于启动时快捷安装
+# --sync 开发环境时,当 app.collection() 有更新时快速建表或更新表
+```
+
+
+
+- app.constructor()
+- app.parse()
+ - yarn nocobase start
+ 初始化安装
+ - app.load()
+ 加载配置
+ - app.emitAsync('beforeLoad')
+ 所有配置加载之前的钩子
+ - app.pluginManager.load()
+ 按顺序载入所有激活的插件的配置
+ - 加载 plugin-collections 的配置
+ - 添加 app.on('start') 监听
+ - db.getModel('collections').load()
+ 把 collections 表的配置都导入 db.table(),在 start 流程里不需要再 db.sync
+ - app.emitAsync('afterLoad')
+ 所有配置加载之后的钩子
+ - app.db.sync({force: false})
+ yarn nocobase start --sync 有更新时快速建表或更新表
+ yarn nocobase start --init 快捷 init
+ - app.emitAsync('init')
+ yarn nocobase start --init 快捷 init
+ - app.emitAsync('start')
+ 执行所有 start listeners,一般是从数据表里读取一些必要的数据
+ - app.listen()
+ 启动 http server
diff --git a/docs/guide/kernel-principle/microkernel-architecture.md b/docs/guide/kernel-principle/microkernel-architecture.md
new file mode 100644
index 0000000000..b43ed79dd0
--- /dev/null
+++ b/docs/guide/kernel-principle/microkernel-architecture.md
@@ -0,0 +1,13 @@
+---
+order: 0
+group:
+ title: Kernel Principle
+ path: /guide/kernel-principle
+ order: 6
+---
+
+# Microkernel Architecture
+
+
+import React from 'react';
+import { MemoryRouter } from 'react-router-dom';
+import { ClientSDK, Application } from '@nocobase/client';
+
+// 初始化 client 实例
+const client = new ClientSDK({
+ request: (options) => Promise.resolve({}),
+});
+
+// 适配 Route Component
+const RouteSwitch = createRouteSwitch({
+ components: {
+ AdminLayout,
+ AuthLayout,
+ RouteSchemaRenderer,
+ },
+});
+
+ReactDOM.render(
+
+
+
+
+ ,
+ document.getElementById('root'),
+);
+
+
+更多细节,可以通过 `create-nocobase-app` 初始化项目脚手架并体验。
+
+```bash
+yarn create nocobase-app my-nocobase-project
+```
+
+nocobase-app 默认使用 umijs 作为项目构建工具,并集成了 Server 作数据接口,初始化的目录结构如下:
+
+```bash
+|- src
+ |- pages
+ |- apis
+|- .env
+|- .umirc.ts
+|- package.json
+```
+
+## 场景 - Cases
+
+小型管理信息系统,具备完整的前后端。
+
+
+import React from 'react';
+import { MemoryRouter } from 'react-router-dom';
+import { ClientSDK, Application } from '@nocobase/client';
+
+// 初始化 client 实例
+const client = new ClientSDK({
+ request: (options) => Promise.resolve({}),
+});
+
+// 适配 Route Component
+const RouteSwitch = createRouteSwitch({
+ components: {
+ AdminLayout,
+ AuthLayout,
+ RouteSchemaRenderer,
+ },
+});
+
+ReactDOM.render(
+
+
+
+
+ ,
+ document.getElementById('root'),
+);
+
+
+更多细节,可以通过 `create-nocobase-app` 初始化项目脚手架并体验。
+
+```bash
+yarn create nocobase-app my-nocobase-project
+```
+
+nocobase-app 默认使用 umijs 作为项目构建工具,并集成了 Server 作数据接口,初始化的目录结构如下:
+
+```bash
+|- src
+ |- pages
+ |- apis
+|- .env
+|- .umirc.ts
+|- package.json
+```
+
+## 场景 - Cases
+
+小型管理信息系统,具备完整的前后端。
+
+{t('hello')}
+{t('hello')}
+
-import React from 'react';
-import { MemoryRouter } from 'react-router-dom';
-import { ClientSDK, Application } from '@nocobase/client';
-
-// 初始化 client 实例
-const client = new ClientSDK({
- request: (options) => Promise.resolve({}),
-});
-
-// 适配 Route Component
-const RouteSwitch = createRouteSwitch({
- components: {
- AdminLayout,
- AuthLayout,
- RouteSchemaRenderer,
- },
-});
-
-ReactDOM.render(
-
-
-
-
- ,
- document.getElementById('root'),
-);
-
-
-更多细节,可以通过 `create-nocobase-app` 初始化项目脚手架并体验。
-
-```bash
-yarn create nocobase-app my-nocobase-project
-```
-
-nocobase-app 默认使用 umijs 作为项目构建工具,并集成了 Server 作数据接口,初始化的目录结构如下:
-
-```bash
-|- src
- |- pages
- |- apis
-|- .env
-|- .umirc.ts
-|- package.json
-```
-
-## 场景 - Cases
-
-小型管理信息系统,具备完整的前后端。
-
-