Giter VIP home page Giter VIP logo

sula's Introduction

简体中文 | English

sula (beta)

Sula 当前还处于 beta 社区内测阶段,建议在对内生产项目使用,对外生产项目暂时不要使用。

旧文档地址

里程碑

非常抱歉,由于最近业务爆发导致没有按照既定里程碑发布 sula 1.0 和 builder,我们根据目前看到业务排期修改里程碑,如下,

  • 10月30日:发布 1.0 正式版,以及配套文档
  • 11月6日:开源 Sula Builder 前端部分(后端部分还无法给出准确时间点)

codecov GitHub Actions status npm npm

特点

  • 💻 产品级配置,sula 通过行为链管理实现了渲染组件与用户行为的连接,实现了行为配置,极大扩展了配置范围。
  • 🌴 语义化,通过渲染插件与行为插件的组合,一段段配置可以语义化的描述UI呈现及用户行为动作。
  • 🚀 开发提效,sula 提供 4 大配置模板,可以满足80%以上的中台场景,提效明显。
  • 🔌 高扩展性,sula 通过 ctx 实现了插件与核心组件的通信,配置规则灵活且易于扩展。
  • 📦 开箱即用,sula 内置请求插件与灵活扩展点、国际化,路由等能力,让开发者更加专注核心功能的开发。
  • 📀 自动 loading,sula 不侵入式帮助用户完成按钮、超链接、图标点击过程的 loading 管理。

📺 视频教程

🔥 Sula 可视化搭建平台(尝鲜版)

🍳 Sula 在线配置化工具

仅通过 JSON 配置就可以完成整个项目的「产品级配置」。

🥗 Real Sula

sula-real 是面向 admin 中台应用场景的 low pro code 解决方案,预览地址

🍙 例子

📦 安装

npm i sula --save

🔨 用法

import { Form, Table, CreateForm, QueryTable, StepForm, StepQueryTable } from 'sula';

📋 待完成

  • umi-plugin-sula
  • 最终的模板设计
  • 更好的 typescript 支持
  • 文档

🔗 友情链接

讨论群

sula's People

Contributors

dpzxsm avatar evan-lin9 avatar haolic avatar jiyingzhi avatar kang-chen-20230331 avatar rodchen-king avatar vuquangthinh avatar xieyx avatar xz8la8 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sula's Issues

RFC - 请求规范

当前 sula fetch 是基于 axios 的封装。

sula 针对数据返回阶段添加了各种钩子,这些钩子都是基于后端业务级响应格式的,这些钩子分为两类handleradapter,你可以通过全局设置和局部设置两种方式来使用他们。

同时fetch还有两个插件(符合sula插件规范)扩展点,

  • convertParams 请求参数转换
  • converter 响应数据转换

钩子

handler

handler的主要职责是做出行为处理,

  • bizRedirectHandler 业务重定向
  • bizNotifyHandler 成功/错误信息提示

adapter

针对后端业务级响应数据进行转换供handler以及业务模块的消费。

  • bizDevErrorAdapter 开发阶段错误数据转换(供开发人员查看)
  • bizErrorMessageAdapter 用户错误信息转换(用户查看,例如邮箱已注册等)
  • bizSuccessMessageAdapter 成功信息转换
  • bizDataAdapter 调用fetch侧所需要的最终字段对应数据

示例

// global.js  (umi) 
import FetchPlugin from '@sula/plugin-fetch';
// 全局配置
FetchPlugin.use({
  bizRedirectHandler(response) {
    const { data, code } = response;
    if (Number(code) === 302 && data) {
      window.location.href = data;
    }
    return response;
  }
})

// 针对某个url的配置
FetchPlugin.use('/task/v1/info', {
  bizRedirectHandler(response) {
    const { data, code } = response;
    if (Number(code) === 302 && data) {
      window.location.href = data;
    }
    return response;
  }
})

插件

convertParams

const config = {
  type: 'fetch',
  url: '/api/info.json',
  method: 'GET',
  params: {
    name: 'sula'
  },
  convertParams: ({params}) => {
    return {
	  ...params,
	  category: 'fruit',
	}
  },
  // 也支持数组,前一个的转换params会传入下一个
   convertParams: [({params}) => {
    return {
	  ...params,
	  category: 'fruit',
	}
  }, 'uniformTransform'] // 采用插件名称
}

converter

const config = {
  type: 'fetch',
  url: '/api/info.json',
  method: 'GET',
  params: {
    name: 'sula'
  },
  converter: ({data}) => {
    return {
	  ...data,
	  area: 'apple',
	}
  },
  // 同convertParams,也支持数组格式
}

其他

errorMessage

类型:boolean | string;

  • false(默认)不会按照bizSuccessMessageAdapter去取错误信息提示
  • true 按照bizSuccessMessageAdapter去取错误信息提示
  • 成功提示信息(string)自定义成功提示信息

successMessage

类型:boolean | string;

  • false(默认)不会按照bizErrorMessageAdapter去取错误信息提示
  • true 按照bizErrorMessageAdapter去取错误信息提示
  • 错误提示信息(string)自定义错误提示信息

Question: 有基于sula的表单设计器案例么?

Question

想弄一个表单设计器,需要满足下面的需求

1、使用react-dnd拖拽(或者其他)
2、基于sula完成渲染表单
3、表单元素校验(支持单个校验或多个元素关联校验)
4、自定义组件 :查询框(点击Input弹出modal,选中记录 回填数据),table等
5、等等。。

另外:sula和formily的设计思路,覆盖的场景的区别?

Description

大致效果如下:

image

Feature: Reduce the bundle output size

Description

Currently, Sula + AntD + dependencies (lodash, moment, axios etc.) are coming up to 1.4MB bundle size in production mode. This is large and preferable to reduce it as much as possible.

Solution

  • There seems to be individual UI components such as rc-menu (35KB), rc-select (34KB), rc-field-form (31KB) etc. that are being used in addition to AntD. Not sure if this duplication is required. It would be great if all these rc-* components could be replaced with just AntD components, since AntD is anyway being used for the rest. Also, just 35KB for menu (rc-menu), or 34KB for select (rc-select) etc. sounds lot of wasteful size.
  • Not sure if axios (12.47Kb) is a required dependency for sula core functionality? Can it be made a peer-dependency (optional by the user)?
  • moment (57.62KB) probably need to be replaced with day.js
  • lodash (26.39KB) not sure how to reduce it - probably most of these used methods are already supported by ES6 natively? For example, assign, isArray etc. are natively supported by JS and utilizing them will reduce the additional dependency.

image

Bug: request插件期望可以完全自定义

request插件期望可以完全自定义

Description

1.一个表单配置了N个下拉选择框 都是远程数据,其中可能有大部分是重复的数据源
2.保存的axios想使用系统里面自定义好的axios实例(已经定义了拦截器、响应器不想再在sula中再写一次)

Solution

是否可以提供一个扩展 传递一个axios实例,完成替换掉sula的axios;
这样重复的字典数据请求,授权的拦截、响应的拦截 在系统层面可以保存一致

Question: 请问一下, sula 是否支持我自己写一个上一页 下一页, 不带total 这种分页

Question

请问一下, sula 是否支持我自己写一个上一页 下一页, 不带total 这种分页

Description

业务场景: 由于后端大部份 是通过mysql 来存储, 有的时候考虑到mysql select count(*) 的性能问题, 我们是不给前端返回分页总数的, 但是sula 目前的分页组件,好像需要返回总数才可以使用, 所以请问一下, 我们如何自定义这种分页组件,给官方提pr ?

Feature: 表单和表格或许可以共用fields 列表

 const config = {
   fields: [
     {
       name: 'name',
       label: 'Name',
       field: 'input',
       show: true,
       editable:true,
       search:true
     }, {
       name: 'name2',
       label: 'Name2',
       field: 'input',
      editable:true,
}
]}

这里show表示可以显示在表格中, editable表示可以显示在表单中可编辑,search表示可以作为表单查询

Feature: Dynamic Imports, CDN / External scripts import in browser

Description

Currently the antd, react, eCharts etc. are hard-linked into the package, making the produced bundle size large. Please consider

  • enabling dynamic imports
  • allowing external libraries to be loaded from CDN also

This will reduce the bundle size, and webpack compile times will be small.

Solution

UMI documentation allows to use external scripts such as:

  scripts: process.env.NODE_ENV === 'development' ? [
    'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.development.js',
    'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.development.js',
  ] : [
    'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.production.min.js',
    'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.production.min.js',
  ],

But in the code, in many places, the packages are hard coded as:

import React from 'react';
import { Form as AForm } from 'antd';

It would be great if the code loads such third party packages

  1. dynamically, load on demand (Ref: https://umijs.org/docs/load-on-demand#load-component-on-demand )
  2. check if the package is already loaded externally first. If not do the import.
    • For example, do the import only if window.React is not already available. If already available, use it, instead of importing

RFC - Form 配置组件

Form 配置组件(Sula-Form)为表单插件(Field Plugin)的宿主配置组件,扮演了向表单插件提供 ctx 的角色;另一方面对 antd-form v4 的实例 API 进行了扩充与改写(支持表单关联)以及其他功能性扩充。

表单与分组配置

配置A

const config = {
  container: {
    // 分组 group
    type: 'card',
    props: {
      title: 'Head',
    },
  },
  fields: [
    {
      name: 'input',
      field: {
        type: 'input',
        props: {
          placeholder: 'i am input',
        },
      },
    },
    {
      name: 'select',
      field: {
        type: 'select',
        props: {
          placeholder: 'i am select',
        },
      },
    },
    {
      // 嵌套
      container: {
        type: 'card',
        props: {
          title: 'Inner Head',
        },
      },
      fields: [
        {
          name: 'innerInput',
          field: 'input',
        },
      ],
    },
  ],
};

<Form {...config} />;

Form

Form可以理解为是 antd form的载体,将antd form的配置属性放入React Context中,供Field与FieldGroup组件使用,施加在 Form 上的 containerField 配置并不被 Form直接消费,而是转交给 FieldGroupField 组件消费

配置与组件映射

为了支持分组(Group)与表单(Field)更灵活的布局,配置可以映射为对应组件

Field

const config = {
  name: 'input',
  field: {
    type: 'select',
  }
}

return <Field {...config} />

FieldGroup

const config = {
  container: {
    type: 'card',
    props: { title: 'Head' }
  },
  fields: [{
     name: 'input',
     field: {
       type: 'select',
     }
  }]
}

return <FieldGroup {...config} />

因此对于最上面的配置A可以映射为多种形式

形式1

const config = {...};
<Form>
   <FieldGroup {...config} />
 </Form>

形式2

<Form>
    <FieldGroup container={{type: 'card', props: {title: 'Head'}}}>
	    <Field name="input" label="Input" field={{type: 'input', props: {placeholder: "i am input"}}} />
	    <Field name="select" label="Select" field={{type: 'select', props: {placeholder: "i am select"}}} />
	    <FieldGroup container={{type: 'card', props: {title: 'Inner Head'}}}>
		    <Field name="innerInput" field={{type: 'input'}}/>
		</FieldGroup>
    </FieldGroup>
 </Form>

表单行为 - actionsRender

const config = {
  actionsPosition: 'bottom', // 'default' / 'center' / 'right'
  actionsRender: [
    {
      type: 'button',
      props: {
        children: 'Submit',
        type: 'primary',
      },
      action: 'validateFields',
    },
  ],
};

Field扩展

对应and Form.Item, 扩展属性

  • noCollect 不参加 validateFields / validateGroupFields

实例API

sula form 对 antd form 进行了实例API与扩展,

扩展部分

  • setFieldValue 会触发表单关联

  • setFieldSource

  • setFieldVisible

  • setFieldDisabled

  • getFieldValue

  • getFieldSource

  • getFieldVisible

  • getFieldDisabled

  • validateGroupFields

重写部分

  • setFieldsValue 结果与 antd form 一致,会触发表单关联
  • setFields 结果与 antd form 一致,如果设置了值会触发表单关联
  • validateFields 默认行为 field 或者所在 group 不可见则不会收集值,否则与antd form一致

表单关联

表单关联规范

Field 关联

支持

  • value
  • source
  • visible
  • disabled

FieldGroup 关联

只支持 visible 关联

Table组件使用remoteDataSource后页面一直报错

只要使用了Table组件的remoteDataSource属性,固定返回一个静态List也会报错。

Versions

  • sula:^1.0.0-beta.6
  • umi-plugin-sula:^1.0.0-beta.1
  • OS:windows
  • Browser:chrome

Steps to reproduce

  1. yarn create umi-app
    2.复制一个官方Table组件demo到一个空路由页中

What is Expected?

使用remoteDataSource不报错

What is actually happening?

image

Feature: add buttonProps to submit and back

Description

希望可以定制 CreateForm/StepForm/ModalForm submit 和 back 按钮属性

Solution

增加buttonProps

{
   submitButtonProps: {
       icon: 'plus',
       children: '新建'
   },
   submit: {
     url: '/v1/api',
   }
}

Bug: Unable to resolve path to module sula.

Versions

  • sula: 1.0.0-beta.5
  • umi-plugin-sula: 1.0.0-beta.1
  • OS: MacOS 10.15
  • Browser: Chrome

Steps to reproduce

eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src

What is Expected?

Unable to resolve path to module sula.

What is actually happening?

Feature: add List

Description

add List Component, just like,

import { List } from 'sula';

and try to keep it's consistent with usage of table.

RFC - 表单关联规范

什么是表单关联,即当值放生变化时所关联影响的表单组件属性的行为,如下图,

关联场景

表单关联场景可以分为四类:

  • source 数据源关联
  • value 值关联
  • visible 显示关联
  • disabled 可用/禁用关联

关联规则

以显示关联为例,当A为1且B为2或3时,C显示,否则C不显示。

基于以上我们可以将此规则抽象为,

const config = {
  name: 'C',
  dependency: {
    visible: {
	  relates: ['A', 'B'],
	  inputs: [[1], [2,3]],
	  output: false,
	  defaultOutput: true, // inputs 未匹配时
	}
  }
}

插件关联(自定义)

表单关联场景非常多,例如下面场景

基于以上我们可以将此规则抽象为,

const config = {
  name: 'C',
  dependency: {
    visible: {
	  relates: ['A'],
	  type: (ctx) => {
		fetch('/api/record.json').then(res => {
		   ctx.form.setFieldVisible(res.foo);
		})
	  },
	  defaultOutput: true,
	}
  }
}

多场景关联

假设A为1,C不显示,B为2,C也不显示,可以将此规则抽象为

const config = {
  name: 'C',
  dependency: {
    visible: {
	  cases: [
		{
		   relates: ['A'],
		   inputs: [[1]],
		   output: false,
		}, 
		{
		   relates: ['B'],
		   inputs: [[2]],
		   output: false,
		}
	  ],
	  defaultOutput: true,
	}
  }
}

类型

export type DependencyType = 'source' | 'value' | 'visible' | 'disabled';

export interface Dependency {
  relates: FieldNamePath[];
  inputs?: any[][];
  output?: any;
  defaultOutput?: any;
  type?: DependencyPlugin;
  cases?: Dependency[];
}

export type Dependencies = Record<DependencyType, Dependency >;

Feature: 请求数据传headers参数,requestConfig中取不到,希望可以扩展

Description

bizRequestAdapter(requestConfig) {
   const { url, params, method } = requestConfig;
  // requestConfig参数能取到url, params, method等参数,但是取不到headers参数
    ......
}

希望扩展一些参数

Solution

bizRequestAdapter(requestConfig) {
   const { header } = requestConfig;
  // 可以取到headers等一些参数
  .....
}

Bug: QueryTable里的table超出屏幕没有自动加上滚动条

Versions

  • sula: ^1.0.0-beta.0
  • umi-plugin-sula:
  • OS: Windows10
  • Browser: chrome 83.0.4103.116

Steps to reproduce

1、table里columns每一项都超长
2、columns的内容总长度超出屏幕长度,如图
image

What is Expected?

columns的内容总长度超出屏幕长度s时,自动加上滚动条

What is actually happening?

Feature: sula 定制主题怎么解决

Description

sula中未引入antd样式,在src目录下新建global.ts并导入antd主题

// global.ts
import 'antd/dist/antd.less';

如果我想换个主题怎么做,例如修改@primary-color.
antd中关于定制主题,可以通过建立一个单独的 less 变量文件,引入这个文件覆盖 antd.less 里的变量。这种方式我试了不可行。所以有其他解决方案吗?

RFC - 行为链规范

行为链指一串行为序列,例如,请求 -> 弹窗 -> 刷新表格 -> 隐藏loading,这就是一串行为序列,sula 使用 rope(绳子)来喻指行为序列。

sula rope 分为两部分 rope-container 和 rope。

  • rope-container 连接渲染插件与rope的行为触发器,
  • rope 将行为粘合到一起来响应渲染插件的事件,参考了connect

rope-container

  • disabled(默认是false)
  • visible (默认是true)
  • confirm string | PopconfirmProps
  • tooltip string | TooltipProps

示例

const config = {
  render: {
    type: 'button',
	props: {
	  children: 'Submit'
	},
	confirm: 'Confirm to submit?',
	tooltip: 'Submit information',
	disabled: false,
	visible: false,
	action: {
	  type: 'fetch',
	  url: '/api/info',
	  method: 'GET'
	}
  }
}

rope

  • before 决定是否触发该action,如果不触发则终止行为链
  • finish 下一个action
  • error 执行 action 出错,终止行为链
  • final 不论成功or失败,均执行
  • resultPropName 执行结果保存在ctx.results中的属性名

示例

const config = {
  before: (ctx) => ctx.name === 'sula',
  finish: (ctx) => { ... }
  error: (ctx) => {...}
  final: (ctx) => {...}
  resultPropName: validateFields
}

行为链形态

例如有a,b,c,d四个行为,在rope中最终都会转成

const config = ['a', 'b', 'c', 'd'];

例如,

const config = {
  type: 'a',
  finish: {
    type: 'b',
	finish: ['c', 'd']
  }
}

一个和渲染插件结合的示例

const config = {
  type: 'button',
  props: {
    children: 'Submit'
  },
  action: [
	 {
	   type: 'validateGroupFields',
	   args: ['TaskGroup'],
	   resultPropName: 'taskGroupFieldsValue',
	 },
	 (ctx) => {
	   return 'hello'
	 },
	 {
	   type: 'fetch',
	   url: '/api/info',
	   convertParams(ctx) {
         return {
            ...ctx.results.taskGroupFieldsValue,
            word: ctx.result,
         }
	    }
    }
  ]
}

Question: 相互影响的表单关联

Question

  1. dependency配置相互关联表单栈溢出

Description

fields配置如下,CNY与USD的值相互影响关联

    fields: [
      {
        name: 'CNY',
        label: 'CNY',
        field: 'inputnumber',
        dependency: {
          value: {
            relates: ['USD'],
            type: (ctx) => {
              const { form, relates } = ctx;
              const relatesValue = form.getFieldsValue(relates);
              const value = relatesValue[relates[0]];
              ctx.form.setFieldValue(ctx.name, value / 7);
            },
          },
        },
      },
      {
        name: 'USD',
        label: 'USD',
        field: 'inputnumber',
        dependency: {
          value: {
            relates: ['CNY'],
            type: (ctx) => {
              const { form, relates } = ctx;
              const relatesValue = form.getFieldsValue(relates);
              const value = relatesValue[relates[0]];
              ctx.form.setFieldValue(ctx.name, value * 7);
            },
          },
        },
      },
    ],

触发关联时报错:RangeError: Maximum call stack size exceeded
image

陷入死循环代码:
image

暂时解决方案:
不通过dependency,直接在onValuesChange中写关联逻辑

Feature: Load Antd components lazily, with Dynamic Imports

Description

Currently antd components are being loaded statically. This increases the bundle size and initial load time. Since not all components are needed at the start, please load all AntD React components dynamically.

Lazy loading the components will avoid loading unused components. For example, if user registers their own components for, say table, then their components will be loaded (and the in-built table will never be loaded).

Solution

Please use something like below:

const Button = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/button/button'));
const Col = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/grid/col'));
const Form = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/form/Form'));
const FormItem = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/form/FormItem'));
const Input = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/input/Input'));
const InputPassword = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/input/Password'));
const Message = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/message/index'));
const Row = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/grid/row'));
const Spin = React.lazy(() => import(/* webpackChunkName: "sula-antd" */ 'antd/lib/spin/index'));

sula users

如果您和您的公司或组织使用了sula,非常感谢您的支持,非常欢迎您能留下公司或产品名,您的回复将成为维护者和观望者的信心来源。

在不泄露信息的前提下,建议把截图晒一晒~

Feature: 纯后端驱动方案

Description

希望完全在后端管理界面描述的json,前端只需要嵌入sula事先打包好的框架js即可,无需做前端开发,仅需装载页面对应的json即可完成页面功能

Solution

使用ant design pro 模板,样式丢失?

先创建ant design pro 模板,完全复制文档中的代码,依据文档中的说明安装插件和依赖,结果样式显示有问题。
最后一行return <CreateForm {...config} /> vscode提示如下错误:
(alias) const CreateForm: typeof _CreateForm
import CreateForm
No overload matches this call.
Overload 1 of 2, '(props: Readonly): CreateForm', gave the following error.
不能将类型“{ fields: { name: string; label: string; field: string; }[]; submit: { url: string; method: string; }; }”分配给类型“Pick<Readonly & Readonly<{ children?: ReactNode; }>, "name" | "form" | "slot" | "style" | "title" | "children" | ... 283 more ... | "ctxGetter">”。
The types of 'submit.method' are incompatible between these types.
不能将类型“string”分配给类型“"POST" | "head" | "link" | "get" | "GET" | "delete" | "DELETE" | "HEAD" | "options" | "OPTIONS" | "post" | "put" | "PUT" | "patch" | "PATCH" | "LINK" | "unlink" | "UNLINK" | undefined”。
Overload 2 of 2, '(props: CreateFormProps, context?: any): CreateForm', gave the following error.
不能将类型“{ fields: { name: string; label: string; field: string; }[]; submit: { url: string; method: string; }; }”分配给类型“Pick<Readonly & Readonly<{ children?: ReactNode; }>, "name" | "form" | "slot" | "style" | "title" | "children" | ... 283 more ... | "ctxGetter">”。
属性“submit”的类型不兼容。
不能将类型“{ url: string; method: string; }”分配给类型“RequestConfig”。ts(2769)
速览问题 (Alt+F8)
没有可用的快速修复

Feature: add field validator plugin

Description

add ValidatorPlugin

const formConfig = {
  fields: [
    {
      name: "input",
      label: "Input",
      field: {
        type: "input",
      },
      rules: [
        {
          validator: 'yourValidatorPlugin',
        },
        {
          validator(ctx) {
            return new Promise((resolve, reject) => {
              if (ctx.value === "sula") {
                resolve();
              } else {
                reject(new Error("请输入sula"));
              }
            });
          },
        },
      ],
    },
  ],
};

RFC - 插件规范

插件类型

插件可以简单分为UI展示插件行为插件,通过插件可以方便扩展配置规则,同时「基于宿主配置组件」的上下文(后面简称ctx),插件可以承载更加强大与灵活的能力。

所有插件都有如下形态

{
   plugin: 'someone', // 可以理解为下面没有额外属性的简写
   // 或者
   plugin: {
     type: 'someone', // 插件名称
     prop1: 'foo',
     prop2: 'boo'
   }
  // 或者
  plugin: (ctx) => {
     // ...someone logic
  }
}

插件场景

插件支持三种类型(还有dependency、convertParams、converter插件会单独一part列出):

  1. 渲染插件
  2. 行为插件
  3. 表单插件

1. 渲染插件(render)

场景:

  • 表格渲染单元icon、tag、badge等
  • 表格操作按钮等
  • 表单操作按钮等

除了config,渲染插件可以通过ctx来改变组件属性。

2. 行为插件(action)

场景:

  • 生命周期(组件初始化等)
  • 与渲染插件结合,由渲染插件事件触发

常见行为如请求、路由跳转、弹窗等,行为插件基于ctx可以将行为反馈结果施加到宿主配置组件。

3. 表单插件(field)

场景:

  • 表单
  • 搜索条件

与Form配置组件结合使用,antd数据录入组件及符合antd表单自定义组件规范的都可以转化为表单插件。

插件规范

export type PluginType = 'render' | 'field' | 'action';

以下RenderPlugin、FieldPlugin、ActionPlugin对应了三种插件的配置规则。

1. 渲染插件

// 渲染插件
export type RenderPluginFunction = (ctx: Ctx) => React.ReactElement;
// 渲染插件配置规则
export type RenderPlugin = {
  type: string | RenderPluginFunction;
  props: Record<string, any>;
  functionProps: Record<string, (ctx: Ctx) => string>;
};

示例

const ctx = {name: 'sula'}
// 配置
const config = {
   type: 'tag',
   props: {
      children: 'i am ${name}'
   },
  functionProps: {
     closable: (ctx) => ctx.name === 'sula'
  }
}
// 结果为
<Tag closable>i am sula</Tag>

2. 行为插件

// 行为插件
export type ActionPluginFunction = (ctx: Ctx) => Promise<any> | any | void;
export type ActionBeforeFunction = (ctx: Ctx) => Promise<boolean> | boolean | void;
export type ActionHookFunction = (ctx: Ctx) => void;
// 行为插件配置规则
export type ActionPlugin = {
  type: string | ActionPluginFunction;
  before?: ActionBeforeFunction;
  error?: ActionHookFunction;
  final?: ActionHookFunction;
  finish?: ActionPlugin | ActionPlugin[];
  [key: string]: any;
};

示例

const ctx = {
   table: {
  	  refresh: () => {},
   }
}
// 配置
const config = {
   render: {
	   type: 'button',
	   props: {
		  children: 'submit'
	   },
	    action: (ctx) => { // 可以变成一个插件例如refreshTable
			ctx.table.refresh();
		 }
   },
}
// 结果为
<Button onClick={() => {
  ctx.table.refresh();
}}>submit</Button>

3. 表单插件

表单插件与渲染插件格式上是类似的,只是ctx与场景上的不同。

// 表单插件配置规则
export type FieldPlugin = RenderPlugin;

示例

const ctx = {mode: 'view'}
// 配置
const config = {
   type: 'input',
   props: {
      placeholder: '@{mode} mode'
   },
  functionProps: {
     disabled: (ctx) => ctx.name === 'view'
  }
}
// 结果为
<Input placeholder="view mode" disabled />

插件注册

插件是为了将重复逻辑更加复用,因此直接写方法可以理解为是插件的“内联”形式。

// 注册渲染插件
sula.renderType('tag', (ctx, config) => {
  return <Tag {...config.props} />;
});

render: {
  type: 'tag',
  props: {
    type: 'primary'
  }
}

// 内联写法
render: (ctx) => {
  return <Tag type="primary" />;
}

Bug: action access modalform results

const config = {
  action: [
    {
       type: 'modalform',
       fields: [...],
       submit: ...
    },
    (ctx) => {
        // access fieldsValue and submit result by ctx.results
     }
  ]
}

视频教程内容征集

Sula 的同学们内部讨论了下,觉得当前5分钟左右的视频教程是最有效的,因此最近我们会先着手录制《Sula 五分钟》系列教程,大家有特别希望了解的点请踊跃回复,非常感谢。

Question: 使用ModalForm如何通过ref修改成edit模式同时带参查询

Question

使用ModalForm如何通过ref修改成edit模式?
同时ModalForm组件,使用remoteValues查询的时候需要动态带参,没找到哪儿可以传进参数的地方,只有看到写死的方式。

另一个问题,直接return ctx.modal.modalOk()或者return ctx.modal.modalCancel()外部show().then()中接收到的都是undefined,这时候我需要发送请求成功时才刷新页面,就得手动返回信息才能做判断,有些麻烦

Description

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.