├── .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 | 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 | 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 | 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 | 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 | 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 | 重渲染检测:{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 | 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 | 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 | 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 | 11 | 12 | -------------------------------------------------------------------------------- /packages/sifo-vue/demo/quick-start.vue: -------------------------------------------------------------------------------- 1 | 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 | --------------------------------------------------------------------------------