├── .gitignore ├── LICENSE ├── README.md ├── init.sql ├── online-code-backend ├── .gitignore ├── compileflow-core │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── alibaba │ │ └── compileflow │ │ ├── engine │ │ ├── BpmnProcessEngineFactory.java │ │ └── process │ │ │ ├── impl │ │ │ └── BpmnStringProcessEngineImpl.java │ │ │ └── preruntime │ │ │ ├── compiler │ │ │ └── impl │ │ │ │ └── BpmnFlowClassLoader.java │ │ │ └── converter │ │ │ └── impl │ │ │ └── parser │ │ │ └── support │ │ │ └── bpmn │ │ │ ├── DecisionParser.java │ │ │ ├── IncomingParser.java │ │ │ ├── OutgoingParser.java │ │ │ ├── SequenceFlowParser.java │ │ │ └── TaskParser.java │ │ └── extension │ │ ├── cmd │ │ └── AbstractJavaCmd.java │ │ ├── core │ │ ├── CompilerCache.java │ │ └── JavaStringCompiler.java │ │ ├── exception │ │ ├── CompilerException.java │ │ └── RunCmdException.java │ │ ├── executor │ │ ├── JavaExecutor.java │ │ └── service │ │ │ └── JavaService.java │ │ ├── monitor │ │ └── FlowMonitor.java │ │ ├── runtime │ │ └── RuntimeVar.java │ │ └── util │ │ ├── FlowUtils.java │ │ └── VarUtils.java ├── leaf-core │ ├── .gitignore │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── sankuai │ │ └── inf │ │ └── leaf │ │ ├── IDGen.java │ │ ├── common │ │ ├── PropertyFactory.java │ │ ├── Result.java │ │ ├── Status.java │ │ └── ZeroIDGen.java │ │ ├── exception │ │ └── InitException.java │ │ └── segment │ │ ├── SegmentIDGenImpl.java │ │ ├── dao │ │ ├── IDAllocDao.java │ │ ├── IDAllocMapper.java │ │ └── impl │ │ │ └── IDAllocDaoImpl.java │ │ └── model │ │ ├── LeafAlloc.java │ │ ├── Segment.java │ │ └── SegmentBuffer.java ├── online-code-admin │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── onlinecode │ │ │ │ └── admin │ │ │ │ ├── AdminApplication.java │ │ │ │ ├── aspectj │ │ │ │ └── GlobalExceptionHandler.java │ │ │ │ ├── config │ │ │ │ ├── BpmInitializer.java │ │ │ │ ├── CorsConfig.java │ │ │ │ ├── CronConfig.java │ │ │ │ ├── DruidConfig.java │ │ │ │ ├── LeafIDGenConfig.java │ │ │ │ ├── PageHelperConfig.java │ │ │ │ ├── RedisConfig.java │ │ │ │ ├── SaTokenConfig.java │ │ │ │ └── ThreadPoolConfig.java │ │ │ │ ├── constant │ │ │ │ ├── FlowConstants.java │ │ │ │ └── ProcConstants.java │ │ │ │ ├── cron │ │ │ │ ├── controller │ │ │ │ │ └── CronController.java │ │ │ │ ├── dao │ │ │ │ │ └── CronMapper.java │ │ │ │ ├── model │ │ │ │ │ └── SysCron.java │ │ │ │ └── service │ │ │ │ │ ├── CronService.java │ │ │ │ │ └── impl │ │ │ │ │ ├── CronServiceImpl.java │ │ │ │ │ └── CronTaskRegistrar.java │ │ │ │ ├── enums │ │ │ │ ├── AuthTypeEnum.java │ │ │ │ ├── IdKeyEnum.java │ │ │ │ └── StatusEnum.java │ │ │ │ ├── exception │ │ │ │ ├── BusinessException.java │ │ │ │ └── SQLErrorException.java │ │ │ │ ├── filter │ │ │ │ └── RepeatableFilter.java │ │ │ │ ├── interceptor │ │ │ │ ├── PermsInterceptor.java │ │ │ │ └── RepeatedlyRequestWrapper.java │ │ │ │ ├── process │ │ │ │ ├── controller │ │ │ │ │ └── ProcessController.java │ │ │ │ ├── dao │ │ │ │ │ ├── DefaultSqlRunner.java │ │ │ │ │ ├── ProcessMapper.java │ │ │ │ │ ├── ProcessTaskMapper.java │ │ │ │ │ ├── SqlRunner.java │ │ │ │ │ ├── SqlRunnerFactory.java │ │ │ │ │ └── StatementHolder.java │ │ │ │ ├── model │ │ │ │ │ ├── RunParam.java │ │ │ │ │ ├── SysProcess.java │ │ │ │ │ └── SysProcessTask.java │ │ │ │ └── service │ │ │ │ │ ├── ProcessService.java │ │ │ │ │ └── impl │ │ │ │ │ └── ProcessServiceImpl.java │ │ │ │ ├── redis │ │ │ │ ├── DLock.java │ │ │ │ ├── DistributedLock.java │ │ │ │ └── RedissonDistributedLock.java │ │ │ │ ├── sys │ │ │ │ ├── controller │ │ │ │ │ └── LoginController.java │ │ │ │ └── service │ │ │ │ │ └── impl │ │ │ │ │ ├── LoginService.java │ │ │ │ │ └── LoginServiceImpl.java │ │ │ │ ├── util │ │ │ │ ├── HttpUtils.java │ │ │ │ ├── JsonUtils.java │ │ │ │ └── SpringUtils.java │ │ │ │ └── web │ │ │ │ ├── R.java │ │ │ │ └── page │ │ │ │ ├── PageParam.java │ │ │ │ └── PageTable.java │ │ └── resources │ │ │ ├── application-db.yml │ │ │ ├── application-token.yml │ │ │ ├── application.yml │ │ │ └── logback.xml │ │ └── test │ │ ├── java │ │ ├── com │ │ │ └── onlinecode │ │ │ │ └── admin │ │ │ │ └── process │ │ │ │ └── dao │ │ │ │ └── SqlRunnerTest.java │ │ └── sqlrunner │ │ │ └── SqlRunnerDemo.java │ │ └── resources │ │ ├── application-db.yml │ │ ├── application-token.yml │ │ └── application.yml └── pom.xml ├── online-code-frontend-init.png ├── online-code-frontend ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .prettierrc.js ├── build.json ├── build.plugin.js ├── package.json ├── public │ ├── css │ │ ├── AlifdFusionUi.css │ │ ├── AlifdLayout.css │ │ ├── AlilcLowcodeMaterials.css │ │ ├── next-table.css │ │ ├── next.min.css │ │ ├── onlinecode-editor.css │ │ └── onlinecode.css │ ├── editor.html │ ├── favicon.png │ ├── fixtures │ │ └── basic-fusion-with-single-component │ │ │ ├── meta.js │ │ │ ├── view.css │ │ │ └── view.js │ ├── font │ │ ├── font_515771_xjdbujl2iu.woff2 │ │ ├── roboto-bold.woff2 │ │ ├── roboto-regular.woff │ │ └── roboto-regular.woff2 │ ├── img │ │ ├── O1CN01rie9sh1CmpqL3fSKD_!!6000000000124-2-tps-300-206.png │ │ ├── TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png │ │ ├── github.png │ │ ├── login_bg.png │ │ └── login_bg2.jpg │ ├── index.ejs │ ├── index.html │ ├── js │ │ ├── AlifdFusionUi.js │ │ ├── AlifdLayout.js │ │ ├── AlilcLowcodeMaterials.js │ │ ├── font_2535522_4oyyibdwj5v.js │ │ ├── lodash.min.js │ │ ├── moment.min.js │ │ ├── next-table.js │ │ ├── next-with-locales.min.js │ │ ├── next.min.js │ │ ├── prop-types.js │ │ ├── react-dom.production.min.js │ │ └── react.production.min.js │ ├── lowcode │ │ ├── assets-daily.json │ │ ├── assets-dev.json │ │ ├── assets-prod.json │ │ ├── designer.html │ │ ├── index.html │ │ ├── index.js │ │ ├── meta.js │ │ ├── preview.css │ │ ├── preview.html │ │ ├── preview.js │ │ ├── render │ │ │ └── default │ │ │ │ ├── view.css │ │ │ │ └── view.js │ │ ├── view.css │ │ └── view.js │ ├── mock-pages.json │ ├── mock │ │ └── info.json │ └── preview.html ├── scripts │ └── watchdog.js ├── src │ ├── appHelper.ts │ ├── assets │ │ ├── copy-one.svg │ │ ├── delete.svg │ │ ├── edit.svg │ │ ├── exclusive-gateway.svg │ │ ├── full-screen-one.svg │ │ ├── full-screen-two.svg │ │ ├── handle-round.svg │ │ ├── http-code.svg │ │ ├── java-code.svg │ │ ├── logo.png │ │ ├── new-efferent.svg │ │ ├── off-screen-one.svg │ │ ├── off-screen-two.svg │ │ ├── python-code.svg │ │ ├── round.svg │ │ └── sql-code.svg │ ├── components │ │ ├── ProcessDesign │ │ │ ├── canvas │ │ │ │ ├── bpmn.css │ │ │ │ ├── bpmn │ │ │ │ │ ├── custom │ │ │ │ │ │ ├── CustomContextPadProvider.js │ │ │ │ │ │ ├── CustomPalette.js │ │ │ │ │ │ ├── CustomRenderer.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── utils │ │ │ │ │ │ ├── bpmn-util.js │ │ │ │ │ │ ├── event-bus.js │ │ │ │ │ │ └── processStr.js │ │ │ │ ├── connection.css │ │ │ │ ├── context-pad.css │ │ │ │ ├── editor │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.scss │ │ │ │ ├── index.tsx │ │ │ │ ├── label.css │ │ │ │ ├── palette.css │ │ │ │ ├── property-panel.css │ │ │ │ └── run-code │ │ │ │ │ └── index.tsx │ │ │ ├── index.scss │ │ │ └── index.tsx │ │ ├── pages │ │ │ ├── Notice │ │ │ │ ├── index.module.css │ │ │ │ └── index.tsx │ │ │ ├── index.module.css │ │ │ ├── index.tsx │ │ │ ├── renderer.md │ │ │ └── renderer.tsx │ │ └── routes.tsx │ ├── fetchHandler.ts │ ├── global.scss │ ├── index.ts │ ├── plugins │ │ ├── plugin-component-panel │ │ │ └── index.tsx │ │ ├── plugin-custom-setter-sample │ │ │ ├── index.tsx │ │ │ └── setters │ │ │ │ ├── behavior-setter.tsx │ │ │ │ └── custom-setter.tsx │ │ ├── plugin-default-setters-registry │ │ │ └── index.tsx │ │ ├── plugin-editor-init │ │ │ └── index.tsx │ │ ├── plugin-load-incremental-assets-widget │ │ │ └── index.tsx │ │ ├── plugin-logo-sample │ │ │ ├── index.scss │ │ │ └── index.tsx │ │ ├── plugin-lowcode-component │ │ │ ├── index.ts │ │ │ └── lowcode-schema.json │ │ ├── plugin-pages │ │ │ ├── index.scss │ │ │ └── index.tsx │ │ ├── plugin-preview-sample │ │ │ └── index.tsx │ │ ├── plugin-save-sample │ │ │ └── index.tsx │ │ └── plugin-simulator-locale │ │ │ └── index.tsx │ ├── preview.tsx │ └── services │ │ ├── assets.json │ │ ├── defaultI18nSchema.json │ │ ├── defaultPageSchema.json │ │ ├── mockService.ts │ │ ├── schema.json │ │ └── schemaService.ts └── tsconfig.json └── plugin-custom ├── README.md └── plugin-custom-renderer ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .markdownlint.json ├── .markdownlintignore ├── .npmignore ├── .prettierrc.js ├── .stylelintignore ├── .stylelintrc.js ├── README.md ├── build.json ├── build.lowcode.js ├── commitlint.config.js ├── demo └── usage.md ├── f2elint.config.js ├── jest.config.js ├── lowcode └── plugin-custom-renderer │ └── meta.ts ├── package.json ├── src ├── index.scss └── index.tsx ├── test ├── index.test.jsx └── setupTests.js └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .flowclasses/ 3 | 4 | # Package Files # 5 | *.jar 6 | *.war 7 | *.ear 8 | *.versionsBackup 9 | 10 | 11 | *.iml 12 | .idea/ 13 | target/ 14 | logs/ 15 | log/ 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Aaron Sun 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # online-code 2 | 线上编程方案的尝试 3 | 4 | ## online-code-frontend 5 | ### 项目启动 6 | ``` 7 | cd ./online-code-frontend 8 | npm i -f 9 | npm run start 10 | ``` 11 | ### 初始化 12 | ![init](online-code-frontend-init.png) -------------------------------------------------------------------------------- /online-code-backend/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | .DS_Store 9 | .project 10 | .classpath 11 | .settings 12 | 13 | .flowclasses/ 14 | 15 | target 16 | .target/ 17 | *.com 18 | build 19 | 20 | # eclipse # 21 | .project 22 | .classpath 23 | /.settings/ 24 | .settings/ 25 | 26 | # Intellij IDEA # 27 | *.iws 28 | *.iml 29 | *.ipr 30 | *.idea 31 | /.idea/ 32 | .idea/ 33 | 34 | 35 | # Mac OS # 36 | .DS_Store 37 | 38 | # Windows # 39 | Thumbs.db 40 | *.com 41 | 42 | .compileflow_demo.iml -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | online-code-backend 8 | com.onlinecode 9 | 1.0.0 10 | 11 | compileflow-core 12 | jar 13 | 1.0.0 14 | compileflow-core 15 | 16 | 17 | 18 | com.alibaba.compileflow 19 | compileflow 20 | 21 | 22 | spring-core 23 | org.springframework 24 | 25 | 26 | spring-context 27 | org.springframework 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/engine/BpmnProcessEngineFactory.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.engine; 2 | 3 | import com.alibaba.compileflow.engine.process.impl.BpmnStringProcessEngineImpl; 4 | 5 | public class BpmnProcessEngineFactory { 6 | 7 | private static final BpmnStringProcessEngineImpl BPMN_PROCESS_ENGINE = new BpmnStringProcessEngineImpl(); 8 | 9 | public static BpmnStringProcessEngineImpl getProcessEngine() { 10 | return BPMN_PROCESS_ENGINE; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/engine/process/preruntime/compiler/impl/BpmnFlowClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.engine.process.preruntime.compiler.impl; 2 | 3 | import com.alibaba.compileflow.engine.common.CompileFlowException; 4 | 5 | import java.net.*; 6 | import java.util.*; 7 | 8 | public class BpmnFlowClassLoader extends URLClassLoader { 9 | private static volatile BpmnFlowClassLoader instance = null; 10 | 11 | public BpmnFlowClassLoader(URL[] urls, ClassLoader parent) { 12 | super(urls, parent); 13 | } 14 | 15 | public static BpmnFlowClassLoader getInstance() { 16 | if (instance == null) { 17 | synchronized (BpmnFlowClassLoader.class) { 18 | if (instance == null) { 19 | try { 20 | URL url = new URL("file:///" + CompileConstants.FLOW_COMPILE_CLASS_DIR); 21 | List urls = new ArrayList<>(); 22 | urls.add(url); 23 | URLClassLoader parent = (URLClassLoader) Thread.currentThread().getContextClassLoader(); 24 | urls.addAll(Arrays.asList(parent.getURLs())); 25 | instance = new BpmnFlowClassLoader(urls.toArray(new URL[]{}), parent); 26 | } catch (MalformedURLException var3) { 27 | throw new CompileFlowException(var3); 28 | } 29 | } 30 | } 31 | } 32 | return instance; 33 | } 34 | 35 | public void clearCache() { 36 | instance = null; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/engine/process/preruntime/converter/impl/parser/support/bpmn/IncomingParser.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.support.bpmn; 2 | 3 | import com.alibaba.compileflow.engine.definition.bpmn.Activity; 4 | import com.alibaba.compileflow.engine.definition.bpmn.BpmnModelConstants; 5 | import com.alibaba.compileflow.engine.definition.common.Element; 6 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.model.ParseContext; 7 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.model.XMLSource; 8 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.support.AbstractBpmnElementParser; 9 | 10 | public class IncomingParser extends AbstractBpmnElementParser { 11 | 12 | @Override 13 | protected Activity doParse(XMLSource xmlSource, ParseContext parseContext) throws Exception { 14 | return null; 15 | } 16 | 17 | @Override 18 | protected void attachChildElement(Element childElement, Activity element, ParseContext parseContext) { 19 | 20 | } 21 | 22 | @Override 23 | public String getName() { 24 | return BpmnModelConstants.BPMN_ELEMENT_INCOMING; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/engine/process/preruntime/converter/impl/parser/support/bpmn/OutgoingParser.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.support.bpmn; 2 | 3 | import com.alibaba.compileflow.engine.definition.bpmn.Activity; 4 | import com.alibaba.compileflow.engine.definition.bpmn.BpmnModelConstants; 5 | import com.alibaba.compileflow.engine.definition.common.Element; 6 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.model.ParseContext; 7 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.model.XMLSource; 8 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.support.AbstractBpmnElementParser; 9 | 10 | public class OutgoingParser extends AbstractBpmnElementParser { 11 | 12 | @Override 13 | protected Activity doParse(XMLSource xmlSource, ParseContext parseContext) throws Exception { 14 | return null; 15 | } 16 | 17 | @Override 18 | protected void attachChildElement(Element childElement, Activity element, ParseContext parseContext) { 19 | 20 | } 21 | 22 | @Override 23 | public String getName() { 24 | return BpmnModelConstants.BPMN_ELEMENT_OUTGOING; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/engine/process/preruntime/converter/impl/parser/support/bpmn/SequenceFlowParser.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.support.bpmn; 2 | 3 | import com.alibaba.compileflow.engine.definition.bpmn.BpmnModelConstants; 4 | import com.alibaba.compileflow.engine.definition.bpmn.Expression; 5 | import com.alibaba.compileflow.engine.definition.bpmn.SequenceFlow; 6 | import com.alibaba.compileflow.engine.definition.common.Element; 7 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.model.ParseContext; 8 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.model.XMLSource; 9 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.support.AbstractBpmnElementParser; 10 | import org.apache.commons.lang.StringUtils; 11 | 12 | public class SequenceFlowParser extends AbstractBpmnElementParser { 13 | public SequenceFlowParser() { 14 | } 15 | 16 | private String flowId; 17 | private String flowName; 18 | 19 | @Override 20 | protected SequenceFlow doParse(XMLSource xmlSource, ParseContext parseContext) throws Exception { 21 | SequenceFlow sequenceFlow = new SequenceFlow(); 22 | sequenceFlow.setId(xmlSource.getString("id")); 23 | sequenceFlow.setName(xmlSource.getString("name")); 24 | sequenceFlow.setSourceRef(xmlSource.getString("sourceRef")); 25 | sequenceFlow.setTargetRef(xmlSource.getString("targetRef")); 26 | sequenceFlow.setImmediate(xmlSource.getBoolean("isImmediate")); 27 | this.flowId = sequenceFlow.getId(); 28 | this.flowName = sequenceFlow.getName(); 29 | return sequenceFlow; 30 | } 31 | 32 | @Override 33 | protected void attachChildElement(Element childElement, SequenceFlow element, ParseContext parseContext) { 34 | if (childElement instanceof Expression) { 35 | String conditionValue = ((Expression) childElement).getValue(); 36 | if (StringUtils.isNotEmpty(conditionValue)) { 37 | element.setConditionExpression("new JavaExecutor().decide((Map)DataType.transfer(vars, Map.class), \"" 38 | + this.flowId + "\", \"" + this.flowName + "\")"); 39 | } else { 40 | element.setConditionExpression(conditionValue); 41 | } 42 | } 43 | } 44 | 45 | @Override 46 | public String getName() { 47 | return BpmnModelConstants.BPMN_ELEMENT_SEQUENCE_FLOW; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/cmd/AbstractJavaCmd.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.cmd; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author 孙鹏 7 | * @description Java代码执行 8 | * @date Created in 10:39 2023/6/27 9 | * @modified By 10 | */ 11 | public abstract class AbstractJavaCmd { 12 | 13 | /** 14 | * 执行节点代码 15 | * 16 | * @param vars 流程参数 17 | * @return 执行结果 18 | */ 19 | public abstract Object execute(Map vars); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/core/CompilerCache.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.core; 2 | 3 | import javax.tools.JavaFileObject; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | public class CompilerCache { 9 | 10 | public static Map> javaFileCache = new ConcurrentHashMap<>(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/exception/CompilerException.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.exception; 2 | 3 | public class CompilerException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | /** 8 | * 错误码 9 | */ 10 | private Integer code; 11 | 12 | /** 13 | * 错误提示 14 | */ 15 | private String message; 16 | 17 | /** 18 | * 空构造方法,避免反序列化问题 19 | */ 20 | public CompilerException() { 21 | } 22 | 23 | public CompilerException(String message) { 24 | this.code = 500; 25 | this.message = message; 26 | } 27 | 28 | public CompilerException(String message, Integer code) { 29 | this.message = message; 30 | this.code = code; 31 | } 32 | 33 | public CompilerException(String message, Throwable cause) { 34 | super(message, cause); 35 | this.message = message; 36 | this.code = 500; 37 | } 38 | 39 | @Override 40 | public String getMessage() { 41 | return message; 42 | } 43 | 44 | public Integer getCode() { 45 | return code; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/exception/RunCmdException.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.exception; 2 | 3 | public class RunCmdException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | /** 8 | * 错误码 9 | */ 10 | private Integer code; 11 | 12 | /** 13 | * 错误提示 14 | */ 15 | private String message; 16 | 17 | /** 18 | * 空构造方法,避免反序列化问题 19 | */ 20 | public RunCmdException() { 21 | } 22 | 23 | public RunCmdException(String message) { 24 | this.code = 500; 25 | this.message = message; 26 | } 27 | 28 | public RunCmdException(String message, Integer code) { 29 | this.message = message; 30 | this.code = code; 31 | } 32 | 33 | public RunCmdException(String message, Throwable cause) { 34 | super(message, cause); 35 | this.message = message; 36 | this.code = 500; 37 | } 38 | 39 | @Override 40 | public String getMessage() { 41 | return message; 42 | } 43 | 44 | public Integer getCode() { 45 | return code; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/executor/JavaExecutor.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.executor; 2 | 3 | import com.alibaba.compileflow.engine.process.preruntime.compiler.impl.BpmnFlowClassLoader; 4 | import com.alibaba.compileflow.extension.cmd.AbstractJavaCmd; 5 | import com.alibaba.compileflow.extension.core.JavaStringCompiler; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.io.UnsupportedEncodingException; 10 | import java.util.Map; 11 | 12 | public class JavaExecutor { 13 | 14 | private static final Logger log = LoggerFactory.getLogger(JavaExecutor.class); 15 | 16 | @SuppressWarnings("unchecked") 17 | public Map execute(Map flowVars, Map vars, String taskId, String taskName) throws UnsupportedEncodingException { 18 | log.debug("==========================="); 19 | log.debug("执行{}({})节点", taskName, taskId); 20 | if (!flowVars.containsKey(taskId)) { 21 | log.debug("节点未配置代码,无需执行,跳过"); 22 | return vars; 23 | } 24 | String code = flowVars.get(taskId).toString(); 25 | return (Map) execute(code, vars); 26 | } 27 | 28 | public boolean decide(Map flowVars, Map vars, String flowId, String flowName) { 29 | log.debug("==========================="); 30 | log.debug("执行{}({})流", flowName, flowId); 31 | if (!flowVars.containsKey(flowId)) { 32 | log.debug("连线未配置代码,无需执行,跳过"); 33 | return true; 34 | } 35 | String code = flowVars.get(flowId).toString(); 36 | Object result = execute(code, vars); 37 | if (!(result instanceof Boolean)) { 38 | return true; 39 | } 40 | return (boolean) result; 41 | } 42 | 43 | public Object execute(String code, Map vars) { 44 | JavaStringCompiler compiler = compiler(code); 45 | log.debug("开始运行"); 46 | long startTime = System.currentTimeMillis(); 47 | Object result = ((AbstractJavaCmd) compiler.getClassInstance()).execute(vars); 48 | log.debug("运行成功"); 49 | log.debug("运行耗时:{}ms", System.currentTimeMillis() - startTime); 50 | return result; 51 | } 52 | 53 | public JavaStringCompiler compiler(String code) { 54 | JavaStringCompiler compiler = new JavaStringCompiler(code); 55 | compiler.setFlowClassLoader(BpmnFlowClassLoader.getInstance()); 56 | log.debug("开始编译"); 57 | if (!compiler.compile()) { 58 | log.debug("编译异常:\n{}", compiler.getCompilerMessage()); 59 | throw new RuntimeException("编译异常:\n" + compiler.getCompilerMessage()); 60 | } 61 | log.debug("编译成功"); 62 | log.debug("编译耗时:{}ms", compiler.getCompilerTakeTime()); 63 | return compiler; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/executor/service/JavaService.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.executor.service; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author 孙鹏 7 | * @description Java节点服务 8 | * @date Created in 17:57 2023/2/24 9 | * @modified By 10 | */ 11 | public interface JavaService { 12 | 13 | /** 14 | * 执行节点代码 15 | * 16 | * @param vars 流程参数 17 | * @return 执行结果 18 | */ 19 | Object execute(Map vars); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/monitor/FlowMonitor.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.monitor; 2 | 3 | public class FlowMonitor { 4 | } 5 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/runtime/RuntimeVar.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.runtime; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | public class RuntimeVar { 7 | 8 | public RuntimeVar() { 9 | } 10 | 11 | public static ThreadLocal> getInstance() { 12 | return Holder.INSTANCE; 13 | } 14 | 15 | public static void runTask(String taskId) { 16 | RuntimeVar.getInstance().get().put("this.task", taskId); 17 | } 18 | 19 | public static String getRunTask() { 20 | return RuntimeVar.getInstance().get().get("this.task").toString(); 21 | } 22 | 23 | private static class Holder { 24 | private static final ThreadLocal> INSTANCE = new ThreadLocal<>(); 25 | 26 | static { 27 | INSTANCE.set(new ConcurrentHashMap<>()); 28 | } 29 | 30 | private Holder() { 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /online-code-backend/compileflow-core/src/main/java/com/alibaba/compileflow/extension/util/FlowUtils.java: -------------------------------------------------------------------------------- 1 | package com.alibaba.compileflow.extension.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | public class FlowUtils { 9 | 10 | private static final Pattern ID_PATTERN = Pattern.compile("(.*?)"); 14 | 15 | /** 16 | * 过滤bpmn字符串中无用内容 17 | * 18 | * @param bpmn bpmn字符串 19 | * @return 结果 20 | */ 21 | public static String getFlowStr(String bpmn) { 22 | if (org.apache.commons.lang3.StringUtils.isEmpty(bpmn)) { 23 | return null; 24 | } 25 | // 过滤掉不支持的dataAction属性 26 | Matcher matcher = DATA_ACTION_PATTERN.matcher(bpmn); 27 | while (matcher.find()) { 28 | bpmn = bpmn.replace(matcher.group(), ""); 29 | } 30 | // 过滤掉不需要存储的conditionExpression标签 31 | matcher = CONDITION_PATTERN.matcher(bpmn); 32 | while (matcher.find()) { 33 | bpmn = bpmn.replace(matcher.group(), ""); 34 | } 35 | // 过滤掉不需要解析bpmndi 36 | bpmn = bpmn.substring(0, bpmn.indexOf(""; 37 | return bpmn; 38 | } 39 | 40 | /** 41 | * 替换bpmn字符串中的流程编码 42 | * 43 | * @param bpmn bpmn字符串 44 | * @param procCode 流程编码 45 | * @return 结果 46 | */ 47 | public static String replaceProcCode(String bpmn, String procCode) { 48 | if (StringUtils.isEmpty(bpmn)) { 49 | return null; 50 | } 51 | // 替换的id属性 52 | Matcher matcher = ID_PATTERN.matcher(bpmn); 53 | while (matcher.find()) { 54 | bpmn = bpmn.replace(matcher.group(), " vars; 11 | 12 | public VarUtils(Map vars) { 13 | this.vars = vars; 14 | } 15 | 16 | public Map getVars() { 17 | return vars; 18 | } 19 | 20 | public void setVars(Map vars) { 21 | this.vars = vars; 22 | } 23 | 24 | public String getString(String key) { 25 | if (MapUtils.isEmpty(vars) || !vars.containsKey(key) || vars.get(key) == null 26 | || StringUtils.isBlank(vars.get(key).toString())) { 27 | return null; 28 | } 29 | return vars.get(key).toString(); 30 | } 31 | 32 | public Integer getInt(String key) { 33 | return getString(key) == null ? null : Integer.parseInt(vars.get(key).toString()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | *.versionsBackup 8 | 9 | 10 | *.iml 11 | .idea/ 12 | target/ 13 | logs/ 14 | log/ 15 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.onlinecode 6 | online-code-backend 7 | 1.0.0 8 | 9 | leaf-core 10 | jar 11 | 1.0.0 12 | leaf-core 13 | 14 | 15 | 16 | org.mybatis 17 | mybatis 18 | 19 | 20 | org.perf4j 21 | perf4j 22 | 23 | 24 | org.slf4j 25 | slf4j-api 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/IDGen.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf; 2 | 3 | import com.sankuai.inf.leaf.common.Result; 4 | 5 | public interface IDGen { 6 | Result get(String key); 7 | 8 | boolean init(); 9 | } 10 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/common/PropertyFactory.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.common; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.IOException; 7 | import java.util.Properties; 8 | 9 | public class PropertyFactory { 10 | private static final Logger logger = LoggerFactory.getLogger(PropertyFactory.class); 11 | private static final Properties prop = new Properties(); 12 | 13 | static { 14 | try { 15 | prop.load(PropertyFactory.class.getClassLoader().getResourceAsStream("leaf.properties")); 16 | } catch (IOException e) { 17 | logger.warn("Load Properties Ex", e); 18 | } 19 | } 20 | 21 | public static Properties getProperties() { 22 | return prop; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/common/Result.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.common; 2 | 3 | public class Result { 4 | private long id; 5 | private Status status; 6 | 7 | public Result() { 8 | 9 | } 10 | 11 | public Result(long id, Status status) { 12 | this.id = id; 13 | this.status = status; 14 | } 15 | 16 | public long getId() { 17 | return id; 18 | } 19 | 20 | public void setId(long id) { 21 | this.id = id; 22 | } 23 | 24 | public Status getStatus() { 25 | return status; 26 | } 27 | 28 | public void setStatus(Status status) { 29 | this.status = status; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | final StringBuilder sb = new StringBuilder("Result{"); 35 | sb.append("id=").append(id); 36 | sb.append(", status=").append(status); 37 | sb.append('}'); 38 | return sb.toString(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/common/Status.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.common; 2 | 3 | public enum Status { 4 | SUCCESS, 5 | EXCEPTION 6 | } 7 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/common/ZeroIDGen.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.common; 2 | 3 | import com.sankuai.inf.leaf.IDGen; 4 | 5 | public class ZeroIDGen implements IDGen { 6 | @Override 7 | public Result get(String key) { 8 | return new Result(0, Status.SUCCESS); 9 | } 10 | 11 | @Override 12 | public boolean init() { 13 | return true; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/exception/InitException.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.exception; 2 | 3 | public class InitException extends Exception { 4 | public InitException(String msg) { 5 | super(msg); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/segment/dao/IDAllocDao.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.segment.dao; 2 | 3 | import com.sankuai.inf.leaf.segment.model.LeafAlloc; 4 | 5 | import java.util.List; 6 | 7 | public interface IDAllocDao { 8 | List getAllLeafAllocs(); 9 | 10 | LeafAlloc updateMaxIdAndGetLeafAlloc(String tag); 11 | 12 | LeafAlloc updateMaxIdByCustomStepAndGetLeafAlloc(LeafAlloc leafAlloc); 13 | 14 | List getAllTags(); 15 | } 16 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/segment/dao/IDAllocMapper.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.segment.dao; 2 | 3 | import com.sankuai.inf.leaf.segment.model.LeafAlloc; 4 | import org.apache.ibatis.annotations.*; 5 | 6 | import java.util.List; 7 | 8 | public interface IDAllocMapper { 9 | 10 | @Select("SELECT biz_tag, max_id, step, update_time FROM leaf_alloc") 11 | @Results(value = { 12 | @Result(column = "biz_tag", property = "key"), 13 | @Result(column = "max_id", property = "maxId"), 14 | @Result(column = "step", property = "step"), 15 | @Result(column = "update_time", property = "updateTime") 16 | }) 17 | List getAllLeafAllocs(); 18 | 19 | @Select("SELECT biz_tag, max_id, step FROM leaf_alloc WHERE biz_tag = #{tag}") 20 | @Results(value = { 21 | @Result(column = "biz_tag", property = "key"), 22 | @Result(column = "max_id", property = "maxId"), 23 | @Result(column = "step", property = "step") 24 | }) 25 | LeafAlloc getLeafAlloc(@Param("tag") String tag); 26 | 27 | @Update("UPDATE leaf_alloc SET max_id = max_id + step WHERE biz_tag = #{tag}") 28 | void updateMaxId(@Param("tag") String tag); 29 | 30 | @Update("UPDATE leaf_alloc SET max_id = max_id + #{step} WHERE biz_tag = #{key}") 31 | void updateMaxIdByCustomStep(@Param("leafAlloc") LeafAlloc leafAlloc); 32 | 33 | @Select("SELECT biz_tag FROM leaf_alloc") 34 | List getAllTags(); 35 | } 36 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/segment/dao/impl/IDAllocDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.segment.dao.impl; 2 | 3 | import com.sankuai.inf.leaf.segment.dao.IDAllocDao; 4 | import com.sankuai.inf.leaf.segment.dao.IDAllocMapper; 5 | import com.sankuai.inf.leaf.segment.model.LeafAlloc; 6 | import org.apache.ibatis.mapping.Environment; 7 | import org.apache.ibatis.session.Configuration; 8 | import org.apache.ibatis.session.SqlSession; 9 | import org.apache.ibatis.session.SqlSessionFactory; 10 | import org.apache.ibatis.session.SqlSessionFactoryBuilder; 11 | import org.apache.ibatis.transaction.TransactionFactory; 12 | import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; 13 | 14 | import javax.sql.DataSource; 15 | import java.util.List; 16 | 17 | public class IDAllocDaoImpl implements IDAllocDao { 18 | 19 | SqlSessionFactory sqlSessionFactory; 20 | 21 | public IDAllocDaoImpl(DataSource dataSource) { 22 | TransactionFactory transactionFactory = new JdbcTransactionFactory(); 23 | Environment environment = new Environment("development", transactionFactory, dataSource); 24 | Configuration configuration = new Configuration(environment); 25 | configuration.addMapper(IDAllocMapper.class); 26 | sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); 27 | } 28 | 29 | @Override 30 | public List getAllLeafAllocs() { 31 | SqlSession sqlSession = sqlSessionFactory.openSession(false); 32 | try { 33 | return sqlSession.selectList("com.sankuai.inf.leaf.segment.dao.IDAllocMapper.getAllLeafAllocs"); 34 | } finally { 35 | sqlSession.close(); 36 | } 37 | } 38 | 39 | @Override 40 | public LeafAlloc updateMaxIdAndGetLeafAlloc(String tag) { 41 | SqlSession sqlSession = sqlSessionFactory.openSession(); 42 | try { 43 | sqlSession.update("com.sankuai.inf.leaf.segment.dao.IDAllocMapper.updateMaxId", tag); 44 | LeafAlloc result = sqlSession.selectOne("com.sankuai.inf.leaf.segment.dao.IDAllocMapper.getLeafAlloc", tag); 45 | sqlSession.commit(); 46 | return result; 47 | } finally { 48 | sqlSession.close(); 49 | } 50 | } 51 | 52 | @Override 53 | public LeafAlloc updateMaxIdByCustomStepAndGetLeafAlloc(LeafAlloc leafAlloc) { 54 | SqlSession sqlSession = sqlSessionFactory.openSession(); 55 | try { 56 | sqlSession.update("com.sankuai.inf.leaf.segment.dao.IDAllocMapper.updateMaxIdByCustomStep", leafAlloc); 57 | LeafAlloc result = sqlSession.selectOne("com.sankuai.inf.leaf.segment.dao.IDAllocMapper.getLeafAlloc", leafAlloc.getKey()); 58 | sqlSession.commit(); 59 | return result; 60 | } finally { 61 | sqlSession.close(); 62 | } 63 | } 64 | 65 | @Override 66 | public List getAllTags() { 67 | SqlSession sqlSession = sqlSessionFactory.openSession(false); 68 | try { 69 | return sqlSession.selectList("com.sankuai.inf.leaf.segment.dao.IDAllocMapper.getAllTags"); 70 | } finally { 71 | sqlSession.close(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/segment/model/LeafAlloc.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.segment.model; 2 | 3 | public class LeafAlloc { 4 | private String key; 5 | private long maxId; 6 | private int step; 7 | private String updateTime; 8 | 9 | public String getKey() { 10 | return key; 11 | } 12 | 13 | public void setKey(String key) { 14 | this.key = key; 15 | } 16 | 17 | public long getMaxId() { 18 | return maxId; 19 | } 20 | 21 | public void setMaxId(long maxId) { 22 | this.maxId = maxId; 23 | } 24 | 25 | public int getStep() { 26 | return step; 27 | } 28 | 29 | public void setStep(int step) { 30 | this.step = step; 31 | } 32 | 33 | public String getUpdateTime() { 34 | return updateTime; 35 | } 36 | 37 | public void setUpdateTime(String updateTime) { 38 | this.updateTime = updateTime; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /online-code-backend/leaf-core/src/main/java/com/sankuai/inf/leaf/segment/model/Segment.java: -------------------------------------------------------------------------------- 1 | package com.sankuai.inf.leaf.segment.model; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | public class Segment { 6 | private AtomicLong value = new AtomicLong(0); 7 | private volatile long max; 8 | private volatile int step; 9 | private SegmentBuffer buffer; 10 | 11 | public Segment(SegmentBuffer buffer) { 12 | this.buffer = buffer; 13 | } 14 | 15 | public AtomicLong getValue() { 16 | return value; 17 | } 18 | 19 | public void setValue(AtomicLong value) { 20 | this.value = value; 21 | } 22 | 23 | public long getMax() { 24 | return max; 25 | } 26 | 27 | public void setMax(long max) { 28 | this.max = max; 29 | } 30 | 31 | public int getStep() { 32 | return step; 33 | } 34 | 35 | public void setStep(int step) { 36 | this.step = step; 37 | } 38 | 39 | public SegmentBuffer getBuffer() { 40 | return buffer; 41 | } 42 | 43 | public long getIdle() { 44 | return this.getMax() - getValue().get(); 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | StringBuilder sb = new StringBuilder("Segment("); 50 | sb.append("value:"); 51 | sb.append(value); 52 | sb.append(",max:"); 53 | sb.append(max); 54 | sb.append(",step:"); 55 | sb.append(step); 56 | sb.append(")"); 57 | return sb.toString(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | .DS_Store 9 | .project 10 | .classpath 11 | .settings 12 | 13 | .flowclasses/ 14 | 15 | target 16 | .target/ 17 | *.com 18 | build 19 | 20 | # eclipse # 21 | .project 22 | .classpath 23 | /.settings/ 24 | .settings/ 25 | 26 | # Intellij IDEA # 27 | *.iws 28 | *.iml 29 | *.ipr 30 | *.idea 31 | /.idea/ 32 | .idea/ 33 | 34 | 35 | # Mac OS # 36 | .DS_Store 37 | 38 | # Windows # 39 | Thumbs.db 40 | *.com 41 | 42 | .compileflow_demo.iml -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/AdminApplication.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin; 2 | 3 | import com.slowsql.spring.boot.autoconfigure.EnableSlowSqlMonitor; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; 7 | import org.springframework.scheduling.annotation.EnableScheduling; 8 | 9 | /** 10 | * @author xuan 11 | * @since 2020/8/16 12 | */ 13 | @SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}) 14 | @EnableScheduling 15 | @EnableSlowSqlMonitor 16 | public class AdminApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(AdminApplication.class, args); 20 | System.out.println("onlinecode server start ok!!!"); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/aspectj/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.aspectj; 2 | 3 | import com.alibaba.compileflow.extension.exception.CompilerException; 4 | import com.alibaba.compileflow.extension.exception.RunCmdException; 5 | import com.onlinecode.admin.exception.BusinessException; 6 | import com.onlinecode.admin.exception.SQLErrorException; 7 | import com.onlinecode.admin.web.R; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.core.Ordered; 11 | import org.springframework.core.annotation.Order; 12 | import org.springframework.web.bind.annotation.ExceptionHandler; 13 | import org.springframework.web.bind.annotation.RestControllerAdvice; 14 | 15 | /** 16 | * @author 孙鹏 17 | * @description 全局异常处理器 18 | * @date Created in 14:11 2023/8/9 19 | * @modified By 20 | */ 21 | @RestControllerAdvice 22 | @Order(Ordered.HIGHEST_PRECEDENCE) 23 | public class GlobalExceptionHandler { 24 | 25 | private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); 26 | 27 | /** 28 | * 编译异常 29 | */ 30 | @ExceptionHandler(value = CompilerException.class) 31 | public R handleCompilerException(CompilerException e) { 32 | log.error(e.getMessage(), e); 33 | return R.error(e.getCode(), e.getMessage()); 34 | } 35 | 36 | /** 37 | * 代码执行异常 38 | */ 39 | @ExceptionHandler(value = RunCmdException.class) 40 | public R handleRumCmdException(RunCmdException e) { 41 | log.error(e.getMessage(), e); 42 | return R.error(e.getCode(), e.getMessage()); 43 | } 44 | 45 | /** 46 | * SQL异常 47 | */ 48 | @ExceptionHandler(value = SQLErrorException.class) 49 | public R handleSQLErrorException(SQLErrorException e) { 50 | log.error(e.getMessage(), e); 51 | return R.error(e.getCode(), e.getMessage()); 52 | } 53 | 54 | /** 55 | * 标准化接口异常 56 | */ 57 | @ExceptionHandler(value = BusinessException.class) 58 | public R handleServiceException(BusinessException e) { 59 | log.error(e.getMessage(), e); 60 | return R.error(e.getCode(), e.getMessage()); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/BpmInitializer.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import com.alibaba.compileflow.engine.BpmnProcessEngineFactory; 4 | import com.alibaba.compileflow.engine.process.impl.BpmnStringProcessEngineImpl; 5 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.provider.support.BpmnElementParserProvider; 6 | import com.alibaba.compileflow.engine.process.preruntime.converter.impl.parser.support.bpmn.*; 7 | import com.alibaba.compileflow.engine.process.preruntime.generator.bean.SpringApplicationContextProvider; 8 | import com.alibaba.compileflow.extension.util.FlowUtils; 9 | import com.onlinecode.admin.process.model.SysProcess; 10 | import com.onlinecode.admin.process.service.ProcessService; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.BeansException; 14 | import org.springframework.beans.factory.InitializingBean; 15 | import org.springframework.context.ApplicationContext; 16 | import org.springframework.context.ApplicationContextAware; 17 | import org.springframework.context.annotation.Configuration; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @author 孙鹏 23 | * @description 注意:这里是想让系统启动时,预先加载bpm流程到内存,防止第一次调用时,初始化流程所带来的耗时 24 | * @date Created in 17:57 2023/2/24 25 | * @modified By 26 | */ 27 | @Configuration 28 | public class BpmInitializer implements InitializingBean, ApplicationContextAware { 29 | 30 | private static final Logger log = LoggerFactory.getLogger(BpmInitializer.class); 31 | 32 | private ApplicationContext applicationContext; 33 | 34 | @Override 35 | public void afterPropertiesSet() throws Exception { 36 | BpmnElementParserProvider bpmnElementParserProvider = BpmnElementParserProvider.getInstance(); 37 | bpmnElementParserProvider.registerParser(new DecisionParser()); 38 | bpmnElementParserProvider.registerParser(new IncomingParser()); 39 | bpmnElementParserProvider.registerParser(new OutgoingParser()); 40 | bpmnElementParserProvider.registerParser(new SequenceFlowParser()); 41 | bpmnElementParserProvider.registerParser(new TaskParser()); 42 | ProcessService processService = this.applicationContext.getBean(ProcessService.class); 43 | List list = processService.listAll(); 44 | if (list.isEmpty()) { 45 | log.info("no process bpmn need to init..."); 46 | } else { 47 | BpmnStringProcessEngineImpl processEngine = BpmnProcessEngineFactory.getProcessEngine(); 48 | log.info("start process bpmn init..."); 49 | for (SysProcess p : list) { 50 | try { 51 | processEngine.setFlowString(FlowUtils.getFlowStr(p.getBpmn())); 52 | processEngine.preCompile(p.getProcCode()); 53 | log.info("--> {}({}) bpmn init success", p.getProcCode(), p.getProcName()); 54 | } catch (Exception e) { 55 | log.error("--> {}({}) bpmn init failed", p.getProcCode(), p.getProcName(), e); 56 | } 57 | } 58 | } 59 | } 60 | 61 | @Override 62 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 63 | SpringApplicationContextProvider.applicationContext = applicationContext; 64 | this.applicationContext = applicationContext; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.cors.CorsConfiguration; 6 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 7 | import org.springframework.web.filter.CorsFilter; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | /** 11 | * 通用配置 12 | * 13 | * @author ruoyi 14 | */ 15 | @Configuration 16 | public class CorsConfig implements WebMvcConfigurer { 17 | 18 | /** 19 | * 跨域配置 20 | */ 21 | @Bean 22 | public CorsFilter corsFilter() { 23 | CorsConfiguration config = new CorsConfiguration(); 24 | config.setAllowCredentials(true); 25 | // 设置访问源地址 26 | config.addAllowedOriginPattern("*"); 27 | // 设置访问源请求头 28 | config.addAllowedHeader("*"); 29 | // 设置访问源请求方法 30 | config.addAllowedMethod("*"); 31 | // 有效期 1800秒 32 | config.setMaxAge(1800L); 33 | // 添加映射路径,拦截一切请求 34 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 35 | source.registerCorsConfiguration("/**", config); 36 | // 返回新的CorsFilter 37 | return new CorsFilter(source); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/DruidConfig.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import javax.sql.DataSource; 9 | 10 | /** 11 | * druid 配置多数据源 12 | * 13 | * @author ruoyi 14 | */ 15 | @Configuration 16 | public class DruidConfig { 17 | 18 | @Bean 19 | @ConfigurationProperties(prefix = "spring.datasource") 20 | public DataSource masterDataSource() { 21 | return new DruidDataSource(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/LeafIDGenConfig.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import com.sankuai.inf.leaf.IDGen; 4 | import com.sankuai.inf.leaf.exception.InitException; 5 | import com.sankuai.inf.leaf.segment.SegmentIDGenImpl; 6 | import com.sankuai.inf.leaf.segment.dao.IDAllocDao; 7 | import com.sankuai.inf.leaf.segment.dao.impl.IDAllocDaoImpl; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | import javax.sql.DataSource; 14 | 15 | @Configuration 16 | public class LeafIDGenConfig { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(LeafIDGenConfig.class); 19 | 20 | @Bean 21 | public IDGen idGen(DataSource dataSource) throws InitException { 22 | // Config Dao 23 | IDAllocDao dao = new IDAllocDaoImpl(dataSource); 24 | // Config ID Gen 25 | SegmentIDGenImpl idGen = new SegmentIDGenImpl(); 26 | idGen.setDao(dao); 27 | if (idGen.init()) { 28 | log.info("Segment Service Init Successfully"); 29 | } else { 30 | throw new InitException("Segment Service Init Fail"); 31 | } 32 | return idGen; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/PageHelperConfig.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import com.github.pagehelper.PageInterceptor; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.Properties; 8 | 9 | @Configuration 10 | public class PageHelperConfig { 11 | 12 | @Bean(name = "pageProperties") 13 | public Properties pageProperties() { 14 | Properties properties = new Properties(); 15 | properties.setProperty("helperDialect", "mysql"); 16 | properties.setProperty("reasonable", "true"); 17 | properties.setProperty("supportMethodsArguments", "true"); 18 | properties.setProperty("defaultCount", "true"); 19 | properties.setProperty("params", "count=countsql"); 20 | return properties; 21 | } 22 | 23 | @Bean 24 | public PageInterceptor pageInterceptor() { 25 | PageInterceptor interceptor = new PageInterceptor(); 26 | interceptor.setProperties(pageProperties()); 27 | return interceptor; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 6 | import com.fasterxml.jackson.annotation.PropertyAccessor; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.databind.SerializationFeature; 9 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.data.redis.connection.RedisConnectionFactory; 13 | import org.springframework.data.redis.core.RedisTemplate; 14 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 15 | import org.springframework.data.redis.serializer.RedisSerializer; 16 | import org.springframework.data.redis.serializer.StringRedisSerializer; 17 | 18 | @Configuration 19 | public class RedisConfig { 20 | 21 | @Bean("redisTemplate") 22 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { 23 | RedisTemplate redisTemplate = new RedisTemplate<>(); 24 | redisTemplate.setConnectionFactory(redisConnectionFactory); 25 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); 26 | RedisSerializer redisSerializer = new StringRedisSerializer(); 27 | ObjectMapper objectMapper = new ObjectMapper(); 28 | // 日期时间转换 29 | objectMapper.registerModule(new JavaTimeModule()); 30 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 31 | // 非final类型的对象,把对象类型也序列化进去,以便反序列化推测正确的类型 32 | objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), 33 | ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY); 34 | // null字段不显示 35 | objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 36 | // 无public属性或方法时不报错 37 | objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 38 | jackson2JsonRedisSerializer.setObjectMapper(objectMapper); 39 | redisTemplate.setKeySerializer(redisSerializer); 40 | redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); 41 | redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); 42 | redisTemplate.setHashKeySerializer(redisSerializer); 43 | redisTemplate.afterPropertiesSet(); 44 | return redisTemplate; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/SaTokenConfig.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import com.onlinecode.admin.filter.RepeatableFilter; 4 | import com.onlinecode.admin.interceptor.PermsInterceptor; 5 | import com.onlinecode.admin.process.service.ProcessService; 6 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 10 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 11 | 12 | @Configuration 13 | public class SaTokenConfig implements WebMvcConfigurer { 14 | 15 | private final ProcessService processService; 16 | 17 | public SaTokenConfig(ProcessService processService) { 18 | this.processService = processService; 19 | } 20 | 21 | // 注册拦截器 22 | @Override 23 | public void addInterceptors(InterceptorRegistry registry) { 24 | // 注册拦截器 25 | registry.addInterceptor(new PermsInterceptor(processService)) 26 | .addPathPatterns("/**") 27 | .excludePathPatterns("/error", "/login", "/logout", "/isLogin"); 28 | } 29 | 30 | @Bean 31 | public FilterRegistrationBean someFilterRegistration() { 32 | FilterRegistrationBean registration = new FilterRegistrationBean(); 33 | registration.setFilter(new RepeatableFilter()); 34 | registration.addUrlPatterns("/*"); 35 | registration.setName("repeatableFilter"); 36 | registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE); 37 | return registration; 38 | } 39 | } -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/config/ThreadPoolConfig.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.core.task.TaskExecutor; 6 | import org.springframework.scheduling.annotation.EnableAsync; 7 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 8 | 9 | import java.util.concurrent.ThreadPoolExecutor; 10 | 11 | /** 12 | * @author 孙鹏 13 | * @description 线程池配置 14 | * @date Created in 16:15 2024/6/26 15 | * @modified By 16 | */ 17 | @EnableAsync 18 | @Configuration 19 | public class ThreadPoolConfig { 20 | 21 | /** 22 | * 动态编译的代码中使用的线程池 23 | * 24 | * @return 线程池 25 | */ 26 | @Bean(name = "dynamicCompilerTaskExecutor") 27 | public TaskExecutor dynamicCompilerTaskExecutor() { 28 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 29 | // 设置核心线程数等于系统核数--8核 30 | int availableProcessors = Runtime.getRuntime().availableProcessors(); 31 | executor.setCorePoolSize(availableProcessors); 32 | // 设置最大线程数 33 | executor.setMaxPoolSize(availableProcessors * 2 + 1); 34 | //配置队列大小 35 | executor.setQueueCapacity(1024); 36 | // 设置线程活跃时间(秒) 37 | executor.setKeepAliveSeconds(600); 38 | // 设置默认线程名称 39 | executor.setThreadNamePrefix("compiler-task"); 40 | // 等待所有任务结束后再关闭线程池 41 | executor.setWaitForTasksToCompleteOnShutdown(true); 42 | // 线程满了之后由调用者所在的线程来执行 43 | // 拒绝策略:CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 44 | executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 45 | //执行初始化 46 | executor.initialize(); 47 | 48 | 49 | return executor; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/constant/FlowConstants.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.constant; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * @author 孙鹏 7 | * @description 静态常量 8 | * @date Created in 17:57 2023/2/24 9 | * @modified By 10 | */ 11 | public class FlowConstants { 12 | 13 | public static final String FLOW_PROCESS_DIR = System.getProperty("user.dir") + File.separator 14 | + ".flowprocesses" + File.separator; 15 | public static final String FLOW_PROCESS_SUFFIX = ".json"; 16 | /** 17 | * 分布式业务锁key的前缀 18 | */ 19 | public static final String BUSINESS_LOCK = "business_lock:"; 20 | /** 21 | * 分布式业务数据缓存key的前缀 22 | */ 23 | public static final String BUSINESS_CACHE = "business_cache:"; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/constant/ProcConstants.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.constant; 2 | 3 | /** 4 | * @author 孙鹏 5 | * @description 静态常量 6 | * @date Created in 17:57 2023/2/24 7 | * @modified By 8 | */ 9 | public class ProcConstants { 10 | 11 | /** 12 | * 根据菜单编码获取菜单 13 | */ 14 | public static final String MENU_GET_BY_CODE = "menuGetByCode"; 15 | /** 16 | * 根据菜单编码获取菜单 17 | */ 18 | public static final String PROC_CODE = "procCode"; 19 | /** 20 | * 根据菜单编码获取菜单 21 | */ 22 | public static final String PROC_RUN_URL = "/process/run"; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/cron/controller/CronController.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.cron.controller; 2 | 3 | import com.onlinecode.admin.cron.model.SysCron; 4 | import com.onlinecode.admin.cron.service.CronService; 5 | import com.onlinecode.admin.web.R; 6 | import com.onlinecode.admin.web.page.PageParam; 7 | import com.onlinecode.admin.web.page.PageTable; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | @RestController 11 | @RequestMapping("/cron") 12 | public class CronController { 13 | 14 | private final CronService cronService; 15 | 16 | public CronController(CronService cronService) { 17 | this.cronService = cronService; 18 | } 19 | 20 | @PostMapping("/list") 21 | public R list(@RequestBody PageParam pageParam) { 22 | return cronService.list(pageParam); 23 | } 24 | 25 | @GetMapping("/getById") 26 | public R getById(@RequestParam long id) { 27 | return R.ok(cronService.getById(id)); 28 | } 29 | 30 | @PostMapping("/save") 31 | public R save(@RequestBody SysCron process) { 32 | cronService.save(process); 33 | return R.ok(); 34 | } 35 | 36 | @DeleteMapping("/delete") 37 | public R delete(@RequestParam Long id) { 38 | cronService.delete(id); 39 | return R.ok(); 40 | } 41 | 42 | // @PostMapping("/run") 43 | // public R run(@RequestBody RunParam param) { 44 | // return R.ok(cronService.run(param.getProcCode(), param.getVars())); 45 | // } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/cron/service/CronService.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.cron.service; 2 | 3 | import com.onlinecode.admin.cron.model.SysCron; 4 | import com.onlinecode.admin.web.R; 5 | import com.onlinecode.admin.web.page.PageParam; 6 | import com.onlinecode.admin.web.page.PageTable; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author 孙鹏 12 | * @description 定时任务服务 13 | * @date Created in 10:17 2024/6/5 14 | * @modified By 15 | */ 16 | public interface CronService { 17 | 18 | /** 19 | * 分页查询 20 | */ 21 | R list(PageParam pageParam); 22 | 23 | /** 24 | * 查询所有定时任务信息 25 | * 26 | * @return 所有定时任务信息 27 | */ 28 | List listAll(); 29 | 30 | /** 31 | * 根据id查询定时任务信息 32 | */ 33 | SysCron getById(long id); 34 | 35 | /** 36 | * 保存定时任务 37 | * 38 | * @param cron 定时任务对象 39 | */ 40 | void save(SysCron cron); 41 | 42 | /** 43 | * 删除 44 | * 45 | * @param id 定时任务ID 46 | */ 47 | void delete(Long id); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/cron/service/impl/CronTaskRegistrar.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.cron.service.impl; 2 | 3 | import org.springframework.scheduling.config.CronTask; 4 | import org.springframework.scheduling.config.ScheduledTask; 5 | import org.springframework.scheduling.config.ScheduledTaskRegistrar; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | /** 12 | * @author 孙鹏 13 | * @description 定时任务注册启停 14 | * @date Created in 10:17 2024/6/5 15 | * @modified By 16 | */ 17 | @Service 18 | public class CronTaskRegistrar { 19 | 20 | private static final Map TASK_MAP = new ConcurrentHashMap<>(32); 21 | 22 | private ScheduledTaskRegistrar taskRegistrar; 23 | 24 | public void setTaskRegistrar(ScheduledTaskRegistrar taskRegistrar) { 25 | this.taskRegistrar = taskRegistrar; 26 | } 27 | 28 | public void startTask(String taskCode, String cron, Runnable task) { 29 | if (TASK_MAP.containsKey(taskCode)) { 30 | return; 31 | } 32 | CronTask cronTask = new CronTask(task, cron); 33 | ScheduledTask scheduledTask = taskRegistrar.scheduleCronTask(cronTask); 34 | TASK_MAP.put(taskCode, scheduledTask); 35 | } 36 | 37 | public void stopTask(String taskCode) { 38 | if (TASK_MAP.containsKey(taskCode)) { 39 | TASK_MAP.get(taskCode).cancel(); 40 | TASK_MAP.remove(taskCode); 41 | } 42 | } 43 | 44 | public void stopAllTask() { 45 | TASK_MAP.forEach((k, v) -> { 46 | v.cancel(); 47 | TASK_MAP.remove(k); 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/enums/AuthTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.enums; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author 孙鹏 8 | * @description 鉴权类型枚举 9 | * @date Created in 10:17 2024/6/5 10 | * @modified By 11 | */ 12 | public enum AuthTypeEnum { 13 | 14 | ANON("0", "匿名访问"), 15 | AUTH("1", "需要登录"), 16 | PERMS("2", "需要授权"); 17 | 18 | private final String code; 19 | private final String description; 20 | 21 | AuthTypeEnum(String code, String description) { 22 | this.code = code; 23 | this.description = description; 24 | } 25 | 26 | public String getCode() { 27 | return code; 28 | } 29 | 30 | public String getDescription() { 31 | return description; 32 | } 33 | 34 | public boolean equals(String code) { 35 | return this.code.equals(code); 36 | } 37 | 38 | private static final Map LOCAL_MAP = new HashMap<>(); 39 | 40 | static { 41 | for (AuthTypeEnum e : values()) { 42 | LOCAL_MAP.put(e.getCode(), e); 43 | } 44 | } 45 | 46 | public static AuthTypeEnum getByCode(String code) { 47 | return LOCAL_MAP.getOrDefault(code, null); 48 | } 49 | 50 | public static Boolean isValid(String code) { 51 | if (code == null || code.isEmpty()) { 52 | return false; 53 | } 54 | return null != LOCAL_MAP.get(code); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/enums/IdKeyEnum.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.enums; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author 孙鹏 8 | * @description ID枚举 9 | * @date Created in 10:17 2024/6/5 10 | * @modified By 11 | */ 12 | public enum IdKeyEnum { 13 | 14 | SYS_PROCESS("sys_process", "流程信息表"), 15 | SYS_CRON("sys_cron", "定时任务表"); 16 | 17 | private final String code; 18 | private final String description; 19 | 20 | IdKeyEnum(String code, String description) { 21 | this.code = code; 22 | this.description = description; 23 | } 24 | 25 | public String getCode() { 26 | return code; 27 | } 28 | 29 | public String getDescription() { 30 | return description; 31 | } 32 | 33 | public boolean equals(String code) { 34 | return this.code.equals(code); 35 | } 36 | 37 | private static final Map LOCAL_MAP = new HashMap<>(); 38 | 39 | static { 40 | for (IdKeyEnum e : values()) { 41 | LOCAL_MAP.put(e.getCode(), e); 42 | } 43 | } 44 | 45 | public static IdKeyEnum getByCode(String code) { 46 | return LOCAL_MAP.getOrDefault(code, null); 47 | } 48 | 49 | public static Boolean isValid(String code) { 50 | if (code == null || code.isEmpty()) { 51 | return false; 52 | } 53 | return null != LOCAL_MAP.get(code); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/enums/StatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.enums; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author 孙鹏 8 | * @description 状态枚举 9 | * @date Created in 10:17 2024/6/5 10 | * @modified By 11 | */ 12 | public enum StatusEnum { 13 | 14 | DISABLED("0", "禁用"), 15 | ENABLED("1", "启用"); 16 | 17 | private final String code; 18 | private final String description; 19 | 20 | StatusEnum(String code, String description) { 21 | this.code = code; 22 | this.description = description; 23 | } 24 | 25 | public String getCode() { 26 | return code; 27 | } 28 | 29 | public String getDescription() { 30 | return description; 31 | } 32 | 33 | public boolean equals(String code) { 34 | return this.code.equals(code); 35 | } 36 | 37 | private static final Map LOCAL_MAP = new HashMap<>(); 38 | 39 | static { 40 | for (StatusEnum e : values()) { 41 | LOCAL_MAP.put(e.getCode(), e); 42 | } 43 | } 44 | 45 | public static StatusEnum getByCode(String code) { 46 | return LOCAL_MAP.getOrDefault(code, null); 47 | } 48 | 49 | public static Boolean isValid(String code) { 50 | if (code == null || code.isEmpty()) { 51 | return false; 52 | } 53 | return null != LOCAL_MAP.get(code); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/exception/BusinessException.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.exception; 2 | 3 | public class BusinessException extends RuntimeException { 4 | private static final long serialVersionUID = 1L; 5 | 6 | /** 7 | * 错误码 8 | */ 9 | private Integer code; 10 | 11 | /** 12 | * 错误提示 13 | */ 14 | private String message; 15 | 16 | /** 17 | * 空构造方法,避免反序列化问题 18 | */ 19 | public BusinessException() { 20 | } 21 | 22 | public BusinessException(String message) { 23 | this.code = 500; 24 | this.message = message; 25 | } 26 | 27 | public BusinessException(String message, Integer code) { 28 | this.message = message; 29 | this.code = code; 30 | } 31 | 32 | public BusinessException(String message, Throwable cause) { 33 | super(message, cause); 34 | this.message = message; 35 | this.code = 500; 36 | } 37 | 38 | @Override 39 | public String getMessage() { 40 | return message; 41 | } 42 | 43 | public Integer getCode() { 44 | return code; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/exception/SQLErrorException.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.exception; 2 | 3 | public class SQLErrorException extends RuntimeException { 4 | private static final long serialVersionUID = 1L; 5 | 6 | /** 7 | * 错误码 8 | */ 9 | private Integer code; 10 | 11 | /** 12 | * 错误提示 13 | */ 14 | private String message; 15 | 16 | /** 17 | * 空构造方法,避免反序列化问题 18 | */ 19 | public SQLErrorException() { 20 | } 21 | 22 | public SQLErrorException(String message) { 23 | this.code = 500; 24 | this.message = message; 25 | } 26 | 27 | public SQLErrorException(String message, Integer code) { 28 | this.message = message; 29 | this.code = code; 30 | } 31 | 32 | public SQLErrorException(String message, Throwable cause) { 33 | super(message, cause); 34 | this.message = message; 35 | this.code = 500; 36 | } 37 | 38 | @Override 39 | public String getMessage() { 40 | return message; 41 | } 42 | 43 | public Integer getCode() { 44 | return code; 45 | } 46 | } -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/filter/RepeatableFilter.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.filter; 2 | 3 | import com.onlinecode.admin.interceptor.RepeatedlyRequestWrapper; 4 | 5 | import javax.servlet.*; 6 | import javax.servlet.http.HttpServletRequest; 7 | import java.io.IOException; 8 | 9 | /** 10 | * Repeatable 过滤器 11 | * 12 | * @author ruoyi 13 | */ 14 | public class RepeatableFilter implements Filter { 15 | @Override 16 | public void init(FilterConfig filterConfig) throws ServletException { 17 | 18 | } 19 | 20 | @Override 21 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 22 | throws IOException, ServletException { 23 | ServletRequest requestWrapper = null; 24 | if (request instanceof HttpServletRequest) { 25 | requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); 26 | } 27 | if (null == requestWrapper) { 28 | chain.doFilter(request, response); 29 | } else { 30 | chain.doFilter(requestWrapper, response); 31 | } 32 | } 33 | 34 | @Override 35 | public void destroy() { 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/interceptor/RepeatedlyRequestWrapper.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.interceptor; 2 | 3 | import org.apache.commons.lang3.exception.ExceptionUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.servlet.ReadListener; 8 | import javax.servlet.ServletInputStream; 9 | import javax.servlet.ServletRequest; 10 | import javax.servlet.ServletResponse; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletRequestWrapper; 13 | import java.io.*; 14 | import java.nio.charset.StandardCharsets; 15 | 16 | /** 17 | * 构建可重复读取inputStream的request 18 | * 19 | * @author ruoyi 20 | */ 21 | public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { 22 | 23 | private static final Logger log = LoggerFactory.getLogger(RepeatedlyRequestWrapper.class); 24 | 25 | private final byte[] body; 26 | 27 | public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException { 28 | super(request); 29 | request.setCharacterEncoding("UTF-8"); 30 | response.setCharacterEncoding("UTF-8"); 31 | 32 | body = getBodyString(request).getBytes("UTF-8"); 33 | } 34 | 35 | public static String getBodyString(ServletRequest request) { 36 | StringBuilder sb = new StringBuilder(); 37 | BufferedReader reader = null; 38 | try (InputStream inputStream = request.getInputStream()) { 39 | reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); 40 | String line = ""; 41 | while ((line = reader.readLine()) != null) { 42 | sb.append(line); 43 | } 44 | } catch (IOException e) { 45 | log.warn("getBodyString出现问题!"); 46 | } finally { 47 | if (reader != null) { 48 | try { 49 | reader.close(); 50 | } catch (IOException e) { 51 | log.error(ExceptionUtils.getMessage(e)); 52 | } 53 | } 54 | } 55 | return sb.toString(); 56 | } 57 | 58 | @Override 59 | public BufferedReader getReader() throws IOException { 60 | return new BufferedReader(new InputStreamReader(getInputStream())); 61 | } 62 | 63 | @Override 64 | public ServletInputStream getInputStream() throws IOException { 65 | final ByteArrayInputStream bais = new ByteArrayInputStream(body); 66 | return new ServletInputStream() { 67 | @Override 68 | public int read() throws IOException { 69 | return bais.read(); 70 | } 71 | 72 | @Override 73 | public int available() throws IOException { 74 | return body.length; 75 | } 76 | 77 | @Override 78 | public boolean isFinished() { 79 | return false; 80 | } 81 | 82 | @Override 83 | public boolean isReady() { 84 | return false; 85 | } 86 | 87 | @Override 88 | public void setReadListener(ReadListener readListener) { 89 | 90 | } 91 | }; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/controller/ProcessController.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.controller; 2 | 3 | import com.onlinecode.admin.process.model.RunParam; 4 | import com.onlinecode.admin.process.model.SysProcess; 5 | import com.onlinecode.admin.process.service.ProcessService; 6 | import com.onlinecode.admin.web.R; 7 | import com.onlinecode.admin.web.page.PageParam; 8 | import com.onlinecode.admin.web.page.PageTable; 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.apache.commons.lang3.exception.ExceptionUtils; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | @RestController 14 | @RequestMapping("/process") 15 | public class ProcessController { 16 | 17 | private final ProcessService processService; 18 | 19 | public ProcessController(ProcessService processService) { 20 | this.processService = processService; 21 | } 22 | 23 | @PostMapping("/list") 24 | public R list(@RequestBody PageParam pageParam) { 25 | return processService.list(pageParam); 26 | } 27 | 28 | @GetMapping("/getById") 29 | public R getById(@RequestParam long id) { 30 | return R.ok(processService.getById(id)); 31 | } 32 | 33 | @GetMapping("/getInfoWithTaskById") 34 | public R getInfoWithTaskById(@RequestParam long id) { 35 | return R.ok(processService.getInfoWithTaskById(id)); 36 | } 37 | 38 | @PostMapping("/save") 39 | public R save(@RequestBody SysProcess process) { 40 | processService.save(process); 41 | return R.ok(); 42 | } 43 | 44 | @PostMapping("/copy") 45 | public R copy(@RequestBody SysProcess process) { 46 | processService.copy(process); 47 | return R.ok(); 48 | } 49 | 50 | @DeleteMapping("/delete") 51 | public R delete(@RequestParam Long id) { 52 | processService.delete(id); 53 | return R.ok(); 54 | } 55 | 56 | @PostMapping("/run") 57 | public R run(@RequestBody RunParam param) { 58 | return R.ok(processService.run(param.getProcCode(), param.getVars())); 59 | } 60 | 61 | @PostMapping("/runTask") 62 | public R runTask(@RequestBody RunParam param) { 63 | return R.ok(processService.runTask(param.getProcCode(), param.getTaskCode(), param.getVars())); 64 | } 65 | 66 | @PostMapping("/runCmd") 67 | public R runCmd(@RequestBody RunParam param) { 68 | if (StringUtils.isBlank(param.getCmd())) { 69 | return R.error("代码不可为空"); 70 | } 71 | try { 72 | return R.ok(processService.runCmd(param.getCmd(), param.getVars())); 73 | } catch (Exception e) { 74 | return R.error("节点执行失败,错误信息:\n" + ExceptionUtils.getStackTrace(e)); 75 | } 76 | } 77 | 78 | @GetMapping("/autocomplete") 79 | public R autocomplete() { 80 | return R.ok(processService.autocomplete()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/dao/ProcessTaskMapper.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.dao; 2 | 3 | import com.onlinecode.admin.process.model.SysProcessTask; 4 | import org.apache.ibatis.annotations.*; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author 孙鹏 10 | * @description 编排流程节点Mapper 11 | * @date Created in 10:17 2024/6/5 12 | * @modified By 13 | */ 14 | public interface ProcessTaskMapper { 15 | 16 | @Select("SELECT id, proc_code, task_code, task_name, execute_cmd FROM sys_process_task") 17 | @Results(value = { 18 | @Result(column = "id", property = "id"), 19 | @Result(column = "proc_code", property = "procCode"), 20 | @Result(column = "task_code", property = "taskCode"), 21 | @Result(column = "task_name", property = "taskName"), 22 | @Result(column = "execute_cmd", property = "executeCmd") 23 | }) 24 | List getAllTask(); 25 | 26 | @Select("SELECT id, proc_code, task_code, task_name, execute_cmd FROM sys_process_task" + 27 | " WHERE proc_code = #{procCode}") 28 | @Results(value = { 29 | @Result(column = "id", property = "id"), 30 | @Result(column = "proc_code", property = "procCode"), 31 | @Result(column = "task_code", property = "taskCode"), 32 | @Result(column = "task_name", property = "taskName"), 33 | @Result(column = "execute_cmd", property = "executeCmd") 34 | }) 35 | List getByProcCode(@Param("procCode") String procCode); 36 | 37 | 38 | @Select("SELECT id, proc_code, task_code, task_name, execute_cmd FROM sys_process_task" + 39 | " WHERE proc_code = #{procCode}") 40 | @Results(value = { 41 | @Result(column = "id", property = "id"), 42 | @Result(column = "proc_code", property = "procCode"), 43 | @Result(column = "task_code", property = "taskCode"), 44 | @Result(column = "task_name", property = "taskName"), 45 | @Result(column = "execute_cmd", property = "executeCmd") 46 | }) 47 | SysProcessTask getByProcCodeAndTaskCode(@Param("procCode") String procCode, @Param("taskCode") String taskCode); 48 | 49 | @Insert("") 56 | void insertBatch(@Param("list") List list); 57 | 58 | @Delete("DELETE FROM sys_process_task WHERE proc_code = #{procCode}") 59 | void deleteByProcCode(@Param("procCode") String procCode); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/dao/SqlRunner.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.dao; 2 | 3 | import com.onlinecode.admin.web.page.PageTable; 4 | 5 | import java.io.Closeable; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author 孙鹏 11 | * @description 自定义Sql执行器 12 | * @date Created in 10:17 2024/6/5 13 | * @modified By 14 | */ 15 | public interface SqlRunner extends Closeable { 16 | 17 | List> selectList(String sql); 18 | 19 | List> selectList(String sql, Map parameters); 20 | 21 | List> selectList(String sql, Map parameters, boolean camelCase); 22 | 23 | PageTable selectPage(String sql, int pageNum, int pageSize); 24 | 25 | PageTable selectPage(String sql, Map parameters); 26 | 27 | PageTable selectPage(String sql, Map parameters, boolean camelCase); 28 | 29 | Map selectOne(String sql); 30 | 31 | Map selectOne(String sql, Map parameters); 32 | 33 | Map selectOne(String sql, Map parameters, boolean camelCase); 34 | 35 | int insert(String sql, Map parameters); 36 | 37 | int insertBatch(String sql, List> parameters, String collection, int batchSize); 38 | 39 | int update(String sql, Map parameters); 40 | 41 | int delete(String sql, Map parameters); 42 | 43 | void commit(); 44 | 45 | void rollback(); 46 | 47 | void close(); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/dao/SqlRunnerFactory.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.dao; 2 | 3 | import org.apache.ibatis.session.TransactionIsolationLevel; 4 | import org.apache.ibatis.transaction.TransactionFactory; 5 | import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.sql.DataSource; 10 | import java.sql.SQLException; 11 | import java.util.Properties; 12 | 13 | @Service 14 | public class SqlRunnerFactory { 15 | 16 | private final TransactionFactory transactionFactory; 17 | private final DataSource dataSource; 18 | private final Properties pageProperties; 19 | 20 | public SqlRunnerFactory(DataSource dataSource, @Qualifier("pageProperties") Properties pageProperties) { 21 | transactionFactory = new JdbcTransactionFactory(); 22 | this.dataSource = dataSource; 23 | this.pageProperties = pageProperties; 24 | } 25 | 26 | public DefaultSqlRunner openRunner() { 27 | return openRunner(null, false); 28 | } 29 | 30 | public DefaultSqlRunner openRunner(boolean autoCommit) { 31 | return openRunner(null, autoCommit); 32 | } 33 | 34 | public DefaultSqlRunner openRunner(TransactionIsolationLevel level, boolean autoCommit) { 35 | try { 36 | return new DefaultSqlRunner(transactionFactory.newTransaction(dataSource, level, autoCommit) 37 | .getConnection(), pageProperties); 38 | } catch (SQLException throwables) { 39 | throwables.printStackTrace(); 40 | return null; 41 | } 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/dao/StatementHolder.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.dao; 2 | 3 | /** 4 | * @author 孙鹏 5 | * @description 自定义Statement持有者 6 | * @date Created in 10:17 2024/6/5 7 | * @modified By 8 | */ 9 | @FunctionalInterface 10 | public interface StatementHolder { 11 | 12 | R apply(T t) throws Exception; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/model/RunParam.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.model; 2 | 3 | import java.io.Serializable; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author 孙鹏 8 | * @description 执行参数 9 | * @date Created in 10:17 2024/6/5 10 | * @modified By 11 | */ 12 | public class RunParam implements Serializable { 13 | 14 | private static final long serialVersionUID = 7829125842083645635L; 15 | 16 | private String procCode; 17 | private String taskCode; 18 | private String cmd; 19 | private Map vars; 20 | 21 | public String getProcCode() { 22 | return procCode; 23 | } 24 | 25 | public void setProcCode(String procCode) { 26 | this.procCode = procCode; 27 | } 28 | 29 | public String getTaskCode() { 30 | return taskCode; 31 | } 32 | 33 | public void setTaskCode(String taskCode) { 34 | this.taskCode = taskCode; 35 | } 36 | 37 | public String getCmd() { 38 | return cmd; 39 | } 40 | 41 | public void setCmd(String cmd) { 42 | this.cmd = cmd; 43 | } 44 | 45 | public Map getVars() { 46 | return vars; 47 | } 48 | 49 | public void setVars(Map vars) { 50 | this.vars = vars; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/model/SysProcessTask.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.model; 2 | 3 | /** 4 | * @author 孙鹏 5 | * @description 编排流程节点实体 6 | * @date Created in 10:17 2024/6/5 7 | * @modified By 8 | */ 9 | public class SysProcessTask { 10 | 11 | private Long id; 12 | private String procCode; 13 | private String taskCode; 14 | private String taskName; 15 | private String executeCmd; 16 | 17 | public SysProcessTask() { 18 | } 19 | 20 | public SysProcessTask(Long id, String procCode, String taskCode, String taskName, String executeCmd) { 21 | this.id = id; 22 | this.procCode = procCode; 23 | this.taskCode = taskCode; 24 | this.taskName = taskName; 25 | this.executeCmd = executeCmd; 26 | } 27 | 28 | public Long getId() { 29 | return id; 30 | } 31 | 32 | public void setId(Long id) { 33 | this.id = id; 34 | } 35 | 36 | public String getProcCode() { 37 | return procCode; 38 | } 39 | 40 | public void setProcCode(String procCode) { 41 | this.procCode = procCode; 42 | } 43 | 44 | public String getTaskCode() { 45 | return taskCode; 46 | } 47 | 48 | public void setTaskCode(String taskCode) { 49 | this.taskCode = taskCode; 50 | } 51 | 52 | public String getTaskName() { 53 | return taskName; 54 | } 55 | 56 | public void setTaskName(String taskName) { 57 | this.taskName = taskName; 58 | } 59 | 60 | public String getExecuteCmd() { 61 | return executeCmd; 62 | } 63 | 64 | public void setExecuteCmd(String executeCmd) { 65 | this.executeCmd = executeCmd; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/process/service/ProcessService.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.process.service; 2 | 3 | import com.onlinecode.admin.process.model.SysProcess; 4 | import com.onlinecode.admin.web.R; 5 | import com.onlinecode.admin.web.page.PageParam; 6 | import com.onlinecode.admin.web.page.PageTable; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author 孙鹏 13 | * @description 流程服务 14 | * @date Created in 17:57 2023/2/24 15 | * @modified By 16 | */ 17 | public interface ProcessService { 18 | 19 | /** 20 | * 分页查询 21 | */ 22 | R list(PageParam pageParam); 23 | 24 | /** 25 | * 查询所有流程信息 26 | * 27 | * @return 所有流程信息 28 | */ 29 | List listAll(); 30 | 31 | /** 32 | * 根据id查询流程信息 33 | */ 34 | SysProcess getById(long id); 35 | 36 | /** 37 | * 根据id查询流程信息,包含节点信息 38 | */ 39 | SysProcess getInfoWithTaskById(long id); 40 | 41 | /** 42 | * 保存流程 43 | * 44 | * @param process 流程对象 45 | */ 46 | void save(SysProcess process); 47 | 48 | /** 49 | * 拷贝流程 50 | * 51 | * @param process 流程对象 52 | */ 53 | void copy(SysProcess process); 54 | 55 | /** 56 | * 删除 57 | * 58 | * @param id 流程ID 59 | */ 60 | void delete(Long id); 61 | 62 | /** 63 | * 运行 64 | * 65 | * @param code 流程编码 66 | * @param params 运行参数 67 | * @return 结果 68 | */ 69 | Object run(String code, Map params); 70 | 71 | /** 72 | * 运行单个节点 73 | * 74 | * @param procCode 流程编码 75 | * @param taskCode 节点编码 76 | * @param params 运行参数 77 | * @return 结果 78 | */ 79 | Object runTask(String procCode, String taskCode, Map params); 80 | 81 | /** 82 | * 运行命令 83 | * 84 | * @param cmd 命令代码 85 | * @param params 运行参数 86 | * @return 结果 87 | */ 88 | Object runCmd(String cmd, Map params); 89 | 90 | /** 91 | * 自动补全 92 | * 93 | * @return 结果 94 | */ 95 | Object autocomplete(); 96 | 97 | } 98 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/redis/DLock.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.redis; 2 | 3 | import java.util.Objects; 4 | 5 | public class DLock implements AutoCloseable { 6 | 7 | private T lock; 8 | private DistributedLock distributedLock; 9 | 10 | public DLock() { 11 | } 12 | 13 | public DLock(T lock, DistributedLock distributedLock) { 14 | this.lock = lock; 15 | this.distributedLock = distributedLock; 16 | } 17 | 18 | public T getLock() { 19 | return lock; 20 | } 21 | 22 | public void setLock(T lock) { 23 | this.lock = lock; 24 | } 25 | 26 | public DistributedLock getDistributedLock() { 27 | return distributedLock; 28 | } 29 | 30 | public void setDistributedLock(DistributedLock distributedLock) { 31 | this.distributedLock = distributedLock; 32 | } 33 | 34 | @Override 35 | public void close() throws Exception { 36 | if (Objects.nonNull(lock)) { 37 | distributedLock.unLock(lock); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/redis/DistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.redis; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | public interface DistributedLock { 6 | 7 | /** 8 | * 获取锁,默认30秒失效,失败一直等待,直到获取到锁 9 | * 10 | * @param key 锁的key 11 | * @return 锁对象 12 | */ 13 | DLock lock(String key); 14 | 15 | /** 16 | * 获取锁,失败一直等待,直到获取到锁 17 | * 18 | * @param key 锁的key 19 | * @param lockTime 加锁的时间,超过这个时间后,自动解锁;如果为-1,则保持锁定,直到手动解锁 20 | * @param unit 参数的时间单位 21 | * @param fair 是否公平锁 22 | * @return 锁对象 23 | */ 24 | DLock lock(String key, long lockTime, TimeUnit unit, boolean fair); 25 | 26 | /** 27 | * 获取锁,默认30秒失效,失败一直等待,直到获取到锁 28 | * 29 | * @param key 锁的key 30 | * @param tryTime 获取锁的最大尝试时间 31 | * @return 锁对象 32 | * @throws Exception 异常 33 | */ 34 | DLock tryLock(String key, long tryTime) throws Exception; 35 | 36 | /** 37 | * 获取锁,获取不到返回null 38 | * 39 | * @param key 锁的key 40 | * @param tryTime 获取锁的最大尝试时间 41 | * @param lockTime 加锁的时间,超过这个时间后,自动解锁;如果为-1,则保持锁定,直到手动解锁 42 | * @param unit 参数的时间单位 43 | * @param fair 是否公平锁 44 | * @return 锁对象 45 | * @throws Exception 异常 46 | */ 47 | DLock tryLock(String key, long tryTime, long lockTime, TimeUnit unit, boolean fair) throws Exception; 48 | 49 | /** 50 | * 解锁 51 | * 52 | * @param lock 锁对象 53 | */ 54 | void unLock(T lock); 55 | 56 | /** 57 | * 解锁 58 | * 59 | * @param lock 锁对象 60 | */ 61 | default void unLock(DLock lock) { 62 | if (lock != null) { 63 | unLock(lock.getLock()); 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/redis/RedissonDistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.redis; 2 | 3 | import org.redisson.api.RLock; 4 | import org.redisson.api.RedissonClient; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.concurrent.TimeUnit; 11 | 12 | @Service 13 | public class RedissonDistributedLock implements DistributedLock { 14 | 15 | private static final Logger log = LoggerFactory.getLogger(RedissonDistributedLock.class); 16 | 17 | @Autowired 18 | private RedissonClient redissonClient; 19 | 20 | @Override 21 | public DLock lock(String key) { 22 | return this.lock(key, 0L, TimeUnit.SECONDS, false); 23 | } 24 | 25 | @Override 26 | public DLock lock(String key, long lockTime, TimeUnit unit, boolean fair) { 27 | RLock lock = this.getLock(key, fair); 28 | // 获取锁,失败一直等待,直到获取锁,不支持自动续期 29 | if (lockTime > 0) { 30 | lock.lock(lockTime, unit); 31 | } else { 32 | // 具有watch dog自动续期机制,默认续30s,每个30/3=10s,续到30s 33 | lock.lock(); 34 | } 35 | return new DLock<>(lock, this); 36 | } 37 | 38 | @Override 39 | public DLock tryLock(String key, long tryTime) throws Exception { 40 | return this.tryLock(key, tryTime, 0L, TimeUnit.SECONDS, false); 41 | } 42 | 43 | @Override 44 | public DLock tryLock(String key, long tryTime, long lockTime, TimeUnit unit, boolean fair) throws Exception { 45 | RLock lock = this.getLock(key, fair); 46 | boolean lockAcquired; 47 | if (lockTime > 0) { 48 | lockAcquired = lock.tryLock(tryTime, lockTime, unit); 49 | } else { 50 | lockAcquired = lock.tryLock(tryTime, unit); 51 | } 52 | 53 | if (lockAcquired) { 54 | return new DLock<>(lock, this); 55 | } 56 | return null; 57 | } 58 | 59 | private RLock getLock(String key, boolean fair) { 60 | return fair ? redissonClient.getFairLock(key) : redissonClient.getLock(key); 61 | } 62 | 63 | @Override 64 | public void unLock(RLock lock) { 65 | if (lock.isLocked()) { 66 | try { 67 | lock.unlock(); 68 | } catch (IllegalMonitorStateException e) { 69 | log.error("释放分布式锁异常", e); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/sys/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.sys.controller; 2 | 3 | import cn.dev33.satoken.stp.StpUtil; 4 | import com.onlinecode.admin.process.service.ProcessService; 5 | import com.onlinecode.admin.web.R; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | @RestController 15 | public class LoginController { 16 | 17 | private final ProcessService processService; 18 | 19 | public LoginController(ProcessService processService) { 20 | this.processService = processService; 21 | } 22 | 23 | @PostMapping("/login") 24 | public R login(@RequestParam String username, @RequestParam String password) { 25 | Map vars = new HashMap<>(); 26 | vars.put("username", username); 27 | vars.put("password", password); 28 | return R.ok(processService.run("login", vars)); 29 | } 30 | 31 | @GetMapping("/logout") 32 | public R logout() { 33 | StpUtil.logout(); 34 | return R.ok(); 35 | } 36 | 37 | @GetMapping("/isLogin") 38 | public R isLogin() { 39 | return R.ok(StpUtil.isLogin()); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/sys/service/impl/LoginService.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.sys.service.impl; 2 | 3 | import java.util.Map; 4 | 5 | public interface LoginService { 6 | 7 | /** 8 | * 获取用户角色及权限 9 | * 10 | * @param username 用户名 11 | * @return 角色和权限 12 | */ 13 | Map getRoleAndPermission(String username); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/sys/service/impl/LoginServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.sys.service.impl; 2 | 3 | import com.onlinecode.admin.process.dao.DefaultSqlRunner; 4 | import com.onlinecode.admin.process.dao.SqlRunnerFactory; 5 | import org.springframework.stereotype.Service; 6 | 7 | import java.util.Map; 8 | 9 | @Service 10 | public class LoginServiceImpl implements LoginService { 11 | 12 | private final SqlRunnerFactory sqlRunnerFactory; 13 | 14 | public LoginServiceImpl(SqlRunnerFactory sqlRunnerFactory) { 15 | this.sqlRunnerFactory = sqlRunnerFactory; 16 | } 17 | 18 | @Override 19 | public Map getRoleAndPermission(String username) { 20 | DefaultSqlRunner sqlRunner = sqlRunnerFactory.openRunner(); 21 | 22 | return null; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/util/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.util; 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * @author 孙鹏 13 | * @description JSON工具类 14 | * @date Created in 18:22 2024/6/7 15 | * @modified By 16 | */ 17 | public class JsonUtils { 18 | 19 | private static final Logger log = LoggerFactory.getLogger(JsonUtils.class); 20 | 21 | public static Map convertJsonToMap(String json) { 22 | if (StringUtils.isBlank(json)) { 23 | return null; 24 | } 25 | ObjectMapper objectMapper = new ObjectMapper(); 26 | try { 27 | return objectMapper.readValue(json, new TypeReference>() { 28 | }); 29 | } catch (Exception e) { 30 | log.error("字符串转Map异常:{}", e.getMessage(), e); 31 | return null; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/web/page/PageParam.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.web.page; 2 | 3 | public class PageParam { 4 | 5 | private int pageNum; 6 | private int pageSize; 7 | private T param; 8 | 9 | public int getPageNum() { 10 | return pageNum; 11 | } 12 | 13 | public void setPageNum(int pageNum) { 14 | this.pageNum = pageNum; 15 | } 16 | 17 | public int getPageSize() { 18 | return pageSize; 19 | } 20 | 21 | public void setPageSize(int pageSize) { 22 | this.pageSize = pageSize; 23 | } 24 | 25 | public T getParam() { 26 | return param; 27 | } 28 | 29 | public void setParam(T param) { 30 | this.param = param; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/java/com/onlinecode/admin/web/page/PageTable.java: -------------------------------------------------------------------------------- 1 | package com.onlinecode.admin.web.page; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | /** 8 | * 表格分页数据对象 9 | * 10 | * @author ruoyi 11 | */ 12 | public class PageTable implements Serializable { 13 | private static final long serialVersionUID = 1L; 14 | 15 | /** 16 | * 总记录数 17 | */ 18 | private long total; 19 | 20 | /** 21 | * 列表数据 22 | */ 23 | private List rows; 24 | 25 | /** 26 | * 表格数据对象 27 | */ 28 | public PageTable() { 29 | } 30 | 31 | public PageTable total(long total) { 32 | this.total = total; 33 | return this; 34 | } 35 | 36 | public PageTable rows(List rows) { 37 | this.rows = rows; 38 | return this; 39 | } 40 | 41 | public static PageTable empty() { 42 | return new PageTable().total(0).rows(new ArrayList<>()); 43 | } 44 | 45 | public static PageTable page(long total, List rows) { 46 | return new PageTable().total(total).rows(rows); 47 | } 48 | 49 | public long getTotal() { 50 | return total; 51 | } 52 | 53 | public void setTotal(long total) { 54 | this.total = total; 55 | } 56 | 57 | public List getRows() { 58 | return rows; 59 | } 60 | 61 | public void setRows(List rows) { 62 | this.rows = rows; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/resources/application-db.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | # 数据源配置 3 | datasource: 4 | type: com.alibaba.druid.pool.DruidDataSource 5 | driverClassName: com.mysql.cj.jdbc.Driver 6 | url: jdbc:mysql://124.222.119.198:3306/onlinecode?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai 7 | username: root 8 | password: fEJ0CnDop54mQYB! 9 | # 初始连接数 10 | initialSize: 5 11 | # 最小连接池数量 12 | minIdle: 10 13 | # 最大连接池数量 14 | maxActive: 20 15 | # 配置获取连接等待超时的时间 16 | maxWait: 60000 17 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 18 | timeBetweenEvictionRunsMillis: 60000 19 | # 配置一个连接在池中最小生存的时间,单位是毫秒 20 | minEvictableIdleTimeMillis: 300000 21 | # 配置一个连接在池中最大生存的时间,单位是毫秒 22 | maxEvictableIdleTimeMillis: 900000 23 | # 配置检测连接是否有效 24 | validationQuery: SELECT 1 FROM DUAL 25 | testWhileIdle: true 26 | testOnBorrow: false 27 | testOnReturn: false 28 | webStatFilter: 29 | enabled: true 30 | statViewServlet: 31 | enabled: true 32 | # 设置白名单,不填则允许所有访问 33 | allow: 34 | url-pattern: /druid/* 35 | # 控制台管理用户名和密码 36 | login-username: onlinecode 37 | login-password: 123456 38 | filter: 39 | stat: 40 | enabled: true 41 | # 慢SQL记录 42 | log-slow-sql: true 43 | slow-sql-millis: 1000 44 | merge-sql: true 45 | wall: 46 | config: 47 | multi-statement-allow: true 48 | slow-sql-monitor: 49 | slow-millis: 1000 50 | log-slow-sql: false 51 | elasticsearch: 52 | enabled: true 53 | uris: http://127.0.0.1:9200 54 | username: elastic 55 | password: 123456 56 | sendMillis: 0 -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/resources/application-token.yml: -------------------------------------------------------------------------------- 1 | ############## Sa-Token 配置 (文档: https://sa-token.cc) ############## 2 | sa-token: 3 | # token 名称(同时也是 cookie 名称) 4 | token-name: satoken 5 | # token 有效期(单位:秒) 默认30天,-1 代表永久有效 6 | timeout: 2592000 7 | # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 8 | active-timeout: 3600 9 | # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) 10 | is-concurrent: true 11 | # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) 12 | is-share: true 13 | # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) 14 | token-style: uuid 15 | # 是否输出操作日志 16 | is-log: true 17 | # 配置 Sa-Token 单独使用的 Redis 连接 18 | alone-redis: 19 | # 普通集群 20 | pattern: cluster 21 | # 集群只是用db0 22 | database: 0 23 | # Redis服务器连接用户名(默认为空) 24 | username: 25 | # Redis服务器连接密码(默认为空) 26 | password: V6ZuPvR1M2UA 27 | # 连接超时时间(毫秒) 28 | timeout: 3000 29 | cluster: 30 | # Redis集群服务器节点地址 31 | nodes: 124.222.119.198:6379,124.222.119.198:6380,124.222.119.198:6381,124.222.119.198:6382,124.222.119.198:6383,124.222.119.198:6384 32 | # 最大重定向次数 33 | maxRedirects: 5 34 | lettuce: 35 | pool: 36 | # Redis连接池在给定时间可以分配的最大连接数。使用负值无限制 37 | max-active: 2000 38 | # 连接分配在池被耗尽时抛出异常之前应该阻塞的最长时间量(以毫秒为单位)。使用负值可以无限期地阻止 39 | max-wait: 1000 40 | # 连接池中的最大空闲连接 41 | max-idle: 500 42 | # 目标为保持在池中的最小空闲连接数。这个设置只有在设置max-idle的情况下才有效果 43 | min-idle: 5 -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ${log.pattern} 12 | 13 | 14 | 15 | 16 | 17 | ${log.path}/sys-info.log 18 | 19 | 20 | 21 | ${log.path}/sys-info.%d{yyyy-MM-dd}.log 22 | 23 | 60 24 | 25 | 26 | ${log.pattern} 27 | 28 | 29 | 30 | INFO 31 | 32 | ACCEPT 33 | 34 | DENY 35 | 36 | 37 | 38 | 39 | ${log.path}/sys-error.log 40 | 41 | 42 | 43 | ${log.path}/sys-error.%d{yyyy-MM-dd}.log 44 | 45 | 60 46 | 47 | 48 | ${log.pattern} 49 | 50 | 51 | 52 | ERROR 53 | 54 | ACCEPT 55 | 56 | DENY 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/test/resources/application-db.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | # 数据源配置 3 | datasource: 4 | type: com.alibaba.druid.pool.DruidDataSource 5 | driverClassName: com.mysql.cj.jdbc.Driver 6 | url: jdbc:mysql://124.222.119.198:3306/onlinecode?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 7 | username: root 8 | password: fEJ0CnDop54mQYB! 9 | # 初始连接数 10 | initialSize: 5 11 | # 最小连接池数量 12 | minIdle: 10 13 | # 最大连接池数量 14 | maxActive: 20 15 | # 配置获取连接等待超时的时间 16 | maxWait: 60000 17 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 18 | timeBetweenEvictionRunsMillis: 60000 19 | # 配置一个连接在池中最小生存的时间,单位是毫秒 20 | minEvictableIdleTimeMillis: 300000 21 | # 配置一个连接在池中最大生存的时间,单位是毫秒 22 | maxEvictableIdleTimeMillis: 900000 23 | # 配置检测连接是否有效 24 | validationQuery: SELECT 1 FROM DUAL 25 | testWhileIdle: true 26 | testOnBorrow: false 27 | testOnReturn: false 28 | webStatFilter: 29 | enabled: true 30 | statViewServlet: 31 | enabled: true 32 | # 设置白名单,不填则允许所有访问 33 | allow: 34 | url-pattern: /druid/* 35 | # 控制台管理用户名和密码 36 | login-username: onlinecode 37 | login-password: 123456 38 | filter: 39 | stat: 40 | enabled: true 41 | # 慢SQL记录 42 | log-slow-sql: true 43 | slow-sql-millis: 1000 44 | merge-sql: true 45 | wall: 46 | config: 47 | multi-statement-allow: true -------------------------------------------------------------------------------- /online-code-backend/online-code-admin/src/test/resources/application-token.yml: -------------------------------------------------------------------------------- 1 | ############## Sa-Token 配置 (文档: https://sa-token.cc) ############## 2 | sa-token: 3 | # token 名称(同时也是 cookie 名称) 4 | token-name: satoken 5 | # token 有效期(单位:秒) 默认30天,-1 代表永久有效 6 | timeout: 2592000 7 | # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 8 | active-timeout: 3600 9 | # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) 10 | is-concurrent: true 11 | # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) 12 | is-share: true 13 | # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) 14 | token-style: uuid 15 | # 是否输出操作日志 16 | is-log: true 17 | # 配置 Sa-Token 单独使用的 Redis 连接 18 | alone-redis: 19 | # 普通集群 20 | pattern: cluster 21 | # 集群只是用db0 22 | database: 0 23 | # Redis服务器连接用户名(默认为空) 24 | username: 25 | # Redis服务器连接密码(默认为空) 26 | password: V6ZuPvR1M2UA 27 | # 连接超时时间(毫秒) 28 | timeout: 3000 29 | cluster: 30 | # Redis集群服务器节点地址 31 | nodes: 124.222.119.198:6379,124.222.119.198:6380,124.222.119.198:6381,124.222.119.198:6382,124.222.119.198:6383,124.222.119.198:6384 32 | # 最大重定向次数 33 | maxRedirects: 5 34 | lettuce: 35 | pool: 36 | # Redis连接池在给定时间可以分配的最大连接数。使用负值无限制 37 | max-active: 2000 38 | # 连接分配在池被耗尽时抛出异常之前应该阻塞的最长时间量(以毫秒为单位)。使用负值可以无限期地阻止 39 | max-wait: 1000 40 | # 连接池中的最大空闲连接 41 | max-idle: 500 42 | # 目标为保持在池中的最小空闲连接数。这个设置只有在设置max-idle的情况下才有效果 43 | min-idle: 5 -------------------------------------------------------------------------------- /online-code-frontend-init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzusp/online-code/bc6ede23a5c3ac7b07348647bddbe2f987725a3b/online-code-frontend-init.png -------------------------------------------------------------------------------- /online-code-frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 2 9 | indent_style = space 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /online-code-frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | .* 4 | ~* 5 | gulpfile.js 6 | node_modules/ 7 | -------------------------------------------------------------------------------- /online-code-frontend/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/@recore/config/.eslintrc" 3 | } 4 | -------------------------------------------------------------------------------- /online-code-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | es/ 4 | lib/ 5 | .idea/ 6 | .vscode/ 7 | jsconfig.json 8 | typings.json 9 | typings/ 10 | ~* 11 | 12 | # Packages # 13 | ############ 14 | # it's better to unpack these files and commit the raw source 15 | # git has its own built in compression methods 16 | *.7z 17 | *.dmg 18 | *.gz 19 | *.iso 20 | *.jar 21 | *.rar 22 | *.tar 23 | *.zip 24 | 25 | # Logs and databases # 26 | ###################### 27 | *.log 28 | *.sql 29 | *.sqlite 30 | 31 | # OS generated files # 32 | ###################### 33 | .DS_Store 34 | *.swp 35 | .DS_Store? 36 | ._* 37 | .Spotlight-V100 38 | .Trashes 39 | ehthumbs.db 40 | Thumbs.db 41 | .lock 42 | package-lock.json 43 | .vdev 44 | -------------------------------------------------------------------------------- /online-code-frontend/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.iml 3 | .idea/ 4 | .vscode/ 5 | jsconfig.json 6 | typings.json 7 | typings/ 8 | *~ 9 | ~* 10 | *.diff 11 | *.log 12 | *.patch 13 | *.bak 14 | .DS_Store 15 | Thumbs.db 16 | .project 17 | .*proj 18 | .svn/ 19 | *.swp 20 | .lock 21 | package-lock.json 22 | .vdev 23 | # demo 24 | # mock 25 | -------------------------------------------------------------------------------- /online-code-frontend/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /online-code-frontend/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "entry": { 3 | "routes": "./src/components/routes.tsx", 4 | "preview": "./src/preview.tsx", 5 | "index": "./src/index.ts" 6 | }, 7 | "vendor": false, 8 | "devServer": { 9 | "hot": false 10 | }, 11 | "proxy": { 12 | "/onlinecode-api": { 13 | "target": "http://127.0.0.1:7001/", 14 | "changeOrigin": true, 15 | "pathRewrite": { "^/onlinecode-api" : "/" } 16 | } 17 | }, 18 | "publicPath": "/", 19 | "externals": { 20 | "react": "var window.React", 21 | "react-dom": "var window.ReactDOM", 22 | "prop-types": "var window.PropTypes", 23 | "@alifd/next": "var window.Next", 24 | "@alilc/lowcode-engine": "var window.AliLowCodeEngine", 25 | "@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt", 26 | "moment": "var window.moment", 27 | "lodash": "var window._" 28 | }, 29 | "plugins": [ 30 | [ 31 | "build-plugin-react-app" 32 | ], 33 | [ 34 | "build-plugin-moment-locales", 35 | { 36 | "locales": [ 37 | "zh-cn" 38 | ] 39 | } 40 | ], 41 | "./build.plugin.js" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /online-code-frontend/build.plugin.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | const { version } = JSON.parse(fs.readFileSync('./package.json', 'utf8')); 6 | 7 | module.exports = ({ onGetWebpackConfig }) => { 8 | onGetWebpackConfig((config) => { 9 | config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [ 10 | { 11 | configFile: './tsconfig.json', 12 | }, 13 | ]); 14 | 15 | config.merge({ 16 | node: { 17 | fs: 'empty', 18 | }, 19 | }); 20 | 21 | config 22 | .plugin('index') 23 | .use(HtmlWebpackPlugin, [ 24 | { 25 | inject: false, 26 | minify: false, 27 | templateParameters: { 28 | version, 29 | }, 30 | template: require.resolve('./public/index.ejs'), 31 | filename: 'index.html', 32 | }, 33 | ]); 34 | config 35 | .plugin('preview') 36 | .use(HtmlWebpackPlugin, [ 37 | { 38 | inject: false, 39 | templateParameters: { 40 | }, 41 | template: require.resolve('./public/preview.html'), 42 | filename: 'preview.html', 43 | }, 44 | ]); 45 | 46 | config.plugins.delete('hot'); 47 | config.devServer.hot(false); 48 | 49 | config.module // fixes https://github.com/graphql/graphql-js/issues/1272 50 | .rule('mjs$') 51 | .test(/\.mjs$/) 52 | .include 53 | .add(/node_modules/) 54 | .end() 55 | .type('javascript/auto'); 56 | }); 57 | }; 58 | -------------------------------------------------------------------------------- /online-code-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lowcode-editor-online-code-frontend", 3 | "author": "aaron.sun", 4 | "version": "1.0.0", 5 | "description": "online-code-frontend", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "scripts": { 9 | "start": "build-scripts start --disable-reload --port 5556", 10 | "build": "build-scripts build", 11 | "prepublishOnly": "npm run build", 12 | "pub": "node ./scripts/watchdog.js && npm pub" 13 | }, 14 | "files": [ 15 | "build" 16 | ], 17 | "config": {}, 18 | "dependencies": { 19 | "@alilc/lowcode-datasource-fetch-handler": "^1.0.1", 20 | "@alilc/lowcode-plugin-code-editor": "^1.0.3", 21 | "@alilc/lowcode-plugin-code-generator": "^1.0.4", 22 | "@alilc/lowcode-plugin-components-pane": "^2.0.0", 23 | "@alilc/lowcode-plugin-datasource-pane": "^1.0.9", 24 | "@alilc/lowcode-plugin-inject": "^1.2.1", 25 | "@alilc/lowcode-plugin-manual": "^1.0.4", 26 | "@alilc/lowcode-plugin-schema": "^1.0.2", 27 | "@alilc/lowcode-plugin-set-ref-prop": "^1.0.1", 28 | "@alilc/lowcode-plugin-simulator-select": "^1.0.2", 29 | "@alilc/lowcode-plugin-undo-redo": "^1.0.0", 30 | "@alilc/lowcode-plugin-zh-en": "^1.0.0", 31 | "@alilc/lowcode-react-renderer": "^1.1.2", 32 | "@alilc/lowcode-setter-behavior": "^1.0.0", 33 | "@alilc/lowcode-setter-title": "^1.0.2", 34 | "@icedesign/title": "^1.0.5", 35 | "antd": "^4.21.4", 36 | "bcryptjs": "^2.4.3", 37 | "bpmn-js": "^13.2.2", 38 | "bpmn-js-properties-panel": "^3.0.0", 39 | "moment": "^2.29.3", 40 | "react-json-view-lite": "^1.0.0", 41 | "react-router-dom": "^6.14.1", 42 | "uuid": "^8.3.2" 43 | }, 44 | "devDependencies": { 45 | "@alib/build-scripts": "^0.1.18", 46 | "@alilc/lowcode-engine": "^1.1.4", 47 | "@alilc/lowcode-engine-ext": "^1.0.5", 48 | "@alilc/lowcode-types": "^1.1.4", 49 | "@types/events": "^3.0.0", 50 | "@types/react": "^16.8.3", 51 | "@types/react-dom": "^16.8.2", 52 | "@types/streamsaver": "^2.0.0", 53 | "@types/uuid": "^8.3.4", 54 | "build-plugin-fusion": "^0.1.0", 55 | "build-plugin-moment-locales": "^0.1.0", 56 | "build-plugin-react-app": "^1.1.2", 57 | "fs-extra": "^10.0.1", 58 | "tsconfig-paths-webpack-plugin": "^3.2.0" 59 | }, 60 | "resolutions": { 61 | "@babel/core": "7.20.12", 62 | "@alilc/lowcode-plugin-code-editor/@babel/preset-env": "7.22.9", 63 | "@alilc/lowcode-plugin-datasource-pane/@babel/preset-env": "7.22.9" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /online-code-frontend/public/css/onlinecode-editor.css: -------------------------------------------------------------------------------- 1 | .fusion-ui-pro-table-content .next-overlay-wrapper { 2 | position: absolute !important; 3 | z-index: 1000; 4 | right: 0; 5 | } 6 | -------------------------------------------------------------------------------- /online-code-frontend/public/css/onlinecode.css: -------------------------------------------------------------------------------- 1 | #ice-container { 2 | box-sizing: border-box; 3 | padding: 0; 4 | margin: 0; 5 | overflow: hidden; 6 | text-rendering: optimizeLegibility; 7 | -webkit-user-select: auto; 8 | -webkit-user-drag: none; 9 | -webkit-text-size-adjust: none; 10 | -webkit-touch-callout: none; 11 | -webkit-font-smoothing: antialiased; 12 | width: 100%; 13 | height: 100%; 14 | } 15 | 16 | .fd-layout-page { 17 | height: 100%; 18 | min-height: auto !important; 19 | } 20 | 21 | .fusion-ui-pro-table-content .next-overlay-wrapper { 22 | position: absolute !important; 23 | z-index: 1000; 24 | right: 0; 25 | } 26 | 27 | ::-webkit-scrollbar { 28 | width: 5px; 29 | height: 5px; 30 | } 31 | ::-webkit-scrollbar-thumb { 32 | background-color: rgba(0,0,0,.3); 33 | border-radius: 5px; 34 | } 35 | -------------------------------------------------------------------------------- /online-code-frontend/public/editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 阿里低代码引擎 Demo 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 |
46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /online-code-frontend/public/fixtures/basic-fusion-with-single-component/view.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzusp/online-code/bc6ede23a5c3ac7b07348647bddbe2f987725a3b/online-code-frontend/public/fixtures/basic-fusion-with-single-component/view.css -------------------------------------------------------------------------------- /online-code-frontend/public/fixtures/basic-fusion-with-single-component/view.js: -------------------------------------------------------------------------------- 1 | !function e(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.M220318=n():t.M220318=n()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function t(){return e.default}:function t(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=345)}({3:function(e,t){e.exports=window.React},345:function(e,t,n){e.exports=n(429)},346:function(e,t,n){},429:function(e,t,n){"use strict";n.r(t),n.d(t,"default",(function(){return l}));var r={};n.r(r),n.d(r,"default",(function(){return l}));var o=n(3),u=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,r=Object.getOwnPropertySymbols(e);o 2 | 3 | 4 | 5 | 6 | 在线开发平台 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /online-code-frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 勿删,删了有奇妙的 bug😄~ -------------------------------------------------------------------------------- /online-code-frontend/public/lowcode/assets-daily.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "package": "plugin-custom-renderer", 5 | "version": "0.1.0", 6 | "library": "BizComp", 7 | "urls": [ 8 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.js", 9 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.css" 10 | ], 11 | "editUrls": [ 12 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/view.js", 13 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/view.css" 14 | ], 15 | "advancedUrls": { 16 | "default": [ 17 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.js", 18 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.css" 19 | ] 20 | }, 21 | "advancedEditUrls": {} 22 | } 23 | ], 24 | "components": [ 25 | { 26 | "exportName": "PluginCustomRendererMeta", 27 | "npm": { 28 | "package": "plugin-custom-renderer", 29 | "version": "0.1.0" 30 | }, 31 | "url": "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/meta.js", 32 | "urls": { 33 | "default": "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/meta.js" 34 | }, 35 | "advancedUrls": { 36 | "default": [ 37 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/meta.js" 38 | ] 39 | } 40 | } 41 | ], 42 | "sort": { 43 | "groupList": [ 44 | "精选组件", 45 | "原子组件" 46 | ], 47 | "categoryList": [ 48 | "基础元素", 49 | "布局容器类", 50 | "表格类", 51 | "表单详情类", 52 | "帮助类", 53 | "对话框类", 54 | "业务类", 55 | "通用", 56 | "引导", 57 | "信息输入", 58 | "信息展示", 59 | "信息反馈" 60 | ] 61 | }, 62 | "groupList": [ 63 | "精选组件", 64 | "原子组件" 65 | ], 66 | "ignoreComponents": {} 67 | } -------------------------------------------------------------------------------- /online-code-frontend/public/lowcode/assets-dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "package": "plugin-custom-renderer", 5 | "version": "0.1.0", 6 | "library": "BizComp", 7 | "urls": [ 8 | "./render/default/view.js", 9 | "./render/default/view.css" 10 | ], 11 | "editUrls": [ 12 | "./view.js", 13 | "./view.css" 14 | ], 15 | "advancedUrls": { 16 | "default": [ 17 | "./render/default/view.js", 18 | "./render/default/view.css" 19 | ] 20 | }, 21 | "advancedEditUrls": {} 22 | } 23 | ], 24 | "components": [ 25 | { 26 | "exportName": "PluginCustomRendererMeta", 27 | "npm": { 28 | "package": "plugin-custom-renderer", 29 | "version": "0.1.0" 30 | }, 31 | "url": "./meta.js", 32 | "urls": { 33 | "default": "./meta.js" 34 | }, 35 | "advancedUrls": { 36 | "default": [ 37 | "./meta.js" 38 | ] 39 | } 40 | } 41 | ], 42 | "sort": { 43 | "groupList": [ 44 | "精选组件", 45 | "原子组件" 46 | ], 47 | "categoryList": [ 48 | "基础元素", 49 | "布局容器类", 50 | "表格类", 51 | "表单详情类", 52 | "帮助类", 53 | "对话框类", 54 | "业务类", 55 | "通用", 56 | "引导", 57 | "信息输入", 58 | "信息展示", 59 | "信息反馈" 60 | ] 61 | }, 62 | "groupList": [ 63 | "精选组件", 64 | "原子组件" 65 | ], 66 | "ignoreComponents": {} 67 | } -------------------------------------------------------------------------------- /online-code-frontend/public/lowcode/assets-prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "package": "plugin-custom-renderer", 5 | "version": "0.1.0", 6 | "library": "BizComp", 7 | "urls": [ 8 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.js", 9 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.css" 10 | ], 11 | "editUrls": [ 12 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/view.js", 13 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/view.css" 14 | ], 15 | "advancedUrls": { 16 | "default": [ 17 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.js", 18 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/render/default/view.css" 19 | ] 20 | }, 21 | "advancedEditUrls": {} 22 | } 23 | ], 24 | "components": [ 25 | { 26 | "exportName": "PluginCustomRendererMeta", 27 | "npm": { 28 | "package": "plugin-custom-renderer", 29 | "version": "0.1.0" 30 | }, 31 | "url": "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/meta.js", 32 | "urls": { 33 | "default": "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/meta.js" 34 | }, 35 | "advancedUrls": { 36 | "default": [ 37 | "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/meta.js" 38 | ] 39 | } 40 | } 41 | ], 42 | "sort": { 43 | "groupList": [ 44 | "精选组件", 45 | "原子组件" 46 | ], 47 | "categoryList": [ 48 | "基础元素", 49 | "布局容器类", 50 | "表格类", 51 | "表单详情类", 52 | "帮助类", 53 | "对话框类", 54 | "业务类", 55 | "通用", 56 | "引导", 57 | "信息输入", 58 | "信息展示", 59 | "信息反馈" 60 | ] 61 | }, 62 | "groupList": [ 63 | "精选组件", 64 | "原子组件" 65 | ], 66 | "ignoreComponents": {} 67 | } -------------------------------------------------------------------------------- /online-code-frontend/public/lowcode/preview.css: -------------------------------------------------------------------------------- 1 | html.lc-cursor-dragging,html.lc-cursor-dragging *{cursor:move!important}html.lc-cursor-x-resizing,html.lc-cursor-x-resizing *{cursor:col-resize}html.lc-cursor-y-resizing,html.lc-cursor-y-resizing *{cursor:row-resize}html.lc-cursor-copy,html.lc-cursor-copy *{cursor:copy!important}.visual-dom .panel-container{-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #e9e9e9}.visual-dom .panel-container .title{display:block;font-size:12px;color:#333;background-color:#ebecf0;line-height:28px;padding:0 12px;border-bottom:1px solid #e9e9e9}.visual-dom .panel-container .content{min-height:20px;padding:5px} -------------------------------------------------------------------------------- /online-code-frontend/public/lowcode/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | App 渲染器 10 | 11 | 12 | 13 | 14 | 15 |
16 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /online-code-frontend/public/lowcode/render/default/view.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzusp/online-code/bc6ede23a5c3ac7b07348647bddbe2f987725a3b/online-code-frontend/public/lowcode/render/default/view.css -------------------------------------------------------------------------------- /online-code-frontend/public/lowcode/view.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzusp/online-code/bc6ede23a5c3ac7b07348647bddbe2f987725a3b/online-code-frontend/public/lowcode/view.css -------------------------------------------------------------------------------- /online-code-frontend/public/mock-pages.json: -------------------------------------------------------------------------------- 1 | {"success":true,"content":[{"gmtModified":"2021-03-06 00:40:54","formUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentNavUuid":"NAV-SYSTEM-PARENT-UUID","hidden":"n","navUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","navType":"PAGE","isIndex":"n","isNew":"n","gmtCreate":"2021-03-06 00:27:26","title":{"en-US":"页面1","zh-CN":"页面1","type":"i18n"},"relateUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentId":0,"listOrder":0,"id":556103}]} -------------------------------------------------------------------------------- /online-code-frontend/public/mock/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": "Hello AliLowCode!!" 3 | } -------------------------------------------------------------------------------- /online-code-frontend/public/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 阿里低代码引擎 Demo - 预览页 7 | 8 | 9 | 10 | 11 |
12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /online-code-frontend/scripts/watchdog.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'); 3 | const { join } = require('path'); 4 | 5 | const workingDir = process.cwd(); 6 | 7 | const pkg = JSON.parse(fs.readFileSync(join(workingDir, 'package.json'), 'utf-8')); 8 | if (pkg.private) return; 9 | const { files } = pkg; 10 | files.forEach(file => { 11 | const fileDir = join(workingDir, file); 12 | if (!fs.existsSync(fileDir)) { 13 | throw new Error(`${fileDir} does not exist, plz run build`); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /online-code-frontend/src/appHelper.ts: -------------------------------------------------------------------------------- 1 | // import { createFetchHandler } from '@alilc/lowcode-datasource-fetch-handler'; 2 | 3 | import {createFetchHandler} from "./fetchHandler"; 4 | 5 | const appHelper = { 6 | requestHandlersMap: { 7 | fetch: createFetchHandler(), 8 | }, 9 | utils: { 10 | demoUtil: (...params: any[]) => { console.log(`this is a demoUtil with params ${params}`) }, 11 | navigate: (path: string, options?: any) => { console.log(`not set navigate`) }, 12 | getBcrypt: () => { console.log(`not set Bcrypt`) }, 13 | getBase64: () => { console.log(`not set Base64`) }, 14 | getMessage: () => { console.log(`not set Message`) }, 15 | renderer: (page: string, onRender?: Function) => { console.log(`not set renderer`) } 16 | }, 17 | constants: { 18 | ConstantA: 'ConstantA', 19 | ConstantB: 'ConstantB' 20 | } 21 | }; 22 | 23 | 24 | export default appHelper; 25 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/copy-one.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/delete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/exclusive-gateway.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/full-screen-one.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/full-screen-two.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/handle-round.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/http-code.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Http 7 | 8 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/java-code.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Java 7 | 8 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzusp/online-code/bc6ede23a5c3ac7b07348647bddbe2f987725a3b/online-code-frontend/src/assets/logo.png -------------------------------------------------------------------------------- /online-code-frontend/src/assets/new-efferent.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/off-screen-one.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/off-screen-two.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/python-code.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Python 7 | 8 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/round.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /online-code-frontend/src/assets/sql-code.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | SQL 7 | 8 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/bpmn.css: -------------------------------------------------------------------------------- 1 | /* 背景 */ 2 | .djs-container svg { 3 | background-color: #fefefe !important; 4 | background-image: radial-gradient(#ebebeb 15%, transparent 0) !important; 5 | background-size: 15px 15px !important; 6 | } 7 | 8 | .djs-element .djs-outline { 9 | rx: 5; 10 | ry: 5; 11 | stroke-width: 3px !important; 12 | stroke-dasharray: 5,5 !important; 13 | } 14 | 15 | .djs-drag-group rect { 16 | stroke: #ddd !important; 17 | stroke-width: 3px !important; 18 | stroke-dasharray: 5,5 !important; 19 | } 20 | 21 | /* 隐藏powered-by */ 22 | .containers .bjs-powered-by { 23 | display: none; 24 | } 25 | 26 | .djs-direct-editing-parent { 27 | border-radius: 5px; 28 | height: 28px !important; 29 | border: 3px dashed #FF8888 !important; 30 | } 31 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/bpmn/custom/CustomPalette.js: -------------------------------------------------------------------------------- 1 | import { assign } from 'min-dash'; 2 | import { customConfig } from "../utils/bpmn-util"; 3 | import { getDi } from "bpmn-js/lib/util/ModelUtil.js"; 4 | 5 | /** 6 | * A palette that allows you to create BPMN _and_ custom elements. 7 | */ 8 | export default function PaletteProvider(palette, elementFactory, globalConnect, modeling, create) { 9 | this.elementFactory = elementFactory 10 | this.globalConnect = globalConnect 11 | this.modeling = modeling 12 | this.create = create 13 | 14 | palette.registerProvider(this) 15 | } 16 | 17 | PaletteProvider.$inject = [ 18 | 'palette', 19 | 'elementFactory', 20 | 'globalConnect', 21 | 'modeling', 22 | 'create' 23 | ] 24 | 25 | PaletteProvider.prototype.getPaletteEntries = function (element) { 26 | const { 27 | modeling, 28 | create, 29 | elementFactory 30 | } = this; 31 | 32 | function createAction(dataAction, type, group, className, title, options) { 33 | 34 | function createListener(event) { 35 | const shape = elementFactory.createShape(assign({type: type}, options)); 36 | if (options) { 37 | getDi(shape).isExpanded = options.isExpanded; 38 | } 39 | shape.businessObject.name = title; 40 | const {attr} = customConfig[dataAction] 41 | shape.width = attr.width; 42 | shape.height = attr.height; 43 | modeling.updateProperties(shape, { dataAction: dataAction }); 44 | create.start(event, shape); 45 | } 46 | 47 | const shortType = type.replace(/^bpmn:/, ''); 48 | return { 49 | group: group, 50 | className: className, 51 | title: title || 'Create ' + shortType, 52 | action: { 53 | dragstart: createListener, 54 | click: createListener 55 | } 56 | }; 57 | } 58 | 59 | const actions = {}; 60 | for (const key in customConfig) { 61 | actions[key] = createAction(key, customConfig[key]['type'], customConfig[key]['group'], 62 | customConfig[key]['className'], customConfig[key]['title'], {}); 63 | } 64 | return actions; 65 | } 66 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/bpmn/custom/index.js: -------------------------------------------------------------------------------- 1 | import CustomPalette from './CustomPalette' 2 | import CustomRenderer from './CustomRenderer' 3 | import CustomContextPadProvider from './CustomContextPadProvider' 4 | 5 | export default { 6 | __init__: ['paletteProvider', 'customRenderer', 'contextPadProvider'], 7 | paletteProvider: ['type', CustomPalette], 8 | customRenderer: ['type', CustomRenderer], 9 | // contextPadProvider完全自定义 10 | contextPadProvider: ['type', CustomContextPadProvider] 11 | } 12 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/bpmn/index.js: -------------------------------------------------------------------------------- 1 | import Modeler from 'bpmn-js/lib/Modeler' 2 | 3 | import inherits from 'inherits' 4 | 5 | import CustomModule from './custom' 6 | 7 | export default function CustomModeler(options) { 8 | Modeler.call(this, options); 9 | } 10 | 11 | inherits(CustomModeler, Modeler); 12 | 13 | CustomModeler.prototype._modules = [].concat( 14 | CustomModeler.prototype._modules, [ 15 | CustomModule 16 | ] 17 | ); 18 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/bpmn/utils/bpmn-util.js: -------------------------------------------------------------------------------- 1 | // 自定义元素的配置 2 | const customConfig = { 3 | 'create.start-event': { 4 | 'type': 'bpmn:StartEvent', 5 | 'group': 'base', 6 | 'className': 'icon-custom icon-custom-start', 7 | 'title': '开始', 8 | 'url': require('../../../../../assets/round.svg'), 9 | 'attr': {x: 0, y: 0, width: 32, height: 32} 10 | }, 11 | 'create.exclusive-gateway': { 12 | 'type': 'bpmn:ExclusiveGateway', 13 | 'group': 'base', 14 | 'className': 'icon-custom exclusive-gateway', 15 | 'title': '分支', 16 | 'url': require('../../../../../assets/exclusive-gateway.svg'), 17 | 'attr': {x: 0, y: 0, width: 32, height: 32} 18 | }, 19 | 'create.end-event': { 20 | 'type': 'bpmn:EndEvent', 21 | 'group': 'base', 22 | 'className': 'icon-custom icon-custom-end', 23 | 'title': '结束', 24 | 'url': require('../../../../../assets/handle-round.svg'), 25 | 'attr': {x: 0, y: 0, width: 32, height: 32} 26 | }, 27 | 'create.java-task': { 28 | 'type': 'bpmn:Task', 29 | 'group': 'code', 30 | 'className': 'icon-custom java-task', 31 | 'title': 'Java', 32 | 'url': require('../../../../../assets/java-code.svg'), 33 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 34 | }, 35 | 'create.sql-task': { 36 | 'type': 'bpmn:Task', 37 | 'group': 'code', 38 | 'className': 'icon-custom sql-task', 39 | 'title': 'SQL', 40 | 'url': require('../../../../../assets/sql-code.svg'), 41 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 42 | }, 43 | 'create.http-task': { 44 | 'type': 'bpmn:Task', 45 | 'group': 'code', 46 | 'className': 'icon-custom http-task', 47 | 'title': 'Http', 48 | 'url': require('../../../../../assets/http-code.svg'), 49 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 50 | }, 51 | 'create.python-task': { 52 | 'type': 'bpmn:Task', 53 | 'group': 'code', 54 | 'className': 'icon-custom python-task', 55 | 'title': 'Python', 56 | 'url': require('../../../../../assets/python-code.svg'), 57 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 58 | }, 59 | 'create.email-task': { 60 | 'type': 'bpmn:Task', 61 | 'group': 'message', 62 | 'className': 'icon-custom python-task', 63 | 'title': '邮件', 64 | 'url': require('../../../../../assets/python-code.svg'), 65 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 66 | }, 67 | 'create.official-task': { 68 | 'type': 'bpmn:Task', 69 | 'group': 'message', 70 | 'className': 'icon-custom python-task', 71 | 'title': '公众号', 72 | 'url': require('../../../../../assets/python-code.svg'), 73 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 74 | }, 75 | 'create.wecom-task': { 76 | 'type': 'bpmn:Task', 77 | 'group': 'message', 78 | 'className': 'icon-custom python-task', 79 | 'title': '企业微信', 80 | 'url': require('../../../../../assets/python-code.svg'), 81 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 82 | }, 83 | 'create.ding-task': { 84 | 'type': 'bpmn:Task', 85 | 'group': 'message', 86 | 'className': 'icon-custom python-task', 87 | 'title': '钉钉', 88 | 'url': require('../../../../../assets/python-code.svg'), 89 | 'attr': {x: 0, y: 0, width: 32, height: 32, padding: '4px'} 90 | } 91 | } 92 | 93 | export { customConfig } 94 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/bpmn/utils/event-bus.js: -------------------------------------------------------------------------------- 1 | function EventBus() { 2 | 3 | const subscriptions = {}; 4 | 5 | this.subscribe = (eventType, callback) => { 6 | const id = Symbol('id'); 7 | 8 | if (!subscriptions[eventType]) subscriptions[eventType] = {}; 9 | 10 | subscriptions[eventType][id] = callback; 11 | return { 12 | unsubscribe: function unsubscribe() { 13 | delete subscriptions[eventType][id]; 14 | if (Object.getOwnPropertySymbols(subscriptions[eventType]).length === 0) { 15 | delete subscriptions[eventType]; 16 | } 17 | } 18 | } 19 | } 20 | 21 | this.publish = (eventType, args) => { 22 | if (!subscriptions[eventType]) return; 23 | Object.getOwnPropertySymbols(subscriptions[eventType]).forEach(key => subscriptions[eventType][key](args)); 24 | } 25 | 26 | } 27 | 28 | export default new EventBus; 29 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/bpmn/utils/processStr.js: -------------------------------------------------------------------------------- 1 | export var bpmnStr = "\n" + 2 | "\n" + 3 | " \n" + 4 | " \n" + 5 | " \n" + 6 | " \n" + 7 | "\n" 8 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/connection.css: -------------------------------------------------------------------------------- 1 | /* 自定义 连线 的样式 */ 2 | 3 | .djs-connection .djs-visual path { 4 | stroke: #dddddd !important; 5 | stroke-width: 3px !important; 6 | marker-start: none !important; 7 | marker-end: url(#sequenceflow-arrow-normal) !important; 8 | } 9 | 10 | .djs-connection-preview path { 11 | stroke: #dddddd !important; 12 | stroke-width: 3px !important; 13 | stroke-dasharray: 8 !important; 14 | marker-end: url(#sequenceflow-arrow-activities) !important; 15 | } 16 | 17 | .djs-connection-preview polyline { 18 | stroke: #dddddd !important; 19 | stroke-width: 3px !important; 20 | stroke-dasharray: 8 !important; 21 | marker-end: url(#sequenceflow-arrow-activities) !important; 22 | } 23 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/editor/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | 3 | import SingleMonacoEditorComponent from '@alilc/lowcode-plugin-base-monaco-editor'; 4 | 5 | class CodeEditor extends React.Component { 6 | 7 | render() { 8 | return ( 9 | 18 | ); 19 | } 20 | } 21 | 22 | export default CodeEditor; 23 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/index.scss: -------------------------------------------------------------------------------- 1 | .canvas { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | .panel { 7 | position: absolute; 8 | right: 0; 9 | top: 0; 10 | width: 300px; 11 | } 12 | 13 | .buttons { 14 | position: absolute; 15 | left: 20px; 16 | bottom: 20px; 17 | } 18 | 19 | .buttons li { 20 | display: inline-block; 21 | margin: 5px; 22 | } 23 | 24 | .buttons li a { 25 | color: #999; 26 | background: #eee; 27 | cursor: not-allowed; 28 | padding: 8px; 29 | border: 1px solid #ccc; 30 | text-decoration: none; 31 | } 32 | 33 | .buttons li a.active { 34 | color: #333; 35 | background: #fff; 36 | cursor: pointer; 37 | } 38 | 39 | .modal { 40 | background-color: rgba(0, 0, 0, 0.6); 41 | width: 100vw; 42 | height: 100vh; 43 | position: fixed; 44 | top: 0; 45 | left: 0; 46 | } 47 | 48 | .modal-content { 49 | width: 100%; 50 | height: 100%; 51 | position: relative; 52 | } 53 | 54 | .modal-ctx { 55 | position: absolute; 56 | width: 300px; 57 | height: 250px; 58 | background-color: #fff; 59 | top: 50%; 60 | left: 50%; 61 | transform: translate(-50%, -50%); 62 | box-shadow: 0 0 5px 2px rgba(225, 225, 225, 0.8); 63 | } 64 | 65 | .modal-item { 66 | padding: 10px; 67 | width: 100%; 68 | } 69 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/label.css: -------------------------------------------------------------------------------- 1 | .djs-label { 2 | font-size: 12px !important; 3 | } 4 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/palette.css: -------------------------------------------------------------------------------- 1 | .djs-palette { 2 | width: 138px !important; 3 | max-height: 80%; 4 | overflow-x: hidden; 5 | overflow-y: scroll; 6 | } 7 | 8 | .djs-palette .entry:hover { 9 | } 10 | 11 | .djs-palette .djs-palette-entries { 12 | display: flex; 13 | flex-flow: wrap; 14 | width: 138px; 15 | padding-bottom: 10px; 16 | } 17 | 18 | .djs-palette .djs-palette-entries .group { 19 | display: flex; 20 | flex-flow: wrap; 21 | width: 138px; 22 | } 23 | 24 | .djs-palette .djs-palette-entries .group .entry { 25 | flex-grow: 0; 26 | margin: 0 0 24px 14px; 27 | border: solid 1px #ddd; 28 | position: relative; 29 | } 30 | 31 | .djs-palette .djs-palette-entries .group .title { 32 | flex-grow: 0; 33 | width: 138px; 34 | font-size: 14px; 35 | text-align: center; 36 | font-weight: bold; 37 | padding: 4px 0 14px 0; 38 | } 39 | 40 | .djs-palette .djs-palette-entries .group .entry .label { 41 | width: 48px; 42 | font-size: 8px; 43 | position: absolute; 44 | bottom: -34px; 45 | left: 0; 46 | } 47 | 48 | .djs-popup, .djs-palette { 49 | background-color: #fff; 50 | border-radius: 5px; 51 | border: solid 1px #fff; 52 | box-shadow: 0 10px 16px 0 #ddd, 0 6px 20px 0 #ddd; 53 | } 54 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/property-panel.css: -------------------------------------------------------------------------------- 1 | .property-panel { 2 | position: absolute; 3 | top: 40px; 4 | right: 20px; 5 | background-color: #fff; 6 | border-radius: 5px; 7 | box-shadow: 0 10px 16px 0 #ddd, 0 6px 20px 0 #ddd; 8 | transition: all 0.2s; 9 | overflow: hidden; 10 | } 11 | 12 | .property-panel.expand { 13 | width: 600px; 14 | height: 90%; 15 | z-index: 101; 16 | overflow-y: scroll; 17 | } 18 | 19 | .property-panel.collapse { 20 | width: 40px; 21 | height: 40px; 22 | } 23 | 24 | .property-panel.code-mode { 25 | z-index: 101; 26 | width: 100%; 27 | height: calc(100vh - 90px); 28 | top: unset !important; 29 | right: unset !important; 30 | transition: unset !important; 31 | } 32 | 33 | .panel-top-toolbar { 34 | position: absolute; 35 | top: 10px; 36 | right: 10px; 37 | } 38 | 39 | .off-screen { 40 | float: right; 41 | width: 20px; 42 | height: 20px; 43 | background-image: url('../../../assets/off-screen-one.svg'); 44 | background-size: cover; 45 | } 46 | 47 | .off-screen-two { 48 | z-index: 999; 49 | position: absolute; 50 | top: 4px; 51 | right: 4px; 52 | width: 20px; 53 | height: 20px; 54 | background-image: url('../../../assets/off-screen-two.svg'); 55 | background-size: cover; 56 | } 57 | 58 | .off-screen-code { 59 | height: 260px; 60 | } 61 | 62 | .full-screen { 63 | float: right; 64 | width: 20px; 65 | height: 20px; 66 | background-image: url('../../../assets/full-screen-one.svg'); 67 | background-size: cover; 68 | } 69 | 70 | .full-screen-two { 71 | z-index: 999; 72 | position: absolute; 73 | top: 4px; 74 | right: 4px; 75 | width: 20px; 76 | height: 20px; 77 | background-image: url('../../../assets/full-screen-two.svg'); 78 | background-size: cover; 79 | } 80 | 81 | .full-screen-code { 82 | z-index: 997; 83 | position: fixed; 84 | top: 0; 85 | right: 0; 86 | width: 100%; 87 | height: 100%; 88 | background-color: #ffffff; 89 | } 90 | 91 | .screen-code { 92 | z-index: 998; 93 | position: absolute; 94 | top: 1px; 95 | right: 1px; 96 | width: 28px; 97 | height: 28px; 98 | background-color: #ffffff; 99 | } 100 | 101 | .task-code-editor-pane { 102 | border-radius: 5px; 103 | border: 1px solid #DCDFE6; 104 | line-height: 17px !important; 105 | height: 100% !important; 106 | } 107 | 108 | .react-monaco-editor-container { 109 | height: 100% !important; 110 | } 111 | 112 | .base-monaco-full-screen-icon { 113 | background-image: url('../../../assets/full-screen-two.svg') !important; 114 | /*top: 0 !important;*/ 115 | /*right: -30px !important;*/ 116 | } 117 | 118 | .base-monaco-full-screen-icon-cancel { 119 | background-image: url('../../../assets/off-screen-two.svg') !important; 120 | } 121 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/canvas/run-code/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | 3 | import {Form, Input, Nav, Shell, Box, Button, ResponsiveGrid, Radio, Card} from '@alifd/next'; 4 | import IceTitle from '@icedesign/title'; 5 | import { JsonView, allExpanded, darkStyles, defaultStyles } from 'react-json-view-lite'; 6 | import 'react-json-view-lite/dist/index.css'; 7 | import {createFetch} from "../../../../fetchHandler"; 8 | 9 | class RunCode extends React.Component { 10 | 11 | state = { 12 | inputVal: '{}', 13 | outputVal: '' 14 | } 15 | 16 | async runCmd() { 17 | console.log(this.props?.code); 18 | const param = { 19 | cmd: this.props?.code, 20 | vars: JSON.parse(this.state.inputVal) 21 | } 22 | await createFetch({url: '/onlinecode-api/process/runCmd', method: 'POST', data: param}) 23 | .then((res: any) => { 24 | console.log(res); 25 | if (res.status === 200 && res.data) { 26 | this.setState({outputVal: res.data}); 27 | } else { 28 | this.setState({outputVal: res}); 29 | } 30 | }) 31 | .catch((err: any) => {}); 32 | } 33 | 34 | render() { 35 | return ( 36 |
37 | 38 |
39 | 40 |
41 |
42 | 43 | 44 | {this.setState({inputVal: value})}} 53 | /> 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
64 |
65 | ); 66 | } 67 | } 68 | 69 | export default RunCode; 70 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/ProcessDesign/index.scss: -------------------------------------------------------------------------------- 1 | .next-shell-content-inner { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | .next-tabs-tabpane.active { 7 | width: 100%; 8 | height: 100%; 9 | } 10 | 11 | .next-tabs-tab.active .next-tabs-tab-close { 12 | color: #fff; 13 | } 14 | 15 | .next-tabs-capsule>.next-tabs-bar .next-tabs-tab { 16 | border-radius: unset !important; 17 | } 18 | 19 | .containers { 20 | background-color: #ffffff; 21 | width: 100%; 22 | display: flex; 23 | height: 100%; 24 | } 25 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/pages/Notice/index.module.css: -------------------------------------------------------------------------------- 1 | .noticeIcon { 2 | width: 40px; 3 | line-height: 50px; 4 | text-align: center; 5 | cursor: pointer; 6 | } 7 | 8 | .close { 9 | display: none; 10 | cursor: pointer; 11 | } 12 | 13 | .noticeContainer { 14 | width: 270px; 15 | background: var(--color-white, #fff); 16 | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12); 17 | } 18 | 19 | .noticeContainer :global .next-list-header { 20 | margin: 0 12px; 21 | } 22 | .noticeContainer :global .next-list-footer { 23 | border: 0; 24 | } 25 | 26 | .noticeContainer :global .next-list-item-title, 27 | .noticeContainer :global .next-list-item { 28 | font-weight: normal; 29 | } 30 | 31 | .noticeContainer :global .next-list-item { 32 | padding: 8px 12px; 33 | font-size: var(--font-size-caption, 12px); 34 | } 35 | 36 | .noticeItem:hover { 37 | background: var(--color-fill1-2, #f2f3f7); 38 | } 39 | 40 | .noticeItem:hover :global .close { 41 | display: block; 42 | } 43 | 44 | .title, 45 | .footer { 46 | height: 16px; 47 | font-weight: normal; 48 | line-height: 16px; 49 | } 50 | 51 | .title h4 { 52 | display: inline-block; 53 | margin: 0; 54 | color: var(--color-text1-4, #333); 55 | font-size: var(--font-size-body-1, 12px); 56 | line-height: 16px; 57 | } 58 | 59 | .footer { 60 | text-align: center; 61 | } 62 | 63 | .footer a { 64 | color: var(--color-text1-3, #666); 65 | font-size: var(--font-size-caption, 12px); 66 | cursor: pointer; 67 | } 68 | 69 | .empty :global .next-list-item-content { 70 | align-items: center; 71 | height: 40px; 72 | } 73 | 74 | .clear { 75 | float: right; 76 | color: var(--color-text1-3, #666); 77 | font-size: var(--font-size-caption, 12px); 78 | cursor: pointer; 79 | } 80 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/pages/Notice/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Icon, Badge, Overlay, Avatar, Message, List } from '@alifd/next'; 3 | import styles from './index.module.css'; 4 | 5 | export interface INotcieItem { 6 | id: number; 7 | name: string; 8 | message: string; 9 | avatar: string; 10 | } 11 | 12 | const { Popup } = Overlay; 13 | const defaultNoticeList: INotcieItem[] = [ 14 | { 15 | id: 1, 16 | name: 'Aric', 17 | avatar: 'https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png', 18 | message: '新标识怎么去掉?', 19 | }, 20 | { 21 | id: 2, 22 | name: 'Mark', 23 | avatar: 'https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png', 24 | message: '如何查看新增页面?', 25 | }, 26 | ]; 27 | export interface NoticeProps { 28 | noticeList?: INotcieItem[]; 29 | } 30 | 31 | const Notice: React.FC = ({ noticeList }) => { 32 | const [badgeCount, setBageCount] = useState(2); 33 | const [readList, setReadList] = useState([]); 34 | 35 | function markAsRead(id: number) { 36 | setReadList([...readList, id]); 37 | setBageCount(badgeCount - 1); 38 | } 39 | 40 | function clearNotice() { 41 | const noticeIds = (noticeList as INotcieItem[]).map((item) => item.id); 42 | setBageCount(0); 43 | setReadList(noticeIds); 44 | } 45 | 46 | function viewMore() { 47 | Message.success('点击了查看更多操作'); 48 | } 49 | 50 | const renderList = (noticeList as INotcieItem[]).filter((item) => readList.indexOf(item.id) === -1); 51 | return ( 52 | 55 | 56 | 57 | 58 | 59 | )} 60 | triggerType="click" 61 | > 62 | 68 |

通知

69 | 清空通知 70 | 71 | )} 72 | footer={( 73 |
74 | 查看更多 75 |
76 | )} 77 | > 78 | {renderList.map((noticeItem: INotcieItem) => { 79 | const { id, name, avatar, message } = noticeItem; 80 | return ( 81 | } 86 | extra={ markAsRead(id)}>} 87 | > 88 | {message} 89 | 90 | ); 91 | })} 92 | {renderList.length === 0 && ( 93 | 94 | 你已查看所有通知 95 | 96 | )} 97 |
98 |
99 | ); 100 | }; 101 | 102 | Notice.defaultProps = { 103 | noticeList: defaultNoticeList, 104 | }; 105 | export default Notice; 106 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/pages/index.module.css: -------------------------------------------------------------------------------- 1 | .headerAvatar { 2 | height: 100%; 3 | padding: 10px; 4 | cursor: pointer; 5 | } 6 | 7 | .avatarPopup { 8 | min-width: 210px; 9 | padding: 4px 0; 10 | background-color: #fff; 11 | border-radius: 2px; 12 | box-shadow: 0 2px 4px rgba(0, 0, 0, .5); 13 | } 14 | 15 | .next-shell-action .next-avatar-small { 16 | border: 1px solid #ddd !important; 17 | } 18 | 19 | .menu { 20 | line-height: 40px; 21 | border: 0 !important; 22 | border-radius: unset !important; 23 | border-top: 1px solid #dcdee3 !important; 24 | } 25 | 26 | .menu :global .next-menu-item { 27 | color: var(--color-text1-3, #666); 28 | } 29 | 30 | .menu :global .next-menu-item-inner { 31 | height: 36px; 32 | } 33 | 34 | .menu :global .next-icon { 35 | margin-right: 8px; 36 | } 37 | 38 | .profile { 39 | display: flex; 40 | flex: 1 1 auto; 41 | align-items: flex-start; 42 | min-width: 200px; 43 | padding: 8px 16px 4px 16px; 44 | font-size: 0; 45 | } 46 | 47 | .avatar { 48 | margin-right: 12px; 49 | } 50 | 51 | .content { 52 | flex: 1 0 auto; 53 | } 54 | 55 | .content h4 { 56 | margin: 0; 57 | font-weight: bold; 58 | font-size: 14px; 59 | line-height: 22px; 60 | } 61 | 62 | .content span { 63 | color: var(--color-text1-3, #666); 64 | font-size: 12px; 65 | } 66 | -------------------------------------------------------------------------------- /online-code-frontend/src/components/routes.tsx: -------------------------------------------------------------------------------- 1 | import { createHashRouter, Navigate, RouterProvider, useParams } from "react-router-dom"; 2 | import ReactDOM from "react-dom"; 3 | import React from "react"; 4 | 5 | import Pages from "./pages"; 6 | import ProcessDesign from "./ProcessDesign"; 7 | 8 | const router = createHashRouter([ 9 | { 10 | path: '/pages/:page', 11 | element: 12 | }, 13 | { 14 | path: '/process/design/:id', 15 | element: 16 | }, 17 | { 18 | path: '/', 19 | element: 20 | } 21 | ]); 22 | 23 | ReactDOM.render(, document.getElementById('ice-container')); 24 | -------------------------------------------------------------------------------- /online-code-frontend/src/fetchHandler.ts: -------------------------------------------------------------------------------- 1 | import { RuntimeOptionsConfig } from '@alilc/lowcode-datasource-types'; 2 | 3 | import request from 'universal-request'; 4 | import { RequestOptions, AsObject } from 'universal-request/lib/types'; 5 | import {Message, Dialog} from "@alifd/next"; 6 | 7 | // config 留着扩展 8 | export function createFetchHandler(config?: Record) { 9 | // eslint-disable-next-line space-before-function-paren 10 | return async function(options: RuntimeOptionsConfig) { 11 | const requestConfig: RequestOptions = { 12 | ...options, 13 | url: options.uri, 14 | method: options.method as RequestOptions['method'], 15 | data: options.params as AsObject, 16 | headers: options.headers as AsObject, 17 | ...config, 18 | }; 19 | return await createFetch(requestConfig); 20 | }; 21 | } 22 | 23 | // config 留着扩展 24 | export async function createFetch(options: RequestOptions) { 25 | return new Promise(((resolve, reject) => { 26 | request(options).then((res: any) => { 27 | if (res.status === 200) { 28 | if (res.data.code === 200) { 29 | return resolve(res); 30 | } else if (res.data.code === 401) { 31 | Dialog.confirm({ 32 | title: '系统提示', 33 | content: '登录状态已过期,您可以继续留在该页面,或者重新登录', 34 | okProps: { children: '重新登录' }, 35 | cancelProps: { children: '取消' }, 36 | onOk: () => { location.href = '/#/pages/login' }, 37 | onCancel: () => {}, 38 | messageProps: { 39 | v2: true, 40 | type: 'warning' 41 | } 42 | }); 43 | } else if (res.data.code === 403 || res.data.code === 500) { 44 | Message.error(res.data.message); 45 | return resolve(res); 46 | } 47 | } else { 48 | console.log('res error', res) 49 | Message.error('后端接口连接异常'); 50 | } 51 | }).catch((res: any) => { 52 | console.log('error', res) 53 | let { message } = res; 54 | if (message == "Network Error" || message == "{\"status\":500}") { 55 | message = "后端接口连接异常"; 56 | } 57 | else if (message.includes("timeout")) { 58 | message = "系统接口请求超时"; 59 | } 60 | else if (message.includes("Request failed with status code")) { 61 | message = "系统接口" + message.substr(message.length - 3) + "异常"; 62 | } 63 | Message.error(message); 64 | }) 65 | })); 66 | } 67 | -------------------------------------------------------------------------------- /online-code-frontend/src/global.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma, Arial, PingFang SC-Light, Microsoft YaHei; 3 | font-size: 12px; 4 | * { 5 | box-sizing: border-box; 6 | } 7 | } 8 | 9 | body, #lce-container { 10 | position: fixed; 11 | left: 0; 12 | right: 0; 13 | bottom: 0; 14 | top: 0; 15 | box-sizing: border-box; 16 | padding: 0; 17 | margin: 0; 18 | overflow: hidden; 19 | text-rendering: optimizeLegibility; 20 | -webkit-user-select: none; 21 | -webkit-user-drag: none; 22 | -webkit-text-size-adjust: none; 23 | -webkit-touch-callout: none; 24 | -webkit-font-smoothing: antialiased; 25 | #engine { 26 | width: 100%; 27 | height: 100%; 28 | } 29 | } 30 | 31 | html { 32 | min-width: 1024px; 33 | } 34 | 35 | .save-sample { 36 | width: 80px; 37 | height: 30px; 38 | background-color: #5584FF; 39 | border: none; 40 | outline: none; 41 | border-radius: 4px; 42 | color: white; 43 | cursor: pointer; 44 | } 45 | 46 | .load-assets { 47 | width: 100px; 48 | height: 30px; 49 | background-color: #5584FF; 50 | border: none; 51 | outline: none; 52 | border-radius: 4px; 53 | color: white; 54 | cursor: pointer; 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-component-panel/index.tsx: -------------------------------------------------------------------------------- 1 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 2 | import ComponentsPane from '@alilc/lowcode-plugin-components-pane'; 3 | const ComponentPanelPlugin = (ctx: IPublicModelPluginContext) => { 4 | return { 5 | async init() { 6 | const { skeleton, project } = ctx; 7 | // 注册组件面板 8 | const componentsPane = skeleton.add({ 9 | area: 'leftArea', 10 | type: 'PanelDock', 11 | name: 'componentsPane', 12 | content: ComponentsPane, 13 | contentProps: {}, 14 | props: { 15 | align: 'top', 16 | icon: 'zujianku', 17 | description: '组件库', 18 | }, 19 | }); 20 | componentsPane?.disable?.(); 21 | project.onSimulatorRendererReady(() => { 22 | componentsPane?.enable?.(); 23 | }) 24 | }, 25 | }; 26 | } 27 | ComponentPanelPlugin.pluginName = 'ComponentPanelPlugin'; 28 | export default ComponentPanelPlugin; -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-custom-setter-sample/index.tsx: -------------------------------------------------------------------------------- 1 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 2 | import TitleSetter from '@alilc/lowcode-setter-title'; 3 | import BehaviorSetter from './setters/behavior-setter'; 4 | import CustomSetter from './setters/custom-setter'; 5 | 6 | // 保存功能示例 7 | const CustomSetterSamplePlugin = (ctx: IPublicModelPluginContext) => { 8 | return { 9 | async init() { 10 | const { setters } = ctx; 11 | 12 | setters.registerSetter('TitleSetter', TitleSetter); 13 | setters.registerSetter('BehaviorSetter', BehaviorSetter); 14 | setters.registerSetter('CustomSetter', CustomSetter); 15 | }, 16 | }; 17 | } 18 | CustomSetterSamplePlugin.pluginName = 'CustomSetterSamplePlugin'; 19 | export default CustomSetterSamplePlugin; -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-custom-setter-sample/setters/behavior-setter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import BehaviorSetter from '@alilc/lowcode-setter-behavior'; 3 | 4 | 5 | const defaultExtraBehaviorActions: any[] = []; 6 | class LocalBehaviorSetter extends React.Component { 7 | render() { 8 | // ignore url && responseFormatter props, use default ones 9 | const { url: propsUrl, responseFormatter: propsFormatter, extraBehaviorActions: propsExtraBehaviorActions = [], ...otherProps } = this.props; 10 | const url = 'https://hn.algolia.com/api/v1/search?query'; 11 | const responseFormatter = (response) => response.hits.map((item) => ({ 12 | label: item.title, 13 | value: item.author 14 | })); 15 | const extraBehaviorActions = propsExtraBehaviorActions.concat(defaultExtraBehaviorActions); 16 | return ( 17 | 23 | ); 24 | } 25 | } 26 | 27 | export default LocalBehaviorSetter; -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-custom-setter-sample/setters/custom-setter.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | // import classNames from 'classnames'; 3 | 4 | class CustomSetter extends Component { 5 | render() { 6 | const { defaultValue, value, onChange } = this.props; 7 | const { editor } = this.props.field; 8 | 9 | return
hello world
; 10 | } 11 | } 12 | 13 | export default CustomSetter; 14 | -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-default-setters-registry/index.tsx: -------------------------------------------------------------------------------- 1 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 2 | import AliLowCodeEngineExt from '@alilc/lowcode-engine-ext'; 3 | 4 | // 设置内置 setter 和事件绑定、插件绑定面板 5 | const DefaultSettersRegistryPlugin = (ctx: IPublicModelPluginContext) => { 6 | return { 7 | async init() { 8 | const { setterMap, pluginMap } = AliLowCodeEngineExt; 9 | const { setters, skeleton } = ctx; 10 | // 注册 setterMap 11 | setters.registerSetter(setterMap); 12 | // 注册插件 13 | // 注册事件绑定面板 14 | skeleton.add({ 15 | area: 'centerArea', 16 | type: 'Widget', 17 | content: pluginMap.EventBindDialog, 18 | name: 'eventBindDialog', 19 | props: {}, 20 | }); 21 | 22 | // 注册变量绑定面板 23 | skeleton.add({ 24 | area: 'centerArea', 25 | type: 'Widget', 26 | content: pluginMap.VariableBindDialog, 27 | name: 'variableBindDialog', 28 | props: {}, 29 | }); 30 | }, 31 | }; 32 | } 33 | DefaultSettersRegistryPlugin.pluginName = 'DefaultSettersRegistryPlugin'; 34 | export default DefaultSettersRegistryPlugin; -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-editor-init/index.tsx: -------------------------------------------------------------------------------- 1 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 2 | import { injectAssets } from '@alilc/lowcode-plugin-inject'; 3 | import assets from '../../services/assets.json'; 4 | import { getProjectSchema } from '../../services/schemaService'; 5 | import appHelper from "../../appHelper"; 6 | import ReactDOM from "react-dom"; 7 | import { renderToString } from 'react-dom/server' 8 | import React from "react"; 9 | import Renderer from "../../components/pages/renderer"; 10 | const EditorInitPlugin = (ctx: IPublicModelPluginContext, options: any) => { 11 | return { 12 | async init() { 13 | const { material, project, config } = ctx; 14 | const scenarioName = config.get('scenarioName') || options['scenarioName']; 15 | const scenarioDisplayName = options['displayName'] || scenarioName; 16 | const scenarioInfo = options['info'] || {}; 17 | // 保存在 config 中用于引擎范围其他插件使用 18 | config.set('scenarioName', scenarioName); 19 | config.set('scenarioDisplayName', scenarioDisplayName); 20 | config.set('scenarioInfo', scenarioInfo); 21 | // 设置物料描述 22 | 23 | await material.setAssets(await injectAssets(assets)); 24 | 25 | const schema = await getProjectSchema(scenarioName); 26 | // 加载 schema 27 | project.importSchema(schema as any); 28 | appHelper.utils.renderer = (page) => { 29 | return 30 | }; 31 | }, 32 | }; 33 | } 34 | EditorInitPlugin.pluginName = 'EditorInitPlugin'; 35 | EditorInitPlugin.meta = { 36 | preferenceDeclaration: { 37 | title: '保存插件配置', 38 | properties: [ 39 | { 40 | key: 'scenarioName', 41 | type: 'string', 42 | description: '用于localstorage存储key', 43 | }, 44 | { 45 | key: 'displayName', 46 | type: 'string', 47 | description: '用于显示的场景名', 48 | }, 49 | { 50 | key: 'info', 51 | type: 'object', 52 | description: '用于扩展信息', 53 | } 54 | ], 55 | }, 56 | }; 57 | export default EditorInitPlugin; 58 | -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-logo-sample/index.scss: -------------------------------------------------------------------------------- 1 | .lowcode-plugin-logo { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: flex-start; 5 | align-items: flex-end; 6 | width: 300px; 7 | .logo { 8 | display: block; 9 | width: 139px; 10 | height: 26px; 11 | cursor: pointer; 12 | background-size: contain; 13 | background-position: center; 14 | background-repeat: no-repeat; 15 | } 16 | .scenario-name { 17 | display: block; 18 | margin-left: 20px; 19 | margin-right: 5px; 20 | font-size: 15px; 21 | } 22 | .info-dropdown { 23 | display: block; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-logo-sample/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 3 | import { Dropdown, Menu } from '@alifd/next'; 4 | import './index.scss'; 5 | export interface IProps { 6 | logo?: string; 7 | href?: string; 8 | scenarioInfo?: any; 9 | scenarioDisplayName?: string; 10 | } 11 | 12 | const Logo: React.FC = (props): React.ReactElement => { 13 | const { scenarioDisplayName, scenarioInfo } = props; 14 | const urls = scenarioInfo?.urls || []; 15 | return ( 16 | 44 | ); 45 | }; 46 | // 示例 Logo widget 47 | const LogoSamplePlugin = (ctx: IPublicModelPluginContext) => { 48 | return { 49 | async init() { 50 | const { skeleton, config } = ctx; 51 | const scenarioDisplayName = config.get('scenarioDisplayName'); 52 | const scenarioInfo = config.get('scenarioInfo'); 53 | // 注册 logo widget 54 | skeleton.add({ 55 | area: 'topArea', 56 | type: 'Widget', 57 | name: 'logo', 58 | content: , 59 | contentProps: { 60 | logo: 'https://img.alicdn.com/imgextra/i4/O1CN013w2bmQ25WAIha4Hx9_!!6000000007533-55-tps-137-26.svg', 61 | href: 'https://lowcode-engine.cn', 62 | }, 63 | props: { 64 | align: 'left', 65 | }, 66 | }); 67 | }, 68 | }; 69 | } 70 | LogoSamplePlugin.pluginName = 'LogoSamplePlugin'; 71 | LogoSamplePlugin.meta = { 72 | dependencies: ['EditorInitPlugin'], 73 | }; 74 | export default LogoSamplePlugin; -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-lowcode-component/index.ts: -------------------------------------------------------------------------------- 1 | import { IPublicModelPluginContext } from "@alilc/lowcode-types"; 2 | import lowcodeSchema from './lowcode-schema.json' 3 | 4 | const lowcodePlugin = (ctx: IPublicModelPluginContext) => { 5 | return { 6 | async init() { 7 | const { material } = ctx; 8 | material.loadIncrementalAssets({ 9 | version: '', 10 | components: [{ 11 | devMode: 'lowCode', 12 | componentName: 'LowcodeDemo', 13 | title: '低代码组件示例', 14 | group: '低代码组件', 15 | schema: lowcodeSchema as any, 16 | snippets: [{ 17 | schema: { 18 | componentName: 'LowcodeDemo' 19 | }, 20 | }] 21 | }], 22 | }) 23 | }, 24 | }; 25 | } 26 | lowcodePlugin.pluginName = 'lowcodePlugin'; 27 | lowcodePlugin.meta = { 28 | }; 29 | export default lowcodePlugin; -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-pages/index.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzusp/online-code/bc6ede23a5c3ac7b07348647bddbe2f987725a3b/online-code-frontend/src/plugins/plugin-pages/index.scss -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import {IPublicModelPluginContext} from '@alilc/lowcode-types'; 2 | import React from 'react'; 3 | import {Nav} from '@alifd/next'; 4 | import './index.scss'; 5 | import {getProjectSchema, getProjectSchemaFromDb} from 'src/services/schemaService'; 6 | import {createFetch} from "../../fetchHandler"; 7 | 8 | const { Item } = Nav; 9 | 10 | const PagesPlugin = (ctx: IPublicModelPluginContext) => { 11 | return { 12 | async init() { 13 | const { skeleton, project, config } = ctx; 14 | const defaultPage = 'login'; 15 | config.set('scenarioName', defaultPage); 16 | config.set('scenarioDisplayName', defaultPage); 17 | config.set('scenarioInfo', {}); 18 | 19 | let menuNav: React.JSX.Element[] = []; 20 | await createFetch({url: '/onlinecode-api/process/run', method: 'POST', data: { 21 | procCode: 'menuList' 22 | }}) 23 | .then((res: any) => { 24 | if (res.status === 200 && res.data && res.data.code === 200) { 25 | const menus = res.data.data; 26 | menuNav = toNav(menus); 27 | } 28 | }) 29 | .catch((err: any) => {}); 30 | 31 | function toNav(menus: any[]) { 32 | if (!menus || menus.length === 0) { 33 | return []; 34 | } 35 | let arr: React.JSX.Element[] = []; 36 | menus.forEach(m => { 37 | // 菜单组 38 | if (m.type === '0') { 39 | arr.push({toNav(m.children)}); 40 | } else { // 菜单 41 | if (m.mode === '0') { // schema 42 | arr.push({m.name}); 43 | } 44 | } 45 | }); 46 | return arr; 47 | } 48 | 49 | const onSelect = async (keys: string[]) => { 50 | const key = keys[0]; 51 | console.log('selected', key); 52 | // 保存在 config 中用于引擎范围其他插件使用 53 | config.set('scenarioName', key); 54 | config.set('scenarioDisplayName', key); 55 | config.set('scenarioInfo', {}); 56 | 57 | let scenarioSchema = await getProjectSchemaFromDb(key); 58 | if (!scenarioSchema) { 59 | scenarioSchema = await getProjectSchema(); 60 | let schema = scenarioSchema?.componentsTree?.[0]; 61 | if (schema) { 62 | scenarioSchema.componentsTree[0]['meta'] = {title: key, locator: key, router: '/' + key}; 63 | } 64 | } 65 | // 加载schema 66 | project.importSchema(scenarioSchema as any); 67 | project.simulatorHost?.rerender(); 68 | }; 69 | // 注册组件面板 70 | const pagesPane = skeleton.add({ 71 | area: 'leftArea', 72 | type: 'PanelDock', 73 | name: 'pagesPane', 74 | content: () => { 75 | return 78 | }, 79 | contentProps: {}, 80 | props: { 81 | align: 'top', 82 | icon: 'list', 83 | description: '页面管理', 84 | }, 85 | }, { index: -999 }); 86 | pagesPane?.disable?.(); 87 | project.onSimulatorRendererReady(() => { 88 | pagesPane?.enable?.(); 89 | }) 90 | }, 91 | }; 92 | } 93 | PagesPlugin.pluginName = 'PagesPlugin'; 94 | export default PagesPlugin; 95 | -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-preview-sample/index.tsx: -------------------------------------------------------------------------------- 1 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 2 | import { Button } from '@alifd/next'; 3 | import { 4 | saveSchema, 5 | } from '../../services/schemaService'; 6 | 7 | // 保存功能示例 8 | const PreviewSamplePlugin = (ctx: IPublicModelPluginContext) => { 9 | return { 10 | async init() { 11 | const { skeleton, config } = ctx; 12 | const doPreview = () => { 13 | const scenarioName = config.get('scenarioName'); 14 | saveSchema(scenarioName); 15 | setTimeout(() => { 16 | const search = location.search ? `${location.search}&scenarioName=${scenarioName}` : `?scenarioName=${scenarioName}`; 17 | window.open(`./preview.html${search}`); 18 | }, 500); 19 | }; 20 | skeleton.add({ 21 | name: 'previewSample', 22 | area: 'topArea', 23 | type: 'Widget', 24 | props: { 25 | align: 'right', 26 | }, 27 | content: ( 28 | 31 | ), 32 | }); 33 | }, 34 | }; 35 | } 36 | PreviewSamplePlugin.pluginName = 'PreviewSamplePlugin'; 37 | PreviewSamplePlugin.meta = { 38 | dependencies: ['EditorInitPlugin'], 39 | }; 40 | export default PreviewSamplePlugin; 41 | -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-save-sample/index.tsx: -------------------------------------------------------------------------------- 1 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 2 | import { Button } from '@alifd/next'; 3 | import { 4 | resetSchema, 5 | } from '../../services/mockService'; 6 | import { 7 | saveSchema 8 | } from '../../services/schemaService'; 9 | 10 | // 保存功能示例 11 | const SaveSamplePlugin = (ctx: IPublicModelPluginContext | any) => { 12 | return { 13 | async init() { 14 | const { skeleton, hotkey, config } = ctx; 15 | 16 | const save = () => { 17 | const scenarioName = config.get('scenarioName'); 18 | saveSchema(scenarioName); 19 | } 20 | 21 | const reset = () => { 22 | const scenarioName = config.get('scenarioName'); 23 | resetSchema(scenarioName); 24 | } 25 | 26 | skeleton.add({ 27 | name: 'saveSample', 28 | area: 'topArea', 29 | type: 'Widget', 30 | props: { 31 | align: 'right', 32 | }, 33 | content: ( 34 | 37 | ), 38 | }); 39 | skeleton.add({ 40 | name: 'resetSchema', 41 | area: 'topArea', 42 | type: 'Widget', 43 | props: { 44 | align: 'right', 45 | }, 46 | content: ( 47 | 50 | ), 51 | }); 52 | hotkey.bind('command+s', (e: any) => { 53 | e.preventDefault(); 54 | save(); 55 | }); 56 | }, 57 | }; 58 | } 59 | SaveSamplePlugin.pluginName = 'SaveSamplePlugin'; 60 | SaveSamplePlugin.meta = { 61 | dependencies: ['EditorInitPlugin'], 62 | }; 63 | export default SaveSamplePlugin; 64 | -------------------------------------------------------------------------------- /online-code-frontend/src/plugins/plugin-simulator-locale/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IPublicModelPluginContext } from '@alilc/lowcode-types'; 3 | import { Select } from '@alifd/next'; 4 | 5 | const Option = Select.Option; 6 | export interface IProps { 7 | currentLocale: string; 8 | onChange: (value: string) => void; 9 | } 10 | 11 | const LocaleSelect: React.FC = (props): React.ReactElement => { 12 | const { currentLocale, onChange } = props; 13 | const currentLocaleValue = currentLocale || 'zh-CN'; 14 | return ( 15 |
16 | 26 |
27 | ); 28 | }; 29 | // 画布区域语言切换 30 | const SimulatorLocalePlugin = (ctx: IPublicModelPluginContext) => { 31 | return { 32 | async init() { 33 | const { project, skeleton } = ctx; 34 | const currentLocale = project.simulatorHost?.get('locale') || 'zh-CN'; 35 | const onLocaleChange = (value: string): void => { 36 | project.simulatorHost.set('locale', value); 37 | } 38 | skeleton.add({ 39 | area: 'topArea', 40 | type: 'Widget', 41 | name: 'simulatorLocale', 42 | content: , 43 | props: { 44 | align: 'center', 45 | }, 46 | }); 47 | }, 48 | }; 49 | } 50 | SimulatorLocalePlugin.pluginName = 'SimulatorLocalePlugin'; 51 | SimulatorLocalePlugin.meta = { 52 | }; 53 | export default SimulatorLocalePlugin; -------------------------------------------------------------------------------- /online-code-frontend/src/services/defaultI18nSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "zh-CN": { 3 | "i18n-jwg27yo4": "你好 ", 4 | "i18n-jwg27yo3": "{name} 博士" 5 | }, 6 | "en-US": { 7 | "i18n-jwg27yo4": "Hello ", 8 | "i18n-jwg27yo3": "Doctor {name}" 9 | } 10 | } -------------------------------------------------------------------------------- /online-code-frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "declaration": true, 5 | "lib": ["es2015", "dom"], 6 | // Target latest version of ECMAScript. 7 | "target": "esnext", 8 | // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 9 | "module": "esnext", 10 | // Search under node_modules for non-relative imports. 11 | "moduleResolution": "node", 12 | // Process & infer types from .js files. 13 | "allowJs": true, 14 | // Report errors in .js files. 15 | "checkJs": false, 16 | // Don't emit; allow Babel to transform files. 17 | // "noEmit": true, 18 | // Enable strictest settings like strictNullChecks & noImplicitAny. 19 | "strict": true, 20 | // Allow default imports from modules with no default export. This does not affect code emit, just typechecking. 21 | "allowSyntheticDefaultImports": true, 22 | // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 23 | "esModuleInterop": true, 24 | // Specify JSX code generation: 'preserve', 'react-native', or 'react'. 25 | "jsx": "preserve", 26 | // Import emit helpers (e.g. __extends, __rest, etc..) from tslib 27 | "importHelpers": true, 28 | // Enables experimental support for ES7 decorators. 29 | "experimentalDecorators": true, 30 | // Generates corresponding .map file. 31 | "sourceMap": true, 32 | // Disallow inconsistently-cased references to the same file. 33 | "forceConsistentCasingInFileNames": true, 34 | // Allow json import 35 | "resolveJsonModule": true, 36 | // skip type checking of declaration files 37 | "skipLibCheck": true, 38 | "outDir": "lib" 39 | }, 40 | "include": [ 41 | "./src/" 42 | ], 43 | "exclude": ["**/test", "**/lib", "**/es", "node_modules"] 44 | } 45 | -------------------------------------------------------------------------------- /plugin-custom/README.md: -------------------------------------------------------------------------------- 1 | npm init @alilc/element your-element-name 2 | cd your-element-name 3 | npm install 4 | npm start -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | quote_type = single 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | dist/ 4 | **/*.min.js 5 | **/*-min.js 6 | **/*.bundle.js 7 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'eslint-config-ali/typescript/react', 4 | "prettier", 5 | 'prettier/@typescript-eslint', 6 | 'prettier/react', 7 | ], 8 | }; 9 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | package-lock.json 10 | yarn.lock 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (https://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # TypeScript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | 63 | # next.js build output 64 | .next 65 | 66 | # special demo file for locally reappear issue 67 | docs/**/demo/issues.md 68 | 69 | precss.css 70 | .sass-cache/ 71 | scripts/server-remote 72 | __html/ 73 | umd/ 74 | es/ 75 | lib/ 76 | lowcode_es/ 77 | lowcode_lib/ 78 | types/ 79 | demos/ 80 | !scripts/demos/ 81 | /platform 82 | build/ 83 | test/coverage/ 84 | test/**/coverage/ 85 | mochawesome-report/ 86 | coverage/ 87 | gemini-report/ 88 | .idea/ 89 | .vscode/ 90 | *.iml 91 | .tea/ 92 | /platform/ 93 | react/ 94 | platform/ 95 | dist/ 96 | _docs_/ 97 | doc.json 98 | meet-react/ 99 | miniapp-preview/ 100 | .tmp/ 101 | 102 | .umi/ 103 | .umi-production/ -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "markdownlint-config-ali" 3 | } 4 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.markdownlintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | dist/ 4 | 5 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.npmignore: -------------------------------------------------------------------------------- 1 | miniapp-preview/ 2 | .idea/ 3 | .vscode/ 4 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | arrowParens: 'always', 8 | }; 9 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.stylelintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | dist/ 4 | **/*.min.css 5 | **/*-min.css 6 | **/*.bundle.css 7 | 8 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'stylelint-config-ali', 3 | }; 4 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/README.md: -------------------------------------------------------------------------------- 1 | # demo component 2 | 3 | @alifd/example-component 4 | 5 | intro component 6 | 7 | ## API 8 | 9 | | 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 | 10 | | ------ | ---- | ---- | ---- | ------ | ---- | 11 | | | | | | | | 12 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "library": "BizComp", 3 | "plugins": [ 4 | "build-plugin-component", 5 | "build-plugin-fusion", 6 | [ 7 | "build-plugin-moment-locales", 8 | { 9 | "locales": ["zh-cn"] 10 | } 11 | ] 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/build.lowcode.js: -------------------------------------------------------------------------------- 1 | const { library } = require('./build.json'); 2 | 3 | module.exports = { 4 | alias: { 5 | '@': './src', 6 | }, 7 | plugins: [ 8 | [ 9 | '@alifd/build-plugin-lowcode', 10 | { 11 | library, 12 | engineScope: "@alilc" 13 | }, 14 | ], 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['ali'], 3 | }; 4 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/demo/usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Simple Usage 3 | order: 1 4 | --- 5 | 6 | 本 Demo 演示一行文字的用法。 7 | 8 | ```jsx 9 | import React, { Component } from 'react'; 10 | import ReactDOM from 'react-dom'; 11 | import ExampleComponent from 'plugin-custom-renderer'; 12 | 13 | class App extends Component { 14 | render() { 15 | return ( 16 |
17 | 18 |
19 | ); 20 | } 21 | } 22 | 23 | ReactDOM.render(, mountNode); 24 | ``` 25 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/f2elint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | enableStylelint: true, 3 | enableMarkdownlint: true, 4 | enablePrettier: true, 5 | }; 6 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | setupFilesAfterEnv: ['/test/setupTests.js'], 3 | }; 4 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/lowcode/plugin-custom-renderer/meta.ts: -------------------------------------------------------------------------------- 1 | 2 | import { IPublicTypeComponentMetadata, IPublicTypeSnippet } from '@alilc/lowcode-types'; 3 | 4 | const PluginCustomRendererMeta: IPublicTypeComponentMetadata = { 5 | "group": "低代码组件", 6 | "componentName": "PluginCustomRenderer", 7 | "title": "PluginCustomRenderer", 8 | "docUrl": "", 9 | "screenshot": "", 10 | "devMode": "proCode", 11 | "npm": { 12 | "package": "plugin-custom-renderer", 13 | "version": "0.1.0", 14 | "exportName": "default", 15 | "main": "src\\index.tsx", 16 | "destructuring": false, 17 | "subName": "" 18 | }, 19 | "configure": { 20 | "props": [ 21 | { 22 | "title": { 23 | "label": { 24 | "type": "i18n", 25 | "en-US": "name", 26 | "zh-CN": "name" 27 | } 28 | }, 29 | "name": "name", 30 | "description": "低代码组件", 31 | "setter": [ 32 | { 33 | "componentName": "StringSetter", 34 | "isRequired": false, 35 | "initialValue": {} 36 | }, 37 | ], 38 | }, 39 | { 40 | "title": { 41 | "label": { 42 | "type": "i18n", 43 | "en-US": "element", 44 | "zh-CN": "element" 45 | } 46 | }, 47 | "name": "element", 48 | "description": "低代码组件", 49 | "setter": [ 50 | { 51 | "componentName": "ObjectSetter", 52 | "isRequired": false, 53 | "initialValue": {} 54 | }, 55 | ], 56 | }, 57 | ], 58 | "supports": { 59 | "events": ['onRender', 60 | { 61 | "name": "onRender" 62 | }], 63 | "style": true 64 | }, 65 | "component": {} 66 | } 67 | }; 68 | const snippets: IPublicTypeSnippet[] = [ 69 | { 70 | "title": "PluginCustomRenderer", 71 | "screenshot": "", 72 | "schema": { 73 | "componentName": "PluginCustomRenderer", 74 | "props": {} 75 | } 76 | } 77 | ]; 78 | 79 | export default { 80 | ...PluginCustomRendererMeta, 81 | snippets 82 | }; 83 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plugin-custom-renderer", 3 | "version": "0.1.0", 4 | "description": "plugin-custom-renderer", 5 | "files": [ 6 | "demo/", 7 | "es/", 8 | "lib/", 9 | "build/", 10 | "dist/", 11 | "lowcode/", 12 | "lowcode_lib/", 13 | "lowcode_es/" 14 | ], 15 | "main": "lib/index.js", 16 | "module": "es/index.js", 17 | "exports": { 18 | "./*": "./*", 19 | ".": { 20 | "import": "./es/index.js", 21 | "require": "./lib/index.js" 22 | }, 23 | "./prototype": { 24 | "require": "./lowcode_lib/meta.js", 25 | "import": "./lowcode_es/meta.js" 26 | }, 27 | "./prototypeView": { 28 | "require": "./lowcode_lib/view.js", 29 | "import": "./lowcode_es/view.js" 30 | } 31 | }, 32 | "stylePath": "style.js", 33 | "scripts": { 34 | "start": "build-scripts start", 35 | "build": "build-scripts build", 36 | "lowcode:dev": "build-scripts start --config ./build.lowcode.js", 37 | "lowcode:build": "build-scripts build --config ./build.lowcode.js", 38 | "test": "build-scripts test", 39 | "prepublishOnly": "npm run build && npm run lowcode:build", 40 | "eslint": "eslint --cache --ext .js,.jsx ./", 41 | "eslint:fix": "npm run eslint -- --fix", 42 | "stylelint": "stylelint \"**/*.{css,scss,less}\"", 43 | "lint": "npm run eslint && npm run stylelint", 44 | "f2elint-scan": "f2elint scan", 45 | "f2elint-fix": "f2elint fix" 46 | }, 47 | "keywords": [ 48 | "ice", 49 | "react", 50 | "component" 51 | ], 52 | "dependencies": { 53 | "moment": "^2.29.4", 54 | "@alifd/next": "^1.25.27", 55 | "react": "^16.x", 56 | "react-dom": "^16.x", 57 | "@babel/runtime": "^7.0.0" 58 | }, 59 | "devDependencies": { 60 | "@alib/build-scripts": "^0.1.3", 61 | "@alifd/build-plugin-lowcode": "^0.4.0", 62 | "@types/react": "^16.9.13", 63 | "@types/react-dom": "^16.9.4", 64 | "build-plugin-fusion": "^0.1.0", 65 | "build-plugin-component": "^1.0.0", 66 | "template-component-demo": "^2.0.3", 67 | "build-plugin-moment-locales": "^0.1.0", 68 | "f2elint": "^1.2.0" 69 | }, 70 | "peerDependencies": { 71 | "moment": "latest", 72 | "react": "^16.x", 73 | "react-dom": "^16.x" 74 | }, 75 | "componentConfig": { 76 | "name": "ExampleComponent", 77 | "title": "demo component", 78 | "category": "Information", 79 | "materialSchema": "https://unpkg.com/plugin-custom-renderer@0.1.0/build/lowcode/assets-prod.json" 80 | }, 81 | "lcMeta": { 82 | "type": "component" 83 | }, 84 | "license": "MIT" 85 | } -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/src/index.scss: -------------------------------------------------------------------------------- 1 | /* write style here */ 2 | .CustomRendererComponent { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | interface ComponentProps { 4 | name: string, 5 | element: any, 6 | onRender: Function|undefined 7 | } 8 | 9 | export default class CustomRendererComponent extends React.Component { 10 | 11 | constructor(props) { 12 | super(props); 13 | this.state = { 14 | name: props.name, 15 | element: props.element, 16 | onRender: props.onRender 17 | }; 18 | this.ref = React.createRef(); 19 | } 20 | 21 | componentDidMount() { 22 | if (this.state.onRender !== undefined) { 23 | this.state.onRender(this.ref); 24 | } 25 | } 26 | 27 | render() { 28 | return ( 29 |
30 |
31 | {this.state.element || 'no element'} 32 |
33 |
34 | ) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/test/index.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ExampleComponent from '../src/index'; 4 | import '../src/main.scss'; 5 | 6 | it('renders', () => { 7 | const wrapper = shallow(); 8 | expect(wrapper.find('.ExampleComponent').length).toBe(1); 9 | }); 10 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/test/setupTests.js: -------------------------------------------------------------------------------- 1 | import { configure } from 'enzyme'; 2 | import Adapter from 'enzyme-adapter-react-16'; 3 | 4 | configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /plugin-custom/plugin-custom-renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "buildOnSave": false, 4 | "compilerOptions": { 5 | "outDir": "build", 6 | "module": "esnext", 7 | "target": "es6", 8 | "jsx": "react", 9 | "moduleResolution": "node", 10 | "lib": ["es6", "dom"], 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "noUnusedLocals": true, 14 | "noImplicitReturns": true, 15 | "noImplicitThis": true, 16 | "noImplicitAny": true, 17 | "skipLibCheck": true 18 | }, 19 | "include": ["src/*.ts", "src/*.tsx"], 20 | "exclude": ["node_modules", "build", "public"] 21 | } 22 | --------------------------------------------------------------------------------