feat: update docs (#1006)
* feat: update docs * feat: update docs * feat: update docs
153
docs/en-US/development/server/collections/association-fields.md
Normal file
@ -0,0 +1,153 @@
|
||||
# 关系字段配置
|
||||
|
||||
在关系数据库里,标准的建表关系的方式是添加一个外键字段,然后设置上个外键约束。例如 Knex 建表的例子:
|
||||
|
||||
```ts
|
||||
knex.schema.table('posts', function (table) {
|
||||
table.integer('userId').unsigned();
|
||||
table.foreign('userId').references('users.id');
|
||||
});
|
||||
```
|
||||
|
||||
这个过程会在 posts 表里创建一个 userId 字段,并且设置上外键约束 posts.userId 引用 users.id。而在 NocoBase 的 Collection 中,是通过配置关系字段来建立上这样一种关系约束,如:
|
||||
|
||||
```ts
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'user',
|
||||
target: 'users',
|
||||
foreignKey: 'userId',
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## 关系参数说明
|
||||
|
||||
### BelongsTo
|
||||
|
||||
```ts
|
||||
interface BelongsTo {
|
||||
type: 'belongsTo';
|
||||
name: string;
|
||||
// 默认值为 name 复数
|
||||
target?: string;
|
||||
// 默认值为 target model 的主键,一般为 'id'
|
||||
targetKey?: any;
|
||||
// 默认值为 target + 'Id'
|
||||
foreignKey?: any;
|
||||
}
|
||||
|
||||
// authors 表主键 id 和 books 表外键 authorId 相连
|
||||
{
|
||||
name: 'books',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'author',
|
||||
target: 'authors',
|
||||
targetKey: 'id', // authors 表主键
|
||||
foreignKey: 'authorId', // 外键在 books 表
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### HasOne
|
||||
|
||||
```ts
|
||||
interface HasOne {
|
||||
type: 'hasOne';
|
||||
name: string;
|
||||
// 默认值为 name 复数
|
||||
target?: string;
|
||||
// 默认值为 source model 的主键,一般为 'id'
|
||||
sourceKey?: string;
|
||||
// 默认值为 source collection name 的单数形态 + 'Id'
|
||||
foreignKey?: string;
|
||||
}
|
||||
|
||||
// users 表主键 id 和 profiles 外键 userId 相连
|
||||
{
|
||||
name: 'users',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasOne',
|
||||
name: 'profile',
|
||||
target: 'profiles',
|
||||
sourceKey: 'id', // users 表主键
|
||||
foreignKey: 'userId', // 外键在 profiles 表
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### HasMany
|
||||
|
||||
```ts
|
||||
interface HasMany {
|
||||
type: 'hasMany';
|
||||
name: string;
|
||||
// 默认值为 name
|
||||
target?: string;
|
||||
// 默认值为 source model 的主键,一般为 'id'
|
||||
sourceKey?: string;
|
||||
// 默认值为 source collection name 的单数形态 + 'Id'
|
||||
foreignKey?: string;
|
||||
}
|
||||
|
||||
// posts 表主键 id 和 comments 表 postId 相连
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'comments',
|
||||
target: 'comments',
|
||||
sourceKey: 'id', // posts 表主键
|
||||
foreignKey: 'postId', // 外键在 comments 表
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### BelongsToMany
|
||||
|
||||
```ts
|
||||
interface BelongsToMany {
|
||||
type: 'belongsToMany';
|
||||
name: string;
|
||||
// 默认值为 name
|
||||
target?: string;
|
||||
// 默认值为 source collection name 和 target 的首字母自然顺序拼接的字符串
|
||||
through?: string;
|
||||
//默认值为 source collection name 的单数形态 + 'Id'
|
||||
foreignKey?: string;
|
||||
// 默认值为 source model 的主键,一般为 id
|
||||
sourceKey?: string;
|
||||
//默认值为 target 的单数形态 + 'Id'
|
||||
otherKey?: string;
|
||||
// 默认值为 target model 的主键,一般为 id
|
||||
targetKey?: string;
|
||||
}
|
||||
|
||||
// tags 表主键、posts 表主键和 posts_tags 两个外键相连
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'tags',
|
||||
target: 'tags',
|
||||
through: 'posts_tags', // 中间表
|
||||
foreignKey: 'tagId', // 外键1,在 posts_tags 表里
|
||||
otherKey: 'postId', // 外键2,在 posts_tags 表里
|
||||
targetKey: 'id', // tags 表主键
|
||||
sourceKey: 'id', // posts 表主键
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
1
docs/en-US/development/server/collections/cm.svg
Normal file
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 8.2 KiB |
@ -0,0 +1,82 @@
|
||||
# Collection 模板
|
||||
|
||||
<Alert>
|
||||
📢 Collection 模板计划在 2022 年第四季度提供。
|
||||
</Alert>
|
||||
|
||||
在实际的业务场景中,不同的 collection 可能有自己的初始化规则和业务逻辑,NocoBase 通过提供 Collection 模板来解决这类问题。
|
||||
|
||||
## 常规表
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
}
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 树结构表
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'categories',
|
||||
tree: 'adjacency-list',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'description',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'parent',
|
||||
target: 'categories',
|
||||
foreignKey: 'parentId',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'children',
|
||||
target: 'categories',
|
||||
foreignKey: 'parentId',
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 父子继承表
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'a',
|
||||
fields: [
|
||||
|
||||
],
|
||||
});
|
||||
|
||||
db.collection({
|
||||
name: 'b',
|
||||
inherits: 'a',
|
||||
fields: [
|
||||
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 更多模板
|
||||
|
||||
如日历表,每个初始化的表都需要初始化特殊的 cron 和 exclude 字段,而这种字段的定义就由模板来完成
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'events',
|
||||
template: 'calendar',
|
||||
});
|
||||
```
|
62
docs/en-US/development/server/collections/configure.md
Normal file
@ -0,0 +1,62 @@
|
||||
# 如何配置数据表?
|
||||
|
||||
NocoBase 有三种方式配置数据表:
|
||||
|
||||
<img src="./cm.svg" style="max-width: 800px;" />
|
||||
|
||||
## 通过界面配置数据表
|
||||
|
||||
业务数据一般建议使用界面配置,NocoBase 平台提供了两种界面配置数据表
|
||||
|
||||
### 常规的表格界面
|
||||
|
||||
<img src="./table.jpg" style="max-width: 800px;" />
|
||||
|
||||
### 图形化配置界面
|
||||
|
||||
<img src="./graph.jpg" style="max-width: 800px;" />
|
||||
|
||||
## 在插件代码里定义
|
||||
|
||||
一般用于配置插件功能表或系统配置表,用户可以读写数据,但不能修改表结构。
|
||||
|
||||
```ts
|
||||
export class MyPlugin extends Plugin {
|
||||
load() {
|
||||
this.db.collection();
|
||||
this.db.import();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
相关 API 参考
|
||||
|
||||
- [db.collection()](/api/database#collection)
|
||||
- [db.import()](/api/database#import)
|
||||
|
||||
在插件里配置的 collection,插件激活时自动与数据库同步,生相对应的数据表和字段。
|
||||
|
||||
## 通过 REST API 管理数据表
|
||||
|
||||
第三方还可以通过 HTTP 接口管理数据表(需要开放权限)
|
||||
|
||||
### Collections
|
||||
|
||||
```bash
|
||||
GET /api/collections
|
||||
POST /api/collections
|
||||
GET /api/collections/<collectionName>
|
||||
PUT /api/collections/<collectionName>
|
||||
DELETE /api/collections/<collectionName>
|
||||
```
|
||||
|
||||
### Collection fields
|
||||
|
||||
```bash
|
||||
GET /api/collections/<collectionName>/fields
|
||||
POST /api/collections/<collectionName>/fields
|
||||
GET /api/collections/<collectionName>/fields/<fieldName>
|
||||
PUT /api/collections/<collectionName>/fields/<fieldName>
|
||||
DELETE /api/collections/<collectionName>/fields/<fieldName>
|
||||
```
|
||||
|
39
docs/en-US/development/server/collections/field-extension.md
Normal file
@ -0,0 +1,39 @@
|
||||
# 字段扩展
|
||||
|
||||
在 NocoBase 中 Collection Field 的构成包括:
|
||||
|
||||
<img src="./collection-field.svg" />
|
||||
|
||||
## Field Type 扩展
|
||||
|
||||
例如扩展密码类型字段 `type: 'password'`
|
||||
|
||||
```ts
|
||||
export class MyPlugin extends Plugin {
|
||||
beforeLoad() {
|
||||
this.db.registerFieldTypes({
|
||||
password: PasswordField
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class PasswordField extends Field {
|
||||
get dataType() {
|
||||
return DataTypes.STRING;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [更多内置 field types 的实现点此查看](https://github.com/nocobase/nocobase/tree/main/packages/core/database/src/fields)
|
||||
- 也可以查看完整的 samples 插件 [packages/samples/shop-modeling](https://github.com/nocobase/nocobase/tree/main/packages/samples/shop-modeling)
|
||||
|
||||
## Field Component 扩展
|
||||
|
||||
相关扩展文档查看:
|
||||
|
||||
- [扩展 Schema 组件](/development/client/ui-schema-designer/extending-schema-components)
|
||||
- [Schema 组件库](/development/client/ui-schema-designer/component-library)
|
||||
|
||||
## Field Interface 扩展
|
||||
|
||||
- [内置 field interfaces 点此查看](https://github.com/nocobase/nocobase/tree/main/packages/core/client/src/collection-manager/interfaces)
|
BIN
docs/en-US/development/server/collections/graph.jpg
Normal file
After Width: | Height: | Size: 209 KiB |
194
docs/en-US/development/server/collections/index.md
Normal file
@ -0,0 +1,194 @@
|
||||
# 核心概念
|
||||
|
||||
## Collection
|
||||
|
||||
Collection 是所有种类数据的集合,中文翻译为「数据表」,如订单、商品、用户、评论等都是 Collection,不同 Collection 通过 name 区分,如:
|
||||
|
||||
```ts
|
||||
// 订单
|
||||
{
|
||||
name: 'orders',
|
||||
}
|
||||
// 商品
|
||||
{
|
||||
name: 'products',
|
||||
}
|
||||
// 用户
|
||||
{
|
||||
name: 'users',
|
||||
}
|
||||
// 评论
|
||||
{
|
||||
name: 'comments',
|
||||
}
|
||||
```
|
||||
|
||||
## Collection Field
|
||||
|
||||
每个 Collection 都有若干 Fields。
|
||||
|
||||
```ts
|
||||
// Collection 配置
|
||||
{
|
||||
name: 'users',
|
||||
fields: [
|
||||
{ type: 'string', name: 'name' },
|
||||
{ type: 'integer', name: 'age' },
|
||||
// 其他字段
|
||||
],
|
||||
}
|
||||
// 示例数据
|
||||
[
|
||||
{
|
||||
name: '张三',
|
||||
age: 20,
|
||||
},
|
||||
{
|
||||
name: '李四',
|
||||
age: 18,
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
在 NocoBase 中 Collection Field 的构成包括:
|
||||
|
||||
<img src="./collection-field.svg" />
|
||||
|
||||
### Field Type
|
||||
|
||||
不同字段通过 name 区分,type 表示字段的数据类型,分为 Attribute Type 和 Association Type,如:
|
||||
|
||||
**属性 - Attribute Type**
|
||||
|
||||
- string
|
||||
- text
|
||||
- date
|
||||
- boolean
|
||||
- time
|
||||
- float
|
||||
- json
|
||||
- location
|
||||
- password
|
||||
- virtual
|
||||
- ...
|
||||
|
||||
**关系 - Association Type**
|
||||
|
||||
- hasOne
|
||||
- hasMany
|
||||
- belongsTo
|
||||
- belongsToMany
|
||||
- ...
|
||||
|
||||
### Field Component
|
||||
|
||||
只有数据类型的字段,字段值的 IO 没问题了,但是还不够,如果需要将字段展示在界面上,还需要另一个维度的配置 —— `uiSchema`,如:
|
||||
|
||||
```tsx | pure
|
||||
// 邮箱字段,用 Input 组件展示,使用 email 校验规则
|
||||
{
|
||||
type: 'string',
|
||||
name: 'email',
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': { size: 'large' },
|
||||
'x-validator': 'email',
|
||||
'x-pattern': 'editable', // 可编辑状态,还有 readonly 不可编辑状态、read-pretty 阅读态
|
||||
},
|
||||
}
|
||||
|
||||
// 数据示例
|
||||
{
|
||||
email: 'admin@nocobase.com',
|
||||
}
|
||||
|
||||
// 组件示例
|
||||
<Input name={'email'} size={'large'} value={'admin@nocobase.com'} />
|
||||
```
|
||||
|
||||
uiSchema 用于配置字段展示在界面上的组件,每个字段组件都会对应一个 value,包括几个维护的配置:
|
||||
|
||||
- 字段的组件
|
||||
- 组件的参数
|
||||
- 字段的校验规则
|
||||
- 字段的模式(editable、readonly、read-pretty)
|
||||
- 字段的默认值
|
||||
- 其他
|
||||
|
||||
[更多信息查看 UI Schema 章节](/development/client/ui-schema-designer/what-is-ui-schema)。
|
||||
|
||||
NocoBase 内置的字段组件有:
|
||||
|
||||
- Input
|
||||
- InputNumber
|
||||
- Select
|
||||
- Radio
|
||||
- Checkbox
|
||||
- ...
|
||||
|
||||
### Field Interface
|
||||
|
||||
有了 Field Type 和 Field Component 就可以自由组合出若干字段,我们将这种组合之后的模板称之为 Field Interface,如:
|
||||
|
||||
```ts
|
||||
// 邮箱字段 string + input,email 校验规则
|
||||
{
|
||||
type: 'string',
|
||||
name: 'email',
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'email',
|
||||
},
|
||||
}
|
||||
|
||||
// 手机字段 string + input,phone 校验规则
|
||||
{
|
||||
type: 'string',
|
||||
name: 'phone',
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'phone',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
上面 email 和 phone 每次都需要配置完整的 uiSchema 非常繁琐,为了简化配置,又引申出另一个概念 Field interface,可以将一些参数模板化,如:
|
||||
|
||||
```ts
|
||||
// email 字段的模板
|
||||
interface email {
|
||||
type: 'string';
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'email',
|
||||
};
|
||||
}
|
||||
|
||||
// phone 字段的模板
|
||||
interface phone {
|
||||
type: 'string';
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'phone',
|
||||
};
|
||||
}
|
||||
|
||||
// 简化之后的字段配置
|
||||
// email
|
||||
{
|
||||
interface: 'email',
|
||||
name: 'email',
|
||||
}
|
||||
|
||||
// phone
|
||||
{
|
||||
interface: 'phone',
|
||||
name: 'phone',
|
||||
}
|
||||
```
|
||||
|
||||
[更多 Field Interface 点此查看](https://github.com/nocobase/nocobase/tree/main/packages/core/client/src/collection-manager/interfaces)
|
137
docs/en-US/development/server/collections/options.md
Normal file
@ -0,0 +1,137 @@
|
||||
# Collection 协议
|
||||
|
||||
Collection 是 NocoBase 的中枢,是一种用于描述数据结构(数据表和字段)的协议,和关系型数据库的概念非常接近,但不仅限于关系型数据库,也可以是 NoSQL 数据库、HTTP API 等数据源。
|
||||
|
||||
<img src="./schema.svg" style="max-width: 800px;" >
|
||||
|
||||
现阶段基于 Collection 协议实现了关系型数据库的对接(db.collections),NoSQL 数据库、HTTP API 等数据源在未来也会逐步实现。
|
||||
|
||||
Collection 协议主要包括 CollectionOptions 和 FieldOptions 两部分,因为 Field 是可扩展的,所以 FieldOptions 的参数非常灵活。
|
||||
|
||||
## CollectionOptions
|
||||
|
||||
```ts
|
||||
interface CollectionOptions {
|
||||
name: string;
|
||||
title?: string;
|
||||
// 树结构表,TreeRepository
|
||||
tree?: 'adjacency-list' | 'closure-table' | 'materialized-path' | 'nested-set';
|
||||
// 父子继承
|
||||
inherits?: string | string[];
|
||||
fields?: FieldOptions[];
|
||||
timestamps?: boolean;
|
||||
paranoid?: boolean;
|
||||
sortable?: CollectionSortable;
|
||||
model?: string;
|
||||
repository?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
type CollectionSortable = string | boolean | { name?: string; scopeKey?: string };
|
||||
```
|
||||
|
||||
## FieldOptions
|
||||
|
||||
通用的字段参数
|
||||
|
||||
```ts
|
||||
interface FieldOptions {
|
||||
name: string;
|
||||
type: string;
|
||||
hidden?: boolean;
|
||||
index?: boolean;
|
||||
interface?: string;
|
||||
uiSchema?: ISchema;
|
||||
```
|
||||
|
||||
[UI Schema 的介绍点此查看](/development/client/ui-schema-designer/what-is-ui-schema)
|
||||
|
||||
### Field Type
|
||||
|
||||
Field Type 包括 Attribute Type 和 Association Type 两类:
|
||||
|
||||
**Attribute Type**
|
||||
|
||||
- 'boolean'
|
||||
- 'integer'
|
||||
- 'bigInt'
|
||||
- 'double'
|
||||
- 'real'
|
||||
- 'decimal'
|
||||
- 'string'
|
||||
- 'text'
|
||||
- 'password'
|
||||
- 'date'
|
||||
- 'time'
|
||||
- 'array'
|
||||
- 'json'
|
||||
- 'jsonb'
|
||||
- 'uuid'
|
||||
- 'uid'
|
||||
- 'formula'
|
||||
- 'radio'
|
||||
- 'sort'
|
||||
- 'virtual'
|
||||
|
||||
**Association Type**
|
||||
|
||||
- 'belongsTo'
|
||||
- 'hasOne'
|
||||
- 'hasMany'
|
||||
- 'belongsToMany'
|
||||
|
||||
### Field Interface
|
||||
|
||||
**Basic**
|
||||
|
||||
- input
|
||||
- textarea
|
||||
- phone
|
||||
- email
|
||||
- integer
|
||||
- number
|
||||
- percent
|
||||
- password
|
||||
- icon
|
||||
|
||||
**Choices**
|
||||
|
||||
- checkbox
|
||||
- select
|
||||
- multipleSelect
|
||||
- radioGroup
|
||||
- checkboxGroup
|
||||
- chinaRegion
|
||||
|
||||
**Media**
|
||||
|
||||
- attachment
|
||||
- markdown
|
||||
- richText
|
||||
|
||||
**Date & Time**
|
||||
|
||||
- datetime
|
||||
- time
|
||||
|
||||
**Relation**
|
||||
|
||||
- linkTo - `type: 'belongsToMany'`
|
||||
- oho - `type: 'hasOne'`
|
||||
- obo - `type: 'belongsTo'`
|
||||
- o2m - `type: 'hasMany'`
|
||||
- m2o - `type: 'belongsTo'`
|
||||
- m2m - `type: 'belongsToMany'`
|
||||
|
||||
**Advanced**
|
||||
|
||||
- formula
|
||||
- sequence
|
||||
|
||||
**System info**
|
||||
|
||||
- id
|
||||
- createdAt
|
||||
- createdBy
|
||||
- updatedAt
|
||||
- updatedBy
|
1
docs/en-US/development/server/collections/schema.svg
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
docs/en-US/development/server/collections/table.jpg
Normal file
After Width: | Height: | Size: 271 KiB |
@ -20,13 +20,10 @@ import { InstallOptions, Plugin } from '@nocobase/server';
|
||||
export class MyPlugin extends Plugin {
|
||||
afterAdd() {
|
||||
// 插件 pm.add 注册进来之后,主要用于放置 app beforeLoad 事件的监听
|
||||
this.app.on('beforeLoad');
|
||||
}
|
||||
beforeLoad() {
|
||||
// 自定义类或方法
|
||||
this.db.registerFields();
|
||||
this.db.registerFields();
|
||||
this.db.registerFields();
|
||||
this.db.registerFields();
|
||||
this.db.registerFieldTypes()
|
||||
this.db.registerModels()
|
||||
this.db.registerRepositories()
|
||||
|
@ -116,7 +116,20 @@ export default {
|
||||
type: 'group',
|
||||
children: [
|
||||
'/development/server/index',
|
||||
'/development/server/collections-fields',
|
||||
{
|
||||
title: 'Collections & Fields',
|
||||
'title.zh-CN': '数据表和字段',
|
||||
type: 'subMenu',
|
||||
children: [
|
||||
'/development/server/collections/index',
|
||||
'/development/server/collections/options',
|
||||
'/development/server/collections/configure',
|
||||
'/development/server/collections/association-fields',
|
||||
'/development/server/collections/field-extension',
|
||||
'/development/server/collections/collection-template',
|
||||
],
|
||||
},
|
||||
// '/development/server/collections-fields',
|
||||
'/development/server/resources-actions',
|
||||
'/development/server/middleware',
|
||||
'/development/server/commands',
|
||||
|
153
docs/zh-CN/development/server/collections/association-fields.md
Normal file
@ -0,0 +1,153 @@
|
||||
# 关系字段配置
|
||||
|
||||
在关系数据库里,标准的建表关系的方式是添加一个外键字段,然后设置上个外键约束。例如 Knex 建表的例子:
|
||||
|
||||
```ts
|
||||
knex.schema.table('posts', function (table) {
|
||||
table.integer('userId').unsigned();
|
||||
table.foreign('userId').references('users.id');
|
||||
});
|
||||
```
|
||||
|
||||
这个过程会在 posts 表里创建一个 userId 字段,并且设置上外键约束 posts.userId 引用 users.id。而在 NocoBase 的 Collection 中,是通过配置关系字段来建立上这样一种关系约束,如:
|
||||
|
||||
```ts
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'user',
|
||||
target: 'users',
|
||||
foreignKey: 'userId',
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## 关系参数说明
|
||||
|
||||
### BelongsTo
|
||||
|
||||
```ts
|
||||
interface BelongsTo {
|
||||
type: 'belongsTo';
|
||||
name: string;
|
||||
// 默认值为 name 复数
|
||||
target?: string;
|
||||
// 默认值为 target model 的主键,一般为 'id'
|
||||
targetKey?: any;
|
||||
// 默认值为 target + 'Id'
|
||||
foreignKey?: any;
|
||||
}
|
||||
|
||||
// authors 表主键 id 和 books 表外键 authorId 相连
|
||||
{
|
||||
name: 'books',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'author',
|
||||
target: 'authors',
|
||||
targetKey: 'id', // authors 表主键
|
||||
foreignKey: 'authorId', // 外键在 books 表
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### HasOne
|
||||
|
||||
```ts
|
||||
interface HasOne {
|
||||
type: 'hasOne';
|
||||
name: string;
|
||||
// 默认值为 name 复数
|
||||
target?: string;
|
||||
// 默认值为 source model 的主键,一般为 'id'
|
||||
sourceKey?: string;
|
||||
// 默认值为 source collection name 的单数形态 + 'Id'
|
||||
foreignKey?: string;
|
||||
}
|
||||
|
||||
// users 表主键 id 和 profiles 外键 userId 相连
|
||||
{
|
||||
name: 'users',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasOne',
|
||||
name: 'profile',
|
||||
target: 'profiles',
|
||||
sourceKey: 'id', // users 表主键
|
||||
foreignKey: 'userId', // 外键在 profiles 表
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### HasMany
|
||||
|
||||
```ts
|
||||
interface HasMany {
|
||||
type: 'hasMany';
|
||||
name: string;
|
||||
// 默认值为 name
|
||||
target?: string;
|
||||
// 默认值为 source model 的主键,一般为 'id'
|
||||
sourceKey?: string;
|
||||
// 默认值为 source collection name 的单数形态 + 'Id'
|
||||
foreignKey?: string;
|
||||
}
|
||||
|
||||
// posts 表主键 id 和 comments 表 postId 相连
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'comments',
|
||||
target: 'comments',
|
||||
sourceKey: 'id', // posts 表主键
|
||||
foreignKey: 'postId', // 外键在 comments 表
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### BelongsToMany
|
||||
|
||||
```ts
|
||||
interface BelongsToMany {
|
||||
type: 'belongsToMany';
|
||||
name: string;
|
||||
// 默认值为 name
|
||||
target?: string;
|
||||
// 默认值为 source collection name 和 target 的首字母自然顺序拼接的字符串
|
||||
through?: string;
|
||||
//默认值为 source collection name 的单数形态 + 'Id'
|
||||
foreignKey?: string;
|
||||
// 默认值为 source model 的主键,一般为 id
|
||||
sourceKey?: string;
|
||||
//默认值为 target 的单数形态 + 'Id'
|
||||
otherKey?: string;
|
||||
// 默认值为 target model 的主键,一般为 id
|
||||
targetKey?: string;
|
||||
}
|
||||
|
||||
// tags 表主键、posts 表主键和 posts_tags 两个外键相连
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'tags',
|
||||
target: 'tags',
|
||||
through: 'posts_tags', // 中间表
|
||||
foreignKey: 'tagId', // 外键1,在 posts_tags 表里
|
||||
otherKey: 'postId', // 外键2,在 posts_tags 表里
|
||||
targetKey: 'id', // tags 表主键
|
||||
sourceKey: 'id', // posts 表主键
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
1
docs/zh-CN/development/server/collections/cm.svg
Normal file
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 8.2 KiB |
@ -0,0 +1,82 @@
|
||||
# Collection 模板
|
||||
|
||||
<Alert>
|
||||
📢 Collection 模板计划在 2022 年第四季度提供。
|
||||
</Alert>
|
||||
|
||||
在实际的业务场景中,不同的 collection 可能有自己的初始化规则和业务逻辑,NocoBase 通过提供 Collection 模板来解决这类问题。
|
||||
|
||||
## 常规表
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
}
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 树结构表
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'categories',
|
||||
tree: 'adjacency-list',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'description',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'parent',
|
||||
target: 'categories',
|
||||
foreignKey: 'parentId',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'children',
|
||||
target: 'categories',
|
||||
foreignKey: 'parentId',
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 父子继承表
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'a',
|
||||
fields: [
|
||||
|
||||
],
|
||||
});
|
||||
|
||||
db.collection({
|
||||
name: 'b',
|
||||
inherits: 'a',
|
||||
fields: [
|
||||
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 更多模板
|
||||
|
||||
如日历表,每个初始化的表都需要初始化特殊的 cron 和 exclude 字段,而这种字段的定义就由模板来完成
|
||||
|
||||
```ts
|
||||
db.collection({
|
||||
name: 'events',
|
||||
template: 'calendar',
|
||||
});
|
||||
```
|
62
docs/zh-CN/development/server/collections/configure.md
Normal file
@ -0,0 +1,62 @@
|
||||
# 如何配置数据表?
|
||||
|
||||
NocoBase 有三种方式配置数据表:
|
||||
|
||||
<img src="./cm.svg" style="max-width: 800px;" />
|
||||
|
||||
## 通过界面配置数据表
|
||||
|
||||
业务数据一般建议使用界面配置,NocoBase 平台提供了两种界面配置数据表
|
||||
|
||||
### 常规的表格界面
|
||||
|
||||
<img src="./table.jpg" style="max-width: 800px;" />
|
||||
|
||||
### 图形化配置界面
|
||||
|
||||
<img src="./graph.jpg" style="max-width: 800px;" />
|
||||
|
||||
## 在插件代码里定义
|
||||
|
||||
一般用于配置插件功能表或系统配置表,用户可以读写数据,但不能修改表结构。
|
||||
|
||||
```ts
|
||||
export class MyPlugin extends Plugin {
|
||||
load() {
|
||||
this.db.collection();
|
||||
this.db.import();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
相关 API 参考
|
||||
|
||||
- [db.collection()](/api/database#collection)
|
||||
- [db.import()](/api/database#import)
|
||||
|
||||
在插件里配置的 collection,插件激活时自动与数据库同步,生相对应的数据表和字段。
|
||||
|
||||
## 通过 REST API 管理数据表
|
||||
|
||||
第三方还可以通过 HTTP 接口管理数据表(需要开放权限)
|
||||
|
||||
### Collections
|
||||
|
||||
```bash
|
||||
GET /api/collections
|
||||
POST /api/collections
|
||||
GET /api/collections/<collectionName>
|
||||
PUT /api/collections/<collectionName>
|
||||
DELETE /api/collections/<collectionName>
|
||||
```
|
||||
|
||||
### Collection fields
|
||||
|
||||
```bash
|
||||
GET /api/collections/<collectionName>/fields
|
||||
POST /api/collections/<collectionName>/fields
|
||||
GET /api/collections/<collectionName>/fields/<fieldName>
|
||||
PUT /api/collections/<collectionName>/fields/<fieldName>
|
||||
DELETE /api/collections/<collectionName>/fields/<fieldName>
|
||||
```
|
||||
|
39
docs/zh-CN/development/server/collections/field-extension.md
Normal file
@ -0,0 +1,39 @@
|
||||
# 字段扩展
|
||||
|
||||
在 NocoBase 中 Collection Field 的构成包括:
|
||||
|
||||
<img src="./collection-field.svg" />
|
||||
|
||||
## Field Type 扩展
|
||||
|
||||
例如扩展密码类型字段 `type: 'password'`
|
||||
|
||||
```ts
|
||||
export class MyPlugin extends Plugin {
|
||||
beforeLoad() {
|
||||
this.db.registerFieldTypes({
|
||||
password: PasswordField
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class PasswordField extends Field {
|
||||
get dataType() {
|
||||
return DataTypes.STRING;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [更多内置 field types 的实现点此查看](https://github.com/nocobase/nocobase/tree/main/packages/core/database/src/fields)
|
||||
- 也可以查看完整的 samples 插件 [packages/samples/shop-modeling](https://github.com/nocobase/nocobase/tree/main/packages/samples/shop-modeling)
|
||||
|
||||
## Field Component 扩展
|
||||
|
||||
相关扩展文档查看:
|
||||
|
||||
- [扩展 Schema 组件](/development/client/ui-schema-designer/extending-schema-components)
|
||||
- [Schema 组件库](/development/client/ui-schema-designer/component-library)
|
||||
|
||||
## Field Interface 扩展
|
||||
|
||||
- [内置 field interfaces 点此查看](https://github.com/nocobase/nocobase/tree/main/packages/core/client/src/collection-manager/interfaces)
|
BIN
docs/zh-CN/development/server/collections/graph.jpg
Normal file
After Width: | Height: | Size: 209 KiB |
194
docs/zh-CN/development/server/collections/index.md
Normal file
@ -0,0 +1,194 @@
|
||||
# 核心概念
|
||||
|
||||
## Collection
|
||||
|
||||
Collection 是所有种类数据的集合,中文翻译为「数据表」,如订单、商品、用户、评论等都是 Collection,不同 Collection 通过 name 区分,如:
|
||||
|
||||
```ts
|
||||
// 订单
|
||||
{
|
||||
name: 'orders',
|
||||
}
|
||||
// 商品
|
||||
{
|
||||
name: 'products',
|
||||
}
|
||||
// 用户
|
||||
{
|
||||
name: 'users',
|
||||
}
|
||||
// 评论
|
||||
{
|
||||
name: 'comments',
|
||||
}
|
||||
```
|
||||
|
||||
## Collection Field
|
||||
|
||||
每个 Collection 都有若干 Fields。
|
||||
|
||||
```ts
|
||||
// Collection 配置
|
||||
{
|
||||
name: 'users',
|
||||
fields: [
|
||||
{ type: 'string', name: 'name' },
|
||||
{ type: 'integer', name: 'age' },
|
||||
// 其他字段
|
||||
],
|
||||
}
|
||||
// 示例数据
|
||||
[
|
||||
{
|
||||
name: '张三',
|
||||
age: 20,
|
||||
},
|
||||
{
|
||||
name: '李四',
|
||||
age: 18,
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
在 NocoBase 中 Collection Field 的构成包括:
|
||||
|
||||
<img src="./collection-field.svg" />
|
||||
|
||||
### Field Type
|
||||
|
||||
不同字段通过 name 区分,type 表示字段的数据类型,分为 Attribute Type 和 Association Type,如:
|
||||
|
||||
**属性 - Attribute Type**
|
||||
|
||||
- string
|
||||
- text
|
||||
- date
|
||||
- boolean
|
||||
- time
|
||||
- float
|
||||
- json
|
||||
- location
|
||||
- password
|
||||
- virtual
|
||||
- ...
|
||||
|
||||
**关系 - Association Type**
|
||||
|
||||
- hasOne
|
||||
- hasMany
|
||||
- belongsTo
|
||||
- belongsToMany
|
||||
- ...
|
||||
|
||||
### Field Component
|
||||
|
||||
只有数据类型的字段,字段值的 IO 没问题了,但是还不够,如果需要将字段展示在界面上,还需要另一个维度的配置 —— `uiSchema`,如:
|
||||
|
||||
```tsx | pure
|
||||
// 邮箱字段,用 Input 组件展示,使用 email 校验规则
|
||||
{
|
||||
type: 'string',
|
||||
name: 'email',
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': { size: 'large' },
|
||||
'x-validator': 'email',
|
||||
'x-pattern': 'editable', // 可编辑状态,还有 readonly 不可编辑状态、read-pretty 阅读态
|
||||
},
|
||||
}
|
||||
|
||||
// 数据示例
|
||||
{
|
||||
email: 'admin@nocobase.com',
|
||||
}
|
||||
|
||||
// 组件示例
|
||||
<Input name={'email'} size={'large'} value={'admin@nocobase.com'} />
|
||||
```
|
||||
|
||||
uiSchema 用于配置字段展示在界面上的组件,每个字段组件都会对应一个 value,包括几个维护的配置:
|
||||
|
||||
- 字段的组件
|
||||
- 组件的参数
|
||||
- 字段的校验规则
|
||||
- 字段的模式(editable、readonly、read-pretty)
|
||||
- 字段的默认值
|
||||
- 其他
|
||||
|
||||
[更多信息查看 UI Schema 章节](/development/client/ui-schema-designer/what-is-ui-schema)。
|
||||
|
||||
NocoBase 内置的字段组件有:
|
||||
|
||||
- Input
|
||||
- InputNumber
|
||||
- Select
|
||||
- Radio
|
||||
- Checkbox
|
||||
- ...
|
||||
|
||||
### Field Interface
|
||||
|
||||
有了 Field Type 和 Field Component 就可以自由组合出若干字段,我们将这种组合之后的模板称之为 Field Interface,如:
|
||||
|
||||
```ts
|
||||
// 邮箱字段 string + input,email 校验规则
|
||||
{
|
||||
type: 'string',
|
||||
name: 'email',
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'email',
|
||||
},
|
||||
}
|
||||
|
||||
// 手机字段 string + input,phone 校验规则
|
||||
{
|
||||
type: 'string',
|
||||
name: 'phone',
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'phone',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
上面 email 和 phone 每次都需要配置完整的 uiSchema 非常繁琐,为了简化配置,又引申出另一个概念 Field interface,可以将一些参数模板化,如:
|
||||
|
||||
```ts
|
||||
// email 字段的模板
|
||||
interface email {
|
||||
type: 'string';
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'email',
|
||||
};
|
||||
}
|
||||
|
||||
// phone 字段的模板
|
||||
interface phone {
|
||||
type: 'string';
|
||||
uiSchema: {
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-validator': 'phone',
|
||||
};
|
||||
}
|
||||
|
||||
// 简化之后的字段配置
|
||||
// email
|
||||
{
|
||||
interface: 'email',
|
||||
name: 'email',
|
||||
}
|
||||
|
||||
// phone
|
||||
{
|
||||
interface: 'phone',
|
||||
name: 'phone',
|
||||
}
|
||||
```
|
||||
|
||||
[更多 Field Interface 点此查看](https://github.com/nocobase/nocobase/tree/main/packages/core/client/src/collection-manager/interfaces)
|
137
docs/zh-CN/development/server/collections/options.md
Normal file
@ -0,0 +1,137 @@
|
||||
# Collection 协议
|
||||
|
||||
Collection 是 NocoBase 的中枢,是一种用于描述数据结构(数据表和字段)的协议,和关系型数据库的概念非常接近,但不仅限于关系型数据库,也可以是 NoSQL 数据库、HTTP API 等数据源。
|
||||
|
||||
<img src="./schema.svg" style="max-width: 800px;" >
|
||||
|
||||
现阶段基于 Collection 协议实现了关系型数据库的对接(db.collections),NoSQL 数据库、HTTP API 等数据源在未来也会逐步实现。
|
||||
|
||||
Collection 协议主要包括 CollectionOptions 和 FieldOptions 两部分,因为 Field 是可扩展的,所以 FieldOptions 的参数非常灵活。
|
||||
|
||||
## CollectionOptions
|
||||
|
||||
```ts
|
||||
interface CollectionOptions {
|
||||
name: string;
|
||||
title?: string;
|
||||
// 树结构表,TreeRepository
|
||||
tree?: 'adjacency-list' | 'closure-table' | 'materialized-path' | 'nested-set';
|
||||
// 父子继承
|
||||
inherits?: string | string[];
|
||||
fields?: FieldOptions[];
|
||||
timestamps?: boolean;
|
||||
paranoid?: boolean;
|
||||
sortable?: CollectionSortable;
|
||||
model?: string;
|
||||
repository?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
type CollectionSortable = string | boolean | { name?: string; scopeKey?: string };
|
||||
```
|
||||
|
||||
## FieldOptions
|
||||
|
||||
通用的字段参数
|
||||
|
||||
```ts
|
||||
interface FieldOptions {
|
||||
name: string;
|
||||
type: string;
|
||||
hidden?: boolean;
|
||||
index?: boolean;
|
||||
interface?: string;
|
||||
uiSchema?: ISchema;
|
||||
```
|
||||
|
||||
[UI Schema 的介绍点此查看](/development/client/ui-schema-designer/what-is-ui-schema)
|
||||
|
||||
### Field Type
|
||||
|
||||
Field Type 包括 Attribute Type 和 Association Type 两类:
|
||||
|
||||
**Attribute Type**
|
||||
|
||||
- 'boolean'
|
||||
- 'integer'
|
||||
- 'bigInt'
|
||||
- 'double'
|
||||
- 'real'
|
||||
- 'decimal'
|
||||
- 'string'
|
||||
- 'text'
|
||||
- 'password'
|
||||
- 'date'
|
||||
- 'time'
|
||||
- 'array'
|
||||
- 'json'
|
||||
- 'jsonb'
|
||||
- 'uuid'
|
||||
- 'uid'
|
||||
- 'formula'
|
||||
- 'radio'
|
||||
- 'sort'
|
||||
- 'virtual'
|
||||
|
||||
**Association Type**
|
||||
|
||||
- 'belongsTo'
|
||||
- 'hasOne'
|
||||
- 'hasMany'
|
||||
- 'belongsToMany'
|
||||
|
||||
### Field Interface
|
||||
|
||||
**Basic**
|
||||
|
||||
- input
|
||||
- textarea
|
||||
- phone
|
||||
- email
|
||||
- integer
|
||||
- number
|
||||
- percent
|
||||
- password
|
||||
- icon
|
||||
|
||||
**Choices**
|
||||
|
||||
- checkbox
|
||||
- select
|
||||
- multipleSelect
|
||||
- radioGroup
|
||||
- checkboxGroup
|
||||
- chinaRegion
|
||||
|
||||
**Media**
|
||||
|
||||
- attachment
|
||||
- markdown
|
||||
- richText
|
||||
|
||||
**Date & Time**
|
||||
|
||||
- datetime
|
||||
- time
|
||||
|
||||
**Relation**
|
||||
|
||||
- linkTo - `type: 'belongsToMany'`
|
||||
- oho - `type: 'hasOne'`
|
||||
- obo - `type: 'belongsTo'`
|
||||
- o2m - `type: 'hasMany'`
|
||||
- m2o - `type: 'belongsTo'`
|
||||
- m2m - `type: 'belongsToMany'`
|
||||
|
||||
**Advanced**
|
||||
|
||||
- formula
|
||||
- sequence
|
||||
|
||||
**System info**
|
||||
|
||||
- id
|
||||
- createdAt
|
||||
- createdBy
|
||||
- updatedAt
|
||||
- updatedBy
|
1
docs/zh-CN/development/server/collections/schema.svg
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
docs/zh-CN/development/server/collections/table.jpg
Normal file
After Width: | Height: | Size: 271 KiB |
@ -20,13 +20,10 @@ import { InstallOptions, Plugin } from '@nocobase/server';
|
||||
export class MyPlugin extends Plugin {
|
||||
afterAdd() {
|
||||
// 插件 pm.add 注册进来之后,主要用于放置 app beforeLoad 事件的监听
|
||||
this.app.on('beforeLoad');
|
||||
}
|
||||
beforeLoad() {
|
||||
// 自定义类或方法
|
||||
this.db.registerFields();
|
||||
this.db.registerFields();
|
||||
this.db.registerFields();
|
||||
this.db.registerFields();
|
||||
this.db.registerFieldTypes()
|
||||
this.db.registerModels()
|
||||
this.db.registerRepositories()
|
||||
|