├── .babelrc
├── packages
├── sifo-mplg-drag-react
│ ├── index.less
│ ├── src
│ │ ├── index.less
│ │ ├── editor
│ │ │ └── header.jsx
│ │ ├── componentWrap.js
│ │ └── index.js
│ ├── .babelrc
│ ├── .eslintignore
│ ├── index.js
│ ├── .npmignore
│ └── package.json
├── sifo-mplg-drag-vue
│ ├── index.less
│ ├── src
│ │ ├── index.less
│ │ ├── editor
│ │ │ └── header.vue
│ │ ├── componentWrap.js
│ │ └── index.js
│ ├── .babelrc
│ ├── .eslintignore
│ ├── index.js
│ ├── .npmignore
│ └── package.json
├── sifo-mplg-form-antd
│ ├── index.less
│ ├── index.js
│ ├── .eslintignore
│ ├── .npmignore
│ ├── test
│ │ └── index.test.js
│ ├── .babelrc
│ ├── es.babel.config.js
│ ├── src
│ │ ├── index.js
│ │ └── index.less
│ └── package.json
├── sifo-mplg-form-antdv
│ ├── index.less
│ ├── index.js
│ ├── .eslintignore
│ ├── .npmignore
│ ├── test
│ │ └── index.test.js
│ ├── .babelrc
│ ├── es.babel.config.js
│ ├── src
│ │ ├── index.less
│ │ └── index.js
│ └── package.json
├── sifo-mplg-form-fusion
│ ├── index.scss
│ ├── index.js
│ ├── .eslintignore
│ ├── .npmignore
│ ├── .babelrc
│ ├── es.babel.config.js
│ ├── src
│ │ ├── index.js
│ │ └── index.scss
│ └── package.json
├── sifo-mplg-form-antd-mobile
│ ├── index.less
│ ├── src
│ │ ├── components
│ │ │ ├── button
│ │ │ │ ├── index.less
│ │ │ │ └── index.jsx
│ │ │ ├── cascader-picker
│ │ │ │ └── index.less
│ │ │ ├── container.jsx
│ │ │ ├── field-content
│ │ │ │ ├── index.less
│ │ │ │ └── index.tsx
│ │ │ ├── split-panel
│ │ │ │ ├── index.less
│ │ │ │ └── index.tsx
│ │ │ ├── radio
│ │ │ │ ├── index.less
│ │ │ │ └── index.tsx
│ │ │ ├── checkbox
│ │ │ │ └── index.tsx
│ │ │ ├── index.jsx
│ │ │ ├── date-picker.tsx
│ │ │ └── number-input.jsx
│ │ ├── form
│ │ │ └── index.tsx
│ │ └── index.js
│ ├── index.js
│ ├── .eslintignore
│ ├── .npmignore
│ ├── test
│ │ └── index.test.js
│ ├── .babelrc.js
│ ├── es.babel.config.js
│ └── package.json
├── sifo-model
│ ├── .babelrc
│ ├── index.js
│ ├── .eslintignore
│ ├── src
│ │ ├── index.ts
│ │ ├── types
│ │ │ ├── schemaTypes.ts
│ │ │ └── eventTypes.ts
│ │ ├── TaskQueue.ts
│ │ └── utils
│ │ │ └── schema-utils.ts
│ ├── .npmignore
│ ├── register.js
│ ├── package.json
│ └── test
│ │ └── modelPlugin
│ │ └── reactOptimizeModelPlugin.js
├── sifo-mplg-drag
│ ├── .babelrc
│ ├── .eslintignore
│ ├── index.js
│ ├── .npmignore
│ ├── README.md
│ ├── src
│ │ ├── dragImgs.js
│ │ └── index.css
│ └── package.json
├── sifo-singleton
│ ├── .babelrc
│ ├── .eslintignore
│ ├── index.js
│ ├── src
│ │ └── index.js
│ ├── .npmignore
│ ├── register.js
│ ├── test
│ │ └── schema.json
│ ├── package.json
│ └── README.md
├── sifo-mplg-form-core
│ ├── .babelrc
│ ├── .eslintignore
│ ├── index.js
│ ├── .npmignore
│ ├── test
│ │ └── index.test.js
│ ├── src
│ │ ├── validate.js
│ │ └── utils.js
│ └── package.json
├── sifo-mplg-react-optimize
│ ├── .babelrc
│ ├── .eslintignore
│ ├── demo
│ │ ├── default
│ │ │ ├── index.css
│ │ │ ├── custom-wrap-component.jsx
│ │ │ ├── componnetPlugin.jsx
│ │ │ ├── formModelPlugin.js
│ │ │ └── index.jsx
│ │ └── index.js
│ ├── index.js
│ ├── .npmignore
│ ├── register.js
│ ├── test
│ │ ├── index.test.js
│ │ └── component.test.js
│ ├── src
│ │ └── componentWrap.tsx
│ ├── README.md
│ └── package.json
├── sifo-react
│ ├── .eslintignore
│ ├── demo
│ │ ├── decoratorTest
│ │ │ ├── index.css
│ │ │ ├── index.js
│ │ │ └── Main.jsx
│ │ ├── index.js
│ │ └── quickStart.jsx
│ ├── index.js
│ ├── .npmignore
│ ├── test
│ │ ├── index.test.js
│ │ └── component.test.js
│ ├── src
│ │ ├── modelPlugins
│ │ │ ├── index.js
│ │ │ ├── ReactModelPlugin.js
│ │ │ ├── ComponentNotFound.js
│ │ │ ├── component-proxy
│ │ │ │ └── index.js
│ │ │ ├── logger
│ │ │ │ └── index.jsx
│ │ │ └── PluginResetter.js
│ │ └── utils
│ │ │ ├── tags.js
│ │ │ ├── render-factory.jsx
│ │ │ └── singleton-utils.js
│ ├── index.d.ts
│ └── package.json
└── sifo-vue
│ ├── .eslintignore
│ ├── index.js
│ ├── .npmignore
│ ├── src
│ ├── modelPlugins
│ │ ├── index.js
│ │ ├── AttributesClassify.js
│ │ ├── logger
│ │ │ └── index.jsx
│ │ └── utils.js
│ └── utils
│ │ └── singleton-utils.js
│ ├── index.d.ts
│ ├── package.json
│ └── demo
│ └── quick-start.vue
├── image
├── logo.png
├── sifo-app.gif
├── sifo-elements.png
├── sifo-family.png
├── sifo-optimize-tree.png
├── sifo-model-lifecycle.png
├── sifo-optimize-tree2.png
└── how-sifo-extensions-work.png
├── docs
└── sifo-react-doc
│ ├── form-adm-demo
│ ├── index.less
│ ├── plugins
│ │ └── index.ts
│ └── index.tsx
│ ├── modelPlugin-demo
│ ├── index.less
│ ├── index.tsx
│ ├── schema.json
│ └── mplg-antd-form
│ │ └── componentWrap.jsx
│ ├── test-decorator
│ └── index.css
│ ├── form-demo
│ ├── plugins
│ │ ├── index.js
│ │ └── pagePlugin.js
│ ├── index.less
│ └── index.jsx
│ ├── fusion-form-demo
│ ├── plugins
│ │ ├── index.js
│ │ └── pagePlugin.js
│ └── index.less
│ ├── drag-demo.md
│ ├── drag-editor
│ ├── index.less
│ └── components
│ │ └── gridPanel.less
│ ├── form-demo.md
│ ├── fusion-form-demo.md
│ ├── form-antd-mobile-demo.md
│ └── modelPlugin-demo.md
├── examples-vue
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── assets
│ │ └── logo.png
│ ├── demos
│ │ ├── form-demo
│ │ │ ├── plugins
│ │ │ │ ├── index.js
│ │ │ │ └── pagePlugin.js
│ │ │ └── index.less
│ │ ├── complex-demo
│ │ │ ├── plugins
│ │ │ │ ├── index.js
│ │ │ │ ├── pagePlugin.js
│ │ │ │ └── extend-in-anotherjs.js
│ │ │ ├── components
│ │ │ │ ├── textCell.vue
│ │ │ │ ├── index.js
│ │ │ │ ├── anchored-heading.js
│ │ │ │ ├── inputcell.vue
│ │ │ │ └── s-container.vue
│ │ │ └── Complex.vue
│ │ ├── drag-editor
│ │ │ ├── index.less
│ │ │ └── components
│ │ │ │ ├── common-props-render.vue
│ │ │ │ └── componentConfig.jsx
│ │ ├── test-decorator.js
│ │ ├── quick-start-ext.js
│ │ ├── test-decorator-target.vue
│ │ └── quick-start.vue
│ ├── main.js
│ ├── index.less
│ └── App.vue
├── babel.config.js
├── vue.config.js
├── README.md
├── package.json
└── server.js
├── web-app
├── app
│ ├── form
│ │ ├── plugins
│ │ │ ├── index.js
│ │ │ └── pagePlugin.js
│ │ ├── components
│ │ │ └── gridPanel.less
│ │ └── index.less
│ ├── index.jsx
│ ├── index.less
│ ├── settingPanel
│ │ ├── settings.jsx
│ │ └── index.jsx
│ └── formPanel.jsx
├── extensions
│ ├── system
│ │ ├── openlogger.js
│ │ ├── notice.js
│ │ ├── english.js
│ │ ├── notice.less
│ │ ├── NoticeComp.jsx
│ │ └── english-config.js
│ ├── customerB
│ │ ├── index.less
│ │ ├── index.js
│ │ └── ShowWarehouseCapacity.jsx
│ ├── customerA
│ │ └── submitCheck.jsx
│ ├── config.js
│ └── customerC
│ │ └── schema.json
├── build
│ ├── webpack.prod.js
│ ├── webpack.config.dll.js
│ ├── webpack.dev.js
│ └── vendor
│ │ └── vendor-manifest.json
├── public
│ └── index.html
├── .gitignore
└── babel.config.js
├── .editorconfig
├── .eslintignore
├── lerna.json
├── .gitignore
├── LICENSE
├── .umirc.js
└── babel.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/index.less:
--------------------------------------------------------------------------------
1 | @import './lib/index.less';
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/index.less:
--------------------------------------------------------------------------------
1 | @import './lib/index.less';
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/index.less:
--------------------------------------------------------------------------------
1 | @import './lib/index.less';
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/index.less:
--------------------------------------------------------------------------------
1 | @import './lib/index.less';
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/index.scss:
--------------------------------------------------------------------------------
1 | @import './lib/index.scss';
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/src/index.less:
--------------------------------------------------------------------------------
1 | @import './editor/index.less';
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/index.less:
--------------------------------------------------------------------------------
1 | @import './lib/index.less';
--------------------------------------------------------------------------------
/packages/sifo-model/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/src/index.less:
--------------------------------------------------------------------------------
1 | @import './editor/index.less';
2 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/packages/sifo-singleton/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/image/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/logo.png
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": []
4 | }
--------------------------------------------------------------------------------
/image/sifo-app.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/sifo-app.gif
--------------------------------------------------------------------------------
/image/sifo-elements.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/sifo-elements.png
--------------------------------------------------------------------------------
/image/sifo-family.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/sifo-family.png
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-adm-demo/index.less:
--------------------------------------------------------------------------------
1 | @import "~@schema-plugin-flow/sifo-mplg-form-antd-mobile/index.less";
--------------------------------------------------------------------------------
/image/sifo-optimize-tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/sifo-optimize-tree.png
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/button/index.less:
--------------------------------------------------------------------------------
1 | .sifo-adm-button {
2 | font-size: 14px;
3 | }
--------------------------------------------------------------------------------
/image/sifo-model-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/sifo-model-lifecycle.png
--------------------------------------------------------------------------------
/image/sifo-optimize-tree2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/sifo-optimize-tree2.png
--------------------------------------------------------------------------------
/examples-vue/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/examples-vue/public/favicon.ico
--------------------------------------------------------------------------------
/examples-vue/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/examples-vue/src/assets/logo.png
--------------------------------------------------------------------------------
/packages/sifo-react/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 |
--------------------------------------------------------------------------------
/packages/sifo-vue/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/modelPlugin-demo/index.less:
--------------------------------------------------------------------------------
1 | .sifo-form-demo {
2 | .form-demo-footer{
3 | text-align: center;
4 | }
5 | }
--------------------------------------------------------------------------------
/image/how-sifo-extensions-work.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/schema-plugin-flow/HEAD/image/how-sifo-extensions-work.png
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/test-decorator/index.css:
--------------------------------------------------------------------------------
1 | .decorator-test {
2 | width: 300px;
3 | border: 1px solid #ccc;
4 | padding: 32px;
5 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 |
--------------------------------------------------------------------------------
/packages/sifo-model/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | // defaut export path
5 | module.exports = require('./lib/index.js');
6 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 |
--------------------------------------------------------------------------------
/packages/sifo-react/demo/decoratorTest/index.css:
--------------------------------------------------------------------------------
1 | .decorator-test {
2 | width: 300px;
3 | border: 1px solid #ccc;
4 | padding: 32px;
5 | }
--------------------------------------------------------------------------------
/packages/sifo-react/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | // defaut export path
5 | module.exports = require('./lib/index.js');
6 |
--------------------------------------------------------------------------------
/packages/sifo-singleton/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 | lib/
9 |
--------------------------------------------------------------------------------
/packages/sifo-vue/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | // defaut export path
5 | module.exports = require('./lib/index.js');
6 |
--------------------------------------------------------------------------------
/packages/sifo-model/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 | lib/
9 | src/types
--------------------------------------------------------------------------------
/packages/sifo-model/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | import SifoModel from './SifoModel';
5 |
6 | export default SifoModel;
7 |
--------------------------------------------------------------------------------
/packages/sifo-react/demo/decoratorTest/index.js:
--------------------------------------------------------------------------------
1 | import Main from './Main';
2 | import './custom';
3 | import './index.css';
4 | export default Main;
--------------------------------------------------------------------------------
/packages/sifo-singleton/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | // defaut export path
5 | module.exports = require('./lib/index.js');
6 |
--------------------------------------------------------------------------------
/packages/sifo-singleton/src/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import SifoSingleton from './singleton';
3 |
4 | export default SifoSingleton;
5 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/demo/default/index.css:
--------------------------------------------------------------------------------
1 | .demo-input {
2 | outline: none;
3 | margin: 16px;
4 | border-bottom: 1px solid green;
5 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/demo/index.js:
--------------------------------------------------------------------------------
1 | import DefaultComponent from './default';
2 |
3 | export default {
4 | default: DefaultComponent,
5 | };
6 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author FrominXu
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @author Fromin xusheng
4 | */
5 | // defaut export path
6 | module.exports = require('./lib/index.js');
7 |
--------------------------------------------------------------------------------
/packages/sifo-vue/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | src/
9 | test/
10 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | es.babel.config.js
7 | test/
8 | dist/
9 | lib/
10 | es/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | es.babel.config.js
7 | test/
8 | dist/
9 | lib/
10 | es/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | es.babel.config.js
7 | test/
8 | dist/
9 | lib/
10 | es/
11 |
--------------------------------------------------------------------------------
/packages/sifo-react/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | src/
10 | test/
11 |
--------------------------------------------------------------------------------
/packages/sifo-model/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | src/
10 | test/
11 | .vscode/
--------------------------------------------------------------------------------
/packages/sifo-model/register.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line import/no-extraneous-dependencies
2 | require('@babel/register')({
3 | rootMode: 'upward',
4 | ignore: [/node_modules/]
5 | });
6 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | es.babel.config.js
7 | test/
8 | dist/
9 | lib/
10 | es/
11 |
--------------------------------------------------------------------------------
/packages/sifo-singleton/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | src/
10 | test/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-singleton/register.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line import/no-extraneous-dependencies
2 | require('@babel/register')({
3 | rootMode: 'upward',
4 | ignore: [/node_modules/]
5 | });
6 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | mochawesome-reports/
7 | node_modules/
8 | demo/
9 | test/
10 | src/
11 |
--------------------------------------------------------------------------------
/packages/sifo-react/demo/index.js:
--------------------------------------------------------------------------------
1 | import decoratorTest from './decoratorTest';
2 | import QuickStart from './quickStart';
3 |
4 | export default {
5 | default: QuickStart,
6 | decoratorTest,
7 | };
8 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/register.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line import/no-extraneous-dependencies
2 | require('@babel/register')({
3 | rootMode: 'upward',
4 | ignore: [/node_modules/]
5 | });
6 |
--------------------------------------------------------------------------------
/web-app/app/form/plugins/index.js:
--------------------------------------------------------------------------------
1 | import componentPlugin from './componentPlugin';
2 | import pagePlugin from './pagePlugin';
3 |
4 | const plugins = [{ componentPlugin, pagePlugin }];
5 | export default plugins;
6 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/cascader-picker/index.less:
--------------------------------------------------------------------------------
1 | .sifo-adm-cascader-picker {
2 | .sifo-adm-cascader-popup {
3 |
4 | }
5 | .sifo-adm-cascader-value {
6 | margin-right: 4px;
7 | }
8 | }
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-demo/plugins/index.js:
--------------------------------------------------------------------------------
1 | import componentPlugin from './componentPlugin';
2 | import pagePlugin from './pagePlugin';
3 |
4 | const plugins = [{ componentPlugin, pagePlugin }];
5 | export default plugins;
6 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/form-demo/plugins/index.js:
--------------------------------------------------------------------------------
1 | import componentPlugin from './componentPlugin';
2 | import pagePlugin from './pagePlugin';
3 |
4 | const plugins = [{ componentPlugin, pagePlugin }];
5 | export default plugins;
6 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/fusion-form-demo/plugins/index.js:
--------------------------------------------------------------------------------
1 | import componentPlugin from './componentPlugin';
2 | import pagePlugin from './pagePlugin';
3 |
4 | const plugins = [{ componentPlugin, pagePlugin }];
5 | export default plugins;
6 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/plugins/index.js:
--------------------------------------------------------------------------------
1 | import componentPlugin from './componentPlugin';
2 | import pagePlugin from './pagePlugin';
3 |
4 | const plugins = [{ componentPlugin, pagePlugin }];
5 | export default plugins;
6 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-demo/plugins/pagePlugin.js:
--------------------------------------------------------------------------------
1 | const pagePlugin = {
2 | afterRender: ({ mApi }) => {
3 | console.log("afterRender!!!!");
4 | mApi.setValue("subject", "值123");
5 | },
6 | };
7 |
8 | export default pagePlugin;
9 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/form-demo/plugins/pagePlugin.js:
--------------------------------------------------------------------------------
1 | const pagePlugin = {
2 | afterRender: ({ mApi }) => {
3 | console.log("afterRender!!!!");
4 | mApi.setValue("subject", "值123");
5 | },
6 | };
7 |
8 | export default pagePlugin;
9 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/fusion-form-demo/plugins/pagePlugin.js:
--------------------------------------------------------------------------------
1 | const pagePlugin = {
2 | afterRender: ({ mApi }) => {
3 | console.log("afterRender!!!!");
4 | mApi.setValue("subject", "值123");
5 | },
6 | };
7 |
8 | export default pagePlugin;
9 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/container.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import cls from 'classnames';
3 |
4 | const container = p => (
);
5 |
6 | export default container;
7 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/drag-demo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Drag Demo
3 | order: 5
4 | ---
5 | ```jsx
6 | import * as React from 'react';
7 | import DragEditor from './drag-editor';
8 | //import "./drag-editor/index.less";
9 | //
10 | export default DragEditor;
11 | ```
12 |
13 |
--------------------------------------------------------------------------------
/examples-vue/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ],
5 | plugins: [
6 | ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/test/index.test.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'; // 断言库
2 | import formCoreModelPlugin from '../src/index';
3 |
4 | describe('import', () => {
5 | it('should import correctly', () => {
6 | expect(formCoreModelPlugin).to.not.eql(undefined);
7 | });
8 | });
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/test/index.test.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'; // 断言库
2 | import formCoreModelPlugin from '../src/index';
3 |
4 | describe('import', () => {
5 | it('should import correctly', () => {
6 | expect(formCoreModelPlugin).to.not.eql(undefined);
7 | });
8 | });
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig 代码编辑器配置信息
2 |
3 | root = true
4 |
5 | # 应用于所有文件
6 | [*]
7 | # 字符集
8 | charset = utf-8
9 | # 缩进符
10 | indent_style = space
11 | # 缩进数
12 | indent_size = 2
13 |
14 | end_of_line = lf
15 | insert_final_newline = true
16 | trim_trailing_whitespace = true
17 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/drag-editor/index.less:
--------------------------------------------------------------------------------
1 | .drag-demo {
2 | .form-demo-main {
3 | .ant-select {
4 | width: 100%;
5 | }
6 | }
7 | .footer-opt {
8 | text-align: center;
9 | padding: 16px;
10 | .ant-btn {
11 | margin: 0 8px;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/examples-vue/src/demos/drag-editor/index.less:
--------------------------------------------------------------------------------
1 | .drag-demo {
2 | .form-demo-main {
3 | .ant-select {
4 | width: 100%;
5 | }
6 | }
7 | .footer-opt {
8 | text-align: center;
9 | padding: 16px;
10 | .ant-btn {
11 | margin: 0 8px;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/test/index.test.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'; // 断言库
2 | import formCoreModelPlugin from '../src/index';
3 |
4 | describe('import', () => {
5 | it('should import correctly', () => {
6 | expect(formCoreModelPlugin).to.not.eql(undefined);
7 | });
8 | });
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/test/index.test.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'; // 断言库
2 | import formCoreModelPlugin from '../src/index';
3 |
4 | describe('import', () => {
5 | it('should import correctly', () => {
6 | expect(formCoreModelPlugin).to.not.eql(undefined);
7 | });
8 | });
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": [
4 | [
5 | "import",
6 | {
7 | "libraryName": "antd",
8 | "libraryDirectory": "lib",
9 | "style": "css"
10 | }
11 | ] // `style: true` 会加载 less 文件
12 | ]
13 | }
--------------------------------------------------------------------------------
/packages/sifo-react/test/index.test.js:
--------------------------------------------------------------------------------
1 | // 引入基础依赖
2 | import { expect } from 'chai'; // 断言库
3 |
4 | // 测试描述语法参照 mocha 官方文档 https://mochajs.org/
5 | describe('Without React', () => {
6 | it('should count correctly', () => {
7 | expect(expect).to.be.a('function');
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/form/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { List } from 'antd-mobile';
3 | import cls from 'classnames';
4 |
5 | const Form = props => {
6 | return
;
7 | };
8 | export default Form;
9 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": [
4 | [
5 | "import",
6 | {
7 | "libraryName": "@alifd/next",
8 | "libraryDirectory": "lib",
9 | "style": "css"
10 | }
11 | ] // `style: true` 会加载 less 文件
12 | ]
13 | }
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-adm-demo/plugins/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 导出所有插件
3 | * 插件生命周期或 API 见:https://www.npmjs.com/package/@schema-plugin-flow/sifo-model
4 | */
5 | import componentPlugin from './component';
6 |
7 | const plugins = [{
8 | componentPlugin
9 | }];
10 |
11 | export default plugins;
12 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [],
3 | "plugins": [
4 | [
5 | "import",
6 | {
7 | "libraryName": "ant-design-vue",
8 | "libraryDirectory": "lib",
9 | "style": "css"
10 | }
11 | ] // `style: true` 会加载 less 文件
12 | ]
13 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/test/index.test.js:
--------------------------------------------------------------------------------
1 | // 引入基础依赖
2 | import { expect } from 'chai'; // 断言库
3 |
4 | // 测试描述语法参照 mocha 官方文档 https://mochajs.org/
5 | describe('Without React', () => {
6 | it('should count correctly', () => {
7 | expect(expect).to.be.a('function');
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/packages/sifo-model/src/types/schemaTypes.ts:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * schema node
4 | */
5 | interface SchemaNode {
6 | [key: string]: any;
7 | /**
8 | * 节点唯一标识,不可重复,插件都是以此id进行节点区分
9 | */
10 | id?: string;
11 | component?: string;
12 | attributes?: DynamicObject;
13 | children?: SchemaNode[] | null;
14 | }
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | docs/
3 | demo/
4 | examples/
5 | webpack.config.js
6 | test/
7 | dist/
8 | lib/
9 | node_modules/
10 | /packages/*/node_modules
11 | babel.config.js
12 | es.babel.config.js
13 | /packages/*/lib
14 | /packages/*/es
15 | /packages/*/dist
16 | dist/
17 | mochawesome-reports/
18 | lib/
19 |
--------------------------------------------------------------------------------
/web-app/app/form/plugins/pagePlugin.js:
--------------------------------------------------------------------------------
1 | const pagePlugin = {
2 | onNodePreprocess: node => {
3 | if (node.id === 'main_id') {
4 | // node.children.push({
5 | // component: 'DragDemo'
6 | // })
7 | }
8 | },
9 | afterRender: () => {
10 | }
11 | };
12 |
13 | export default pagePlugin;
14 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-demo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Antd Form Demo
3 | order: 3
4 | ---
5 | Sifo Form with ant-design
6 | ```jsx
7 | import * as React from 'react';
8 | import FormDemo from './form-demo';
9 | import 'antd/dist/antd.css';
10 | import "./form-demo/index.less";
11 | //
12 | export default FormDemo;
13 | ```
14 |
15 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/components/textCell.vue:
--------------------------------------------------------------------------------
1 |
2 | {{text}}
3 |
4 |
--------------------------------------------------------------------------------
/web-app/extensions/system/openlogger.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 |
3 | const singleton = new SifoSingleton('form-demo');
4 |
5 | singleton.registerItem('openlogger', () => {
6 | return {
7 | plugins: [],
8 | openLogger: true
9 | };
10 | });
11 |
12 | export default singleton;
13 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/fusion-form-demo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Fusion Form Demo
3 | order: 4
4 | ---
5 | Sifo Form with Fusion
6 | ```jsx
7 | import * as React from 'react';
8 | import FormDemo from './fusion-form-demo';
9 | import '@alifd/next/dist/next.min.css'
10 | import "./fusion-form-demo/index.less";
11 | //
12 | export default FormDemo;
13 | ```
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-antd-mobile-demo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Antd mobile Form Demo
3 | order: 3
4 | ---
5 | Sifo Form with ant-design
6 | ```jsx
7 | import * as React from 'react';
8 | import FormDemo from './form-adm-demo';
9 | // import 'antd/dist/antd.css';
10 | import "./form-adm-demo/index.less";
11 | //
12 | export default FormDemo;
13 | ```
14 |
15 |
--------------------------------------------------------------------------------
/examples-vue/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | runtimeCompiler: true,
3 | lintOnSave: false, //是否开启eslint保存检测 ,它的有效值为 true || false || 'error'
4 | configureWebpack: {
5 | resolve: {
6 | alias: {
7 | // 'vue$': 'vue/dist/vue.esm.js' // https://www.jianshu.com/p/466510d84e36
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/packages/sifo-vue/src/modelPlugins/index.js:
--------------------------------------------------------------------------------
1 | import VueModelPlugin from './VueModelPlugin';
2 | import AttributesClassify from './AttributesClassify';
3 |
4 | const presetPlugins = [
5 | { modelPlugin: AttributesClassify }
6 | ];
7 | // 前置插件
8 | export const baseOrderPlugins = [
9 | { modelPlugin: VueModelPlugin }
10 | ];
11 | export default presetPlugins;
12 |
--------------------------------------------------------------------------------
/web-app/app/form/components/gridPanel.less:
--------------------------------------------------------------------------------
1 | .grid-panel {
2 | .grid-panel-wrapper {
3 | >.ant-row {
4 | padding: 0;
5 | .grid-panel-item.grid-panel-item-clear-space {
6 | padding: 0;
7 | }
8 | }
9 | }
10 | .grid-panel-item {
11 | padding: 0 4px;
12 | }
13 | &-label {
14 | padding: 16px 4px;
15 | font-weight: bold;
16 | font-size: 14px;
17 | }
18 | }
--------------------------------------------------------------------------------
/docs/sifo-react-doc/drag-editor/components/gridPanel.less:
--------------------------------------------------------------------------------
1 | .grid-panel {
2 | .grid-panel-wrapper {
3 | >.ant-row {
4 | padding: 0;
5 | .grid-panel-item.grid-panel-item-clear-space {
6 | padding: 0;
7 | }
8 | }
9 | }
10 | .grid-panel-item {
11 | padding: 0 4px;
12 | }
13 | &-label {
14 | padding: 16px 4px;
15 | font-weight: bold;
16 | font-size: 14px;
17 | }
18 | }
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/components/index.js:
--------------------------------------------------------------------------------
1 | import S_Container from './s-container'
2 | import AnchoredHeading from './anchored-heading';
3 | import TextCell from './textCell';
4 | import InputCell from './inputcell';
5 | const components = {
6 | "s-container": S_Container,
7 | "anchored-heading": AnchoredHeading,
8 | 's-textcell': TextCell,
9 | 's-inputcell': InputCell
10 | };
11 |
12 | export default components;
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/demo/default/custom-wrap-component.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 |
5 | const CWrap = props => {
6 | const { itemChildren = null,style, ...other } = props;
7 | console.log('CWrap:', other, itemChildren.props)
8 | return (
9 |
10 | {itemChildren && React.createElement(itemChildren, other)}
11 |
12 | )
13 | }
14 | export default CWrap;
15 |
--------------------------------------------------------------------------------
/web-app/build/webpack.prod.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | const path = require('path');
3 | const { merge } = require('webpack-merge'); //合并配置
4 | const DIST_PATH = path.resolve(__dirname, '../dist'); //生产目录
5 | const baseWebpackConfig = require('./webpack.base');
6 | module.exports = merge(baseWebpackConfig, {
7 | mode: 'production',
8 | output: {
9 | filename: '[name].js',
10 | path: DIST_PATH
11 | },
12 | plugins: [
13 | ]
14 | });
--------------------------------------------------------------------------------
/examples-vue/README.md:
--------------------------------------------------------------------------------
1 | # vue-demo
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/components/anchored-heading.js:
--------------------------------------------------------------------------------
1 | // 函数式声明方式
2 | const AnchoredHeading = {
3 | name: 'anchored-heading',
4 | render: function (createElement) {
5 | return createElement(
6 | 'h' + this.level, // 标签名称
7 | this.$slots.default // 子节点数组
8 | )
9 | },
10 | props: {
11 | level: {
12 | type: Number,
13 | required: true
14 | }
15 | }
16 | };
17 |
18 | export default AnchoredHeading;
--------------------------------------------------------------------------------
/examples-vue/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import { DatePicker, Button, Input, Tabs, Table } from 'ant-design-vue';
3 | import App from './App.vue';
4 | import './index.less';
5 | // 这些组件注册为全局组件
6 | [DatePicker, Button, Input, Tabs, Table].forEach(comp => {
7 | Vue.use(comp);
8 | });
9 |
10 | Vue.config.productionTip = false;
11 |
12 | new Vue({
13 | components: { 'test-root': App },
14 | render: h => h('test-root', {}),
15 | }).$mount('#app');
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/components/inputcell.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/packages/sifo-vue/src/modelPlugins/AttributesClassify.js:
--------------------------------------------------------------------------------
1 | import { classifyAttributes } from './utils';
2 |
3 | class AttributesClassify {
4 | static ID = 'sifo_vue_attrs_classify_model_plugin';
5 | constructor() {
6 | this.mApi = null;
7 | }
8 | onNodePreprocess = node => {
9 | const { attributes } = node;
10 | const classifiedAttrs = classifyAttributes({}, attributes);
11 | return { ...node, attributes: classifiedAttrs };
12 | }
13 | }
14 |
15 | export default AttributesClassify;
16 |
17 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/field-content/index.less:
--------------------------------------------------------------------------------
1 | .sifo-adm-field-content{
2 | padding: 0;
3 | height: 16px;
4 | min-height: 16px;
5 | font-size: 14px;
6 | font-weight: 900;
7 | width: auto;
8 | overflow: hidden;
9 | text-overflow: ellipsis;
10 | white-space: nowrap;
11 | position: relative;
12 | .sifo-adm-field-placeholder{
13 | color: #bbb;
14 | }
15 | &.sifo-adm-field-disabled{
16 | // color: #89919d;
17 | opacity: 0.4;
18 | cursor: not-allowed;
19 | }
20 | }
--------------------------------------------------------------------------------
/web-app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | <%= htmlWebpackPlugin.options.title %>
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-demo/index.less:
--------------------------------------------------------------------------------
1 | @import "~@schema-plugin-flow/sifo-mplg-form-antd/index.less";
2 | .form-demo {
3 | .form-demo-main {
4 | padding: 16px;
5 | .sub-panel{
6 | border: 1px solid #ccc;
7 | border-radius: 3px;
8 | margin: 8px 0;
9 | padding: 8px;
10 | }
11 | }
12 | .subject-form-item{
13 | border: 1px solid #daf3da;
14 | .test-subject{
15 | color: #a9e0fa
16 | }
17 | }
18 | .footer-opt{
19 | text-align: center;
20 | padding: 16px;
21 | .ant-btn{
22 | margin: 0 8px;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/plugins/pagePlugin.js:
--------------------------------------------------------------------------------
1 | const pagePlugin = {
2 | onNodePreprocess: (node, info) => {
3 | const { id, component, children } = node;
4 | if (id == '$mainContainer') {
5 | // for (let i = 0; i < 1000; i++) {
6 | // children.push({
7 | // "component": "a-input",
8 | // "id": "name"+i,
9 | // "attributes": {
10 | // "placeholder": "名称"
11 | // }
12 | // })
13 | // }
14 | }
15 | },
16 | afterRender: () => {
17 |
18 | }
19 | }
20 |
21 | export default pagePlugin;
22 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/form-demo/index.less:
--------------------------------------------------------------------------------
1 | @import "~@schema-plugin-flow/sifo-mplg-form-antdv/index.less";
2 | .form-demo {
3 | .form-demo-main {
4 | padding: 16px;
5 | .sub-panel{
6 | border: 1px solid #ccc;
7 | border-radius: 3px;
8 | margin: 8px 0;
9 | padding: 8px;
10 | }
11 | }
12 | .subject-form-item{
13 | border: 1px solid #daf3da;
14 | .test-subject{
15 | color: #a9e0fa
16 | }
17 | }
18 | .footer-opt{
19 | text-align: center;
20 | padding: 16px;
21 | .ant-btn{
22 | margin: 0 8px;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/button/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Button } from 'antd-mobile';
3 | import cls from 'classnames';
4 | import './index.less';
5 |
6 | const ButtonX = props => {
7 | /* eslint-disable react/prop-types */
8 | const {
9 | title, className, label, ...other
10 | } = props;
11 | return (
12 |
18 | );
19 | };
20 |
21 | export default ButtonX;
22 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/split-panel/index.less:
--------------------------------------------------------------------------------
1 | .split-panel {
2 | display: flex;
3 | .split-item {
4 | display: flex;
5 | flex-grow: 0;
6 | .sifo-adm-form-item {
7 | width: 100%;
8 | }
9 | }
10 | > :not(:last-child){
11 | // --border-bottom: solid 1px var(--adm-border-color);
12 | border-right: 1px solid var(--adm-border-color);
13 | }
14 | >:not(:first-child){
15 | // 修复样式
16 | .sifo-adm-form-item{
17 | border-top: 1px solid var(--adm-border-color);
18 | .adm-list-item-content{
19 | border: none;
20 | }
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/web-app/extensions/customerB/index.less:
--------------------------------------------------------------------------------
1 | .capacity {
2 | display: inline-block;
3 | width: 100px;
4 | }
5 | .capacity-select{
6 | display: inline-block;
7 | .capacity-item{
8 | padding: 4px;
9 | border: 1px solid #bbb;
10 | margin: 0 8px;
11 | border-radius: 4px;
12 | &:hover{
13 | cursor: pointer;
14 | }
15 | }
16 | .capacity-item.selected{
17 | border-color: #1890ff;
18 | background-color: rgba(24, 144, 255, 0.5);
19 | }
20 | }
21 | .capacity-refresh{
22 | margin-right: 8px;
23 | &:hover{
24 | color: #1890ff;
25 | font-size: 15px;
26 | }
27 | }
--------------------------------------------------------------------------------
/docs/sifo-react-doc/fusion-form-demo/index.less:
--------------------------------------------------------------------------------
1 | @import "~@schema-plugin-flow/sifo-mplg-form-fusion/index.scss";
2 | .fusion-form-demo {
3 | .fusion-form-demo-main {
4 | padding: 16px;
5 | .sub-panel{
6 | border: 1px solid #ccc;
7 | border-radius: 3px;
8 | margin: 8px 0;
9 | padding: 8px;
10 | }
11 | }
12 | .subject-form-item{
13 | border: 1px solid #daf3da;
14 | .test-subject{
15 | >input{
16 | color: #a9e0fa
17 | }
18 | }
19 | }
20 | .footer-opt{
21 | text-align: center;
22 | padding: 16px;
23 | .next-btn{
24 | margin: 0 8px;
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/.babelrc.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | module.exports = function (api) {
3 | api.cache(true);
4 | const plugins = [
5 | [
6 | "import",
7 | {
8 | "libraryName": "antd-mobile",
9 | "customStyleName": function (transformedMethodName) {
10 | return 'antd-mobile/cjs/components/' + transformedMethodName +"/" + transformedMethodName + ".css";
11 | },
12 | "libraryDirectory": "cjs/components",
13 | "styleLibraryDirectory": "cjs/components",
14 | "style": "css"
15 | }
16 | ]
17 | ];
18 | return {
19 | plugins
20 | };
21 | }
--------------------------------------------------------------------------------
/web-app/app/form/index.less:
--------------------------------------------------------------------------------
1 | .form-demo {
2 | .form-demo-main {
3 | padding: 8px 16px;
4 | .header-title {
5 | border-bottom: 1px solid #eee;
6 | margin-bottom: 32px;
7 | }
8 | .sifo-antd-form-item {
9 | .sifo-antd-form-item-control {
10 | .ant-select {
11 | width: 100%;
12 | }
13 | }
14 | }
15 | .field-panel{
16 | }
17 | }
18 | .footer-opt {
19 | text-align: center;
20 | padding: 16px;
21 | .ant-btn {
22 | margin: 0 8px;
23 | }
24 | }
25 | }
26 | .sifo-antd-form-item-label,.sifo-antd-form-item-control{
27 | // line-height: 32px;
28 | }
--------------------------------------------------------------------------------
/web-app/app/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDom from 'react-dom';
3 | import {
4 | BrowserRouter as Router,
5 | Switch,
6 | Route
7 | } from 'react-router-dom';
8 | import FormPanel from './formPanel';
9 | import Main from './main';
10 |
11 | function App() {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | );
24 | }
25 |
26 | ReactDom.render(
27 | ,
28 | document.getElementById('root')
29 | );
30 |
--------------------------------------------------------------------------------
/packages/sifo-react/src/modelPlugins/index.js:
--------------------------------------------------------------------------------
1 | import ComponentNotFound from './ComponentNotFound';
2 | import componentRenderProxy from './component-proxy';
3 | import ReactModelPlugin from './ReactModelPlugin';
4 |
5 | const { ComponentRenderProxyPre, ComponentRenderProxyAfter } = componentRenderProxy;
6 | // 注意PluginResetter单独用
7 | // // 后置插件
8 | const presetPlugins = [
9 | { modelPlugin: ComponentRenderProxyAfter },
10 | { modelPlugin: ComponentNotFound },
11 | ];
12 |
13 | // 前置插件
14 | export const baseOrderPlugins = [
15 | { modelPlugin: ComponentRenderProxyPre },
16 | { modelPlugin: ReactModelPlugin }
17 | ];
18 |
19 | export default presetPlugins;
20 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/es.babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | console.log('es babel config read!');
4 | const presets = [
5 | [
6 | "@babel/preset-env",
7 | {
8 | modules: false
9 | }
10 | ]
11 | ];
12 | const plugins = [
13 | [
14 | "@babel/plugin-transform-runtime",
15 | {
16 | "corejs": false,
17 | "helpers": true,
18 | "regenerator": true,
19 | "useESModules": false
20 | }
21 | ],
22 | ['@babel/plugin-proposal-class-properties', { loose: true }]
23 | ];
24 | return {
25 | presets,
26 | plugins,
27 | };
28 | }
--------------------------------------------------------------------------------
/web-app/extensions/system/notice.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 | import NoticeComp from './NoticeComp';
3 |
4 | const pagePlugin = {
5 | onNodePreprocess: node => {
6 | if (node.id === 'main_id') {
7 | node.children.unshift({
8 | component: 'NoticeComp'
9 | });
10 | }
11 | }
12 | };
13 | const singleton = new SifoSingleton('form-demo');
14 |
15 | singleton.registerItem('noticeExt', () => {
16 | return {
17 | plugins: [
18 | {
19 | pagePlugin
20 | }
21 | ],
22 | components: {
23 | NoticeComp
24 | }
25 | };
26 | });
27 |
28 | export default singleton;
29 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "independent",
3 | "npmClient": "npm",
4 | "command": {
5 | "publish": {
6 | "ignoreChanges": [
7 | "*.txt",
8 | "docs/**",
9 | "examples/**",
10 | "examples-vue/**",
11 | "**/test/**",
12 | "**/demo/**",
13 | "node_modules/",
14 | "**/node_modules/"
15 | ],
16 | "message": "chore(release): publish"
17 | },
18 | "bootstrap": {
19 | "sifo-build-remarks": ["packages using different build tools"],
20 | "hoist": false,
21 | "npmClientArgs": ["--no-package-lock"]
22 | }
23 | },
24 | "packages": [
25 | "packages/*"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/radio/index.less:
--------------------------------------------------------------------------------
1 | .sifo-adm-form-item-content{
2 | .adm-radio {
3 | .sifo-adm-radio-icon{
4 | display: block;
5 | width: 16px;
6 | height: 16px;
7 | flex-shrink: 0;
8 | flex-grow: 0;
9 | border: 1px solid #ccc;
10 | border-radius: 50%;
11 | transform: rotate(0deg);
12 | box-sizing: border-box;
13 | }
14 | &.adm-radio-checked {
15 | .sifo-adm-radio-icon{
16 | border: 3px solid #1a6df8;
17 | }
18 | }
19 | &.adm-radio-checked.adm-radio-disabled{
20 | .sifo-adm-radio-icon{
21 | border: 3px solid #b7b7b7;
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/es.babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | console.log('es babel config read!');
4 | const presets = [
5 | [
6 | "@babel/preset-env",
7 | {
8 | modules: false
9 | }
10 | ],
11 | "@babel/preset-react"
12 | ];
13 | const plugins = [
14 | [
15 | "@babel/plugin-transform-runtime",
16 | {
17 | "corejs": false,
18 | "helpers": true,
19 | "regenerator": true,
20 | "useESModules": false
21 | }
22 | ],
23 | ['@babel/plugin-proposal-class-properties', { loose: true }]
24 | ];
25 | return {
26 | presets,
27 | plugins,
28 | };
29 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/es.babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | console.log('es babel config read!');
4 | const presets = [
5 | [
6 | "@babel/preset-env",
7 | {
8 | modules: false
9 | }
10 | ],
11 | "@babel/preset-react"
12 | ];
13 | const plugins = [
14 | [
15 | "@babel/plugin-transform-runtime",
16 | {
17 | "corejs": false,
18 | "helpers": true,
19 | "regenerator": true,
20 | "useESModules": false
21 | }
22 | ],
23 | ['@babel/plugin-proposal-class-properties', { loose: true }]
24 | ];
25 | return {
26 | presets,
27 | plugins,
28 | };
29 | }
--------------------------------------------------------------------------------
/examples-vue/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/web-app/build/webpack.config.dll.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | const webpack = require("webpack");
3 | const path = require("path");
4 | const DIST_PATH = path.resolve(__dirname, '../dist');
5 | module.exports = {
6 | context: __dirname,
7 | entry: {
8 | vendor: ['react', 'react-dom','react-router','react-router-dom', 'load-js']
9 | },
10 | // devtool: "source-map",
11 | mode: "production",
12 | output: {
13 | path: DIST_PATH,
14 | filename: "[name].js",
15 | library: "[name]"
16 | },
17 | plugins: [
18 | new webpack.DllPlugin({
19 | context:__dirname,
20 | path: path.join(__dirname, "vendor", "[name]-manifest.json"),
21 | name: "[name]"
22 | })
23 | ]
24 | };
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | node_modules/
7 | /packages/*/node_modules
8 | /packages/*/lib
9 | /packages/*/dist
10 | /examples/*/node_modules
11 | /examples/*/lib
12 | /examples/*/dist
13 | /examples/*/package-lock.json
14 | /**/.umi/
15 | dist/
16 | mochawesome-reports/
17 | lib/
18 | es/
19 | package-lock.json
20 | packages/*/package-lock.json
21 |
22 | .idea
23 | .vscode
24 |
25 | # local env files
26 | .env.local
27 | .env.*.local
28 |
29 | # Log files
30 | npm-debug.log*
31 | yarn-debug.log*
32 | yarn-error.log*
33 | pnpm-debug.log*
34 |
35 | # Editor directories and files
36 | .idea
37 | .vscode
38 | *.suo
39 | *.ntvs*
40 | *.njsproj
41 | *.sln
42 | *.sw?
43 |
--------------------------------------------------------------------------------
/web-app/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | .build
4 | npm-debug.log
5 | npm-debug.log.*
6 | node_modules/
7 | /packages/*/node_modules
8 | /packages/*/lib
9 | /packages/*/dist
10 | /examples/*/node_modules
11 | /examples/*/lib
12 | /examples/*/dist
13 | /examples/*/package-lock.json
14 | /**/.umi/
15 | dist/
16 | mochawesome-reports/
17 | lib/
18 | es/
19 | package-lock.json
20 | packages/*/package-lock.json
21 |
22 | .idea
23 | .vscode
24 |
25 | # local env files
26 | .env.local
27 | .env.*.local
28 |
29 | # Log files
30 | npm-debug.log*
31 | yarn-debug.log*
32 | yarn-error.log*
33 | pnpm-debug.log*
34 |
35 | # Editor directories and files
36 | .idea
37 | .vscode
38 | *.suo
39 | *.ntvs*
40 | *.njsproj
41 | *.sln
42 | *.sw?
43 |
--------------------------------------------------------------------------------
/web-app/build/webpack.dev.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | const path = require('path');
3 | const webpack = require('webpack');
4 | const { merge } = require('webpack-merge');
5 | const DIST_PATH = path.resolve(__dirname, '../dist');
6 | const baseWebpackConfig = require('./webpack.base');
7 | module.exports = merge(baseWebpackConfig, {
8 | mode: 'development',
9 | devServer: {
10 | contentBase: DIST_PATH,
11 | port: 8082,
12 | host: "127.0.0.1",
13 | historyApiFallback: true,
14 | overlay: true,
15 | open: true,
16 | hot: true,
17 | },
18 | //devtool: 'eval-source-map',
19 | output: {
20 | filename: '[name].js',
21 | path: DIST_PATH
22 | },
23 | plugins: [new webpack.HotModuleReplacementPlugin()]
24 | });
--------------------------------------------------------------------------------
/web-app/extensions/system/english.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 | import config from './english-config';
3 |
4 | const pagePlugin = {
5 | onNodePreprocess(node) {
6 | const tItem = config.find(item => item.id === node.id);
7 | if (tItem) {
8 | return {
9 | ...node,
10 | attributes: {
11 | ...node.attributes,
12 | ...tItem.attributes,
13 | }
14 | };
15 | }
16 | return node;
17 | }
18 | };
19 | const singleton = new SifoSingleton('form-demo');
20 |
21 | singleton.registerItem('englishExt', () => {
22 | return {
23 | plugins: [
24 | {
25 | pagePlugin
26 | }
27 | ]
28 | };
29 | });
30 |
31 | export default singleton;
32 |
33 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/README.md:
--------------------------------------------------------------------------------
1 | # SifoDragModelPlugin
2 |
3 | Sifo 拖拽模型插件,在以任意组件与初始 Schema 渲染的基础上,支持对组件进行即时拖拽,构建出新的 Schema.
4 |
5 | ### 设计器 props:
6 | * id: 设计器节点id
7 | * instanceId: sifoApp 实例id
8 | * onDragStart: 拖入添加时调用,参数是节点数据 (newNode)=> bool;
9 | * onDragEnd: 拖入动作结束时调用
10 | * updateAttributes: 更新节点属性,(id, attributes, needReload = false) => {
11 | * updateId: 更新节点id,(id, newId) => void;
12 | * replaceComponent: 更新节点组件,(id, componentName, needReload = false) => void;
13 | * deleteNode: 删除指定节点,id=>void;
14 | * addChildNode: 添加子节点,(newNode, targetId) => bool;
15 | * getSchema: 获取编辑后的schema,等效于 () => this.mApi.getEditedSchema(),
16 | * getNodeInfo: 获取指定节点信息,id => info;
17 | * getDomById: 获取指定节点的DOM,id => Dom;
18 | * setSelectedId: 设置选中的节点id;
19 |
20 | 具体请参照 sifo-mplg-drag-react 和 sifo-mplg-drag-vue.
--------------------------------------------------------------------------------
/examples-vue/src/index.less:
--------------------------------------------------------------------------------
1 | .vue-demo-root {
2 | padding: 16px;
3 | .complex-demo{
4 | padding: 32px;
5 | .sifo-vue {
6 | padding: 16px;
7 | margin: 16px;
8 | }
9 | .vue-app {
10 | border: 1px solid #ccc;
11 | border-radius: 5px;
12 | .ant-input {
13 | margin: 8px;
14 | }
15 | .ant-btn {
16 | margin: 8px;
17 | }
18 | }
19 | .even {
20 | border-color: green;
21 | }
22 | .odd {
23 | border-color: sandybrown;
24 | }
25 | }
26 | }
27 | code {
28 | border-radius: 2px;
29 | background: #f7f7f7;
30 | padding: 0px 5px;
31 | color: red;
32 | }
33 | .decorator-test{
34 | width: 300px;
35 | border: 1px solid #ccc;
36 | padding: 32px;
37 | .ant-input{
38 | margin: 4px 0;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/components/s-container.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{label}}
4 |
5 |
6 |
7 |
8 |
9 |
33 |
34 |
37 |
--------------------------------------------------------------------------------
/packages/sifo-singleton/test/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "id":"container",
3 | "component": "Container",
4 | "attributes": {
5 | "label": "容器"
6 | },
7 | "children": [
8 | {
9 | "component": "Input",
10 | "attributes": {
11 | "onChange": "{onSubjectChange}",
12 | "className": "pcp-subject",
13 | "dataType": "text",
14 | "id": "subject",
15 | "name": "subject",
16 | "label": "询价单标题",
17 | "rules": {
18 | "required": true,
19 | "maxLength": 60
20 | }
21 | }
22 | },
23 | {
24 | "component": "Input",
25 | "attributes": {
26 | "dataType": "text",
27 | "id": "test02",
28 | "name": "test02",
29 | "label": "test02",
30 | "rules": {
31 | }
32 | }
33 | }
34 | ]
35 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/es.babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | console.log('es babel config read!');
4 | const presets = [
5 | [
6 | "@babel/preset-env",
7 | {
8 | modules: false
9 | }
10 | ],
11 | "@babel/preset-react",
12 | [
13 | "@babel/preset-typescript",
14 | {
15 | "happyPackMode": true,
16 | "transpileOnly": true
17 | }
18 | ]
19 | ];
20 | const plugins = [
21 | [
22 | "@babel/plugin-transform-runtime",
23 | {
24 | "corejs": false,
25 | "helpers": true,
26 | "regenerator": true,
27 | "useESModules": false
28 | }
29 | ],
30 | ['@babel/plugin-proposal-class-properties', { loose: true }]
31 | ];
32 | return {
33 | presets,
34 | plugins,
35 | };
36 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/split-panel/index.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import './index.less';
4 |
5 | const SplitPanel = props => {
6 | const { label, colNum, children } = props;
7 | let count = React.Children.count(props.children);
8 | if (count === 0) return null;
9 | // 如果有传列数,直接按列数分
10 | if (colNum) {
11 | count = colNum
12 | }
13 | const style = { width: (100 / count) + "%" };
14 | return (
15 |
16 | {
17 | React.Children.map(children, (child, i) => {
18 | return (
19 |
20 | {
21 | child
22 | }
23 |
24 | )
25 | })
26 | }
27 |
28 | );
29 | }
30 |
31 | export default SplitPanel;
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/checkbox/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Checkbox, Space } from 'antd-mobile';
3 |
4 | interface CheckboxProps {
5 | dataSource: any;
6 | value: any;
7 | onChange: any;
8 | }
9 | const CheckboxX = (props:CheckboxProps) => {
10 | const {
11 | dataSource = [], value, onChange, ...other
12 | } = props;
13 | return (
14 |
15 |
16 | {(dataSource || []).map(item => {
17 | return (
18 |
19 | {item.label || item.value}
20 |
21 | );
22 | })}
23 |
24 |
25 | );
26 | };
27 |
28 | export default CheckboxX;
29 |
--------------------------------------------------------------------------------
/packages/sifo-react/src/modelPlugins/ReactModelPlugin.js:
--------------------------------------------------------------------------------
1 | class ReactModelPlugin {
2 | static ID = 'sifo_react_model_plugin';
3 | constructor(props) {
4 | const { sifoReactInstance } = props;
5 | this.mApi = null;
6 | this.sifoReactInstance = sifoReactInstance;
7 | }
8 | onModelApiCreated = params => {
9 | const { mApi, event } = params;
10 | this.mApi = mApi;
11 | const { applyModelApiMiddleware } = event;
12 | // 定义获取react实例的接口
13 | const getSifoExtProps = next => () => {
14 | const { props = {} } = this.sifoReactInstance || {};
15 | const { sifoExtProps = {} } = props;
16 | return next(sifoExtProps);
17 | };
18 | applyModelApiMiddleware('getSifoExtProps', getSifoExtProps);
19 | }
20 | onDestroy = () => {
21 | this.sifoReactInstance = null;
22 | }
23 | }
24 |
25 | export default ReactModelPlugin;
26 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/src/index.js:
--------------------------------------------------------------------------------
1 | import defaultFormItemWrapper from './componentWrap';
2 |
3 | class AntdFormModelPlugin {
4 | static ID = 'sifo_antd_form_model_plugin';
5 | constructor(props) {
6 | const { formItemWrapper, formItemProps = {} } = props || {};
7 | this.mApi = null;
8 | this.formItemWrapper = formItemWrapper || defaultFormItemWrapper;
9 | // 统一配置 FormItem 属性,如 labelAlign, labelCol
10 | this.formItemProps = formItemProps;
11 | }
12 | onComponentsWrap = components => {
13 | const rComp = Object.assign({}, components);
14 | const wrappedComps = {};
15 | // 包含FormItem组件,识别__isField__属性
16 | Object.keys(rComp).forEach(key => {
17 | const comp = rComp[key];
18 | wrappedComps[key] = this.formItemWrapper(comp, this.formItemProps);
19 | });
20 | return wrappedComps;
21 | }
22 | }
23 | export default AntdFormModelPlugin;
24 |
--------------------------------------------------------------------------------
/web-app/extensions/system/notice.less:
--------------------------------------------------------------------------------
1 | .cosultation-wrap {
2 | background-color: #f9d4a5;
3 | color: #1890ff;
4 | border: 1px solid #eee;
5 | margin-bottom: 32px;
6 | a {
7 | height: 32px;
8 | display: flex;
9 | align-items: center;
10 | width: 100%;
11 | box-sizing: border-box;
12 | .cosulation-news {
13 | position: relative;
14 | padding: 0 16px;
15 | top: 0;
16 | font-size: 13px;
17 | line-height: 32px;
18 | flex-grow: 1;
19 | height: 32px;
20 | overflow: hidden;
21 | > div {
22 | position: absolute;
23 | top: 0;
24 | .consulation-news-item {
25 | width: 100%;
26 | line-height: 32px;
27 | height: 32px;
28 | }
29 | }
30 | .anim {
31 | transition: all 0.5s;
32 | margin-top: -32px; // 向上移动32px
33 | }
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/examples-vue/src/demos/test-decorator.js:
--------------------------------------------------------------------------------
1 |
2 | import { sifoAppDecorator } from "@schema-plugin-flow/sifo-vue";
3 | import TestDecorator from './test-decorator-target.vue';
4 |
5 | const componentPlugin = {
6 | 'test-sifo-decorator': {
7 | onComponentInitial: params => {
8 | const { event, mApi } = params;
9 | mApi.addEventListener(event.key, 'click', (ctx, ...arg) => {
10 | console.log('decorator: clicked', ctx, arg);
11 | const extProps = mApi.getSifoExtProps();
12 | console.log("getSifoExtProps in : ", extProps);
13 | });
14 | }
15 | }
16 | };
17 | const plugins = [{ componentPlugin }];
18 | const App = sifoAppDecorator('test-sifo-decorator', {
19 | externals: { aa: 1 },
20 | plugins,
21 | fragments: ['$dynamic_panel', '$static_panel'],
22 | class: "decorator-test",
23 | openLogger: false
24 | })(TestDecorator);
25 | export default App;
26 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/src/editor/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
29 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/src/index.js:
--------------------------------------------------------------------------------
1 | import defaultFormItemWrapper from './componentWrap';
2 |
3 | class FusionFormModelPlugin {
4 | static ID = 'sifo_fusion_form_model_plugin';
5 | constructor(props) {
6 | const { formItemWrapper, formItemProps = {} } = props || {};
7 | this.mApi = null;
8 | this.formItemWrapper = formItemWrapper || defaultFormItemWrapper;
9 | // 统一配置 FormItem 属性,如 labelAlign, labelCol
10 | this.formItemProps = formItemProps;
11 | }
12 | onComponentsWrap = components => {
13 | const rComp = Object.assign({}, components);
14 | const wrappedComps = {};
15 | // 包含FormItem组件,识别__isField__属性
16 | Object.keys(rComp).forEach(key => {
17 | const comp = rComp[key];
18 | wrappedComps[key] = this.formItemWrapper(comp, this.formItemProps);
19 | });
20 | return wrappedComps;
21 | }
22 | }
23 | export default FusionFormModelPlugin;
24 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/drag-editor/components/common-props-render.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
37 |
--------------------------------------------------------------------------------
/web-app/extensions/customerA/submitCheck.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Modal, Input } from 'antd';
3 | const { confirm } = Modal;
4 |
5 | export function showPasswordConfirm(props) {
6 | let pswd = '';
7 | const onChange = e => {
8 | pswd = e.target.value;
9 | }
10 | confirm({
11 | title: '特殊入库授权',
12 | content: (
13 |
14 |
化学品类一般要求放到三号仓库,建议重新选择仓库,如果仍要入库,请输入特殊入库授权码:
15 |
(visible ? : )}
19 | />
20 |
21 | ),
22 | ...props,
23 | onOk: () => {
24 | if (props.onOk) {
25 | return props.onOk(pswd);
26 | } else {
27 | return Promise.reject();
28 | }
29 | }
30 | });
31 | }
32 | export default {
33 | showPasswordConfirm
34 | };
--------------------------------------------------------------------------------
/packages/sifo-react/src/utils/tags.js:
--------------------------------------------------------------------------------
1 | const TAGS = [
2 | 'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr',
3 | ];
4 | export default TAGS;
5 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/demo/default/componnetPlugin.jsx:
--------------------------------------------------------------------------------
1 | const componentPlugin = {
2 | subject01: {
3 | onComponentInitial: params => {
4 | const { event, mApi } = params;
5 | const originCompName = mApi.getComponentName(event.key);
6 | const comps = mApi.getComponents();
7 | const originComp = comps[originCompName];
8 | mApi.replaceComponent(event.key, 'CWrap');
9 | mApi.setAttributes(event.key, {
10 | itemChildren: originComp,
11 | placeholder: "包装原来的节点组件",
12 | style: {
13 | borderLeft: '2px solid red',
14 | paddingBottom: '8px'
15 | }
16 | })
17 | }
18 | },
19 | test01: {
20 | onComponentInitial: params => {
21 | const { event, mApi } = params;
22 | mApi.setAttributes(event.key, {
23 | placeholder: '关闭渲染标记',
24 | muteRenderOptimizeMark: true, // 关闭渲染标记
25 | });
26 | }
27 | }
28 | }
29 |
30 | export default componentPlugin;
31 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/src/dragImgs.js:
--------------------------------------------------------------------------------
1 | const moveImgBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAfxJREFUWEftl7Fu1EAQhr+5o0FKEwnEkkgR9dGkSI2OlgJocnU6usQ8AaEhpR0eIxQokaiJIqWjDW+Q054iRTQ0SLlBa+Wc9cl7dtZ3R4Nb744/z//vzoxQ85hMjxG2UNbq1jZ6LwxRfthE3rj1MmuTyVQbBY1cZBORIIDJ9AjYjozddNuXWQAWeJJHUj7S5cjuys+mkavWPUr16QN4h/Dh9v1oFsBd+pWX9r2ctvm4v9eXthGA02peH3dxTKbfgX7JhIt2+1QGygDLcHsQYFlut4kMJhAlCUymc3e7+aw9bhj4breJmBDAQtxuUu0jOK3zxzfydAYKgAW4vTL2f4DWGbjV112nV3TYD13R/vGeqwf8PwAu6DCoglgcwKG+QvnmXS6VEK0A1lJ9O4bNYA0QelPl2snR9zMRDbBxoKt/HnJ93wKk8GuUyKp34cQdw1gA4LdNZKU1gAvwTyWoS71pb8JCGgkZpaZZLer5fY6hSfUZsFMUKWEYBfA41c2u8FWFcxE+NbmIAj90EgVQJ1GVCav25G15jAQtAUbA2aRBWRpAqNSXAOjwvG3vX6TfdUVjLqoaEj+DYg71spj73AACp21ngLxaurZ7MoAIQ7sn61XSuQwcA6+b6hq57mQyjE7vzweOZbflJQm8I+OG0RfFPBj5q962kttD4f4CZFdoofuHhuIAAAAASUVORK5CYII=';
2 |
3 | const moveImg = new Image(32, 32);
4 | moveImg.src = moveImgBase64;
5 | // document.body.appendChild(moveImg);
6 | export default {
7 | moveImg
8 | };
9 |
--------------------------------------------------------------------------------
/web-app/extensions/customerB/index.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 | import ShowWarehouseCapacity from './ShowWarehouseCapacity';
3 | import './index.less';
4 | // 客户B在选择仓库时,需要能即时查询库存容量状态,以便选择最合适的仓库
5 | const componentPlugin = {
6 | warehouse: {
7 | onComponentInitial: params => {
8 | const { event, mApi } = params;
9 | // 替换成可展示库存数量的组件
10 | const originCompName = mApi.getComponentName(event.key);
11 | const comps = mApi.getComponents();
12 | const originComp = comps[originCompName];
13 | mApi.replaceComponent(event.key, 'ShowWarehouseCapacity');
14 | mApi.setAttributes(event.key, {
15 | itemChildren: originComp
16 | });
17 | }
18 | }
19 | };
20 | const singleton = new SifoSingleton('form-demo');
21 | singleton.registerItem('customerB_Ext', () => {
22 | return {
23 | plugins: [
24 | {
25 | componentPlugin
26 | }
27 | ],
28 | components: { ShowWarehouseCapacity }
29 | };
30 | });
31 |
32 | export default singleton;
33 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/index.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-unresolved */
2 | /* eslint-disable import/extensions */
3 | import { List, Input, TextArea, ImageUploader, Cascader } from 'antd-mobile';
4 | import Button from './button';
5 | import Picker from './picker';
6 | import SplitPanel from './split-panel';
7 | import DatePicker from './date-picker';
8 | import DateRangePicker from './date-range-picker';
9 | import Container from './container';
10 | import NumberInput from './number-input';
11 | import Checkbox from './checkbox';
12 | import Radio from './radio';
13 | import CascaderPicker from './cascader-picker';
14 |
15 | const None = () => null;
16 |
17 | export default {
18 | Cascader,
19 | // 异步的级联
20 | CascaderPicker,
21 | Button,
22 | List,
23 | ListItem: List.Item,
24 | None, // 由于sifo-adm-form的字段识别依赖组件的渲染
25 | Container,
26 | Picker,
27 | ImageUploader,
28 | Input,
29 | DatePicker,
30 | DateRangePicker,
31 | Checkbox,
32 | TextArea,
33 | SplitPanel,
34 | Radio,
35 | NumberInput
36 | };
37 |
--------------------------------------------------------------------------------
/packages/sifo-react/src/modelPlugins/ComponentNotFound.js:
--------------------------------------------------------------------------------
1 | import TAGS from '../utils/tags';
2 |
3 | class ComponentNotFound {
4 | static ID = 'component_not_found_model_plugin';
5 | constructor() {
6 | this.components = {};
7 | this.notFoundList = [];
8 | }
9 | onComponentsWrap = components => {
10 | Object.assign(this.components, components);
11 | }
12 | onSchemaInstantiated = params => {
13 | const { event } = params;
14 | const { schemaInstance } = event;
15 | schemaInstance.loopDown(node => {
16 | const { component } = node;
17 | if (!this.components[component]
18 | && TAGS.indexOf(component) === -1
19 | && this.notFoundList.indexOf(component) === -1) {
20 | this.notFoundList.push(component);
21 | }
22 | });
23 | if (this.notFoundList.length > 0) {
24 | console.warn('[sifo-react] Component not found: ', this.notFoundList.join(', '));
25 | }
26 | this.components = null;
27 | this.notFoundList = null;
28 | }
29 | }
30 |
31 | export default ComponentNotFound;
32 |
--------------------------------------------------------------------------------
/packages/sifo-react/demo/decoratorTest/Main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Target from './Target';
3 |
4 | class Main extends React.Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | render: true
9 | }
10 | }
11 | rerender = () => {
12 | this.setState({
13 | test: new Date().getMilliseconds().toString()
14 | })
15 | }
16 | destroy = () => {
17 | this.setState({
18 | render: !this.state.render
19 | });
20 | }
21 | render() {
22 | return
23 |
24 |
25 | {
26 | this.state.render && (
27 |
28 |
实例一
29 |
30 | ==================================
31 |
实例二
32 | {
33 |
34 | }
35 |
36 | )
37 | }
38 |
39 | }
40 | }
41 | export default Main;
--------------------------------------------------------------------------------
/packages/sifo-model/src/TaskQueue.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | class TaskQueue {
5 | taskQueue: Function[];
6 | curTaskIndex: number;
7 | constructor() {
8 | this.taskQueue = [];
9 | this.curTaskIndex = 0;
10 | }
11 | push(task: Function | Function[]) {
12 | if (Array.isArray(task)) {
13 | this.taskQueue.push(...task);
14 | } else {
15 | this.taskQueue.push(task);
16 | }
17 | return this;
18 | }
19 | run() {
20 | while (this.taskQueue.length > 0 && this.curTaskIndex < this.taskQueue.length) {
21 | this.next();
22 | }
23 | return this;
24 | }
25 | private next() {
26 | if (this.taskQueue.length > this.curTaskIndex) {
27 | const curTask = this.taskQueue[this.curTaskIndex];
28 | this.curTaskIndex = this.curTaskIndex + 1;
29 | // tslint:disable-next-line: no-unused-expression
30 | curTask && curTask();
31 | }
32 | }
33 | discard() {
34 | this.taskQueue = [];
35 | this.curTaskIndex = 0;
36 | return this;
37 | }
38 | }
39 |
40 | export default TaskQueue;
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/radio/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Radio, Space } from 'antd-mobile';
3 | import './index.less';
4 |
5 | interface RadioProps {
6 | dataSource: any;
7 | value: any;
8 | onChange: any;
9 | }
10 | const RadioX = (props: RadioProps) => {
11 | const {
12 | dataSource = [], value, onChange, ...other
13 | } = props;
14 | return (
15 |
16 |
17 | {(dataSource || []).map(item => {
18 | return (
19 | }
24 | value={item.value}
25 | >
26 | {item.label || item.value}
27 |
28 | );
29 | })}
30 |
31 |
32 | );
33 | };
34 |
35 | export default RadioX;
36 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/quick-start-ext.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 | const singleton = new SifoSingleton('quick-start'); // namespace: quick-start
3 | const componentPlugin = {
4 | test_btn_id: {
5 | onComponentInitial: params => {
6 | const { event, mApi } = params;
7 | mApi.addEventListener(event.key, 'click', () => {
8 | mApi.setAttributes('slogan_id', {
9 | style: { color: 'red' }
10 | });
11 | })
12 | }
13 | }
14 | };
15 | const pagePlugin = {
16 | onNodePreprocess: (node, info) => {
17 | const { id, component, children } = node;
18 | if (id == 'mainId') {
19 | children.unshift(
20 | "This is a extension for quick-start in another js, it changes the color of slogan when the button is clicked.",
21 | {
22 | component: "hr"
23 | }
24 | );
25 | }
26 | },
27 | }
28 | singleton.registerItem('ext-quick-start', () => {
29 | return {
30 | plugins:[
31 | { componentPlugin, pagePlugin }
32 | ],
33 | components: {},
34 | openLogger: true
35 | }
36 | });
--------------------------------------------------------------------------------
/packages/sifo-react/src/modelPlugins/component-proxy/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | import componentWrap from './componentWrap';
5 |
6 | function wrapper(components) {
7 | const wrappedComps = { ...components };
8 | Object.keys(components).forEach(name => {
9 | const component = components[name];
10 | // React.forwardRef 返回带render方法的对象作为组件,增加useSifoRenderProxy标
11 | if (component && component.useSifoRenderProxy &&
12 | component.render && typeof component.render === 'function') {
13 | wrappedComps[name] = componentWrap(component);
14 | }
15 | });
16 | return wrappedComps;
17 | }
18 | /**
19 | * 对提供render(element, props)方法类型的“组件”进行一次封装,以转化为普通React组件
20 | */
21 | class ComponentRenderProxyPre {
22 | static ID = 'render_object_type_component_proxy_pre';
23 | onComponentsWrap = wrapper;
24 | }
25 | /**
26 | * 后置位置时还要进行一次,因为有可能有新的组件加入
27 | */
28 | class ComponentRenderProxyAfter {
29 | static ID = 'render_object_type_component_proxy_after';
30 | onComponentsWrap = wrapper;
31 | }
32 |
33 | export default { ComponentRenderProxyPre, ComponentRenderProxyAfter };
34 |
35 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/test/component.test.js:
--------------------------------------------------------------------------------
1 | // 引入基础依赖
2 | import React from 'react';
3 | import { expect } from 'chai'; // 断言库
4 | // 引入待测试组件
5 | import SifoReactOptimizeModelPlugin from '../src/index';
6 |
7 |
8 | // 测试描述语法参照 mocha 官方文档 https://mochajs.org/
9 | describe('import', () => {
10 | it('should import correctly', () => {
11 | expect(SifoReactOptimizeModelPlugin).to.not.eql(undefined);
12 | });
13 | });
14 |
15 | describe('render', () => {
16 | let componentWrapper = {};
17 |
18 | before(function () {
19 | // runs before all tests in this block
20 | });
21 |
22 | after(function () {
23 | // runs after all tests in this block
24 | });
25 |
26 | beforeEach(function () {
27 | // runs before each test in this block
28 | componentWrapper = mount(
29 |
30 | );
31 | });
32 |
33 | afterEach(function () {
34 | // runs after each test in this block
35 | componentWrapper.unmount();
36 | });
37 |
38 | // test cases
39 | it('should render correctly', () => {
40 | expect(componentWrapper).to.exist;
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Alibaba
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/sifo-vue/index.d.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | declare module '@schema-plugin-flow/sifo-vue' {
4 | import * as SifoModelTypes from '@schema-plugin-flow/sifo-model';
5 | export { SifoModelTypes };
6 |
7 | export interface SifoAppProps {
8 | className?: string;
9 | /**
10 | * SifoModel插件
11 | */
12 | plugins?: SifoModelTypes.SifoPlugin[];
13 | /**
14 | * 命名空间
15 | */
16 | namespace: string;
17 | schema: SifoModelTypes.SchemaNode;
18 | components: SifoModelTypes.ModelOptions['components'];
19 | /**
20 | * 任意外部信息
21 | */
22 | externals?: SifoModelTypes.ModelOptions['externals'];
23 | /**
24 | * 模型实例化可选参数
25 | */
26 | modelApiRef?: SifoModelTypes.ModelOptions['modelApiRef'];
27 | /**
28 | * 是否开启sifo-logger打印
29 | */
30 | openLogger?: boolean;
31 | getModelPluginArgs?: SifoModelTypes.ModelOptions['getModelPluginArgs'];
32 | /**
33 | * 任意对象,mApi.getSifoExtProps 可以取到即时的值,这点与 externals 相区别
34 | */
35 | sifoExtProps?: SifoModelTypes.DynamicObject;
36 | }
37 | interface sifoApp {
38 | [key: string]: any;
39 | }
40 | export default sifoApp;
41 | }
42 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/no-unresolved */
2 | import defaultFormItemWrapper from './componentWrap';
3 | // eslint-disable-next-line import/extensions
4 | import Form from './form';
5 |
6 | export { default as baseComponents } from './components';
7 |
8 | class AdmFormModelPlugin {
9 | static ID = 'sifo_antd_form_model_plugin';
10 | constructor(props) {
11 | const { formItemWrapper, formItemProps = {} } = props || {};
12 | this.mApi = null;
13 | this.formItemWrapper = formItemWrapper || defaultFormItemWrapper;
14 | this.mApi = null;
15 | // this.formItemWrapper = componentWrap;
16 | // 统一配置 FormItem 属性,如 labelAlign, labelCol
17 | this.formItemProps = formItemProps;
18 | }
19 | onComponentsWrap = components => {
20 | const rComp = Object.assign({}, components, { Form });
21 | const wrappedComps = {};
22 | // 包含FormItem组件,识别__isField__属性
23 | Object.keys(rComp).forEach(key => {
24 | const comp = rComp[key];
25 | wrappedComps[key] = this.formItemWrapper(comp, this.formItemProps);
26 | });
27 | return wrappedComps;
28 | }
29 | }
30 | export default AdmFormModelPlugin;
31 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/src/index.scss:
--------------------------------------------------------------------------------
1 | .sifo-fusion-form-item {
2 | margin-bottom: 16px;
3 | &-label{
4 | display: inline-block;
5 | padding-right: 12px;
6 | overflow: hidden;
7 | // line-height: 32px;
8 | color: #585d66;
9 | white-space: nowrap;
10 | text-align: right;
11 | vertical-align: top;
12 | >label{
13 | color: #000000d9;
14 | }
15 | &-top {
16 | margin-bottom: 2px;
17 | }
18 | &-text-left {
19 | text-align: left;
20 | }
21 | }
22 | &-required:before {
23 | display: inline-block;
24 | margin-right: 4px;
25 | color: #ff3b30;
26 | font-size: 14px;
27 | line-height: 1;
28 | content: "*";
29 | }
30 | &-control{
31 | position: relative;
32 | font-size: 14px;
33 | //line-height: 32px;
34 | .next-input,.next-input-group,.next-date-picker,.next-month-picker,.next-range-picker,.next-select,.next-time-picker,.next-year-picker{
35 | width: 100%;
36 | }
37 | }
38 |
39 | &-has-error {
40 | color: #ff3b30;
41 | margin-top: 4px;
42 | font-size: 12px;
43 | line-height: 1.5;
44 | }
45 | }
46 | .sifo-fusion-form-item-with-error {
47 | // margin-bottom: 0; fusion 校验会影响布局
48 | }
--------------------------------------------------------------------------------
/web-app/app/index.less:
--------------------------------------------------------------------------------
1 | .form-demo-space {
2 | height: 100vh;
3 | .form-demo-row {
4 | height: 100%;
5 | .form-demo-settings {
6 | border-left: 1px solid #1890ff;
7 | padding: 16px;
8 | .setting-type{
9 | margin: 16px 16px 16px 0;
10 | }
11 | .setting-title {
12 | color: #002af7;
13 | border-bottom: 1px solid #eee;
14 | .setting-sub-title {
15 | color: #002af7;
16 | }
17 | }
18 | .ant-checkbox-group-item {
19 | //display: block;
20 | margin-bottom: 8px;
21 | }
22 | .system-setting{
23 | margin-bottom: 8px;
24 | }
25 | .customer-setting {
26 | .ant-select {
27 | width: 200px;
28 | }
29 | .customer-description {
30 | border: 1px solid #ccc;
31 | background: #fdfbb3;
32 | padding: 4px;
33 | margin: 8px 0;
34 | }
35 | }
36 | }
37 | .form-demo-display {
38 |
39 | }
40 | }
41 | }
42 | .form-demo-iframe{
43 | width: 100%;
44 | min-height: 450px;
45 | height: 100%;
46 | outline: none;
47 | border: none;
48 | }
49 | .form-demo-spin{
50 | width: 100%;
51 | margin: 50px 0;
52 | }
--------------------------------------------------------------------------------
/packages/sifo-react/src/utils/render-factory.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | import React from 'react';
5 | import TAGS from './tags';
6 |
7 | /**
8 | * 根据schema渲染为相应react树
9 | * @param {*} props
10 | */
11 | function renderFactory(schemaNode, components) {
12 | const {
13 | component,
14 | attributes = {},
15 | children = [],
16 | } = schemaNode;
17 | if (!component) return null;
18 | let Component = null;
19 | const targetComp = components[component];
20 | if (!targetComp) {
21 | if (TAGS.indexOf(component) === -1) return null;
22 | Component = component; // 使用原生tag
23 | } else {
24 | Component = targetComp.default || targetComp;
25 | }
26 | const id = schemaNode.id || attributes.id;
27 | return (
28 |
32 | {
33 | children && children.length > 0 ? children.map(child => {
34 | if (!child) {
35 | return null;
36 | }
37 | if (typeof child === 'string') {
38 | return child;
39 | }
40 | return renderFactory(child, components);
41 | }) : null
42 | }
43 |
44 | );
45 | }
46 |
47 | export default renderFactory;
48 |
--------------------------------------------------------------------------------
/packages/sifo-react/index.d.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | declare module '@schema-plugin-flow/sifo-react' {
4 | import * as SifoModelTypes from '@schema-plugin-flow/sifo-model';
5 | export { SifoModelTypes };
6 |
7 | interface SifoAppProps {
8 | className?: string;
9 | /**
10 | * SifoModel插件
11 | */
12 | plugins?: SifoModelTypes.SifoPlugin[];
13 | /**
14 | * 命名空间
15 | */
16 | namespace: string;
17 | schema: SifoModelTypes.SchemaNode;
18 | components: SifoModelTypes.ModelOptions['components'];
19 | /**
20 | * 任意外部信息
21 | */
22 | externals?: SifoModelTypes.ModelOptions['externals'];
23 | /**
24 | * 模型实例化可选参数
25 | */
26 | modelApiRef?: SifoModelTypes.ModelOptions['modelApiRef'];
27 | /**
28 | * 是否开启sifo-logger打印
29 | */
30 | openLogger?: boolean;
31 | getModelPluginArgs?: SifoModelTypes.ModelOptions['getModelPluginArgs'];
32 | /**
33 | * 任意对象,mApi.getSifoExtProps 可以取到即时的值,这点与 externals 相区别
34 | */
35 | sifoExtProps?: SifoModelTypes.DynamicObject;
36 | }
37 |
38 | interface SifoAppState {
39 | refresh: number;
40 | }
41 |
42 | class SifoApp extends React.PureComponent { }
43 | export default SifoApp;
44 | }
45 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/src/componentWrap.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-underscore-dangle */
2 | const DragItemWrap = {
3 | render() {
4 | return this.$slots.default;
5 | },
6 | updated() {
7 | if (this.__dragNodeId__) {
8 | this.bindDragProps(this.__dragNodeId__, this.$el);
9 | }
10 | },
11 | mounted() {
12 | if (this.__dragNodeId__) {
13 | this.bindDragProps(this.__dragNodeId__, this.$el);
14 | }
15 | },
16 | props: ['bindDragProps', '__dragNodeId__'],
17 | };
18 | /* eslint-disable no-underscore-dangle */
19 | const componentWrap = (Component, bindDragProps) => {
20 | const SifoDragWrap = {
21 | functional: true,
22 | render(createElement, context) {
23 | const {
24 | props, __dragNodeId__, ...rest
25 | } = context.data; // 一般的属性都在props中
26 | return createElement(DragItemWrap, {
27 | key: __dragNodeId__,
28 | props: {
29 | bindDragProps,
30 | __dragNodeId__
31 | }
32 | }, [
33 | createElement(Component, {
34 | ...rest,
35 | props,
36 | key: __dragNodeId__,
37 | }, context.children)
38 | ]);
39 | },
40 | };
41 | return SifoDragWrap;
42 | };
43 |
44 | export default componentWrap;
45 |
--------------------------------------------------------------------------------
/web-app/extensions/config.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | // 描述扩展件对应的打包路径与资源地址
4 | sysExtTypes: [
5 | {
6 | label: '控制台日志插件',
7 | value: 'openlogger',
8 | path: "./extensions/system/openlogger.js",
9 | url: 'openlogger.js'
10 | },
11 | {
12 | label: '切换英文版插件', value: 'english',
13 | path: "./extensions/system/english.js",
14 | url: 'english.js'
15 | },
16 | {
17 | label: '显示系统消息插件', value: 'notice',
18 | path: "./extensions/system/notice.js",
19 | url: 'notice.js'
20 | }
21 | ],
22 | customerTyps: [
23 | {
24 | label: '客户A插件',
25 | value: 'customer-a',
26 | description: "客户A有化学品货物,需要提示入库要求,仍要提交需要验证操作员入库授权码 (演示:6个9)",
27 | path: "./extensions/customerA/index.js",
28 | url: "customer-a.js",
29 | },
30 | {
31 | label: '客户B插件',
32 | value: 'customer-b',
33 | description: "客户B在选择仓库时,需要能即时查询库存容量状态,以便选择最合适的仓库",
34 | path: "./extensions/customerB/index.js",
35 | url: "customer-b.js",
36 | },
37 | {
38 | label: '客户C插件',
39 | value: 'customer-c',
40 | description: "客户C需要保存其它信息,以便后续查阅:货物检查说明、货车车牌、司机姓名、联系方式等",
41 | path: "./extensions/customerC/index.js",
42 | url: "customer-c.js",
43 | }
44 | ]
45 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/src/index.less:
--------------------------------------------------------------------------------
1 | .sifo-antd-form-item {
2 | box-sizing: border-box;
3 | margin: 0;
4 | padding: 0;
5 | color: #000000a6;
6 | font-size: 14px;
7 | font-variant: tabular-nums;
8 | line-height: 1.5;
9 | list-style: none;
10 | font-feature-settings: 'tnum';
11 | margin-bottom: 24px;
12 | vertical-align: top;
13 | &-label{
14 | display: inline-block;
15 | padding-right: 8px;
16 | overflow: hidden;
17 | line-height: 32px;
18 | white-space: nowrap;
19 | text-align: right;
20 | vertical-align: middle;
21 | >label{
22 | color: #000000d9;
23 | }
24 | &-top {
25 | margin-bottom: 2px;
26 | }
27 | &-text-left {
28 | text-align: left;
29 | }
30 | }
31 | &-required:before {
32 | display: inline-block;
33 | margin-right: 4px;
34 | color: #f5222d;
35 | font-size: 14px;
36 | font-family: SimSun,sans-serif;
37 | line-height: 1;
38 | content: "*";
39 | }
40 | &-control{
41 | position: relative;
42 | line-height: 32px;
43 | }
44 | &-has-error {
45 | color: #f5222d;
46 | clear: both;
47 | min-height: 24px;
48 | font-size: 14px;
49 | line-height: 1.5715;
50 | }
51 | }
52 | .sifo-antd-form-item-with-error {
53 | margin-bottom: 0;
54 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/src/editor/header.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-expressions */
2 | import React from 'react';
3 | import PropTypes from 'prop-types';
4 |
5 | const Header = props => {
6 | const {
7 | deleteNode, selectedId, getSchema, onSave, title
8 | } = props;
9 | const save = () => {
10 | const schema = getSchema();
11 | onSave && onSave(schema);
12 | };
13 | const delSelectedNode = () => {
14 | if (selectedId) {
15 | deleteNode(selectedId);
16 | }
17 | };
18 | return (
19 |
20 |
{ title || 'Sifo拖拽插件'}
21 |
22 |
23 |
24 |
25 |
26 | );
27 | };
28 | Header.propTypes = {
29 | deleteNode: PropTypes.func.isRequired,
30 | selectedId: PropTypes.string,
31 | getSchema: PropTypes.func.isRequired,
32 | onSave: PropTypes.func,
33 | title: PropTypes.string,
34 | };
35 | Header.defaultProps = {
36 | selectedId: '',
37 | onSave: e => { console.log('onSave', e); },
38 | title: ''
39 | };
40 |
41 | export default Header;
42 |
--------------------------------------------------------------------------------
/web-app/app/settingPanel/settings.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | import React from 'react';
3 | import { Checkbox, Select } from 'antd';
4 |
5 | const Settings = props => {
6 | const {
7 | sysExtTypes, sysExts = [], customer = '', customerTyps, onSysExtChange, onCustomExtChange
8 | } = props;
9 | return (
10 | <>
11 |
12 |
选择系统扩展:
13 |
19 |
20 |
21 |
选择客户扩展:
22 |
30 | {
31 | customer && (
32 |
33 | {customerTyps.find(c => c.value === customer).description}
34 |
35 | )
36 | }
37 |
38 | >
39 | );
40 | };
41 |
42 | export default Settings;
43 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/src/index.less:
--------------------------------------------------------------------------------
1 | .sifo-antdv-form-item {
2 | box-sizing: border-box;
3 | margin: 0;
4 | padding: 0;
5 | color: #000000a6;
6 | font-size: 14px;
7 | font-variant: tabular-nums;
8 | line-height: 1.5;
9 | list-style: none;
10 | font-feature-settings: 'tnum';
11 | margin-bottom: 24px;
12 | vertical-align: top;
13 | &-label{
14 | display: inline-block;
15 | padding-right: 8px;
16 | overflow: hidden;
17 | line-height: 39.9999px;
18 | white-space: nowrap;
19 | text-align: right;
20 | vertical-align: middle;
21 | >label{
22 | color: #000000d9;
23 | }
24 | &-top {
25 | margin-bottom: 2px;
26 | }
27 | &-text-left {
28 | text-align: left;
29 | }
30 | }
31 | &-required:before {
32 | display: inline-block;
33 | margin-right: 4px;
34 | color: #f5222d;
35 | font-size: 14px;
36 | font-family: SimSun,sans-serif;
37 | line-height: 1;
38 | content: "*";
39 | }
40 | &-control{
41 | position: relative;
42 | line-height: 40px;
43 | zoom: 1;
44 | }
45 | &-has-error {
46 | color: #f5222d;
47 | clear: both;
48 | min-height: 24px;
49 | font-size: 14px;
50 | line-height: 1.5715;
51 | }
52 | }
53 | .sifo-antdv-form-item-with-error {
54 | margin-bottom: 0;
55 | }
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/src/componentWrap.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import PropTypes from 'prop-types';
4 |
5 | const { createElement } = React;
6 | /* eslint-disable no-underscore-dangle */
7 | const componentWrap = (Component, bindDragProps) => {
8 | class DragItemWrap extends React.Component {
9 | toBind() {
10 | const { __dragNodeId__ } = this.props;
11 | if (!__dragNodeId__) return;
12 | // eslint-disable-next-line react/no-find-dom-node
13 | const refDom = ReactDOM.findDOMNode(this);
14 | bindDragProps(__dragNodeId__, refDom);
15 | }
16 |
17 | // eslint-disable-next-line react/sort-comp
18 | componentDidUpdate() {
19 | this.toBind();
20 | }
21 |
22 | componentDidMount() {
23 | this.toBind();
24 | }
25 | render() {
26 | const {
27 | __dragNodeId__,
28 | children, ...rest
29 | } = this.props;
30 | if (!Component) return null;
31 | return createElement(Component, {
32 | key: __dragNodeId__,
33 | ...rest
34 | }, children);
35 | }
36 | }
37 | DragItemWrap.propTypes = {
38 | __dragNodeId__: PropTypes.string
39 | };
40 | DragItemWrap.defaultProps = {
41 | __dragNodeId__: ''
42 | };
43 | return DragItemWrap;
44 | };
45 |
46 | export default componentWrap;
47 |
--------------------------------------------------------------------------------
/web-app/extensions/customerC/schema.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "numberPlate",
4 | "component": "Input",
5 | "attributes": {
6 | "className": "",
7 | "fieldKey": "numberPlate",
8 | "label": "货车牌照",
9 | "placeholder": "请输入货车牌照",
10 | "rules": [
11 | {
12 | "required": true,
13 | "message": "请输入货车牌照"
14 | }
15 | ]
16 | }
17 | },
18 | {
19 | "component": "Input",
20 | "id": "driver",
21 | "attributes": {
22 | "fieldKey": "driver",
23 | "label": "司机姓名",
24 | "placeholder": "司机姓名",
25 | "rules": [
26 | {
27 | "required": true
28 | }
29 | ]
30 | }
31 | },
32 | {
33 | "component": "Input",
34 | "id": "phone",
35 | "attributes": {
36 | "fieldKey": "phone",
37 | "label": "司机联系方式",
38 | "placeholder": "司机联系方式",
39 | "rules": [
40 | {
41 | "required": true
42 | }
43 | ]
44 | }
45 | },
46 | {
47 | "component": "DatePicker",
48 | "id": "time",
49 | "attributes": {
50 | "fieldKey": "time",
51 | "showTime": true,
52 | "label": "到达时间",
53 | "placeholder": "到达时间",
54 | "style": { "width": "100%" },
55 | "rules": [
56 | {
57 | "required": true
58 | }
59 | ]
60 | }
61 | }
62 | ]
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/src/index.css:
--------------------------------------------------------------------------------
1 | .sifo-mplg-drag-editor .sifo-mplg-drag-render-plate *[draggable]:hover{
2 | outline: 1px dotted #4b90f9 !important;
3 | }
4 | .sifo-drag {
5 | outline: 2px dashed #4b90f9 !important;
6 | box-shadow: none !important;
7 | }
8 | .sifo-drag-selected {
9 | box-shadow: 0 0 0px 1px #4b90f9 !important;
10 | }
11 | .sifo-drag-selected:hover{
12 | cursor: grab;
13 | }
14 | .sifo-drag-selected:active{
15 | cursor: grabbing;
16 | }
17 | .sifo-drop-insert{
18 | box-shadow: 0 0 4px 1px #038e13 !important;
19 | }
20 | .sifo-drag-selected.sifo-drop-insert {
21 | box-shadow: 0 0 4px 1px #038e13 !important;
22 | }
23 | .sifo-drop-pre-insert {
24 | box-shadow: -1px -1px 4px 1px #36d3fa !important;
25 | }
26 | .sifo-drag-selected.sifo-drop-pre-insert {
27 | box-shadow: -1px -1px 4px 1px #36d3fa !important;
28 | }
29 | .sifo-drop-pre-insert::before{
30 | content: '';
31 | }
32 | .sifo-drop-sub-insert {
33 | box-shadow: 1px 1px 4px 1px #42d54e !important;
34 | }
35 | .sifo-drag-selected.sifo-drop-sub-insert {
36 | box-shadow: 1px 1px 4px 1px #42d54e !important;
37 | }
38 | .sifo-drop-sub-insert::after{
39 | content: '';
40 | }
41 | .sifo-drop-forbidden {
42 | box-shadow: 0px 0px 4px 1px #ff0000 !important;
43 | }
44 | .sifo-drop-forbidden::before{
45 | content: "";
46 | }
47 | .sifo-drop-forbidden:active{
48 | cursor: wait !important;
49 | }
50 |
--------------------------------------------------------------------------------
/packages/sifo-react/test/component.test.js:
--------------------------------------------------------------------------------
1 | // 引入基础依赖
2 | import React from 'react';
3 | import Enzyme, { mount } from 'enzyme'; // https://github.com/airbnb/enzyme
4 | import Adapter from 'enzyme-adapter-react-15';
5 | import chai, { expect } from 'chai'; // 断言库
6 | import chaiEnzyme from 'chai-enzyme'; // chai的enzyme中间件,API参考 https://github.com/producthunt/chai-enzyme
7 |
8 | // 引入待测试组件
9 | import SifoApp from '../src/index';
10 |
11 | // 初始化测试环境
12 | Enzyme.configure({ adapter: new Adapter() });
13 | chai.use(chaiEnzyme());
14 |
15 | // 测试描述语法参照 mocha 官方文档 https://mochajs.org/
16 | describe('import', () => {
17 | it('should import correctly', () => {
18 | expect(SifoApp).to.not.eql(undefined);
19 | });
20 | });
21 |
22 | describe('render', () => {
23 | let componentWrapper = {};
24 |
25 | before(function () {
26 | // runs before all tests in this block
27 | });
28 |
29 | after(function () {
30 | // runs after all tests in this block
31 | });
32 |
33 | beforeEach(function () {
34 | // runs before each test in this block
35 | componentWrapper = mount(
36 |
37 | );
38 | });
39 |
40 | afterEach(function () {
41 | // runs after each test in this block
42 | componentWrapper.unmount();
43 | });
44 |
45 | // test cases
46 | it('should render correctly', () => {
47 | expect(componentWrapper).to.exist;
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/packages/sifo-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-vue",
3 | "version": "1.7.0",
4 | "author": "FrominXu",
5 | "description": "A highly extensible JavaScript library, for Vue. 高扩展性、可二开的插件式前端开发框架",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-vue"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "plugin",
20 | "vue"
21 | ],
22 | "scripts": {
23 | "build": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "lint": "eslint --ext .js src/",
25 | "precommit": "npm run lint",
26 | "prepare": "npm run lint && npm run build"
27 | },
28 | "dependencies": {
29 | "@babel/runtime": "^7.12.5",
30 | "@schema-plugin-flow/sifo-model": "^1.5.0",
31 | "@schema-plugin-flow/sifo-singleton": "^1.2.0",
32 | "classnames": "^2.2.6",
33 | "uuid": "^3.3.2"
34 | },
35 | "devDependencies": {
36 | "@babel/cli": "^7.2.0",
37 | "@babel/core": "^7.2.2",
38 | "@babel/preset-env": "^7.7.1",
39 | "@babel/register": "^7.0.0",
40 | "chai": "^4.1.2",
41 | "chai-enzyme": "^1.0.0-beta.1",
42 | "eslint": "^7.6.0",
43 | "husky": "^0.14.3",
44 | "vue": "^2.6.11"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/src/validate.js:
--------------------------------------------------------------------------------
1 | import { doValidate } from './validators';
2 |
3 | function getValidators(rules, triggerType) {
4 | if (rules && Array.isArray(rules) && rules.length > 0) {
5 | if (triggerType) {
6 | const curRules = rules.filter(rl => (!rl.trigger || rl.trigger.length === 0
7 | || rl.trigger.indexOf(triggerType) >= 0));
8 | return curRules;
9 | }
10 | return rules;
11 | }
12 | return [];
13 | }
14 | /**
15 | * 触发校验,返回校验结果,调用方需要处理结果展示
16 | * @param {*} mApi
17 | * @param {*} id
18 | * @param {*} triggerType 类型如果有传,只执行相应类型的trigger
19 | * @return Promise.resolve(validateInfo)
20 | */
21 | export const validate = (id, mApi, fieldKey, triggerType) => {
22 | const attributes = mApi.getFormItemProps(id) || {};
23 | const {
24 | value, validators, rules, validateDisabled
25 | } = attributes;
26 | const doRules = getValidators(rules, triggerType);
27 | const doValidators = getValidators(validators, triggerType);
28 | if (validateDisabled !== true && (doRules.length > 0 || doValidators.length > 0)) {
29 | // 注意:校验是异步的
30 | return doValidate({
31 | id,
32 | fieldKey,
33 | value,
34 | rules: doRules,
35 | validators: doValidators,
36 | mApi
37 | }).then(result => {
38 | return result;
39 | });
40 | }
41 | // 清除可能的之前保留的校验信息
42 | return Promise.resolve([]);
43 | };
44 |
45 | export default { validate };
46 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/demo/default/formModelPlugin.js:
--------------------------------------------------------------------------------
1 |
2 | const onChangeHandler = (context, e) => {
3 | const { event, mApi } = context;
4 | const { key, eventName, next, stop, getAttributes, eventReturnValue } = event;
5 | console.log('form onChange', e.target.value, eventReturnValue);
6 | const value = e.target.value;
7 | mApi.setAttributes(key, { value }, true);
8 | }
9 | class formModelPlugin {
10 | // 用来标识模型插件身份
11 | static ID = 'form_test';
12 | constructor() {
13 | // 存储模型状态
14 | this.validator = {};
15 | this.id2Name = {};// 记录id与name的对应关系
16 | this.schemaInstance = null;
17 | this.mApi = null;
18 | }
19 | onSchemaInstantiated = (params) => {
20 | const { mApi, event } = params;
21 | const { schemaInstance } = event;
22 | // 将实例保存起来
23 | this.schemaInstance = schemaInstance;
24 | console.log('schema instance', this.schemaInstance);
25 | }
26 | // 增加表单模型方法
27 | onModelApiCreated = (params) => {
28 | const { mApi } = params;
29 | this.mApi = mApi;
30 | this.schemaInstance.loopDown((node) => {
31 | const { attributes = {}, id } = node;
32 | // 表单默认onChange事件,保证没有绑定组件插件时也能处理
33 | if (attributes.name) {
34 | // 暂未考虑单元格更新事件
35 | mApi.addEventListener(id, 'onChange', onChangeHandler)
36 | }
37 | })
38 | }
39 | // 即将进行渲染
40 | onReadyToRender = (params) => {
41 | //
42 | }
43 | }
44 |
45 | export default formModelPlugin;
46 |
--------------------------------------------------------------------------------
/packages/sifo-react/src/utils/singleton-utils.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 |
3 | export function getRegisteredItems(namespace) {
4 | const singleton = new SifoSingleton(namespace);
5 | const singletonItems = singleton.getRegisteredItems();
6 | const result = {
7 | openLogger: false,
8 | plugins: [],
9 | components: {},
10 | };
11 | singletonItems.forEach(registerItem => {
12 | if (!registerItem) return;
13 | const { components = {}, openLogger = false } = registerItem;
14 | // 允许扩展插件打开日志
15 | if (openLogger) {
16 | result.openLogger = true;
17 | }
18 | let { plugins = [] } = registerItem;
19 | if (!Array.isArray(plugins)) {
20 | plugins = [plugins];
21 | }
22 | // 由接收方来控制获取哪些数据
23 | const validatedPlugins = plugins.map(plg => {
24 | const vplg = {};
25 | // 只支持页面和组件插件
26 | if (plg.pagePlugin) {
27 | vplg.pagePlugin = plg.pagePlugin;
28 | }
29 | if (plg.componentPlugin) {
30 | vplg.componentPlugin = plg.componentPlugin;
31 | }
32 | return vplg;
33 | });
34 | result.plugins = [...result.plugins, ...validatedPlugins];
35 | result.components = { ...result.components, ...components };
36 | });
37 | // const { plugins, components } = result;
38 | // return {
39 | // plugins,
40 | // components
41 | // };
42 | return result;
43 | }
44 |
45 | export default {
46 | getRegisteredItems
47 | };
48 |
--------------------------------------------------------------------------------
/packages/sifo-vue/src/utils/singleton-utils.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 |
3 | export function getRegisteredItems(namespace) {
4 | const singleton = new SifoSingleton(namespace);
5 | const singletonItems = singleton.getRegisteredItems();
6 | const result = {
7 | openLogger: false,
8 | plugins: [],
9 | components: {},
10 | };
11 | singletonItems.forEach(registerItem => {
12 | if (!registerItem) return;
13 | const { components = {}, openLogger = false } = registerItem;
14 | // 允许扩展插件打开日志
15 | if (openLogger) {
16 | result.openLogger = true;
17 | }
18 | let { plugins = [] } = registerItem;
19 | if (!Array.isArray(plugins)) {
20 | plugins = [plugins];
21 | }
22 | // 由接收方来控制获取哪些数据
23 | const validatedPlugins = plugins.map(plg => {
24 | const vplg = {};
25 | // 只支持页面和组件插件
26 | if (plg.pagePlugin) {
27 | vplg.pagePlugin = plg.pagePlugin;
28 | }
29 | if (plg.componentPlugin) {
30 | vplg.componentPlugin = plg.componentPlugin;
31 | }
32 | return vplg;
33 | });
34 | result.plugins = [...result.plugins, ...validatedPlugins];
35 | result.components = { ...result.components, ...components };
36 | });
37 | // const { plugins, components } = result;
38 | // return {
39 | // plugins,
40 | // components
41 | // };
42 | return result;
43 | }
44 |
45 | export default {
46 | getRegisteredItems
47 | };
48 |
--------------------------------------------------------------------------------
/packages/sifo-model/src/types/eventTypes.ts:
--------------------------------------------------------------------------------
1 |
2 | interface SifoEvent {
3 | /**
4 | * 获取事件执行前指定id的属性
5 | */
6 | getOldAttributes: (id: string) => DynamicObject;
7 | /**
8 | * 获取事件执行到当前时,所有更新过的属性
9 | */
10 | getUpdatedStates: () => DynamicObject;
11 | /**
12 | * 事件对象的key,一般是相应schema的节点Id
13 | */
14 | key: string;
15 | eventName: string;
16 | /**
17 | * 阻止后续插件的执行
18 | */
19 | stop: () => void;
20 | /**
21 | * 可修改对后续插件的入参(不包含context),无修改时不需调用
22 | */
23 | next: (...nArg: any[]) => void,
24 | /**
25 | * 有的事件有返回值
26 | */
27 | eventReturnValue?: any;
28 | /**
29 | * 对返回值进行clone
30 | */
31 | cloneReturnValue?: boolean;
32 | }
33 | interface SifoEventArgs {
34 | mApi: ModelApi;
35 | event: SifoEvent;
36 | }
37 | /**
38 | * 事件监听handler
39 | */
40 | type SifoEventListener = (context: SifoEventArgs, ...args: any[]) => any;
41 | interface EventStatus {
42 | getStatus: () => string;
43 | setStatus: (status: string) => void;
44 | }
45 | interface EventKeyType {
46 | id: string;
47 | eventKey: string;
48 | toString: () => string;
49 | valueOf: () => string;
50 | }
51 | interface EmitterArgs {
52 | key: string,
53 | eventName: string,
54 | mApi: ModelApi;
55 | getHandlers: () => SifoEventListener[];
56 | eventStart: DefaultFunc;
57 | eventEnd: DefaultFunc;
58 | eventStatus: EventStatus;
59 | }
60 |
61 | type DispatchPayload = any;
62 | interface DispatchWatchArgs {
63 | [watchKey: string]: DispatchPayload[];
64 | }
--------------------------------------------------------------------------------
/packages/sifo-react/src/modelPlugins/logger/index.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Logger
3 | */
4 | class SifoLogger {
5 | static ID = 'sifo_logger_model_plugin';
6 | constructor() {
7 | console.log('[sifo-logger] Initial');
8 | }
9 | onModelApiCreated = params => {
10 | const { mApi, event } = params;
11 | const { namespace } = mApi;
12 | if (!window.SifoLogger) window.SifoLogger = {};
13 | window.SifoLogger[namespace] = { mApi };
14 | console.log(`[sifo-logger] mApi is appended to %c window.SifoLogger['${namespace}'].mApi`, 'background: yellow; color: red');
15 | const { applyModelApiMiddleware } = event;
16 | Object.keys(mApi).forEach(api => {
17 | if (typeof mApi[api] !== 'function' || /^get/.test(api) || api === 'hasEventListener') return;
18 | const loggerMiddleware = next => (...args) => {
19 | console.log(`[sifo-logger] mApi.${api}. args: `, args);
20 | return next(...args);
21 | };
22 | applyModelApiMiddleware(api, loggerMiddleware);
23 | });
24 | }
25 | onReadyToRender = params => {
26 | const { mApi } = params;
27 | console.log('[sifo-logger] schema: ', mApi.getSchema());
28 | console.log('[sifo-logger] components: ', mApi.getComponents());
29 | }
30 | onDestroy = ({ mApi }) => {
31 | const { namespace } = mApi;
32 | console.log(`[sifo-logger] %c onDestroy: ${namespace}`, 'background: yellow; color: red');
33 | delete window.SifoLogger[namespace];
34 | }
35 | }
36 |
37 | export default SifoLogger;
38 |
--------------------------------------------------------------------------------
/packages/sifo-vue/src/modelPlugins/logger/index.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Logger
3 | */
4 | class SifoLogger {
5 | static ID = 'sifo_logger_model_plugin';
6 | constructor() {
7 | console.log('[sifo-logger] Initial');
8 | }
9 | onModelApiCreated = params => {
10 | const { mApi, event } = params;
11 | const { namespace } = mApi;
12 | if (!window.SifoLogger) window.SifoLogger = {};
13 | window.SifoLogger[namespace] = { mApi };
14 | console.log(`[sifo-logger] mApi is appended to %c window.SifoLogger['${namespace}'].mApi`, 'background: yellow; color: red');
15 | const { applyModelApiMiddleware } = event;
16 | Object.keys(mApi).forEach(api => {
17 | if (typeof mApi[api] !== 'function' || /^get/.test(api) || api === 'hasEventListener') return;
18 | const loggerMiddleware = next => (...args) => {
19 | console.log(`[sifo-logger] mApi.${api}. args: `, args);
20 | return next(...args);
21 | };
22 | applyModelApiMiddleware(api, loggerMiddleware);
23 | });
24 | }
25 | onReadyToRender = params => {
26 | const { mApi } = params;
27 | console.log('[sifo-logger] schema: ', mApi.getSchema());
28 | console.log('[sifo-logger] components: ', mApi.getComponents());
29 | }
30 | onDestroy = ({ mApi }) => {
31 | const { namespace } = mApi;
32 | console.log(`[sifo-logger] %c onDestroy: ${namespace}`, 'background: yellow; color: red');
33 | delete window.SifoLogger[namespace];
34 | }
35 | }
36 |
37 | export default SifoLogger;
38 |
--------------------------------------------------------------------------------
/web-app/extensions/system/NoticeComp.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './notice.less';
3 |
4 | window.nnn = React;
5 | class Notice extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {
9 | numbers: [
10 | { id: '1', message: '仓库容量更新>>' },
11 | { id: '2', message: '张三新入库了一批货物' },
12 | { id: '3', message: '有新的入库申请,请尽快处理>>' }
13 | ],
14 | animate: false
15 | };
16 | }
17 |
18 | componentDidMount = () => {
19 | setInterval(this.Dt, 2000);
20 | }
21 |
22 | Dt = () => {
23 | this.setState({ animate: true }); // 进行动画滚动
24 | setTimeout(() => {
25 | const [first, ...others] = this.state.numbers;
26 | const newNumbers = [...others, first];
27 | // 滚动后将消息向最后移,此时当前位置就是第一个消息位置,不进行动画
28 | this.setState({
29 | numbers: newNumbers,
30 | animate: false
31 | });
32 | }, 1000);
33 | }
34 |
35 | render() {
36 | return (
37 |
50 | );
51 | }
52 | }
53 | export default Notice;
54 |
55 |
--------------------------------------------------------------------------------
/web-app/app/settingPanel/index.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | import React from 'react';
3 | import { Switch } from 'antd';
4 | import Settings from './settings';
5 |
6 | const SettingPanel = props => {
7 | const {
8 | settingType = 'bizPlg', onTypeChange,
9 | useSavedSchema = false, onSchemaTypeChange,
10 | sysExtTypes,
11 | sysExts, customer, customerTyps,
12 | onCustomExtChange, onSysExtChange
13 | } = props;
14 | return (
15 | <>
16 | 页面扩展设置
17 |
24 |
25 |
26 | {
27 | settingType === 'bizPlg' ? (
28 |
36 | ) : (
37 |
38 | 使用Sifo拖拽插件构建新的schema,允许对初始schema的节点进行拖拽编辑,也支持添加注册的组件节点。
39 |
40 | )
41 | }
42 |
43 | >
44 | );
45 | };
46 |
47 | export default SettingPanel;
48 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/demo/default/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import SifoApp from '@schema-plugin-flow/sifo-react';
3 | import test_schema from './schema.json';
4 | import reactOptimizeModelPlugin from '../../src/index';
5 | import formModelPlugin from './formModelPlugin';
6 | import componentPlugin from './componnetPlugin';
7 | import CWrap from './custom-wrap-component'
8 | import './index.css';
9 |
10 | const components = {
11 | 'Container': (props) => ,
12 | 'Input': (props) => {
13 | console.log('input render', props.name);
14 | return {props.name}:重渲染检测:{new Date().getMilliseconds()}
15 | },
16 | CWrap
17 | }
18 | class Component extends React.Component {
19 | constructor(props) {
20 | super(props);
21 | }
22 |
23 | onClick = () => {
24 | this.mApi.forceRefresh().then(() => {
25 | console.log('force refreshed');
26 | });
27 | }
28 |
29 | render() {
30 | return (
31 |
32 |
33 | {
38 | this.mApi = mApi;
39 | }}
40 | plugins={[{ modelPlugin: formModelPlugin, componentPlugin }, { modelPlugin: reactOptimizeModelPlugin }]}
41 | />
42 |
43 | );
44 | }
45 | }
46 |
47 | export default Component;
48 |
--------------------------------------------------------------------------------
/packages/sifo-singleton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-singleton",
3 | "version": "1.2.0",
4 | "author": "FrominXu",
5 | "description": "sifo singleton",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-singleton"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "singleton"
20 | ],
21 | "scripts": {
22 | "build": "npm run build:js",
23 | "build:js": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "test": "mocha --require register.js --compilers js:@babel/register test/index.test.js ",
25 | "lint": "eslint --ext .jsx,.js src/",
26 | "precommit": "npm run lint",
27 | "prepare": "npm run lint && npm run build"
28 | },
29 | "devDependencies": {
30 | "@babel/cli": "^7.2.0",
31 | "@babel/core": "^7.2.2",
32 | "@babel/plugin-proposal-class-properties": "^7.2.1",
33 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
34 | "@babel/preset-env": "^7.7.1",
35 | "@babel/preset-typescript": "^7.1.0",
36 | "@babel/register": "^7.0.0",
37 | "@schema-plugin-flow/sifo-model": "^1.5.0",
38 | "chai": "^4.1.2",
39 | "eslint": "^7.6.0",
40 | "husky": "^0.14.3",
41 | "mocha": "^5.2.0"
42 | },
43 | "dependencies": {
44 | "@babel/runtime": "^7.12.5"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/plugins/extend-in-anotherjs.js:
--------------------------------------------------------------------------------
1 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
2 | import { message } from 'ant-design-vue';
3 | // 扩展组件(局部)
4 | const components = {
5 | 'test-ext-button': {
6 | data: function () {
7 | return {
8 | count: 0
9 | }
10 | },
11 | template: `
12 | `
15 | }
16 | };
17 | const componentPlugin = {
18 | btn_change_id: {
19 | onComponentInitial: params => {
20 | const { event, mApi } = params;
21 | setTimeout(() => {
22 | message.info("外部扩展:点击按钮3次将日期组件改为扩展组件", 3);
23 | mApi.setAttributes(event.key, {
24 | size: "large",
25 | style: {
26 | color: 'red'
27 | }
28 | });
29 | }, 2000);
30 | let count = 0;
31 | mApi.addEventListener(event.key, 'click', () => {
32 | count++;
33 | if (count >= 3) {
34 | mApi.replaceComponent('date', 'test-ext-button');
35 | }
36 | });
37 | }
38 | }
39 | };
40 | // 按namespace注册
41 | const singleton = new SifoSingleton('complex-sifo-demo');
42 | singleton.registerItem('extendId01', () => {
43 | console.log('singleton');
44 | return {
45 | version: '1.0.0',
46 | plugins: [
47 | {
48 | componentPlugin,
49 | pagePlugin: {}
50 | }
51 | ],
52 | components,
53 | openLogger: true
54 | }
55 | });
56 |
--------------------------------------------------------------------------------
/packages/sifo-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-react",
3 | "version": "1.6.0",
4 | "author": "FrominXu",
5 | "description": "A highly extensible JavaScript library, for React. 高扩展性、可二开的插件式前端开发框架",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-react"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "plugin",
20 | "react"
21 | ],
22 | "scripts": {
23 | "build": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "lint": "eslint --ext .jsx,.js src/",
25 | "precommit": "npm run lint",
26 | "prepare": "npm run lint && npm run build"
27 | },
28 | "dependencies": {
29 | "@babel/runtime": "^7.12.5",
30 | "@schema-plugin-flow/sifo-model": "^1.5.0",
31 | "@schema-plugin-flow/sifo-singleton": "^1.2.0",
32 | "classnames": "^2.2.6",
33 | "prop-types": "^15.x",
34 | "react": "^16.10.1",
35 | "react-dom": "^16.10.1"
36 | },
37 | "devDependencies": {
38 | "@babel/cli": "^7.2.0",
39 | "@babel/core": "^7.2.2",
40 | "chai": "^4.1.2",
41 | "chai-enzyme": "^1.0.0-beta.1",
42 | "enzyme": "^3.3.0",
43 | "enzyme-adapter-react-16": "^1.0.0",
44 | "eslint": "^7.6.0",
45 | "husky": "^0.14.3",
46 | "mocha": "^5.2.0",
47 | "react-test-renderer": "^16.x"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/web-app/extensions/customerB/ShowWarehouseCapacity.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/no-static-element-interactions */
2 | /* eslint-disable jsx-a11y/click-events-have-key-events */
3 | /* eslint-disable react/prop-types */
4 | import React, { useEffect, useState } from 'react';
5 | import {
6 | SyncOutlined
7 | } from '@ant-design/icons';
8 |
9 | const ShowWarehouseCapacity = props => {
10 | const [counts, setCount] = useState({});
11 | const refreshCount = () => setTimeout(() => {
12 | const newCounts = { ...counts };
13 | (props.options || []).forEach(item => {
14 | newCounts[item.value] = Math.ceil(Math.random() * 100);
15 | });
16 | setCount(newCounts);
17 | }, 50);
18 | useEffect(() => {
19 | refreshCount();
20 | }, []);
21 | const {
22 | style = {}, options = [], onChange, value
23 | } = props;
24 | return (
25 |
26 |
27 |
28 | {
29 | options.map(item => {
30 | const cls = item.value === value ? 'capacity-item selected' : 'capacity-item';
31 | return (
32 |
onChange(item.value)}
35 | >
36 | {`${item.label} 库存:${counts[item.value] || ''}`}
37 |
38 | );
39 | })
40 | }
41 |
42 |
43 | );
44 | };
45 | export default ShowWarehouseCapacity;
46 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-drag",
3 | "version": "1.6.0",
4 | "author": "FrominXu",
5 | "description": "sifo drag model plugin. 拖拽搭建模型插件",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-mplg-drag"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "sifo-mplg",
20 | "drag"
21 | ],
22 | "scripts": {
23 | "build": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "lint": "eslint --ext .jsx,.js,.tsx src/",
25 | "precommit": "npm run lint",
26 | "prepare": "npm run lint && npm run build",
27 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
28 | },
29 | "devDependencies": {
30 | "@babel/cli": "^7.2.0",
31 | "@babel/core": "^7.2.2",
32 | "@babel/plugin-proposal-class-properties": "^7.2.1",
33 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
34 | "@babel/preset-env": "^7.2.0",
35 | "@babel/preset-typescript": "^7.1.0",
36 | "@babel/register": "^7.0.0",
37 | "@schema-plugin-flow/sifo-model": "^1.5.0",
38 | "chai": "^4.1.2",
39 | "chai-enzyme": "^1.0.0-beta.1",
40 | "eslint": "^7.6.0",
41 | "husky": "^0.14.3",
42 | "mocha": "^5.2.0"
43 | },
44 | "dependencies": {
45 | "@babel/runtime": "^7.12.5"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-form-core",
3 | "version": "1.9.2",
4 | "author": "FrominXu",
5 | "description": "sifo form-core model plugin. 表单内核模型插件",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-mplg-form-core"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "sifo-mplg",
20 | "form"
21 | ],
22 | "scripts": {
23 | "build": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "lint": "eslint --ext .jsx,.js,.tsx src/",
25 | "precommit": "npm run lint",
26 | "prepare": "npm run lint && npm run build",
27 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
28 | },
29 | "devDependencies": {
30 | "@babel/cli": "^7.2.0",
31 | "@babel/core": "^7.2.2",
32 | "@babel/plugin-proposal-class-properties": "^7.2.1",
33 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
34 | "@babel/preset-env": "^7.2.0",
35 | "@babel/preset-typescript": "^7.1.0",
36 | "@babel/register": "^7.0.0",
37 | "@schema-plugin-flow/sifo-model": "^1.5.0",
38 | "chai": "^4.1.2",
39 | "chai-enzyme": "^1.0.0-beta.1",
40 | "eslint": "^7.6.0",
41 | "husky": "^0.14.3",
42 | "mocha": "^5.2.0"
43 | },
44 | "dependencies": {
45 | "@babel/runtime": "^7.12.5"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/sifo-vue/src/modelPlugins/utils.js:
--------------------------------------------------------------------------------
1 | const forbiddenKeys = ['on'];
2 | const classKeys = ['slot', 'key', 'class', 'ref', 'refInFor', 'muteRenderOptimizeMark'];
3 | const classObjects = ['scopedSlots', 'refInFor', 'style', 'attrs', 'props', 'domProps', 'nativeOn'];
4 | const classArray = ['directives'];
5 | /**
6 | * 对新attrs进行分类并与旧attrs合并,返回以新attrs为角度的合并结果,使用者应该用此与旧attrs合并
7 | * @param {*} oldAttrs 旧属性,应该是已经分过类的
8 | * @param {*} newAttrs 新属性,将按key进行分类并合并入旧属性
9 | * @param {*} silent 新属性不允许有on事件属性,否则提示,silent设置是否打印提示,默认为false
10 | */
11 | export function classifyAttributes(oldAttrs, newAttrs, silent = false) {
12 | const reAttrs = {};
13 | // 以新属性为遍历对象,所以最终的reAttrs只有新属性中有的分类
14 | Object.keys(newAttrs).forEach(key => {
15 | if (forbiddenKeys.indexOf(key) >= 0) {
16 | if (silent !== true) {
17 | console.warn('[sifo-vue]: you should use addEventListener to listen events.');
18 | }
19 | return;
20 | }
21 | if (classKeys.indexOf(key) >= 0) {
22 | // 新值替换旧值
23 | reAttrs[key] = newAttrs[key];
24 | } else if (classObjects.indexOf(key) >= 0) {
25 | const oldClassValue = oldAttrs[key] || {};
26 | // 对象合并
27 | reAttrs[key] = {
28 | ...oldClassValue, ...newAttrs[key]
29 | };
30 | } else if (classArray.indexOf(key) >= 0) {
31 | // 数组替换
32 | reAttrs[key] = newAttrs[key];
33 | } else {
34 | // 其余都放到props中
35 | reAttrs.props = { ...oldAttrs.props, ...reAttrs.props, [key]: newAttrs[key] };
36 | }
37 | });
38 | // 返回新属性分类后的结果
39 | return reAttrs;
40 | }
41 |
42 | export default {
43 | classifyAttributes
44 | };
45 |
--------------------------------------------------------------------------------
/web-app/build/vendor/vendor-manifest.json:
--------------------------------------------------------------------------------
1 | {"name":"vendor","content":{"../node_modules/load-js/index.js":{"id":252,"buildMeta":{}},"../node_modules/react-router-dom/esm/react-router-dom.js":{"id":289,"buildMeta":{"exportsType":"namespace"},"exports":["BrowserRouter","HashRouter","Link","MemoryRouter","NavLink","Prompt","Redirect","Route","Router","StaticRouter","Switch","generatePath","matchPath","useHistory","useLocation","useParams","useRouteMatch","withRouter"]},"../node_modules/react/index.js":{"id":378,"buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"},"exports":["Children","Component","Fragment","Profiler","PureComponent","StrictMode","Suspense","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","cloneElement","createContext","createElement","createFactory","createRef","forwardRef","isValidElement","lazy","memo","useCallback","useContext","useDebugValue","useEffect","useImperativeHandle","useLayoutEffect","useMemo","useReducer","useRef","useState","version"]},"../node_modules/react-dom/index.js":{"id":542,"buildMeta":{"exportsType":"dynamic","defaultObject":"redirect"},"exports":["__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","createPortal","findDOMNode","flushSync","hydrate","render","unmountComponentAtNode","unstable_batchedUpdates","unstable_createPortal","unstable_renderSubtreeIntoContainer","version"]},"../node_modules/react-router/esm/react-router.js":{"id":635,"buildMeta":{"exportsType":"namespace"},"exports":["MemoryRouter","Prompt","Redirect","Route","Router","StaticRouter","Switch","__HistoryContext","__RouterContext","generatePath","matchPath","useHistory","useLocation","useParams","useRouteMatch","withRouter"]}}}
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-drag-vue",
3 | "version": "1.6.0",
4 | "author": "FrominXu",
5 | "description": "sifo drag model plugin for Vue. 拖拽搭建模型插件",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-mplg-drag-vue"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "sifo-mplg",
20 | "drag"
21 | ],
22 | "scripts": {
23 | "build": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "lint": "eslint --ext .jsx,.js,.tsx src/",
25 | "precommit": "npm run lint",
26 | "prepare": "npm run lint && npm run build",
27 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
28 | },
29 | "devDependencies": {
30 | "@babel/cli": "^7.2.0",
31 | "@babel/core": "^7.2.2",
32 | "@babel/plugin-proposal-class-properties": "^7.2.1",
33 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
34 | "@babel/preset-env": "^7.2.0",
35 | "@babel/preset-typescript": "^7.1.0",
36 | "@babel/register": "^7.0.0",
37 | "@schema-plugin-flow/sifo-model": "^1.5.0",
38 | "chai": "^4.1.2",
39 | "chai-enzyme": "^1.0.0-beta.1",
40 | "eslint": "^7.6.0",
41 | "husky": "^0.14.3",
42 | "mocha": "^5.2.0"
43 | },
44 | "dependencies": {
45 | "@babel/runtime": "^7.12.5",
46 | "@schema-plugin-flow/sifo-mplg-drag": "^1.6.0",
47 | "vue": "^2.6.11"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/src/componentWrap.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | /* eslint-disable no-underscore-dangle,react/prop-types */
3 | type RenderMarkCompProps = {
4 | renderOptimizeMark: string; // 渲染标识
5 | muteRenderOptimizeMark: boolean; // 是否禁用渲染标识
6 | };
7 | // 因为有children,不好用PurComponent
8 | class RenderMarkComp extends React.Component {
9 | shouldComponentUpdate(nextProps) {
10 | // 无渲染标,直接渲染。有时候将包装组件作为普通组件使用时,就没有标记
11 | // console.log('nextProps.renderOptimizeMark:', nextProps.renderOptimizeMark)
12 | if (!nextProps.renderOptimizeMark) return true;
13 | if (nextProps.muteRenderOptimizeMark) return true;
14 | return this.props.renderOptimizeMark !== nextProps.renderOptimizeMark;
15 | }
16 | render() {
17 | return this.props.children;
18 | }
19 | }
20 | const defaultComponentName = 'SifoReactOptimise';
21 | const componentWrap = Component => {
22 | const compName = Component ?
23 | (Component.name || Component.displayName || defaultComponentName)
24 | : defaultComponentName;
25 | const wrapName = `${compName}RenderMarkWrap`;
26 | const RenderMarkWrap: any = props => {
27 | if (!Component) return null;
28 | const { __renderOptimizeMark__, muteRenderOptimizeMark = false, ...other } = props;
29 | return (
30 |
34 |
35 |
36 | );
37 | };
38 | RenderMarkWrap.displayName = wrapName;
39 | return RenderMarkWrap;
40 | };
41 | export default componentWrap;
42 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/README.md:
--------------------------------------------------------------------------------
1 | # SifoReactOptimizeModelPlugin
2 |
3 | sifo-react-optimize-model-plugin
4 |
5 | react渲染优化的sifo-model modelPlugin模型插件
6 | > `sifo-react` is 'top-down' rendering type, you can use the modelPlugin `@schema-plugin-flow/sifo-mplg-react-optimize` to optimize the rerendering in complex project.
7 |
8 | *In general, you should use it as the last one in the plugins list.*
9 |
10 | codesandbox.io: [sifo-react-mplg-optimize](https://codesandbox.io/s/sifo-react-mplg-optimize-sfmts)
11 |
12 | 代码示例
13 |
14 | ```javascript
15 | import SifoModel from '@schema-plugin-flow/sifo-model';
16 | //
17 | const plugins = [..., { modelPlugin: reactOptimizeModelPlugin }];
18 | new SifoModel(
19 | namespace,
20 | refreshApi,
21 | schema,
22 | plugins
23 | );
24 | ```
25 | ## 扩展的 mApi 模型接口
26 |
27 | *mApi说明*
28 |
29 | | 方法名 | 参数/类型 | 返回值类型 | 描述 |
30 | | ---------------- | -----------------------| --------------------- | ---------------------------------------------------------------------------------------------------|
31 | | forceRefresh | ✘ | - | mApi的setAttributes和refresh是按标记刷新渲染,调用此方法将强制全部刷新 |
32 |
33 | ## attributes
34 |
35 | | 属性名 | 类型 | 默认值 | 描述 |
36 | | ---------------- | -----------------------| --------------------- | ---------------------------------------------------------------------------------------------------|
37 | | muteRenderOptimizeMark | bool | false | 当节点上此属性为true时,该节点不受渲染优化标记的控制,按照普通渲染模式渲染,但仍然受父组件的渲染与否影响 |
38 |
39 |
40 | ## 其它
41 | 此模型插件是通过扩展sifo-model的setAttributes方法实现的。
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-drag-react",
3 | "version": "1.6.0",
4 | "author": "FrominXu",
5 | "description": "sifo drag model plugin for React. 拖拽搭建模型插件",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-mplg-drag-react"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "sifo-mplg",
20 | "drag"
21 | ],
22 | "scripts": {
23 | "build": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "lint": "eslint --ext .jsx,.js,.tsx src/",
25 | "precommit": "npm run lint",
26 | "prepare": "npm run lint && npm run build",
27 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
28 | },
29 | "devDependencies": {
30 | "@babel/cli": "^7.2.0",
31 | "@babel/core": "^7.2.2",
32 | "@babel/plugin-proposal-class-properties": "^7.2.1",
33 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
34 | "@babel/preset-env": "^7.2.0",
35 | "@babel/preset-typescript": "^7.1.0",
36 | "@babel/register": "^7.0.0",
37 | "@schema-plugin-flow/sifo-model": "^1.5.0",
38 | "chai": "^4.1.2",
39 | "chai-enzyme": "^1.0.0-beta.1",
40 | "eslint": "^7.6.0",
41 | "husky": "^0.14.3",
42 | "mocha": "^5.2.0"
43 | },
44 | "dependencies": {
45 | "@babel/runtime": "^7.12.5",
46 | "@schema-plugin-flow/sifo-mplg-drag": "^1.6.0",
47 | "prop-types": "^15.x",
48 | "react": "^16.10.1",
49 | "react-dom": "^16.10.1"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/date-picker.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import { DatePicker } from 'antd-mobile';
4 | import dayjs from 'dayjs';
5 | import FieldContent from './field-content';
6 |
7 | const DATETIME = 'YYYY-MM-DD HH:mm:ss';
8 | const DATE = 'YYYY-MM-DD';
9 | const DatePickerX = (props) => {
10 | const {
11 | label,
12 | placeholder,
13 | disabled,
14 | value,
15 | onChange,
16 | dataType,
17 | format,
18 | setTriggerOnClick,
19 | itemClicked,
20 | resetItemClicked,
21 | ...other
22 | } = props;
23 | const change = (v) => {
24 | const fmat = format ? format : dataType === 'dateTime' ? DATETIME : DATE;
25 | onChange(dayjs(v).format(fmat));
26 | };
27 | const [visible, setVisible] = React.useState(false);
28 | return (
29 | {
34 | setVisible(false);
35 | }}
36 | {...other}
37 | disabled={disabled}
38 | visible={visible}
39 | >
40 | {(val) => {
41 | return (
42 | {
44 | setVisible(true);
45 | }}
46 | label={label}
47 | disabled={disabled}
48 | placeholder={placeholder}
49 | value={value}
50 | setTriggerOnClick={setTriggerOnClick}
51 | itemClicked={itemClicked}
52 | resetItemClicked={resetItemClicked}
53 | />
54 | );
55 | }}
56 |
57 | );
58 | };
59 |
60 | export default DatePickerX;
61 |
--------------------------------------------------------------------------------
/packages/sifo-singleton/README.md:
--------------------------------------------------------------------------------
1 | # sifo-singleton
2 |
3 | 这是一个全局单例容器,用于注册插件与组件,以命名空间区分。
4 |
5 | ## SifoSingleton 类
6 |
7 | *SifoSingleton实例化参数*
8 |
9 | 参数 | 说明 | 类型 | 是否必传 | 默认值
10 | -------------|-------------|-----|-----|-----
11 | namespace | 命名空间,插件与组件通过同一命名空间读取 | string | 是 | - |
12 |
13 |
14 | ## 方法
15 |
16 | | 方法名 | 参数/类型 | 返回值类型 | 描述 |
17 | | --------------------- | -------------------| --------------------- | ---------------------------------------------------------------------------------------------------|
18 | | registerItem | (id: string, item: function) | - | 注册对象 |
19 | | getRegisteredItems | () | array | 获取所有的命名空间下的注册对象 |
20 |
21 | > 代码示例-注册
22 | ```javascript
23 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
24 | const singleton = new SifoSingleton('test');
25 | singleton.registerItem('extendId01', (params) => {
26 | return {
27 | version: '1.0.0',
28 | plugins: [
29 | {
30 | componentPlugin: singleton_comp_plg,
31 | pagePlugin: {}
32 | },
33 | {
34 | pagePlugin: {
35 | onPageInitial: params => {
36 | console.log('singleton1 page plugin')
37 | }
38 | }
39 | }
40 | ],
41 | components: {
42 | test: TestComp
43 | }
44 | }
45 | });
46 | ```
47 |
48 | > 代码示例-取出
49 | ```javascript
50 | import SifoSingleton from '@schema-plugin-flow/sifo-singleton';
51 | const singleton = new SifoSingleton('test');
52 | const singletonItems = singleton.getRegisteredItems({ param1: 'testssss' });
53 | singletonItems.forEach(registerItem => {
54 | const { components = {}, plugins = [] } = registerItem;
55 | });
56 | ```
--------------------------------------------------------------------------------
/web-app/app/formPanel.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Spin } from 'antd';
3 | import loadjs from 'load-js';
4 | import FormDemo from './form';
5 |
6 | const extConfig = JSON.parse(window.extConfig || '{}');
7 | const Form = () => {
8 | const { search } = window.location;
9 | const [loading, setLoading] = useState(true);
10 | const params = new URLSearchParams(search);
11 | const useDragPlg = params.get('useDragPlg') === 'true';
12 | const useSavedSchema = params.get('useSavedSchema') === 'true';
13 | const customer = params.get('customer') || '';
14 | const sysExts = params.get('sysExts') || '';
15 | useEffect(() => {
16 | const { sysExtTypes, customerTyps } = extConfig;
17 | new Promise(res => {
18 | const urls = [];
19 | // 先加载系统扩展
20 | if (sysExts) {
21 | sysExts.split(',').forEach(id => {
22 | const item = sysExtTypes.find(i => i.value === id);
23 | if (item) {
24 | urls.push(item.url);
25 | }
26 | });
27 | }
28 | const citem = customerTyps.find(i => i.value === customer);
29 | if (citem) {
30 | urls.push(citem.url);
31 | }
32 | if (urls.length === 0) return res();
33 | return loadjs(urls).then(() => res());
34 | }).then(() => {
35 | setLoading(false);
36 | });
37 | }, [search]);
38 | if (loading) return ;
39 | return (
40 |
41 |
47 |
48 | );
49 | };
50 |
51 | export default Form;
52 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-react-optimize/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-react-optimize",
3 | "version": "1.3.0",
4 | "author": "FrominXu",
5 | "description": "React rendering optimize for sifo-react.",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "repository": {
9 | "type": "git",
10 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
11 | "directory": "packages/sifo-mplg-react-optimize"
12 | },
13 | "publishConfig": {
14 | "access": "public"
15 | },
16 | "keywords": [
17 | "schema-plugin-flow",
18 | "sifo",
19 | "sifo-mplg",
20 | "sifo-react-optimize"
21 | ],
22 | "scripts": {
23 | "build": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\"",
24 | "lint": "eslint --ext .jsx,.js,.tsx src/",
25 | "precommit": "npm run lint",
26 | "prepare": "npm run lint && npm run build",
27 | "test": "mocha --require register.js --compilers js:@babel/register test/index.test.js "
28 | },
29 | "dependencies": {
30 | "@babel/runtime": "^7.12.5",
31 | "prop-types": "^15.x",
32 | "react": "^16.10.1",
33 | "react-dom": "^16.10.1",
34 | "uuid": "^3.3.2"
35 | },
36 | "devDependencies": {
37 | "@babel/cli": "^7.2.0",
38 | "@babel/core": "^7.2.2",
39 | "@babel/plugin-proposal-class-properties": "^7.2.1",
40 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
41 | "@babel/preset-env": "^7.2.0",
42 | "@babel/preset-typescript": "^7.1.0",
43 | "@babel/register": "^7.0.0",
44 | "@schema-plugin-flow/sifo-react": "^1.6.0",
45 | "@types/react": "^16.9.46",
46 | "chai": "^4.1.2",
47 | "chai-enzyme": "^1.0.0-beta.1",
48 | "eslint": "^7.6.0",
49 | "husky": "^0.14.3",
50 | "mocha": "^5.2.0"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/modelPlugin-demo/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import SifoApp, { SifoModelTypes } from "@schema-plugin-flow/sifo-react";
3 | import FormModelPlugin from './mplg-antd-form';
4 | import schema from './schema.json';
5 |
6 | const components = {
7 | Container: props =>
8 | };
9 | const componentPlugin: SifoModelTypes.ComponentPluginSet = {
10 | $form_id: {
11 | onComponentInitial: params => {
12 | const { event, mApi } = params;
13 | mApi.setAttributes(event.key, {
14 | labelCol: {
15 | span: 6,
16 | },
17 | wrapperCol: {
18 | span: 14,
19 | },
20 | });
21 | mApi.addEventListener(event.key, 'onValuesChange', (ctx, changedValues, allValues) => {
22 | console.log(changedValues);
23 | })
24 | }
25 | },
26 | $submit: {
27 | onComponentInitial: params => {
28 | const { event, mApi } = params;
29 | mApi.addEventListener(event.key, 'onClick', () => {
30 | mApi.validateFields().then(d => {
31 | const values = mApi.getFieldsValue();
32 | console.log('values:', values);
33 | }).catch(e => {
34 | console.log(e)
35 | })
36 | })
37 | }
38 | }
39 | };
40 | const plugins = [
41 | {
42 | componentPlugin, modelPlugin: FormModelPlugin as SifoModelTypes.ModelPlugin
43 | }
44 | ];
45 | type FormDemoProps = {
46 | };
47 | const FormDemo = (props: FormDemoProps) => {
48 | const { } = props;
49 | return (
50 |
58 | );
59 | };
60 |
61 | export default FormDemo;
--------------------------------------------------------------------------------
/examples-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-demo",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "build-lib": "vue-cli-service build --target lib"
9 | },
10 | "dependencies": {
11 | "@schema-plugin-flow/sifo-mplg-form-antdv": "file:../packages/sifo-mplg-form-antdv",
12 | "@schema-plugin-flow/sifo-mplg-form-core": "file:../packages/sifo-mplg-form-core",
13 | "@schema-plugin-flow/sifo-mplg-drag-vue": "file:../packages/sifo-mplg-drag-vue",
14 | "@schema-plugin-flow/sifo-singleton": "^1.0.0",
15 | "@schema-plugin-flow/sifo-vue": "file:../packages/sifo-vue",
16 | "ant-design-vue": "^1.7.4",
17 | "core-js": "^3.6.5",
18 | "vue": "^2.6.11"
19 | },
20 | "devDependencies": {
21 | "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
22 | "@vue/babel-preset-jsx": "^1.1.2",
23 | "@vue/cli-plugin-babel": "~4.5.0",
24 | "@vue/cli-plugin-eslint": "~4.5.0",
25 | "@vue/cli-service": "~4.5.0",
26 | "@vue/compiler-sfc": "^3.0.0-0",
27 | "babel-eslint": "^10.1.0",
28 | "babel-plugin-import": "^1.13.0",
29 | "eslint": "^6.7.2",
30 | "eslint-plugin-vue": "^7.0.0-0",
31 | "less": "^3.12.2",
32 | "less-loader": "^7.0.1",
33 | "vue-loader-v16": "^16.0.0-beta.5.4",
34 | "vue-template-compiler": "^2.6.12"
35 | },
36 | "eslintConfig": {
37 | "root": true,
38 | "env": {
39 | "node": true
40 | },
41 | "extends": [
42 | "plugin:vue/vue3-essential",
43 | "eslint:recommended"
44 | ],
45 | "parserOptions": {
46 | "parser": "babel-eslint"
47 | },
48 | "rules": {}
49 | },
50 | "browserslist": [
51 | "> 1%",
52 | "last 2 versions",
53 | "not dead"
54 | ]
55 | }
56 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-core/src/utils.js:
--------------------------------------------------------------------------------
1 | export const isNumber = s => String(s).trim() !== '' && !Number.isNaN(+String(s));
2 | export const isEmpty = value => (Number.isNaN(value) || value === undefined || value === null
3 | || String(value).trim() === '');
4 | export const hasOwnProperty = (obj, propName) => Object.hasOwnProperty.call(obj, propName);
5 |
6 | export const keyHolder = (key, defValue) => {
7 | if (key === null || key === undefined) return defValue;
8 | return `${key}`;
9 | };
10 | const RULES_KEYS = [
11 | 'required',
12 | 'type',
13 | 'max',
14 | 'min',
15 | 'maxLength',
16 | 'minLength'
17 | ];
18 | export function findRule(rule) {
19 | const ruleKey = RULES_KEYS.find(key => hasOwnProperty(rule, key));
20 | if (ruleKey) {
21 | return {
22 | ruleKey,
23 | ruleType: ruleKey === 'type' ? rule[ruleKey] : ruleKey,
24 | rule,
25 | };
26 | }
27 | return null;
28 | }
29 | /**
30 | * (oldRules:[], rules:[])
31 | */
32 | export const mergeRules = (oldRules = [], rules = []) => {
33 | const newRules = [...oldRules];
34 | const opeRules = [...rules];
35 | const merged = newRules.map(rule => {
36 | const rul = findRule(rule);
37 | if (rul) {
38 | const { ruleType, ruleKey } = rul;
39 | const idx = opeRules.findIndex(it => {
40 | if (hasOwnProperty(it, ruleKey)) {
41 | if (ruleKey === 'type') {
42 | return ruleType === it[ruleKey];
43 | }
44 | return true;
45 | }
46 | return false;
47 | });
48 | if (idx >= 0) {
49 | const [target] = opeRules.splice(idx, 1);
50 | return {
51 | ...rule,
52 | ...target
53 | };
54 | }
55 | }
56 | return rule;
57 | });
58 | return [...merged, ...opeRules];
59 | };
60 |
--------------------------------------------------------------------------------
/packages/sifo-model/src/utils/schema-utils.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | /* tslint:disable: no-any no-empty */
5 | const getDealWithNode = (dealRules: DynamicObject) => (targetNode: SchemaNode) => {
6 | const { component = '' } = targetNode;
7 | const dealFunc = typeof dealRules === 'function' ? dealRules : dealRules[component];
8 | let newNode = targetNode || {};
9 | if (typeof dealFunc !== 'function') return newNode;
10 | newNode = dealFunc(newNode) || newNode;
11 | return newNode;
12 | };
13 | /**
14 | * 节点修正, 预处理式深度优先遍历
15 | * @param {*} schema
16 | * @param {*} dealRules
17 | * @param {*} alias
18 | */
19 | export function nodeRevise(schema: SchemaNode, dealRules: any = {}, alias: DynamicObject = {}) {
20 | const nodeRebuild = (node: SchemaNode) => {
21 | const {
22 | id, component, attributes, children, ...other
23 | } = node;
24 | const attr = node[alias.attributes] || attributes || {};
25 | const newNode = {
26 | ...other, // 允许在节点上放其它属性
27 | component: node[alias.component] || component,
28 | attributes: attr,
29 | children: node[alias.children] || children || [],
30 | id: id || attr.id, // 节点无id则从属性中取id
31 | };
32 | return newNode;
33 | };
34 | const dealWithNode = getDealWithNode(dealRules);
35 | function reviser(node: SchemaNode) {
36 | if (typeof node === 'string') return node;
37 | const children: SchemaNode[] = [];
38 | let builtNode: SchemaNode = nodeRebuild(node);
39 | builtNode = dealWithNode(Object.assign({}, builtNode));
40 | (builtNode.children || []).forEach(child => {
41 | children.push(reviser(child));
42 | });
43 | return Object.assign({}, builtNode, { children });
44 | }// reviser
45 |
46 | return reviser(schema);
47 | }// revise
48 |
49 | export default {
50 | nodeRevise
51 | };
52 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-form-antdv",
3 | "version": "1.12.0",
4 | "author": "FrominXu",
5 | "description": "sifo Form with ant-design-vue.",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "module": "es/index.js",
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
12 | "directory": "packages/sifo-mplg-form-antdv"
13 | },
14 | "publishConfig": {
15 | "access": "public"
16 | },
17 | "keywords": [
18 | "schema-plugin-flow",
19 | "sifo",
20 | "sifo-mplg",
21 | "ant-design-vue",
22 | "antd-vue-form",
23 | "form"
24 | ],
25 | "scripts": {
26 | "build": "babel --root-mode upward src --out-dir lib --copy-files --extensions \".ts,.tsx,.js\"",
27 | "build:es": "babel --no-babelrc --config-file ./es.babel.config.js src --out-dir es --copy-files",
28 | "lint": "eslint --ext .jsx,.js,.tsx src/",
29 | "precommit": "npm run lint",
30 | "prepare": "npm run lint && npm run build",
31 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
32 | },
33 | "dependencies": {
34 | "@babel/runtime": "^7.12.5",
35 | "ant-design-vue": "^1.6.5",
36 | "vue": "^2.6.11"
37 | },
38 | "devDependencies": {
39 | "@babel/cli": "^7.2.0",
40 | "@babel/core": "^7.2.2",
41 | "@babel/plugin-proposal-class-properties": "^7.2.1",
42 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
43 | "@babel/preset-env": "^7.2.0",
44 | "@babel/preset-typescript": "^7.1.0",
45 | "@babel/register": "^7.0.0",
46 | "@schema-plugin-flow/sifo-vue": "^1.7.0",
47 | "chai": "^4.1.2",
48 | "chai-enzyme": "^1.0.0-beta.1",
49 | "eslint": "^7.6.0",
50 | "husky": "^0.14.3",
51 | "mocha": "^5.2.0"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-fusion/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-form-fusion",
3 | "version": "1.8.0",
4 | "author": "FrominXu",
5 | "description": "sifo Form with Fusion.",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "module": "es/index.js",
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
12 | "directory": "packages/sifo-mplg-form-fusion"
13 | },
14 | "publishConfig": {
15 | "access": "public"
16 | },
17 | "keywords": [
18 | "schema-plugin-flow",
19 | "sifo",
20 | "sifo-mplg",
21 | "fusion",
22 | "fusion-form",
23 | "form"
24 | ],
25 | "scripts": {
26 | "build": "npm run build:cjs && npm run build:es",
27 | "build:cjs": "babel --root-mode upward src --out-dir lib --copy-files --extensions \".ts,.tsx,.js,.jsx\"",
28 | "build:es": "babel --no-babelrc --config-file ./es.babel.config.js src --out-dir es --copy-files",
29 | "lint": "eslint --ext .jsx,.js,.tsx src/",
30 | "precommit": "npm run lint",
31 | "prepare": "npm run lint && npm run build",
32 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
33 | },
34 | "dependencies": {
35 | "@alifd/next": "^1.24.14",
36 | "@babel/runtime": "^7.12.5",
37 | "classnames": "^2.2.6",
38 | "prop-types": "15.x",
39 | "react": "16.x",
40 | "react-dom": "16.x"
41 | },
42 | "devDependencies": {
43 | "@babel/cli": "^7.2.0",
44 | "@babel/core": "^7.2.2",
45 | "@babel/plugin-proposal-class-properties": "^7.2.1",
46 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
47 | "@babel/preset-env": "^7.2.0",
48 | "@babel/preset-typescript": "^7.1.0",
49 | "@babel/register": "^7.0.0",
50 | "chai": "^4.1.2",
51 | "chai-enzyme": "^1.0.0-beta.1",
52 | "eslint": "^7.6.0",
53 | "husky": "^0.14.3",
54 | "mocha": "^5.2.0"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-react/src/index.js:
--------------------------------------------------------------------------------
1 | import SifoDragModelPlugin from '@schema-plugin-flow/sifo-mplg-drag';
2 | import dragWrapper from './componentWrap';
3 |
4 | export { default as SifoDragEditor } from './editor';
5 |
6 | const EmptyEditor = () => null;
7 | class DragModelPlugin {
8 | static ID = 'sifo_drag_react_model_plugin';
9 | constructor(props = {}) {
10 | const injectArgs = {
11 | ...props,
12 | dragWrapper,
13 | SifoDragEditor: props.SifoDragEditor || EmptyEditor,
14 | };
15 | this.dragModel = new SifoDragModelPlugin(injectArgs);
16 | }
17 |
18 | onNodePreprocess = (node, informations) => {
19 | if (this.dragModel.onNodePreprocess) {
20 | return this.dragModel.onNodePreprocess(node, informations);
21 | }
22 | return node;
23 | }
24 | onComponentsWrap = components => {
25 | if (this.dragModel.onComponentsWrap) {
26 | return this.dragModel.onComponentsWrap(components);
27 | }
28 | return components;
29 | }
30 | onSchemaInstantiated = params => {
31 | if (this.dragModel.onSchemaInstantiated) {
32 | this.dragModel.onSchemaInstantiated(params);
33 | }
34 | }
35 | onModelApiCreated = params => {
36 | const { mApi } = params;
37 | if (this.dragModel.onModelApiCreated) {
38 | this.dragModel.onModelApiCreated(params);
39 | }
40 | this.mApi = mApi;
41 | }
42 | onReadyToRender = params => {
43 | if (this.dragModel.onReadyToRender) {
44 | this.dragModel.onReadyToRender(params);
45 | }
46 | }
47 | afterRender = params => {
48 | if (this.dragModel.afterRender) {
49 | this.dragModel.afterRender(params);
50 | }
51 | }
52 | onDestroy = params => {
53 | if (this.dragModel.onDestroy) {
54 | this.dragModel.onDestroy(params);
55 | }
56 | }
57 | }
58 | export default DragModelPlugin;
59 |
--------------------------------------------------------------------------------
/examples-vue/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples-vue/server.js:
--------------------------------------------------------------------------------
1 | /* eslint-enable */
2 | const process = require('process');
3 | const fs = require("fs");
4 | const p = require("path");
5 | const exec = require('child_process').exec;
6 | const args = process.argv;
7 | const [host, fullpath, firstArg] = args;
8 | // console.log(`cwd: ${process.cwd()}`);
9 | // const toPath = process.cwd() + '/examples-vue';
10 | console.log("__dirname:", __dirname);
11 | process.chdir(__dirname);
12 |
13 | if (firstArg == 'i') {
14 | installPkgs();
15 | }
16 | if (firstArg == 'start') {
17 | runScript('node_modules/.bin/vue-cli-service serve');
18 | }
19 | if (firstArg == 'dev') {
20 | runScript('node_modules/.bin/vue-cli-service serve');
21 | }
22 | if (firstArg == 'build') {
23 | runScript('node_modules/.bin/vue-cli-service build');
24 | }
25 | function installPkgs(callback) {
26 | let fielPath = p.join(__dirname, "package-lock.json");
27 | if (fs.existsSync(fielPath)) {
28 | fs.unlinkSync(fielPath);
29 | }
30 | console.log('run: npm i');
31 | const cmdStr = 'npm install --no-package-lock';
32 | exec(cmdStr, { maxBuffer: 1024 * 500 }, (err, stdout, stderr) => {
33 | if (err) {
34 | console.log(err);
35 | console.warn(new Date(), cmdStr + ' exec failed');
36 | } else {
37 | console.log(stdout);
38 | console.warn(new Date(), cmdStr + ' exec succeed');
39 | callback && callback();
40 | }
41 | });
42 | }
43 | function runScript(script, callback) {
44 | console.log('run: ' + script);
45 | const cmdStr = script;
46 | exec(cmdStr, { maxBuffer: 1024 * 500, }, (err, stdout, stderr) => {
47 | if (err) {
48 | console.log(err);
49 | console.warn(new Date(), cmdStr + ' exec failed');
50 | } else {
51 | console.log(stdout);
52 | console.warn(new Date(), cmdStr + ' exec succeed');
53 | callback && callback();
54 | }
55 | });
56 | }
57 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-adm-demo/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import SifoApp, { SifoModelTypes } from '@schema-plugin-flow/sifo-react';
3 | import SifoFormCore from "@schema-plugin-flow/sifo-mplg-form-core";
4 | import AdmFormModelPlugin, { baseComponents } from '@schema-plugin-flow/sifo-mplg-form-antd-mobile';
5 | import schema from './schema';
6 | import plugins from './plugins';
7 | import './index.less';
8 |
9 | // 插件配置
10 | const plgs: SifoModelTypes.SifoPlugin[] = [
11 | {
12 | modelPlugin: {
13 | plugin: SifoFormCore,
14 | argsProvider: (mId, info) => {
15 | return {
16 | // 字段的key,无返回值认为不是字段
17 | fieldKey: (attr) => attr.name,
18 | fieldChange: {
19 | // 表单字段change使用的handler
20 | changeHandler: (context, e) => {
21 | const { event, mApi } = context;
22 | let val = e;
23 | if (typeof e === "string" || typeof e === "number") {
24 | val = e;
25 | } else if (e && typeof e === "object") {
26 | val = e.target ? e.target.value : e;
27 | }
28 | mApi.setAttributes(event.key, { value: val }, true);
29 | },
30 | eventName: "onChange",
31 | },
32 | };
33 | },
34 | },
35 | },
36 | {
37 | modelPlugin: AdmFormModelPlugin
38 | },
39 | ...plugins,
40 | ];
41 |
42 | // 应用入口
43 | const FormApp = () => {
44 | return (
45 | <>
46 |
55 | >
56 | );
57 | };
58 |
59 | FormApp.displayName = 'FormApp';
60 |
61 | export default FormApp;
62 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-drag-vue/src/index.js:
--------------------------------------------------------------------------------
1 | import SifoDragModelPlugin from '@schema-plugin-flow/sifo-mplg-drag';
2 | import dragWrapper from './componentWrap';
3 |
4 | export { default as SifoDragEditor } from './editor/index.vue';
5 |
6 | const EmptyEditor = {
7 | render() {
8 | return null;
9 | }
10 | };
11 | class DragModelPlugin {
12 | static ID = 'sifo_drag_vue_model_plugin';
13 | constructor(props = {}) {
14 | const injectArgs = {
15 | ...props,
16 | dragWrapper,
17 | SifoDragEditor: props.SifoDragEditor || EmptyEditor,
18 | };
19 | this.dragModel = new SifoDragModelPlugin(injectArgs);
20 | }
21 |
22 | onNodePreprocess = (node, informations) => {
23 | if (this.dragModel.onNodePreprocess) {
24 | return this.dragModel.onNodePreprocess(node, informations);
25 | }
26 | return node;
27 | }
28 | onComponentsWrap = components => {
29 | if (this.dragModel.onComponentsWrap) {
30 | return this.dragModel.onComponentsWrap(components);
31 | }
32 | return components;
33 | }
34 | onSchemaInstantiated = params => {
35 | if (this.dragModel.onSchemaInstantiated) {
36 | this.dragModel.onSchemaInstantiated(params);
37 | }
38 | }
39 | onModelApiCreated = params => {
40 | const { mApi } = params;
41 | if (this.dragModel.onModelApiCreated) {
42 | this.dragModel.onModelApiCreated(params);
43 | }
44 | this.mApi = mApi;
45 | }
46 | onReadyToRender = params => {
47 | if (this.dragModel.onReadyToRender) {
48 | this.dragModel.onReadyToRender(params);
49 | }
50 | }
51 | afterRender = params => {
52 | if (this.dragModel.afterRender) {
53 | this.dragModel.afterRender(params);
54 | }
55 | }
56 | onDestroy = params => {
57 | if (this.dragModel.onDestroy) {
58 | this.dragModel.onDestroy(params);
59 | }
60 | }
61 | }
62 | export default DragModelPlugin;
63 |
--------------------------------------------------------------------------------
/web-app/extensions/system/english-config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable quotes */
2 | /* eslint-disable quote-props */
3 | // 自定义一个多语言转换的描述规则
4 | const configs = [
5 | {
6 | "id": "header",
7 | "attributes": {
8 | "title": "Goods check-in"
9 | }
10 | },
11 | {
12 | "id": "goodsType",
13 | "attributes": {
14 | "label": "Goods type",
15 | "placeholder": "please select goods type",
16 | "rules": [
17 | {
18 | "required": true,
19 | "message": "please select goods type"
20 | }
21 | ]
22 | }
23 | },
24 | {
25 | "id": "goodsId",
26 | "attributes": {
27 | "label": "Goods name",
28 | "placeholder": "please select goods",
29 | "rules": [
30 | {
31 | "required": true,
32 | "message": "please select goods"
33 | }
34 | ]
35 | }
36 | },
37 | {
38 | "id": "warehouse",
39 | "attributes": {
40 | "label": "Warehouse",
41 | "placeholder": "please select warehouse",
42 | "rules": [
43 | {
44 | "required": true,
45 | "message": "please select warehouse"
46 | }
47 | ]
48 | }
49 | },
50 | {
51 | "id": "quantity",
52 | "attributes": {
53 | "label": "quantity",
54 | "placeholder": "quantity",
55 | "rules": [
56 | {
57 | "required": true,
58 | "message": "please input a quantity"
59 | },
60 | {
61 | "type": "integer",
62 | "message": "need integer"
63 | }
64 | ]
65 | }
66 | },
67 | {
68 | "id": "submitBtn",
69 | "attributes": {
70 | "label": "submit and create warehousing entry"
71 | }
72 | },
73 | {
74 | "id": "notes",
75 | "attributes": {
76 | "label": "notes",
77 | "placeholder": "notes"
78 | }
79 | }
80 | ];
81 | export default configs;
82 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/modelPlugin-demo/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": "Container",
3 | "id": "$form_demo",
4 | "attributes": {
5 | "className": "form-demo"
6 | },
7 | "children": [
8 | {
9 | "component": "Form",
10 | "id": "$form_id",
11 | "attributes": {
12 | "className": "form-demo-form"
13 | },
14 | "children": [
15 | {
16 | "id": "userName",
17 | "component": "Input",
18 | "attributes": {
19 | "name": "userName",
20 | "label": "user name",
21 | "rules": [
22 | {
23 | "required": true
24 | }
25 | ]
26 | }
27 | },
28 | {
29 | "id": "gender",
30 | "component": "Select",
31 | "attributes": {
32 | "name": "gender",
33 | "label": "gender",
34 | "options": [
35 | {
36 | "value": "male",
37 | "label": "male"
38 | },
39 | {
40 | "value": "female",
41 | "label": "female"
42 | },
43 | {
44 | "value": "other",
45 | "label": "other"
46 | }
47 | ],
48 | "rules": [
49 | {
50 | "required": true
51 | }
52 | ]
53 | }
54 | }
55 | ]
56 | },
57 | {
58 | "component": "Container",
59 | "id": "$footer_id",
60 | "attributes": {
61 | "className": "form-demo-footer"
62 | },
63 | "children": [
64 | {
65 | "component": "Button",
66 | "id": "$submit",
67 | "attributes": {
68 | "type": "primary"
69 | },
70 | "children": [
71 | "Submit"
72 | ]
73 | }
74 | ]
75 | }
76 | ]
77 | }
--------------------------------------------------------------------------------
/packages/sifo-react/demo/quickStart.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import SifoApp from '@schema-plugin-flow/sifo-react';
3 | // 一些组件
4 | const Container = props => ;
5 | const Slogan = ({ content, ...other }) => {content}
;
6 | const Button = props => ;
7 | // schema 定义了初始的页面结构
8 | const schema = {
9 | component: "Container",
10 | id: 'mainId',
11 | attributes: {},
12 | children: [
13 | {
14 | component: "Slogan",
15 | id: 'slogan_id',
16 | attributes: {
17 | content: 'hello world'
18 | }
19 | },
20 | {
21 | component: "Button",
22 | id: 'test_btn_id',
23 | attributes: {}
24 | }
25 | ]
26 | };
27 | // 组件插件可以实现与组件相关的功能
28 | const componentPlugin1 = {
29 | test_btn_id: {
30 | onComponentInitial: params => {
31 | const { event, mApi } = params;
32 | mApi.addEventListener(event.key, 'onClick', (context) => {
33 | mApi.setAttributes('slogan_id', {
34 | content: 'hello sifo'
35 | });
36 | })
37 | }
38 | }
39 | };
40 | // 第二个插件
41 | const componentPlugin2 = {
42 | test_btn_id: {
43 | onComponentInitial: params => {
44 | const { event, mApi } = params;
45 | mApi.addEventListener(event.key, 'onClick', () => {
46 | console.log('test_btn_id clicked!')
47 | })
48 | }
49 | }
50 | };
51 | const components = { Container, Slogan, Button };
52 | const plugins = [
53 | { componentPlugin: componentPlugin1 },
54 | { componentPlugin: componentPlugin2 }
55 | ];
56 | class App extends React.Component {
57 | render() {
58 | return (
59 |
67 | );
68 | }
69 | }
70 | export default App;
--------------------------------------------------------------------------------
/examples-vue/src/demos/test-decorator-target.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | count:{{ count }}
5 |
8 |
9 |
10 |
13 |
14 |
15 | 不传参片段:
16 |
17 |
18 |
19 | 动态传参数片段:
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/modelPlugin-demo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: modelPlugin Demo
3 | order: 7
4 | ---
5 | form modelPlugin for Ant Design Form
6 | ```jsx
7 | import * as React from 'react';
8 | import SifoApp, { SifoModelTypes } from "@schema-plugin-flow/sifo-react";
9 | import FormModelPlugin from './modelPlugin-demo/mplg-antd-form';
10 | import schema from './modelPlugin-demo/schema.json';
11 | import 'antd/dist/antd.css';
12 | import './modelPlugin-demo/index.less';
13 | //
14 | const components = {
15 | Container: props =>
16 | };
17 | const componentPlugin = {
18 | $form_id: {
19 | onComponentInitial: params => {
20 | const { event, mApi } = params;
21 | mApi.setAttributes(event.key, {
22 | labelCol: {
23 | span: 6,
24 | },
25 | wrapperCol: {
26 | span: 14,
27 | },
28 | });
29 | mApi.addEventListener(event.key, 'onValuesChange', (ctx, changedValues, allValues) => {
30 | console.log(changedValues);
31 | })
32 | }
33 | },
34 | $submit: {
35 | onComponentInitial: params => {
36 | const { event, mApi } = params;
37 | mApi.addEventListener(event.key, 'onClick', () => {
38 | // mApi.submit()
39 | mApi.validateFields().then(d => {
40 | const values = mApi.getFieldsValue();
41 | console.log('values:', values);
42 | }).catch(e => {
43 | console.log(e)
44 | })
45 | })
46 | }
47 | }
48 | };
49 | const plugins = [
50 | {
51 | componentPlugin, modelPlugin: FormModelPlugin
52 | }
53 | ];
54 | //
55 | const FormDemo = (props) => {
56 | const { } = props;
57 | return (
58 |
66 | );
67 | };
68 | //
69 | export default FormDemo;
70 | ```
71 |
72 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-form-antd",
3 | "version": "1.14.0",
4 | "author": "FrominXu",
5 | "description": "sifo Form with ant-design.",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "module": "es/index.js",
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
12 | "directory": "packages/sifo-mplg-form-antd"
13 | },
14 | "publishConfig": {
15 | "access": "public"
16 | },
17 | "keywords": [
18 | "schema-plugin-flow",
19 | "sifo",
20 | "sifo-mplg",
21 | "ant-design",
22 | "antd-form",
23 | "form"
24 | ],
25 | "scripts": {
26 | "build": "npm run build:cjs && npm run build:es",
27 | "build:cjs": "babel --root-mode upward src --out-dir lib --copy-files --extensions \".ts,.tsx,.js,.jsx\"",
28 | "build:es": "babel --no-babelrc --config-file ./es.babel.config.js src --out-dir es --copy-files",
29 | "lint": "eslint --ext .jsx,.js,.tsx src/",
30 | "precommit": "npm run lint",
31 | "prepare": "npm run lint && npm run build",
32 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
33 | },
34 | "dependencies": {
35 | "@babel/runtime": "^7.12.5",
36 | "antd": "^4.x",
37 | "classnames": "^2.2.6",
38 | "prop-types": "15.x",
39 | "react": "16.x",
40 | "react-dom": "16.x"
41 | },
42 | "devDependencies": {
43 | "@babel/cli": "^7.2.0",
44 | "@babel/core": "^7.2.2",
45 | "@babel/plugin-proposal-class-properties": "^7.2.1",
46 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
47 | "@babel/preset-env": "^7.2.0",
48 | "@babel/preset-typescript": "^7.1.0",
49 | "@babel/register": "^7.0.0",
50 | "@schema-plugin-flow/sifo-react": "^1.6.0",
51 | "chai": "^4.1.2",
52 | "chai-enzyme": "^1.0.0-beta.1",
53 | "eslint": "^7.6.0",
54 | "husky": "^0.14.3",
55 | "mocha": "^5.2.0"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/docs/sifo-react-doc/modelPlugin-demo/mplg-antd-form/componentWrap.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | const formItemProps = ["name", "fieldKey", "noStyle", "dependencies", "prefixCls", "style", "className", "shouldUpdate", "hasFeedback", "help", "rules", "validateStatus", "children", "required", "label", "trigger", "validateTrigger", "hidden"];
3 | function pickItemProps(props) {
4 | const prps = {};
5 | const rest = {};
6 | Object.keys(props).forEach(key => {
7 | if (formItemProps.indexOf(key) >= 0) {
8 | prps[key] = props[key];
9 | } else {
10 | rest[key] = props[key];
11 | }
12 | });
13 | return [prps, rest];
14 | }
15 | const defaultComponentName = 'FieldComp';
16 | const componentWrap = (Component, FormItem) => {
17 | const compName = Component ?
18 | (Component.name || Component.displayName || defaultComponentName)
19 | : defaultComponentName;
20 | const wrapName = `${compName}FormItemWrap`;
21 | const SifoFormWrap = props => {
22 | const {
23 | __isField__, __skipWrap__, children, ...realProps
24 | } = props;
25 | if (!Component) return null;
26 | if (__isField__) {
27 | if (__skipWrap__) {
28 | let child;
29 | if (Array.isArray(children)) {
30 | [child] = children;
31 | } else {
32 | child = children;
33 | }
34 | return ({child});
35 | }
36 | // 捡出所有Form.Item 的属性
37 | const [itemProps, rest] = pickItemProps(realProps);
38 | const {
39 | fieldProps = {}, ...others
40 | } = rest;
41 | return (
42 |
45 | {
46 | React.createElement(Component, { ...fieldProps, ...others }, children)
47 | }
48 |
49 | )
50 | }
51 | return ({children});
52 | }
53 | SifoFormWrap.displayName = wrapName;
54 | return SifoFormWrap;
55 | };
56 |
57 | export default componentWrap;
58 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antdv/src/index.js:
--------------------------------------------------------------------------------
1 | import defaultFormItemWrapper from './componentWrap';
2 |
3 | class AntdVueFormModelPlugin {
4 | static ID = 'sifo_antdv_form_model_plugin';
5 | constructor(props) {
6 | const { formItemWrapper, formItemProps = {} } = props || {};
7 | this.mApi = null;
8 | this.formItemWrapper = formItemWrapper || defaultFormItemWrapper;
9 | // 统一配置 FormItem 属性,如 labelAlign, labelCol
10 | this.formItemProps = formItemProps;
11 | }
12 | onComponentsWrap = components => {
13 | const rComp = Object.assign({}, components);
14 | const wrappedComps = {};
15 | // 包含FormItem组件,识别__isField__属性
16 | Object.keys(rComp).forEach(key => {
17 | const comp = rComp[key];
18 | wrappedComps[key] = this.formItemWrapper(comp, this.formItemProps);
19 | });
20 | return wrappedComps;
21 | }
22 |
23 | onModelApiCreated = params => {
24 | const { mApi, event } = params;
25 | this.mApi = mApi;
26 | const { applyModelApiMiddleware } = event;
27 | const getPropsMiddleware = () => id => {
28 | const attr = this.mApi.getAttributes(id) || {};
29 | return attr.props;
30 | };
31 | applyModelApiMiddleware('getProps', getPropsMiddleware);
32 | const setPropsMiddleware = () => (id, props) => {
33 | return this.mApi.setAttributes(id, { props });
34 | };
35 | applyModelApiMiddleware('setProps', setPropsMiddleware);
36 | // form-core 依赖这个方法取FormItem属性,vue中重写这个方法
37 | const getFormItemPropsMiddleware = () => id => {
38 | const attr = this.mApi.getAttributes(id);
39 | if (!attr) return {};
40 | const props = attr.props || {};
41 | return {
42 | rules: props.rules,
43 | value: props.value,
44 | defaultValue: props.defaultValue,
45 | validators: props.validators,
46 | validateDisabled: props.validateDisabled
47 | };
48 | };
49 | applyModelApiMiddleware('getFormItemProps', getFormItemPropsMiddleware);
50 | }
51 | }
52 | export default AntdVueFormModelPlugin;
53 |
--------------------------------------------------------------------------------
/packages/sifo-model/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-model",
3 | "version": "1.5.0",
4 | "author": "FrominXu",
5 | "description": "A highly extensible JavaScript library, abbreviated as Sifo. 高扩展性、可二开的插件式前端开发框架",
6 | "license": "MIT",
7 | "types": "lib/index.d.ts",
8 | "main": "index.js",
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
12 | "directory": "packages/sifo-model"
13 | },
14 | "publishConfig": {
15 | "access": "public"
16 | },
17 | "keywords": [
18 | "schema-plugin-flow",
19 | "sifo",
20 | "schema",
21 | "plugin",
22 | "model"
23 | ],
24 | "scripts": {
25 | "prepare": "npm run build",
26 | "test": "mocha --require register.js --compilers js:@babel/register test/index.test.js ",
27 | "lint-back": "eslint --ext .jsx,.js,.ts src/",
28 | "lint": "tslint \"src/**/*.ts\" -e \"src/types/*.ts\" --force",
29 | "precommit": "npm run lint",
30 | "backup-prepublish": "npm run lint && npm run build",
31 | "type-check": "tsc --noEmit --watch",
32 | "type-check:watch": "npm run type-check -- --watch",
33 | "build": "npm run build:js",
34 | "check": "npm run type-check",
35 | "build:dts": "tsc --emitDeclarationOnly",
36 | "build:js": "babel --root-mode upward src --out-dir lib --extensions \".ts,.tsx,.js,.jsx\""
37 | },
38 | "dependencies": {
39 | "@babel/runtime": "^7.12.5",
40 | "uuid": "3.2.1"
41 | },
42 | "devDependencies": {
43 | "@babel/cli": "^7.2.0",
44 | "@babel/core": "^7.2.2",
45 | "@babel/plugin-proposal-class-properties": "^7.2.1",
46 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
47 | "@babel/preset-env": "^7.2.0",
48 | "@babel/preset-typescript": "^7.1.0",
49 | "@babel/register": "^7.0.0",
50 | "@types/uuid": "^3.4.4",
51 | "chai": "^4.1.2",
52 | "eslint": "^7.6.0",
53 | "husky": "^0.14.3",
54 | "mocha": "^5.2.0",
55 | "tslint": "^5.11.0",
56 | "typescript": "^3.2.2"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@schema-plugin-flow/sifo-mplg-form-antd-mobile",
3 | "version": "1.3.1",
4 | "author": "FrominXu",
5 | "description": "sifo Form with ant-design-mobile.",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "module": "es/index.js",
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:alibaba/schema-plugin-flow.git",
12 | "directory": "packages/sifo-mplg-form-antd-mobile"
13 | },
14 | "publishConfig": {
15 | "access": "public"
16 | },
17 | "keywords": [
18 | "schema-plugin-flow",
19 | "sifo",
20 | "sifo-mplg",
21 | "ant-design-mobile",
22 | "form"
23 | ],
24 | "scripts": {
25 | "build": "npm run build:cjs && npm run build:es",
26 | "build:cjs": "babel --root-mode upward src --out-dir lib --copy-files --extensions \".ts,.tsx,.js,.jsx\"",
27 | "build:es": "babel --no-babelrc --config-file ./es.babel.config.js src --out-dir es --extensions \".ts,.tsx,.js,.jsx\" --copy-files ",
28 | "lint": "eslint --ext .jsx,.js,.tsx src/",
29 | "precommit": "npm run lint",
30 | "prepare": "npm run lint && npm run build",
31 | "test-back": "mocha --compilers js:@babel/register test/index.test.js "
32 | },
33 | "dependencies": {
34 | "@babel/runtime": "^7.12.5",
35 | "antd-mobile": "5.6.1",
36 | "antd-mobile-icons": "0.2.2",
37 | "classnames": "^2.2.6",
38 | "dayjs": "^1.10.7",
39 | "prop-types": "15.x",
40 | "react": "16.x",
41 | "react-dom": "16.x"
42 | },
43 | "devDependencies": {
44 | "@babel/cli": "^7.2.0",
45 | "@babel/core": "^7.2.2",
46 | "@babel/plugin-proposal-class-properties": "^7.2.1",
47 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
48 | "@babel/preset-env": "^7.2.0",
49 | "@babel/preset-typescript": "^7.1.0",
50 | "@babel/register": "^7.0.0",
51 | "@schema-plugin-flow/sifo-react": "^1.6.0",
52 | "chai": "^4.1.2",
53 | "chai-enzyme": "^1.0.0-beta.1",
54 | "eslint": "^7.6.0",
55 | "husky": "^0.14.3",
56 | "mocha": "^5.2.0"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/complex-demo/Complex.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 控制实例数: {{count}}
4 |
5 |
6 |
21 |
22 |
23 |
24 |
74 |
75 |
77 |
--------------------------------------------------------------------------------
/packages/sifo-model/test/modelPlugin/reactOptimizeModelPlugin.js:
--------------------------------------------------------------------------------
1 | import uuid from 'uuid';
2 |
3 | // 对react 渲染进行优化
4 | class reactOptimizeModelPlugin {
5 | // 用来标识模型插件身份
6 | static ID = 'sifo-react-optimize-model-plugin';
7 | constructor() {
8 | this.schemaInstance = null;
9 | this.mApi = null;
10 | }
11 | // 带优化的SCU组件
12 | onComponentsWrap = components => {
13 | const wrappedComps = {};
14 | return wrappedComps;
15 | }
16 | onSchemaInstantiated = params => {
17 | const { event } = params;
18 | const { schemaInstance } = event;
19 | // 将实例保存起来
20 | this.schemaInstance = schemaInstance;
21 | }
22 | onModelApiCreated = params => {
23 | const { mApi, event } = params;
24 | const { applyModelApiMiddleware } = event;
25 |
26 | const setAttributesMiddleware = next => (key, attributes, refresh = true) => {
27 | const guid = uuid();
28 | // 进行渲染标识
29 | this.schemaInstance.loopUp(node => {
30 | if (!node.attributes) return;
31 | node.attributes.__renderOptimizeMark__ = guid;// eslint-disable-line
32 | }, key);// 从此key向上标记,包含此key的节点
33 | return next(key, attributes, refresh);
34 | };
35 | // 对mApi的setAttributes方法进行再组装
36 | applyModelApiMiddleware('setAttributes', setAttributesMiddleware);
37 |
38 | // 替换渲染组件方法
39 | const replaceComponentMiddleware = next => (key, componentName) => {
40 | mApi.setAttributes(key, {}, false);// 强制标识
41 | return next(key, componentName);
42 | };
43 | applyModelApiMiddleware('replaceComponent', replaceComponentMiddleware);
44 |
45 | // 强制渲染
46 | const forceRefreshMiddleware = next => (...args) => {
47 | const guid = uuid();
48 | // 进行渲染标识
49 | this.schemaInstance.loopDown(node => {
50 | if (!node.attributes) return;
51 | node.attributes.__renderOptimizeMark__ = guid;// eslint-disable-line
52 | });// 从此key向下标记,包含此key的节点
53 | next(...args);
54 | return mApi.refresh();
55 | };
56 | applyModelApiMiddleware('forceRefresh', forceRefreshMiddleware);
57 | }
58 | }
59 |
60 | export default reactOptimizeModelPlugin;
61 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/number-input.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import T from 'prop-types';
3 | import { Input } from 'antd-mobile';
4 | import classnames from 'classnames';
5 |
6 | class NumberInput extends React.Component {
7 | static propTypes = {
8 | value: T.string,
9 | onChange: T.func,
10 | scale: T.number, // 数字的整数位数,默认10
11 | precision: T.number, // 数字的小数精度,默认0
12 | disabled: T.bool,
13 | };
14 | static defaultProps = {
15 | value: '',
16 | onChange: null,
17 | scale: 10,
18 | precision: 0,
19 | disabled: false,
20 | };
21 | constructor(props) {
22 | super(props);
23 | this.state = {
24 | value: props.value || '',
25 | };
26 | }
27 |
28 | componentWillReceiveProps(nextProps) {
29 | this.setState({ value: nextProps.value || '' });
30 | }
31 | onBlur = () => {
32 | const { value } = this.state;
33 | if (value && /\d*\.$/.test(value)) {
34 | const toVal = value.replace('.', '');
35 | this.setState({ value: toVal });
36 | if (this.props.onChange) {
37 | this.props.onChange(toVal);
38 | }
39 | }
40 | };
41 | onChange = val => {
42 | const { precision = 0, scale = 10 } = this.props;// 精度与范围,精度指小数位,范围指整数位数
43 | const floatRegx = precision > 0 ? `(\\.\\d{0,${precision}})?` : '';
44 | const regx = `^\\d{0,${scale}}${floatRegx}$`;// 数字的整数部分不能超过10位
45 | if (new RegExp(regx).test(val) === false) return false;
46 | // 小数点开头补为"0."
47 | const toVal = /^\./.test(val) ? `0${val}` : val;
48 | this.setState({ value: toVal });
49 | if (this.props.onChange) {
50 | this.props.onChange(toVal);
51 | }
52 | return true;
53 | };
54 | render() {
55 | const { disabled, className, ...other } = this.props;
56 | return (
57 |
65 | );
66 | }
67 | }
68 |
69 | export default NumberInput;
70 |
71 |
--------------------------------------------------------------------------------
/web-app/babel.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | module.exports = function (api) {
3 | api.cache(true);
4 | const presets = [
5 | [
6 | "@babel/preset-env",
7 | // {
8 | // "targets": "ie >= 9, chrome >= 36, last 4 version"
9 | // }
10 | ],
11 | "@babel/preset-react",
12 | [
13 | "@babel/preset-typescript",
14 | {
15 | "happyPackMode": true,
16 | "transpileOnly": true
17 | }
18 | ]
19 | ];
20 | const plugins = [
21 | ["import", {
22 | "libraryName": "antd",
23 | "style": true, // or 'css'
24 | }],
25 | [
26 | "@babel/plugin-transform-runtime",
27 | {
28 | "corejs": false,
29 | "helpers": true,
30 | "regenerator": true,
31 | "useESModules": false
32 | }
33 | ],
34 | "@babel/plugin-proposal-function-bind",
35 | "@babel/plugin-proposal-export-default-from",
36 | "@babel/plugin-proposal-logical-assignment-operators",
37 | [
38 | "@babel/plugin-proposal-optional-chaining",
39 | {
40 | "loose": false
41 | }
42 | ],
43 | [
44 | "@babel/plugin-proposal-pipeline-operator",
45 | {
46 | "proposal": "minimal"
47 | }
48 | ],
49 | [
50 | "@babel/plugin-proposal-nullish-coalescing-operator",
51 | {
52 | "loose": false
53 | }
54 | ],
55 | "@babel/plugin-proposal-do-expressions",
56 | [
57 | "@babel/plugin-proposal-decorators",
58 | {
59 | "legacy": true
60 | }
61 | ],
62 | "@babel/plugin-proposal-function-sent",
63 | "@babel/plugin-proposal-export-namespace-from",
64 | "@babel/plugin-proposal-numeric-separator",
65 | "@babel/plugin-proposal-throw-expressions",
66 | "@babel/plugin-syntax-dynamic-import",
67 | "@babel/plugin-syntax-import-meta",
68 | [
69 | "@babel/plugin-proposal-class-properties",
70 | {
71 | "loose": false // use definition instead of assignment: https://2ality.com/2012/08/property-definition-assignment.html
72 | }
73 | ],
74 | "@babel/plugin-proposal-json-strings"
75 | ];
76 | return {
77 | presets,
78 | plugins
79 | };
80 | }
--------------------------------------------------------------------------------
/packages/sifo-react/src/modelPlugins/PluginResetter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author FrominXu
3 | */
4 | import SifoLogger from './logger';
5 | import presetPlugins, { baseOrderPlugins } from './index';
6 | import { getRegisteredItems } from '../utils/singleton-utils';
7 | /**
8 | * 处理reloadPage方法时预置插件、客制插件和组件的重绑
9 | */
10 | class PluginResetter {
11 | // 用来标识模型插件身份
12 | static ID = 'plugin_reset_model_plugin';
13 | constructor(props) {
14 | const { openLogger } = props;
15 | this.openLogger = openLogger;
16 | this.schemaInstance = null;
17 | this.mApi = null;
18 | }
19 | onModelApiCreated = params => {
20 | const { mApi, event } = params;
21 | const { applyModelApiMiddleware } = event;
22 | const { namespace } = mApi;
23 | // 定义setAttributes中间件
24 | const reloadPageMiddleware = next => (reloadPageParams = {}, ...args) => {
25 | const {
26 | plugins, components, ...others
27 | } = reloadPageParams;
28 | let newPlgs = plugins;
29 | let newComps = components;
30 | const {
31 | plugins: customPlugins, components: customComps, openLogger: showLogger = false
32 | } = getRegisteredItems(namespace);
33 | if (plugins) { // 只有当外部传新插件时,才重绑
34 | newPlgs = [...baseOrderPlugins].concat(
35 | plugins,
36 | customPlugins,
37 | ...presetPlugins,
38 | {
39 | modelPlugin: {
40 | plugin: PluginResetter,
41 | argsProvider: () => {
42 | return [{ openLogger: this.openLogger || showLogger }];
43 | }
44 | }
45 | }
46 | );
47 | if (this.openLogger || showLogger) {
48 | newPlgs.push({ modelPlugin: SifoLogger });
49 | }
50 | }
51 | if (components) {
52 | newComps = Object.assign({}, components, customComps); // sifo-model中是做的合并
53 | }
54 | const newReloadParams = {
55 | plugins: newPlgs,
56 | components: newComps,
57 | ...others,
58 | };
59 | return next(newReloadParams, ...args);
60 | };
61 | applyModelApiMiddleware('reloadPage', reloadPageMiddleware);
62 | }
63 | }
64 |
65 | export default PluginResetter;
66 |
--------------------------------------------------------------------------------
/packages/sifo-mplg-form-antd-mobile/src/components/field-content/index.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable jsx-a11y/click-events-have-key-events */
2 | /* eslint-disable jsx-a11y/no-static-element-interactions */
3 | /* eslint-disable no-unused-expressions */
4 | import React from 'react';
5 | import classnames from 'classnames';
6 | import './index.less';
7 |
8 | const { useEffect } = React;
9 | interface FieldContentProps {
10 | label: string;
11 | placeholder?: string;
12 | disabled?: boolean;
13 | value: any;
14 | dataType?: string;
15 | /**
16 | * 渲染内容的方法
17 | */
18 | contentRender?: Function;
19 | resetItemClicked?: Function;
20 | setTriggerOnClick: (trigger: boolean) => void;
21 | itemClicked?: boolean;
22 | onClick?: Function;
23 | }
24 | function defalutFormatter(value: any) {
25 | return `${value}`;
26 | }
27 | // DatePicker、Calender、Picker 等需要提供内容组件
28 | const FieldContent = (props: FieldContentProps) => {
29 | const {
30 | label,
31 | placeholder,
32 | disabled = false,
33 | value,
34 | dataType,
35 | contentRender = defalutFormatter,
36 | setTriggerOnClick,
37 | itemClicked,
38 | resetItemClicked,
39 | ...other
40 | } = props;
41 | const { onClick } = props;
42 | const doClick = () => {
43 | if (!disabled) {
44 | onClick && onClick();
45 | }
46 | };
47 | useEffect(() => {
48 | if (onClick) {
49 | setTriggerOnClick(true); // 有Click事件,就需要在FormItem上透传
50 | }
51 | }, []);
52 | useEffect(() => {
53 | // FormItem 被点击了
54 | if (itemClicked && onClick && resetItemClicked) {
55 | resetItemClicked();
56 | doClick();
57 | }
58 | }, [itemClicked]);
59 | const formatedValue = value ? contentRender(value, props) : '';
60 | const cls = classnames('sifo-adm-field-content', {
61 | 'sifo-adm-field-disabled': disabled,
62 | });
63 | return formatedValue ? (
64 |
65 | {formatedValue}
66 |
67 | ) : (
68 |
69 |
70 | {placeholder || label || '请输入'}
71 |
72 |
73 | );
74 | };
75 |
76 | export default FieldContent;
77 |
--------------------------------------------------------------------------------
/examples-vue/src/demos/drag-editor/components/componentConfig.jsx:
--------------------------------------------------------------------------------
1 | import DefPropsRender from './common-props-render.vue';
2 |
3 | function commonPropsEditor (id, node, api) {
4 | const { attributes } = node;
5 | const { label, fieldKey } = attributes;
6 | const dynamicComp = {
7 | functional: true,
8 | render(createElement) {
9 | return createElement(DefPropsRender, { props: { id, label, fieldKey, api } }, 'ssss');
10 | }
11 | };
12 | return dynamicComp;
13 | }
14 | /**
15 | * 描述组件节点的生成与属性编辑
16 | */
17 | const componentList = [
18 | {
19 | type: 'input',
20 | name: '文本',
21 | component: 'Input',
22 | init: function () {
23 | const uuid = Math.random().toString().substr(3, 3);
24 | return {
25 | id: 'text_' + uuid,
26 | attributes: {
27 | label: '文本-' + uuid,
28 | fieldKey: 'text_' + uuid
29 | }
30 | }
31 | },
32 | propsRender: commonPropsEditor
33 | },
34 | {
35 | type: 'select',
36 | name: '选择器',
37 | component: 'Select',
38 | init: function () {
39 | const uuid = Math.random().toString().substr(3, 3);
40 | return {
41 | id: 'sel_' + uuid,
42 | attributes: {
43 | label: '选择器-' + uuid,
44 | fieldKey: 'sel_' + uuid
45 | }
46 | }
47 | },
48 | propsRender: commonPropsEditor
49 | },
50 | {
51 | type: 'container',
52 | name: '容器',
53 | component: 'Container',
54 | init: function () {
55 | const uuid = Math.random().toString().substr(3, 3);
56 | return {
57 | id: 'con_' + uuid,
58 | acceptable: true, // 可接收子节点
59 | attributes: {
60 | label: '容器-' + uuid,
61 | style: { minHeight: '10px' }
62 | }
63 | }
64 | },
65 | propsRender: commonPropsEditor
66 | },
67 | {
68 | type: 'button',
69 | name: '按钮',
70 | component: 'Button',
71 | init: function () {
72 | const uuid = Math.random().toString().substr(3, 3);
73 | return {
74 | id: 'btn_' + uuid,
75 | acceptable: true, // 可接收子节点
76 | attributes: {
77 | label: '按钮' + uuid
78 | }
79 | }
80 | },
81 | propsRender: commonPropsEditor
82 | }
83 | ];
84 |
85 | export default componentList;
--------------------------------------------------------------------------------
/examples-vue/src/demos/quick-start.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/packages/sifo-vue/demo/quick-start.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.umirc.js:
--------------------------------------------------------------------------------
1 | // 配置文件内容
2 | export default {
3 | // 配置项
4 | favicon: '/sifo.ico',
5 | logo: '/sifo.png',
6 | mode: "site",
7 | resolve: {
8 | includes:['docs', 'packages']
9 | },
10 | menus: {
11 | '/guide': [
12 | {
13 | title: 'Introduction',
14 | // 对应的 Markdown 文件,路径是相对于 resolve.includes 目录识别的
15 | //path: '../guide/description',
16 | children: [
17 | {
18 | title: "description",
19 | path: "../guide/description"
20 | }
21 | ]
22 | },
23 | {
24 | title: 'packages',
25 | children: [
26 | {
27 | title: "sifo-model",
28 | path: '../sifo-model'
29 | },
30 | {
31 | title: "sifo-react",
32 | path: '../sifo-react'
33 | },
34 | {
35 | title: "sifo-mplg-react-optimize",
36 | path: '../sifo-mplg-react-optimize'
37 | },
38 | {
39 | title: "sifo-mplg-form-core",
40 | path: '../sifo-mplg-form-core'
41 | },
42 | {
43 | title: "sifo-mplg-form-antdv",
44 | path: '../sifo-mplg-form-antdv'
45 | },
46 | {
47 | title: "sifo-mplg-form-antd",
48 | path: '../sifo-mplg-form-antd'
49 | },
50 | {
51 | title: "sifo-vue",
52 | path: '../sifo-vue'
53 | },
54 | {
55 | title: "sifo-singleton",
56 | path: '../sifo-singleton'
57 | }
58 | ]
59 | },
60 | {
61 | title: 'Other',
62 |
63 | }
64 | ],
65 | 'sifo-model': [
66 | {
67 | title: "Introduction",
68 | path: "../sifo-model"
69 | },
70 | {
71 | title: "sifo-react",
72 | path: "../sifo-react"
73 | }
74 | ]
75 | },
76 | navs: [
77 | {
78 | title: 'Description',
79 | path: '/guide',
80 | },
81 | {
82 | title: 'sifo-react-demo',
83 | path: '/sifo-react-doc',
84 | },
85 | {
86 | title: 'sifo-vue-demo',
87 | path: '//localhost:8080',
88 | },
89 | {
90 | title: 'GitHub',
91 | path: 'https://github.com/alibaba/schema-plugin-flow',
92 | }
93 | ],
94 | };
95 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | module.exports = function (api) {
3 | api.cache(true);
4 | console.log('babel config read!');
5 | const presets = [
6 | [
7 | "@babel/preset-env",
8 | // {
9 | // "targets": "ie >= 9, chrome >= 36, last 4 version"
10 | // }
11 | ],
12 | "@babel/preset-react",
13 | [
14 | "@babel/preset-typescript",
15 | {
16 | "happyPackMode": true,
17 | "transpileOnly": true
18 | }
19 | ]
20 | ];
21 | const plugins = [
22 | [
23 | "@babel/plugin-transform-runtime",
24 | {
25 | "corejs": false,
26 | "helpers": true,
27 | "regenerator": true,
28 | "useESModules": false
29 | }
30 | ],
31 | "@babel/plugin-proposal-function-bind",
32 | "@babel/plugin-proposal-export-default-from",
33 | "@babel/plugin-proposal-logical-assignment-operators",
34 | [
35 | "@babel/plugin-proposal-optional-chaining",
36 | {
37 | "loose": false
38 | }
39 | ],
40 | [
41 | "@babel/plugin-proposal-pipeline-operator",
42 | {
43 | "proposal": "minimal"
44 | }
45 | ],
46 | [
47 | "@babel/plugin-proposal-nullish-coalescing-operator",
48 | {
49 | "loose": false
50 | }
51 | ],
52 | "@babel/plugin-proposal-do-expressions",
53 | [
54 | "@babel/plugin-proposal-decorators",
55 | {
56 | "legacy": true
57 | }
58 | ],
59 | "@babel/plugin-proposal-function-sent",
60 | "@babel/plugin-proposal-export-namespace-from",
61 | "@babel/plugin-proposal-numeric-separator",
62 | "@babel/plugin-proposal-throw-expressions",
63 | "@babel/plugin-syntax-dynamic-import",
64 | "@babel/plugin-syntax-import-meta",
65 | [
66 | "@babel/plugin-proposal-class-properties",
67 | {
68 | "loose": false // use definition instead of assignment: https://2ality.com/2012/08/property-definition-assignment.html
69 | }
70 | ],
71 | "@babel/plugin-proposal-json-strings"
72 | ];
73 | const babelrcRoots = [
74 | '.', // root 指定只使用root的babelrc文件
75 | "packages/*", // 同时允许使用 subpackage 的 .babelrc.json, https://babeljs.io/docs/en/config-files#monorepos
76 | ];
77 | return {
78 | babelrcRoots,
79 | presets,
80 | plugins
81 | };
82 | }
--------------------------------------------------------------------------------
/docs/sifo-react-doc/form-demo/index.jsx:
--------------------------------------------------------------------------------
1 |
2 | import SifoApp from "@schema-plugin-flow/sifo-react";
3 | import { DatePicker, Button as AButton, Input, Select, Row, Col } from "antd";
4 | import SifoFormCore from "@schema-plugin-flow/sifo-mplg-form-core";
5 | import AntdFormModelPlugin from "@schema-plugin-flow/sifo-mplg-form-antd";
6 | import schema from "./schema-form.json";
7 | import plugins from './plugins';
8 |
9 | const components = {
10 | Container: ({ children, ...other}) => (
11 |
12 | {children}
13 |
14 | ),
15 | Input,
16 | Button: ({ label, title, ...other }) => {label || title},
17 | Row,
18 | Col,
19 | Select,
20 | DatePicker
21 | };
22 | const plgs = [
23 | {
24 | modelPlugin: {
25 | plugin: SifoFormCore,
26 | argsProvider: (mId, info) => {
27 | return {
28 | // 字段的key,无返回值认为不是字段
29 | fieldKey: (attr) => attr.name,
30 | fieldChange: {
31 | // 表单字段change使用的handler
32 | changeHandler: (context, e) => {
33 | const { event, mApi } = context;
34 | let val = e;
35 | if (typeof e === "string" || typeof e === "number") {
36 | val = e;
37 | } else if (e && typeof e === "object") {
38 | val = e.target ? e.target.value : e;
39 | }
40 | mApi.setAttributes(event.key, { value: val }, true);
41 | },
42 | eventName: "onChange",
43 | },
44 | };
45 | },
46 | },
47 | },
48 | {
49 | modelPlugin: {
50 | plugin: AntdFormModelPlugin,
51 | argsProvider: (mId, info) => {
52 | return {
53 | formItemProps: {
54 | labelCol: { span: 8 },
55 | wrapperCol: { span: 16 },
56 | labelTextAlign: "left"
57 | }
58 | };
59 | }
60 | }
61 | },
62 | ...plugins
63 | ];
64 | const FormDemo = props => {
65 | return(
66 |
75 | );
76 | }
77 |
78 | export default FormDemo;
79 |
80 |
--------------------------------------------------------------------------------