├── .flattened-pom.xml ├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── encodings.xml ├── misc.xml ├── uiDesigner.xml └── vcs.xml ├── Dockerfile ├── LICENSE ├── README-en.md ├── README.md ├── distribution ├── .flattened-pom.xml ├── LICENSE-BIN ├── NOTICE-BIN ├── bin │ ├── shutdown.cmd │ ├── shutdown.sh │ ├── startup.cmd │ └── startup.sh ├── conf │ ├── application.properties │ ├── application.properties.example │ ├── cert │ │ ├── mmq.cer │ │ ├── mmq.key │ │ └── mmq.pfx │ ├── cluster.conf.example │ └── mmq-logback.xml ├── plugs │ └── README ├── pom.xml └── release-mmq.xml ├── img ├── Mysql.png ├── SQL模板.png ├── SQL规则.png ├── SqlServer.png ├── kafka.jpg ├── kafka规则.png ├── postgresql.png ├── 启动配置.png ├── 客户端管理.png ├── 规则引擎.png ├── 订阅列表.png ├── 认证鉴权.png ├── 认证鉴权配置.png ├── 资源管理.png └── 集群监测.png ├── mmq-api ├── .flattened-pom.xml ├── pom.xml └── src │ └── main │ └── proto │ └── mmq_grpc_service.proto ├── mmq-auth ├── .flattened-pom.xml ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── monkey │ └── mmq │ └── auth │ ├── annotation │ └── Secured.java │ ├── common │ ├── ActionTypes.java │ ├── AuthConfigs.java │ └── AuthSystemTypes.java │ ├── exception │ └── AccessException.java │ ├── model │ ├── Page.java │ ├── Permission.java │ ├── PermissionInfo.java │ ├── RoleInfo.java │ └── User.java │ ├── parser │ ├── DefaultResourceParser.java │ └── ResourceParser.java │ ├── persistent │ ├── AuthPersistentConsistencyServiceDelegateImpl.java │ ├── KeyBuilder.java │ └── UtilsAndCommons.java │ ├── service │ ├── IMqttAuthService.java │ ├── UserPersistentService.java │ └── impl │ │ └── MqttMqttAuthServiceImpl.java │ └── utils │ └── Loggers.java ├── mmq-broker ├── .flattened-pom.xml ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── monkey │ │ │ └── mmq │ │ │ ├── BrokerApplication.java │ │ │ ├── codec │ │ │ └── MqttWebSocketCodec.java │ │ │ ├── config │ │ │ ├── BrokerConfig.java │ │ │ ├── BrokerProperties.java │ │ │ ├── KeyBuilder.java │ │ │ ├── Loggers.java │ │ │ └── UtilsAndCommons.java │ │ │ ├── metrics │ │ │ ├── GlobalMQTTMessageCounter.java │ │ │ ├── MMQMetric.java │ │ │ ├── MMQMetrics.java │ │ │ └── MetricsHolder.java │ │ │ ├── notifier │ │ │ ├── ClientActor.java │ │ │ └── processor │ │ │ │ ├── PublishRequestProcessor.java │ │ │ │ ├── RejectClientProcessor.java │ │ │ │ └── RpcService.java │ │ │ ├── persistent │ │ │ └── MqttPersistentConsistencyServiceDelegateImpl.java │ │ │ ├── protocol │ │ │ ├── BrokerHandler.java │ │ │ ├── BrokerServer.java │ │ │ ├── Connect.java │ │ │ ├── DisConnect.java │ │ │ ├── PingReq.java │ │ │ ├── ProtocolProcess.java │ │ │ ├── PubAck.java │ │ │ ├── PubComp.java │ │ │ ├── PubRec.java │ │ │ ├── PubRel.java │ │ │ ├── Publish.java │ │ │ ├── RejectHandler.java │ │ │ ├── RequestProcessor.java │ │ │ ├── SSLBrokerServer.java │ │ │ ├── Subscribe.java │ │ │ ├── ThreadFactoryImpl.java │ │ │ └── UnSubscribe.java │ │ │ └── service │ │ │ ├── DupPubRelMessageStoreService.java │ │ │ ├── DupPublishMessageStoreService.java │ │ │ ├── GlobalMetricsStoreService.java │ │ │ ├── RetainMessageStoreService.java │ │ │ ├── SessionStoreService.java │ │ │ └── SubscribeStoreService.java │ └── resources │ │ ├── application.properties │ │ ├── cert │ │ ├── mmq.cer │ │ ├── mmq.key │ │ └── mmq.pfx │ │ └── mmq-version.txt │ └── test │ └── java │ └── org │ └── monkey │ └── mmq │ ├── config │ └── driver │ │ ├── InfluxDB1XDriverTest.java │ │ ├── InfluxDBDriverTest.java │ │ └── KafkaDriverTest.java │ └── notifier │ └── RuleEngineActorTest.java ├── mmq-config ├── .flattened-pom.xml ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── monkey │ └── mmq │ └── config │ ├── Config.java │ ├── actor │ ├── DriverActor.java │ └── RuleEngineActor.java │ ├── config │ ├── Constants.java │ └── Loggers.java │ ├── driver │ ├── AbstractJDBCDriver.java │ ├── DriverFactory.java │ ├── InfluxDB1XDriver.java │ ├── InfluxDBDriver.java │ ├── KafkaDriver.java │ ├── MQTTDriver.java │ ├── MysqlDriver.java │ ├── PostgresqlDriver.java │ ├── RabbitMQDriver.java │ ├── ResourceDriver.java │ ├── SqlServerDriver.java │ └── TDengineDriver.java │ ├── matedata │ ├── DriverMessage.java │ ├── KeyBuilder.java │ ├── ModelEnum.java │ ├── ResourceEnum.java │ ├── ResourcesMateData.java │ ├── RuleEngineMateData.java │ ├── RuleEngineMessage.java │ ├── UpdateRuleEngineMessage.java │ └── UtilsAndCommons.java │ ├── modules │ ├── BaseModule.java │ ├── IModule.java │ ├── ModelMateData.java │ ├── ModuleFactory.java │ ├── acl │ │ ├── AclModule.java │ │ └── AclParam.java │ ├── api │ │ ├── ApiModule.java │ │ └── ApiParam.java │ └── auth │ │ ├── AuthModule.java │ │ └── AuthParam.java │ ├── persistent │ └── ConfigPersistentConsistencyServiceDelegateImpl.java │ └── service │ ├── ModulesService.java │ ├── ResourcesService.java │ └── RuleEngineService.java ├── mmq-core ├── .flattened-pom.xml ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── monkey │ │ │ └── mmq │ │ │ └── core │ │ │ ├── actor │ │ │ ├── ActorMsg.java │ │ │ ├── MsgType.java │ │ │ ├── StopMessage.java │ │ │ ├── message │ │ │ │ ├── ClientPutMessage.java │ │ │ │ ├── ClientRemoveMessage.java │ │ │ │ ├── PublishMessage.java │ │ │ │ ├── RejectMessage.java │ │ │ │ └── SystemMessage.java │ │ │ └── metadata │ │ │ │ ├── message │ │ │ │ ├── ClientMateData.java │ │ │ │ ├── DupPubRelMessageMateData.java │ │ │ │ ├── DupPublishMessageMateData.java │ │ │ │ ├── PublishInOutType.java │ │ │ │ ├── PublishMateData.java │ │ │ │ ├── RetainMessageMateData.java │ │ │ │ └── SessionMateData.java │ │ │ │ ├── subscribe │ │ │ │ └── SubscribeMateData.java │ │ │ │ └── system │ │ │ │ └── SystemInfoMateData.java │ │ │ ├── cluster │ │ │ ├── AbstractMemberLookup.java │ │ │ ├── Member.java │ │ │ ├── MemberChangeListener.java │ │ │ ├── MemberLookup.java │ │ │ ├── MemberMetaDataConstants.java │ │ │ ├── MemberUtil.java │ │ │ ├── MembersChangeEvent.java │ │ │ ├── NodeState.java │ │ │ ├── ServerMemberManager.java │ │ │ ├── Task.java │ │ │ └── lookup │ │ │ │ ├── FileConfigMemberLookup.java │ │ │ │ ├── LookupFactory.java │ │ │ │ └── StandaloneMemberLookup.java │ │ │ ├── code │ │ │ ├── SpringApplicationRunListener.java │ │ │ └── StandaloneProfileApplicationListener.java │ │ │ ├── common │ │ │ ├── Commons.java │ │ │ └── Constants.java │ │ │ ├── consistency │ │ │ ├── CommandOperations.java │ │ │ ├── Config.java │ │ │ ├── ConsistencyProtocol.java │ │ │ ├── DataOperation.java │ │ │ ├── ProtocolMetaData.java │ │ │ ├── RequestProcessor.java │ │ │ ├── SerializeFactory.java │ │ │ ├── Serializer.java │ │ │ ├── ap │ │ │ │ ├── APProtocol.java │ │ │ │ └── RequestProcessor4AP.java │ │ │ ├── cp │ │ │ │ ├── CPProtocol.java │ │ │ │ ├── MetadataKey.java │ │ │ │ └── RequestProcessor4CP.java │ │ │ ├── matedata │ │ │ │ ├── Datum.java │ │ │ │ ├── Record.java │ │ │ │ └── RecordListener.java │ │ │ ├── model │ │ │ │ ├── IResultCode.java │ │ │ │ ├── ResponsePage.java │ │ │ │ ├── RestResult.java │ │ │ │ └── RestResultUtils.java │ │ │ ├── notifier │ │ │ │ ├── PersistentNotifier.java │ │ │ │ └── ValueChangeEvent.java │ │ │ ├── persistent │ │ │ │ ├── BasePersistentServiceProcessor.java │ │ │ │ ├── BatchReadResponse.java │ │ │ │ ├── BatchWriteRequest.java │ │ │ │ ├── ConsistencyService.java │ │ │ │ ├── MmqKvStorage.java │ │ │ │ ├── MmqSnapshotOperation.java │ │ │ │ ├── PersistentConsistencyService.java │ │ │ │ ├── PersistentServiceProcessor.java │ │ │ │ └── StandalonePersistentServiceProcessor.java │ │ │ ├── serialize │ │ │ │ ├── HessianSerializer.java │ │ │ │ └── JacksonSerializer.java │ │ │ └── snapshot │ │ │ │ ├── AbstractSnapshotOperation.java │ │ │ │ ├── LocalFileMeta.java │ │ │ │ ├── Reader.java │ │ │ │ ├── SnapshotOperation.java │ │ │ │ └── Writer.java │ │ │ ├── distributed │ │ │ ├── AbstractConsistencyProtocol.java │ │ │ ├── ConsistencyConfiguration.java │ │ │ ├── ProtocolExecutor.java │ │ │ ├── ProtocolManager.java │ │ │ ├── id │ │ │ │ └── IdGenerator.java │ │ │ └── raft │ │ │ │ ├── JRaftMaintainService.java │ │ │ │ ├── JRaftProtocol.java │ │ │ │ ├── JRaftServer.java │ │ │ │ ├── JSnapshotOperation.java │ │ │ │ ├── MmqClosure.java │ │ │ │ ├── MmqStateMachine.java │ │ │ │ ├── RaftConfig.java │ │ │ │ ├── RaftErrorEvent.java │ │ │ │ ├── RaftEvent.java │ │ │ │ ├── RaftSysConstants.java │ │ │ │ ├── exception │ │ │ │ ├── ConsistencyException.java │ │ │ │ ├── DuplicateRaftGroupException.java │ │ │ │ ├── JRaftException.java │ │ │ │ ├── NoLeaderException.java │ │ │ │ ├── NoSuchLogProcessorException.java │ │ │ │ └── NoSuchRaftGroupException.java │ │ │ │ ├── processor │ │ │ │ ├── AbstractProcessor.java │ │ │ │ ├── MmqGetRequestProcessor.java │ │ │ │ ├── MmqLogProcessor.java │ │ │ │ ├── MmqReadRequestProcessor.java │ │ │ │ └── MmqWriteRequestProcessor.java │ │ │ │ └── utils │ │ │ │ ├── FailoverClosure.java │ │ │ │ ├── FailoverClosureImpl.java │ │ │ │ ├── JRaftConstants.java │ │ │ │ ├── JRaftLogOperation.java │ │ │ │ ├── JRaftOps.java │ │ │ │ ├── JRaftUtils.java │ │ │ │ ├── RaftExecutor.java │ │ │ │ └── RaftOptionsBuilder.java │ │ │ ├── env │ │ │ ├── Constants.java │ │ │ ├── EnvUtil.java │ │ │ └── OriginTrackedPropertiesLoader.java │ │ │ ├── exception │ │ │ ├── ErrorCode.java │ │ │ ├── KvStorageException.java │ │ │ ├── MmqException.java │ │ │ ├── ServiceLoaderException.java │ │ │ └── runtime │ │ │ │ ├── MmqDeserializationException.java │ │ │ │ ├── MmqRuntimeException.java │ │ │ │ └── MmqSerializationException.java │ │ │ ├── executor │ │ │ ├── ExecutorFactory.java │ │ │ ├── NameThreadFactory.java │ │ │ └── ThreadPoolManager.java │ │ │ ├── file │ │ │ ├── FileChangeEvent.java │ │ │ ├── FileWatcher.java │ │ │ └── WatchFileCenter.java │ │ │ ├── lifecycle │ │ │ └── Closeable.java │ │ │ ├── listener │ │ │ ├── LoggingApplicationListener.java │ │ │ ├── MmqApplicationListener.java │ │ │ └── StartingApplicationListener.java │ │ │ ├── monitor │ │ │ ├── MetricsMonitor.java │ │ │ └── MmqMeterRegistry.java │ │ │ ├── notify │ │ │ ├── DefaultPublisher.java │ │ │ ├── DefaultSharePublisher.java │ │ │ ├── Event.java │ │ │ ├── EventPublisher.java │ │ │ ├── EventPublisherFactory.java │ │ │ ├── NotifyCenter.java │ │ │ ├── ShardedEventPublisher.java │ │ │ ├── SlowEvent.java │ │ │ └── listener │ │ │ │ ├── SmartSubscriber.java │ │ │ │ └── Subscriber.java │ │ │ ├── plugs │ │ │ └── PlugsFactory.java │ │ │ ├── spi │ │ │ └── MmqServiceLoader.java │ │ │ ├── storage │ │ │ ├── StorageFactory.java │ │ │ └── kv │ │ │ │ ├── FileKvStorage.java │ │ │ │ ├── KvStorage.java │ │ │ │ ├── MemoryKvStorage.java │ │ │ │ └── RocksDBStorage.java │ │ │ ├── tls │ │ │ ├── FileChangeListener.java │ │ │ ├── SelfHostnameVerifier.java │ │ │ ├── SelfTrustManager.java │ │ │ ├── TlsFileWatcher.java │ │ │ ├── TlsHelper.java │ │ │ └── TlsSystemConfig.java │ │ │ └── utils │ │ │ ├── ApplicationUtils.java │ │ │ ├── BiFunction.java │ │ │ ├── ByteUtils.java │ │ │ ├── ClassUtil.java │ │ │ ├── ClassUtils.java │ │ │ ├── CollectionUtils.java │ │ │ ├── ConvertUtils.java │ │ │ ├── DiskUtils.java │ │ │ ├── ExceptionUtil.java │ │ │ ├── GenericType.java │ │ │ ├── GlobalExecutor.java │ │ │ ├── InetAddressValidator.java │ │ │ ├── InetUtils.java │ │ │ ├── InternetAddressUtil.java │ │ │ ├── IoUtils.java │ │ │ ├── JacksonUtils.java │ │ │ ├── LoggerUtils.java │ │ │ ├── Loggers.java │ │ │ ├── MD5Utils.java │ │ │ ├── MapUtil.java │ │ │ ├── MmqStringUtils.java │ │ │ ├── NetUtils.java │ │ │ ├── NumberUtil.java │ │ │ ├── Objects.java │ │ │ ├── Observable.java │ │ │ ├── Observer.java │ │ │ ├── PasswordEncoderUtil.java │ │ │ ├── ProtoMessageUtil.java │ │ │ ├── PwdUtil.java │ │ │ ├── RemoteUtils.java │ │ │ ├── RsaKeyUtil.java │ │ │ ├── StringUtils.java │ │ │ ├── ThreadUtils.java │ │ │ ├── TimerContext.java │ │ │ └── VersionUtils.java │ ├── proto │ │ ├── Data.proto │ │ └── consistency.proto │ └── resources │ │ ├── META-INF │ │ ├── logback │ │ │ └── mmq.xml │ │ ├── services │ │ │ └── org.monkey.mmq.core.consistency.Serializer │ │ └── spring.factories │ │ └── banner.txt │ └── test │ └── java │ └── org │ └── monkey │ └── mmq │ └── core │ ├── notify │ └── DefaultPublisherTest.java │ └── utils │ └── PasswordEncoderUtilTest.java ├── mmq-plugs ├── .flattened-pom.xml ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── monkey │ └── mmq │ └── plugs │ ├── AbstractMmqPlugs.java │ ├── Constants.java │ ├── IMmqPlugs.java │ ├── utils │ └── Loggers.java │ └── view │ ├── ComponentType.java │ ├── KeyValue.java │ ├── MmqPlugsView.java │ └── PropertyItem.java ├── mmq-rule-engine ├── .flattened-pom.xml ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── monkey │ │ └── mmq │ │ └── rule │ │ └── engine │ │ ├── DefaultReactorQL.java │ │ ├── DefaultReactorQLBuilder.java │ │ ├── DefaultReactorQLContext.java │ │ ├── DefaultReactorQLRecord.java │ │ ├── ReactorQL.java │ │ ├── ReactorQLContext.java │ │ ├── ReactorQLMetadata.java │ │ ├── ReactorQLRecord.java │ │ ├── feature │ │ ├── DistinctFeature.java │ │ ├── Feature.java │ │ ├── FeatureId.java │ │ ├── FilterFeature.java │ │ ├── FromFeature.java │ │ ├── GroupFeature.java │ │ ├── PropertyFeature.java │ │ ├── ValueAggMapFeature.java │ │ ├── ValueFlatMapFeature.java │ │ └── ValueMapFeature.java │ │ ├── supports │ │ ├── DefaultPropertyFeature.java │ │ ├── DefaultReactorQLMetadata.java │ │ ├── ExpressionVisitorAdapter.java │ │ ├── agg │ │ │ ├── CollectListAggFeature.java │ │ │ ├── CollectRowAggMapFeature.java │ │ │ ├── CountAggFeature.java │ │ │ └── MapAggFeature.java │ │ ├── distinct │ │ │ └── DefaultDistinctFeature.java │ │ ├── filter │ │ │ ├── AndFilter.java │ │ │ ├── BetweenFilter.java │ │ │ ├── BinaryFilterFeature.java │ │ │ ├── EqualsFilter.java │ │ │ ├── GreaterEqualsTanFilter.java │ │ │ ├── GreaterTanFilter.java │ │ │ ├── IfValueMapFeature.java │ │ │ ├── InFilter.java │ │ │ ├── LessEqualsTanFilter.java │ │ │ ├── LessTanFilter.java │ │ │ ├── LikeFilter.java │ │ │ ├── OrFilter.java │ │ │ └── RangeFilter.java │ │ ├── fmap │ │ │ └── ArrayValueFlatMapFeature.java │ │ ├── from │ │ │ ├── FromTableFeature.java │ │ │ ├── FromValuesFeature.java │ │ │ ├── SubSelectFromFeature.java │ │ │ └── ZipSelectFeature.java │ │ ├── group │ │ │ ├── GroupByBinaryFeature.java │ │ │ ├── GroupByCalculateBinaryFeature.java │ │ │ ├── GroupByIntervalFeature.java │ │ │ ├── GroupByTakeFeature.java │ │ │ ├── GroupByValueFeature.java │ │ │ ├── GroupByWindowFeature.java │ │ │ └── TraceGroupRowFeature.java │ │ └── map │ │ │ ├── BinaryCalculateMapFeature.java │ │ │ ├── BinaryMapFeature.java │ │ │ ├── CaseMapFeature.java │ │ │ ├── CastFeature.java │ │ │ ├── DateFormatFeature.java │ │ │ ├── FunctionMapFeature.java │ │ │ ├── NowFeature.java │ │ │ ├── PropertyMapFeature.java │ │ │ ├── SelectFeature.java │ │ │ └── SingleParameterFunctionMapFeature.java │ │ └── utils │ │ ├── CalculateUtils.java │ │ ├── CastUtils.java │ │ ├── CompareUtils.java │ │ ├── ExpressionUtils.java │ │ └── SqlUtils.java │ └── test │ └── java │ └── org │ └── monkey │ └── mmq │ └── rule │ └── engine │ └── ReactorQLTest.java ├── mmq-ui ├── .browserslistrc ├── .editorconfig ├── .env ├── .env.development ├── .env.preview ├── .eslintrc.js ├── .eslintrc.json ├── .gitattributes ├── .gitignore ├── .prettierrc ├── .travis.yml ├── LICENSE ├── README.md ├── README.zh-CN.md ├── babel.config.js ├── config │ ├── plugin.config.js │ └── themePluginConfig.js ├── docs │ ├── add-page-loading-animate.md │ └── webpack-bundle-analyzer.md ├── jest.config.js ├── jsconfig.json ├── package.json ├── postcss.config.js ├── public │ ├── avatar2.jpg │ ├── index.html │ └── logo.png ├── src │ ├── App.vue │ ├── api │ │ ├── login.js │ │ ├── manage.js │ │ └── system.js │ ├── assets │ │ ├── background.svg │ │ ├── icons │ │ │ └── bx-analyse.svg │ │ ├── logo.png │ │ └── logo.svg │ ├── components │ │ ├── ArticleListContent │ │ │ ├── ArticleListContent.vue │ │ │ └── index.js │ │ ├── AvatarList │ │ │ ├── Item.jsx │ │ │ ├── List.jsx │ │ │ ├── index.js │ │ │ ├── index.less │ │ │ └── index.md │ │ ├── Charts │ │ │ ├── Bar.vue │ │ │ ├── ChartCard.vue │ │ │ ├── Liquid.vue │ │ │ ├── MiniArea.vue │ │ │ ├── MiniBar.vue │ │ │ ├── MiniProgress.vue │ │ │ ├── MiniSmoothArea.vue │ │ │ ├── Radar.vue │ │ │ ├── RankList.vue │ │ │ ├── TagCloud.vue │ │ │ ├── TransferBar.vue │ │ │ ├── Trend.vue │ │ │ ├── chart.less │ │ │ └── smooth.area.less │ │ ├── Dialog.js │ │ ├── Editor │ │ │ ├── QuillEditor.vue │ │ │ └── WangEditor.vue │ │ ├── Ellipsis │ │ │ ├── Ellipsis.vue │ │ │ ├── index.js │ │ │ └── index.md │ │ ├── FooterToolbar │ │ │ ├── FooterToolBar.vue │ │ │ ├── index.js │ │ │ ├── index.less │ │ │ └── index.md │ │ ├── GlobalFooter │ │ │ └── index.vue │ │ ├── GlobalHeader │ │ │ ├── AvatarDropdown.vue │ │ │ └── RightContent.vue │ │ ├── IconSelector │ │ │ ├── IconSelector.vue │ │ │ ├── README.md │ │ │ ├── icons.js │ │ │ └── index.js │ │ ├── MultiTab │ │ │ ├── MultiTab.vue │ │ │ ├── events.js │ │ │ ├── index.js │ │ │ └── index.less │ │ ├── NProgress │ │ │ └── nprogress.less │ │ ├── NoticeIcon │ │ │ ├── NoticeIcon.vue │ │ │ └── index.js │ │ ├── NumberInfo │ │ │ ├── NumberInfo.vue │ │ │ ├── index.js │ │ │ ├── index.less │ │ │ └── index.md │ │ ├── Other │ │ │ └── CarbonAds.vue │ │ ├── PageLoading │ │ │ └── index.jsx │ │ ├── Search │ │ │ ├── GlobalSearch.jsx │ │ │ └── index.less │ │ ├── SelectLang │ │ │ ├── index.jsx │ │ │ └── index.less │ │ ├── SettingDrawer │ │ │ ├── SettingDrawer.vue │ │ │ ├── SettingItem.vue │ │ │ ├── index.js │ │ │ ├── settingConfig.js │ │ │ └── themeColor.js │ │ ├── StandardFormRow │ │ │ ├── StandardFormRow.vue │ │ │ └── index.js │ │ ├── Table │ │ │ ├── README.md │ │ │ └── index.js │ │ ├── TagSelect │ │ │ ├── TagSelectOption.jsx │ │ │ └── index.jsx │ │ ├── TextArea │ │ │ ├── index.jsx │ │ │ └── style.less │ │ ├── Tree │ │ │ └── Tree.jsx │ │ ├── Trend │ │ │ ├── Trend.vue │ │ │ ├── index.js │ │ │ ├── index.less │ │ │ └── index.md │ │ ├── _util │ │ │ └── util.js │ │ ├── index.js │ │ ├── index.less │ │ └── tools │ │ │ └── TwoStepCaptcha.vue │ ├── config │ │ ├── defaultSettings.js │ │ └── router.config.js │ ├── core │ │ ├── bootstrap.js │ │ ├── directives │ │ │ └── action.js │ │ ├── icons.js │ │ ├── lazy_use.js │ │ ├── permission │ │ │ └── permission.js │ │ └── use.js │ ├── global.less │ ├── layouts │ │ ├── BasicLayout.less │ │ ├── BasicLayout.vue │ │ ├── BlankLayout.vue │ │ ├── PageView.vue │ │ ├── RouteView.vue │ │ ├── UserLayout.vue │ │ └── index.js │ ├── locales │ │ ├── index.js │ │ └── lang │ │ │ ├── en-US.js │ │ │ ├── en-US │ │ │ ├── account.js │ │ │ ├── account │ │ │ │ └── settings.js │ │ │ ├── dashboard.js │ │ │ ├── dashboard │ │ │ │ └── analysis.js │ │ │ ├── form.js │ │ │ ├── form │ │ │ │ └── basicForm.js │ │ │ ├── global.js │ │ │ ├── menu.js │ │ │ ├── overview.js │ │ │ ├── result.js │ │ │ ├── result │ │ │ │ ├── fail.js │ │ │ │ └── success.js │ │ │ ├── setting.js │ │ │ └── user.js │ │ │ ├── zh-CN.js │ │ │ └── zh-CN │ │ │ ├── account.js │ │ │ ├── account │ │ │ └── settings.js │ │ │ ├── dashboard.js │ │ │ ├── dashboard │ │ │ └── analysis.js │ │ │ ├── form.js │ │ │ ├── form │ │ │ └── basicForm.js │ │ │ ├── global.js │ │ │ ├── menu.js │ │ │ ├── overview.js │ │ │ ├── result.js │ │ │ ├── result │ │ │ ├── fail.js │ │ │ └── success.js │ │ │ ├── setting.js │ │ │ └── user.js │ ├── main.js │ ├── mock │ │ ├── index.js │ │ ├── services │ │ │ ├── article.js │ │ │ ├── auth.js │ │ │ ├── manage.js │ │ │ ├── other.js │ │ │ ├── tagCloud.js │ │ │ └── user.js │ │ └── util.js │ ├── permission.js │ ├── router │ │ ├── README.md │ │ ├── generator-routers.js │ │ └── index.js │ ├── store │ │ ├── app-mixin.js │ │ ├── device-mixin.js │ │ ├── getters.js │ │ ├── i18n-mixin.js │ │ ├── index.js │ │ ├── modules │ │ │ ├── app.js │ │ │ ├── async-router.js │ │ │ ├── permission.js │ │ │ └── user.js │ │ └── mutation-types.js │ ├── utils │ │ ├── axios.js │ │ ├── domUtil.js │ │ ├── filter.js │ │ ├── request.js │ │ ├── routeConvert.js │ │ ├── screenLog.js │ │ ├── util.js │ │ └── utils.less │ └── views │ │ ├── 404.vue │ │ ├── dashboard │ │ ├── Clients.vue │ │ ├── Monitor.vue │ │ ├── Subscription.vue │ │ ├── TestWork.vue │ │ ├── Workplace.less │ │ └── module │ │ │ ├── HttpTrace.vue │ │ │ ├── JvmInfo.vue │ │ │ ├── SystemInfo.vue │ │ │ └── TomcatInfo.vue │ │ ├── exception │ │ ├── 403.vue │ │ ├── 404.vue │ │ └── 500.vue │ │ ├── modules │ │ ├── ModulesManager.vue │ │ └── modules │ │ │ ├── AclModuleModel.vue │ │ │ ├── ApiModuleModel.vue │ │ │ └── AuthModuleModel.vue │ │ ├── plugs │ │ ├── PlugsManager.vue │ │ └── modules │ │ │ └── PlugsModule.vue │ │ ├── role │ │ └── RoleList.vue │ │ ├── ruleEngine │ │ ├── Resources.vue │ │ ├── RuleEngine.vue │ │ └── modules │ │ │ ├── ResourceModel.vue │ │ │ └── RuleEngineModel.vue │ │ └── user │ │ ├── AccountSetting.vue │ │ ├── Login.vue │ │ ├── Register.vue │ │ └── RegisterResult.vue ├── tests │ └── unit │ │ └── .eslintrc.js ├── vue.config.js ├── webstorm.config.js └── yarn.lock ├── mmq-web ├── .flattened-pom.xml ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── monkey │ │ └── mmq │ │ └── web │ │ ├── Mmq.java │ │ ├── config │ │ ├── AuthConfig.java │ │ ├── BasicApi.java │ │ ├── BasicApiAspect.java │ │ ├── NotWrap.java │ │ ├── ReturnAdviceHandler.java │ │ └── WebMvcConfiguration.java │ │ ├── controller │ │ ├── AclController.java │ │ ├── ApiController.java │ │ ├── HealthController.java │ │ ├── ModulesController.java │ │ ├── PlugsController.java │ │ ├── ResourcesController.java │ │ ├── RuleEngineController.java │ │ ├── SystemInfoController.java │ │ └── UserController.java │ │ ├── exception │ │ └── MmqExceptionHandler.java │ │ ├── filter │ │ └── JwtAuthenticationTokenFilter.java │ │ ├── security │ │ ├── JwtAuthenticationEntryPoint.java │ │ ├── JwtTokenManager.java │ │ ├── MmqAuthConfig.java │ │ ├── MmqUser.java │ │ ├── MmqUserDetails.java │ │ ├── MmqUserDetailsServiceImpl.java │ │ └── MqttAuthServiceImpl.java │ │ └── util │ │ ├── BaseContextUtil.java │ │ └── RequestUtil.java │ └── resources │ ├── application.properties │ ├── mmq-version.txt │ └── static │ ├── assets │ ├── background.a568162c.svg │ └── logo.b61284bb.svg │ ├── avatar2.jpg │ ├── css │ ├── app.de02f2b3.css │ ├── chunk-0c884780.639d5878.css │ ├── chunk-217b58f0.233089fe.css │ ├── chunk-24a0b0bc.e728df71.css │ ├── chunk-263ae8e2.e4af7fe0.css │ ├── chunk-39a0d16a.c8f72ae8.css │ ├── chunk-552fb8ee.4c06b465.css │ ├── chunk-vendors.8ebf8fd7.css │ └── user.7020778c.css │ ├── index.html │ ├── js │ ├── app.bdfa6c11.js │ ├── chunk-00a4fb94.2fdb98f7.js │ ├── chunk-0c55d5dd.c4fbba53.js │ ├── chunk-0c884780.9808d038.js │ ├── chunk-217b58f0.6b3caabd.js │ ├── chunk-24a0b0bc.687f7869.js │ ├── chunk-263ae8e2.79131220.js │ ├── chunk-2d0dd3d0.f982aded.js │ ├── chunk-341e83a4.5e564cac.js │ ├── chunk-39a0d16a.1b613b6b.js │ ├── chunk-552fb8ee.0f923899.js │ ├── chunk-vendors.8a0a835e.js │ ├── fail.e5dc8464.js │ ├── lang-zh-CN-account-settings.c67af352.js │ ├── lang-zh-CN-account.6801af9f.js │ ├── lang-zh-CN-dashboard-analysis.2fc3e69f.js │ ├── lang-zh-CN-dashboard.219ae12b.js │ ├── lang-zh-CN-form-basicForm.7b3d704b.js │ ├── lang-zh-CN-form.dcf97d1f.js │ ├── lang-zh-CN-global.2ab19788.js │ ├── lang-zh-CN-menu.a4978041.js │ ├── lang-zh-CN-overview.5670809e.js │ ├── lang-zh-CN-result-fail.e3747840.js │ ├── lang-zh-CN-result-success.349556c5.js │ ├── lang-zh-CN-result.1a9c63f2.js │ ├── lang-zh-CN-setting.78d9e9d1.js │ ├── lang-zh-CN-user.c45a5d16.js │ ├── lang-zh-CN.0b6050ec.js │ └── user.40fde1cd.js │ └── logo.png ├── pom.xml └── work └── Tomcat └── localhost └── ROOT ├── upload_05292e21_2a71_46d6_b121_0882c2a1c42a_00000000.tmp ├── upload_05292e21_2a71_46d6_b121_0882c2a1c42a_00000001.tmp ├── upload_15d13a7b_1be2_4f8a_9950_5ec8ca58aea0_00000001.tmp ├── upload_15d13a7b_1be2_4f8a_9950_5ec8ca58aea0_00000002.tmp ├── upload_15d13a7b_1be2_4f8a_9950_5ec8ca58aea0_00000003.tmp ├── upload_22746656_c18e_4aca_b13c_6a18c1ea678f_00000000.tmp ├── upload_22746656_c18e_4aca_b13c_6a18c1ea678f_00000001.tmp ├── upload_240142ee_ddd8_4b72_8866_5e3d473415c8_00000000.tmp ├── upload_240142ee_ddd8_4b72_8866_5e3d473415c8_00000001.tmp ├── upload_46a4c671_c368_42ba_83ce_fdb7b6f827d4_00000000.tmp ├── upload_46a4c671_c368_42ba_83ce_fdb7b6f827d4_00000001.tmp ├── upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000000.tmp ├── upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000001.tmp ├── upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000004.tmp ├── upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000005.tmp ├── upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000006.tmp ├── upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000007.tmp ├── upload_56b26020_9cdb_4e07_9a01_b0f5f533df6f_00000000.tmp ├── upload_56b26020_9cdb_4e07_9a01_b0f5f533df6f_00000001.tmp ├── upload_5cd7a0d8_b12d_4a1a_aa62_0e011aa387df_00000000.tmp ├── upload_5cd7a0d8_b12d_4a1a_aa62_0e011aa387df_00000001.tmp ├── upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000002.tmp ├── upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000003.tmp ├── upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000004.tmp ├── upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000005.tmp ├── upload_98bb9a31_589f_4f58_9d02_9dea13a6b634_00000004.tmp ├── upload_98bb9a31_589f_4f58_9d02_9dea13a6b634_00000005.tmp └── upload_99c060d3_6ed9_4ca3_ba74_5c2ce4c25a0f_00000000.tmp /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # java class file 9 | *.class 10 | 11 | # Package Files # 12 | *.war 13 | *.ear 14 | /target 15 | /.settings 16 | /.classpath 17 | /.project 18 | /.idea 19 | 20 | # ignore Maven generated target folders 21 | target 22 | out 23 | 24 | # ignore eclipse files 25 | .project 26 | .classpath 27 | .settings 28 | .factorypath 29 | .metadata 30 | .idea 31 | *.iml 32 | 33 | # ignore log files 34 | *.log -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 12 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 基础镜像 2 | FROM openjdk:8-jre 3 | # author 4 | MAINTAINER solley 5 | # 挂载目录 6 | VOLUME /home/mmq 7 | # 创建目录 8 | RUN mkdir -p /home/mmq 9 | # 指定路径 10 | WORKDIR /home/mmq 11 | # 复制jar文件到路径 12 | COPY ./distribution/target/mmq-server-1.1.5.tar.gz /home/mmq/mmq-server-1.1.5.tar.gz 13 | # 解压缩 14 | RUN tar -zxvf /home/mmq/mmq-server-1.1.5.tar.gz 15 | # 启动 16 | ENTRYPOINT java -jar '-Duser.timezone=GMT+08' '-Dmmq.standalone=true' mmq/target/mmq-server.jar --spring.config.additional-location=mmq/conf/ -------------------------------------------------------------------------------- /distribution/NOTICE-BIN: -------------------------------------------------------------------------------- 1 | MMQ 2 | Copyright 2018-2019 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Monkey MiddleWare Group. 6 | 7 | ------ 8 | This product has a bundle netty: 9 | The Spring oot Project 10 | ================= 11 | 12 | Please visit the Netty web site for more information: 13 | 14 | * http://netty.io/ 15 | 16 | Copyright 2014 The Netty Project 17 | 18 | The Netty Project licenses this file to you under the Apache License, 19 | version 2.0 (the "License"); you may not use this file except in compliance 20 | with the License. You may obtain a copy of the License at: 21 | 22 | http://www.apache.org/licenses/LICENSE-2.0 23 | 24 | Unless required by applicable law or agreed to in writing, software 25 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 26 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 27 | License for the specific language governing permissions and limitations 28 | under the License. 29 | 30 | Also, please refer to each LICENSE..txt file, which is located in 31 | the 'license' directory of the distribution file, for the license terms of the 32 | components that this product depends on. 33 | 34 | ------ 35 | This product has a bundle commons-lang, which includes software from the Spring Framework, 36 | under the Apache License 2.0 (see: StringUtils.containsWhitespace()) -------------------------------------------------------------------------------- /distribution/bin/shutdown.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem Copyright 2021-2021 Monkey Group. 3 | rem Licensed under the Apache License, Version 2.0 (the "License"); 4 | rem you may not use this file except in compliance with the License. 5 | rem You may obtain a copy of the License at 6 | rem 7 | rem http://www.apache.org/licenses/LICENSE-2.0 8 | rem 9 | rem Unless required by applicable law or agreed to in writing, software 10 | rem distributed under the License is distributed on an "AS IS" BASIS, 11 | rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | rem See the License for the specific language governing permissions and 13 | rem limitations under the License. 14 | if not exist "%JAVA_HOME%\bin\jps.exe" echo Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better! & EXIT /B 1 15 | 16 | setlocal 17 | 18 | set "PATH=%JAVA_HOME%\bin;%PATH%" 19 | 20 | echo killing mmq server 21 | 22 | for /f "tokens=1" %%i in ('jps -m ^| find "mmq.mmq"') do ( taskkill /F /PID %%i ) 23 | 24 | echo Done! 25 | -------------------------------------------------------------------------------- /distribution/bin/shutdown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2021-2021 Monkey Group. 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | cd `dirname $0`/../target 16 | target_dir=`pwd` 17 | 18 | pid=`ps ax | grep -i 'mmq.mmq' | grep ${target_dir} | grep java | grep -v grep | awk '{print $1}'` 19 | if [ -z "$pid" ] ; then 20 | echo "No MmqServer running." 21 | exit -1; 22 | fi 23 | 24 | echo "The mmqServer(${pid}) is running..." 25 | 26 | kill ${pid} 27 | 28 | echo "Send shutdown request to mmqServer(${pid}) OK" 29 | -------------------------------------------------------------------------------- /distribution/conf/cert/mmq.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDozCCAougAwIBAgIUUJo/Ll3YJtLB6UDKoZ9H3k1BAQYwDQYJKoZIhvcNAQEL 3 | BQAwYTELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB1FpbmdkYW8xEDAOBgNVBAcMB1Fp 4 | bmdkYW8xDzANBgNVBAoMBk1vbmtleTEPMA0GA1UECwwGTW9ua2V5MQwwCgYDVQQD 5 | DANtbXEwHhcNMjExMjE0MTUyODQyWhcNMjIxMjE0MTUyODQyWjBhMQswCQYDVQQG 6 | EwJDTjEQMA4GA1UECAwHUWluZ2RhbzEQMA4GA1UEBwwHUWluZ2RhbzEPMA0GA1UE 7 | CgwGTW9ua2V5MQ8wDQYDVQQLDAZNb25rZXkxDDAKBgNVBAMMA21tcTCCASIwDQYJ 8 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBANs5zhJowlbQlHMgVIc8hUVXCoCu8MmH 9 | Oi+0DMGb3oKvQdjLS/eDI5uZNAhKK6Caz0FMzYvWOzmQEXS56BMW8wB1WWj6Ifb8 10 | N+Hj69wOAU87j89q2i1BX+uaIi4T/VGLGU4V2+qeUm+X27uG2tKLo0siNHsvxM2F 11 | GUpib4QN+Oe6WJB2eO6XrEjRmOThR38YuhSu72hRO/ezfNnilQQYFnVNfyoAmgxu 12 | ZcCyg8xDd0Nt1r4OoRwofhVqtqnTP0WlnHopYOhmohxESf+8DKUbLB27FcgrFUJs 13 | nkWGHjh005dNo0dXnWl6P5lOie8bhF7wsiUBcyw7B3FCAOXPsVDIj78CAwEAAaNT 14 | MFEwHQYDVR0OBBYEFNfgQ7dJ0JGkvvMF4Roi5Qq870hgMB8GA1UdIwQYMBaAFNfg 15 | Q7dJ0JGkvvMF4Roi5Qq870hgMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL 16 | BQADggEBACnWx9DpFhyVXgWhm4/ttXNryo5wUD1AREiuP929V25pva6NfEvmlBoe 17 | J3/KrExIK3c6dIdSaf+fVjHtXf32kROvVOV2BsRcMScJuhRS2e50rkeWjfwlqEU4 18 | ERsNmObjpIMBg9Zn4v0TaByzJ+sS7tDVhPPcAnw+PuF5wJJX2dXOuQJKeFlVIxf5 19 | 75yNggRTot07L3a4S+DDsSEkv0sX4OyDRl7EySNDy6+aq9QgUZNBj57X8PMdZXOq 20 | xc5dOVsoS+55nxqhQ9vF4YC2UKnxi0kNBAjTKipAQvqst8DilBIrS/LX8Dimqo0a 21 | obZtPSgMsMTpQLt+5pRhymh3UKoZ/CI= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /distribution/conf/cert/mmq.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/distribution/conf/cert/mmq.pfx -------------------------------------------------------------------------------- /distribution/conf/cluster.conf.example: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 1999-2018 Monkey Group Holding Ltd. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | #it is ip 18 | #example 19 | 192.168.31.9:7777 20 | 192.168.31.9:8848 21 | 192.168.31.9:8888 22 | -------------------------------------------------------------------------------- /distribution/plugs/README: -------------------------------------------------------------------------------- 1 | 插件位置 -------------------------------------------------------------------------------- /img/Mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/Mysql.png -------------------------------------------------------------------------------- /img/SQL模板.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/SQL模板.png -------------------------------------------------------------------------------- /img/SQL规则.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/SQL规则.png -------------------------------------------------------------------------------- /img/SqlServer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/SqlServer.png -------------------------------------------------------------------------------- /img/kafka.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/kafka.jpg -------------------------------------------------------------------------------- /img/kafka规则.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/kafka规则.png -------------------------------------------------------------------------------- /img/postgresql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/postgresql.png -------------------------------------------------------------------------------- /img/启动配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/启动配置.png -------------------------------------------------------------------------------- /img/客户端管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/客户端管理.png -------------------------------------------------------------------------------- /img/规则引擎.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/规则引擎.png -------------------------------------------------------------------------------- /img/订阅列表.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/订阅列表.png -------------------------------------------------------------------------------- /img/认证鉴权.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/认证鉴权.png -------------------------------------------------------------------------------- /img/认证鉴权配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/认证鉴权配置.png -------------------------------------------------------------------------------- /img/资源管理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/资源管理.png -------------------------------------------------------------------------------- /img/集群监测.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/img/集群监测.png -------------------------------------------------------------------------------- /mmq-api/.flattened-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.monkey.mmq 7 | mmq 8 | 1.1.5 9 | 10 | org.monkey.mmq 11 | mmq-api 12 | 1.1.5 13 | 14 | 15 | Apache License, Version 2.0 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | repo 18 | 19 | 20 | 21 | 22 | junit 23 | junit 24 | 4.12 25 | test 26 | 27 | 28 | org.mockito 29 | mockito-core 30 | 2.23.4 31 | test 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /mmq-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mmq 7 | org.monkey.mmq 8 | ../pom.xml 9 | ${revision} 10 | 11 | 4.0.0 12 | 13 | mmq-api 14 | 15 | 16 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/common/ActionTypes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.common; 18 | 19 | /** 20 | * Resource action type definitions. 21 | * 22 | * @author solley 23 | */ 24 | public enum ActionTypes { 25 | /** 26 | * Read. 27 | */ 28 | READ("r"), 29 | /** 30 | * Write. 31 | */ 32 | WRITE("w"); 33 | 34 | private String action; 35 | 36 | ActionTypes(String action) { 37 | this.action = action; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return action; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/common/AuthSystemTypes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.common; 18 | 19 | /** 20 | * Types of all auth implementations. 21 | * 22 | * @author nkorange 23 | */ 24 | public enum AuthSystemTypes { 25 | 26 | /** 27 | * Mmq builtin auth system. 28 | */ 29 | MMQ, 30 | /** 31 | * LDAP. 32 | */ 33 | LDAP 34 | } 35 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/exception/AccessException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.exception; 18 | 19 | 20 | import org.monkey.mmq.core.exception.MmqException; 21 | 22 | /** 23 | * Exception to be thrown if authorization is failed. 24 | * 25 | * @author solley 26 | */ 27 | public class AccessException extends MmqException { 28 | 29 | private static final long serialVersionUID = -2926344920552803270L; 30 | 31 | public AccessException() { 32 | 33 | } 34 | 35 | public AccessException(int code) { 36 | this.setErrCode(code); 37 | } 38 | 39 | public AccessException(String msg) { 40 | this.setErrMsg(msg); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/parser/DefaultResourceParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.parser; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | 21 | /** 22 | * Default resource parser. 23 | * 24 | * @author solley 25 | */ 26 | public class DefaultResourceParser implements ResourceParser { 27 | 28 | @Override 29 | public String parseName(Object request) { 30 | return StringUtils.EMPTY; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/parser/ResourceParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.parser; 18 | 19 | /** 20 | * Resource parser. 21 | * 22 | * @author solley 23 | */ 24 | public interface ResourceParser { 25 | 26 | /** 27 | * Parse a unique name of the resource from the request. 28 | * 29 | * @param request where we can find the resource info. Given it may vary from Http request to gRPC request, we use a 30 | * Object type for future accommodation. 31 | * @return resource name 32 | */ 33 | String parseName(Object request); 34 | } 35 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/persistent/KeyBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.persistent; 18 | 19 | import org.monkey.mmq.config.matedata.UtilsAndCommons; 20 | 21 | import static org.monkey.mmq.auth.persistent.UtilsAndCommons.AUTH_STORE; 22 | 23 | /** 24 | * Key operations for data. 25 | * 26 | * @author solley 27 | * @since 1.0.0 28 | */ 29 | public class KeyBuilder { 30 | 31 | public static boolean matchAuthKey(String key) { 32 | return key.startsWith(AUTH_STORE); 33 | } 34 | 35 | public static String getAuthKey() { 36 | return AUTH_STORE; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/persistent/UtilsAndCommons.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.persistent; 18 | 19 | 20 | import org.monkey.mmq.core.env.EnvUtil; 21 | 22 | import java.io.File; 23 | 24 | /** 25 | * Naming utils and common values. 26 | * 27 | * @author solley 28 | */ 29 | @SuppressWarnings("PMD.ThreadPoolCreationle") 30 | public class UtilsAndCommons { 31 | 32 | public static final String AUTH_STORE = "00-00---000-AUTH_STORE-000---00-00"; 33 | 34 | public static final String DATA_BASE_DIR = 35 | EnvUtil.getMmqHome() + File.separator + "data" + File.separator + "auth"; 36 | } 37 | -------------------------------------------------------------------------------- /mmq-auth/src/main/java/org/monkey/mmq/auth/utils/Loggers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.auth.utils; 18 | 19 | import ch.qos.logback.classic.Level; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | /** 24 | * Loggers for core. 25 | * 26 | * @author solley 27 | * @since 1.2.0 28 | */ 29 | public class Loggers { 30 | 31 | public static final Logger AUTH = LoggerFactory.getLogger("org.monkey.mmq.auth"); 32 | 33 | 34 | public static void setLogLevel(String logName, String level) { 35 | 36 | switch (logName) { 37 | case "mmq-auth": 38 | ((ch.qos.logback.classic.Logger) AUTH).setLevel(Level.valueOf(level)); 39 | break; 40 | default: 41 | break; 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /mmq-broker/src/main/java/org/monkey/mmq/BrokerApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq; 18 | 19 | 20 | import akka.actor.ActorSystem; 21 | import org.springframework.boot.SpringApplication; 22 | import org.springframework.boot.autoconfigure.SpringBootApplication; 23 | import org.springframework.boot.web.servlet.ServletComponentScan; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.scheduling.annotation.EnableScheduling; 26 | 27 | /** 28 | * 通过SpringBoot启动服务 29 | * @author Solley 30 | */ 31 | @EnableScheduling 32 | @ServletComponentScan 33 | @SpringBootApplication(scanBasePackages = {"org.monkey.mmq"}) 34 | public class BrokerApplication { 35 | 36 | public static void main(String[] args) { 37 | SpringApplication.run(BrokerApplication.class, args); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /mmq-broker/src/main/java/org/monkey/mmq/config/BrokerConfig.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config; 2 | 3 | import akka.actor.ActorSystem; 4 | import akka.event.Logging; 5 | import com.alipay.remoting.rpc.RpcClient; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | /** 10 | * @ClassNameBrokerConfig 11 | * @Description 12 | * @Author Solley 13 | * @Date2022/3/17 0:50 14 | * @Version V1.0 15 | **/ 16 | @Configuration 17 | public class BrokerConfig { 18 | @Bean 19 | public ActorSystem actorSystem() { 20 | ActorSystem actorSystem = ActorSystem.create("mmq"); 21 | actorSystem.eventStream().setLogLevel(Logging.ErrorLevel()); 22 | return actorSystem; 23 | } 24 | 25 | @Bean 26 | public RpcClient rpcClient() { 27 | RpcClient client = new RpcClient(); 28 | client.startup(); 29 | return client; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /mmq-broker/src/main/java/org/monkey/mmq/metrics/MMQMetric.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.metrics; 2 | 3 | import com.codahale.metrics.Gauge; 4 | import com.codahale.metrics.Metric; 5 | 6 | import static com.google.common.base.Preconditions.checkNotNull; 7 | 8 | /** 9 | * @ClassNameMMQMetric 10 | * @Description 11 | * @Author Solley 12 | * @Date2022/5/30 15:14 13 | * @Version V1.0 14 | **/ 15 | public class MMQMetric { 16 | private final String name; 17 | private final Class clazz; 18 | 19 | private MMQMetric(final String name, final Class clazz) { 20 | this.name = name; 21 | this.clazz = clazz; 22 | } 23 | 24 | public static MMQMetric valueOf(final String name, final Class metricClass) { 25 | checkNotNull(name, "Name cannot be null"); 26 | 27 | return new MMQMetric<>(name, metricClass); 28 | } 29 | 30 | public static MMQMetric> gaugeValue(final String name) { 31 | checkNotNull(name, "Name cannot be null"); 32 | 33 | return new MMQMetric<>(name, Gauge.class); 34 | } 35 | 36 | public String name() { 37 | return name; 38 | } 39 | 40 | public Class getClazz() { 41 | return clazz; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /mmq-broker/src/main/java/org/monkey/mmq/protocol/RejectHandler.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.protocol; 2 | 3 | import java.util.concurrent.RejectedExecutionException; 4 | import java.util.concurrent.RejectedExecutionHandler; 5 | import java.util.concurrent.ThreadPoolExecutor; 6 | 7 | public class RejectHandler implements RejectedExecutionHandler { 8 | private String task; 9 | private int maxBlockQueueSize; 10 | 11 | public RejectHandler(String task,int maxBlockQueueSize){ 12 | this.task = task; 13 | this.maxBlockQueueSize = maxBlockQueueSize; 14 | }; 15 | 16 | @Override 17 | public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { 18 | throw new RejectedExecutionException("Task:" + task + ",maxBlockQueueSize:" + maxBlockQueueSize 19 | + ",Thread:" + r.toString()); 20 | } 21 | } -------------------------------------------------------------------------------- /mmq-broker/src/main/java/org/monkey/mmq/protocol/RequestProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.protocol; 17 | 18 | import io.netty.channel.ChannelHandlerContext; 19 | import io.netty.handler.codec.mqtt.MqttMessage; 20 | 21 | /** 22 | * @author solley 23 | */ 24 | public interface RequestProcessor { 25 | void processRequest(ChannelHandlerContext ctx, MqttMessage mqttMessage); 26 | } 27 | -------------------------------------------------------------------------------- /mmq-broker/src/main/java/org/monkey/mmq/protocol/ThreadFactoryImpl.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.protocol; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | public class ThreadFactoryImpl implements ThreadFactory { 7 | 8 | private AtomicInteger counter = new AtomicInteger(0); 9 | private String threadName; 10 | 11 | public ThreadFactoryImpl(String threadName){ 12 | this.threadName = threadName; 13 | } 14 | 15 | @Override 16 | public Thread newThread(Runnable r) { 17 | return new Thread(r,threadName + "_" + this.counter.incrementAndGet()); 18 | } 19 | } -------------------------------------------------------------------------------- /mmq-broker/src/main/resources/cert/mmq.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDozCCAougAwIBAgIUUJo/Ll3YJtLB6UDKoZ9H3k1BAQYwDQYJKoZIhvcNAQEL 3 | BQAwYTELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB1FpbmdkYW8xEDAOBgNVBAcMB1Fp 4 | bmdkYW8xDzANBgNVBAoMBk1vbmtleTEPMA0GA1UECwwGTW9ua2V5MQwwCgYDVQQD 5 | DANtbXEwHhcNMjExMjE0MTUyODQyWhcNMjIxMjE0MTUyODQyWjBhMQswCQYDVQQG 6 | EwJDTjEQMA4GA1UECAwHUWluZ2RhbzEQMA4GA1UEBwwHUWluZ2RhbzEPMA0GA1UE 7 | CgwGTW9ua2V5MQ8wDQYDVQQLDAZNb25rZXkxDDAKBgNVBAMMA21tcTCCASIwDQYJ 8 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBANs5zhJowlbQlHMgVIc8hUVXCoCu8MmH 9 | Oi+0DMGb3oKvQdjLS/eDI5uZNAhKK6Caz0FMzYvWOzmQEXS56BMW8wB1WWj6Ifb8 10 | N+Hj69wOAU87j89q2i1BX+uaIi4T/VGLGU4V2+qeUm+X27uG2tKLo0siNHsvxM2F 11 | GUpib4QN+Oe6WJB2eO6XrEjRmOThR38YuhSu72hRO/ezfNnilQQYFnVNfyoAmgxu 12 | ZcCyg8xDd0Nt1r4OoRwofhVqtqnTP0WlnHopYOhmohxESf+8DKUbLB27FcgrFUJs 13 | nkWGHjh005dNo0dXnWl6P5lOie8bhF7wsiUBcyw7B3FCAOXPsVDIj78CAwEAAaNT 14 | MFEwHQYDVR0OBBYEFNfgQ7dJ0JGkvvMF4Roi5Qq870hgMB8GA1UdIwQYMBaAFNfg 15 | Q7dJ0JGkvvMF4Roi5Qq870hgMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL 16 | BQADggEBACnWx9DpFhyVXgWhm4/ttXNryo5wUD1AREiuP929V25pva6NfEvmlBoe 17 | J3/KrExIK3c6dIdSaf+fVjHtXf32kROvVOV2BsRcMScJuhRS2e50rkeWjfwlqEU4 18 | ERsNmObjpIMBg9Zn4v0TaByzJ+sS7tDVhPPcAnw+PuF5wJJX2dXOuQJKeFlVIxf5 19 | 75yNggRTot07L3a4S+DDsSEkv0sX4OyDRl7EySNDy6+aq9QgUZNBj57X8PMdZXOq 20 | xc5dOVsoS+55nxqhQ9vF4YC2UKnxi0kNBAjTKipAQvqst8DilBIrS/LX8Dimqo0a 21 | obZtPSgMsMTpQLt+5pRhymh3UKoZ/CI= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /mmq-broker/src/main/resources/cert/mmq.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/mmq-broker/src/main/resources/cert/mmq.pfx -------------------------------------------------------------------------------- /mmq-broker/src/main/resources/mmq-version.txt: -------------------------------------------------------------------------------- 1 | version=${project.version} 2 | -------------------------------------------------------------------------------- /mmq-broker/src/test/java/org/monkey/mmq/config/driver/InfluxDB1XDriverTest.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.driver; 2 | 3 | import org.junit.Test; 4 | import org.stringtemplate.v4.ST; 5 | 6 | import java.util.*; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | public class InfluxDB1XDriverTest { 11 | @Test 12 | public void testStringTemplate() { 13 | Map map = new HashMap<>(); 14 | map.put("device", "hhh"); 15 | 16 | Map map1 = new HashMap<>(); 17 | map1.put("name", "flow"); 18 | map1.put("value", 441); 19 | Map map2 = new HashMap<>(); 20 | map2.put("name", "flow"); 21 | map2.put("value", 441); 22 | List mapList = new ArrayList<>(); 23 | mapList.add(map1); 24 | mapList.add(map2); 25 | map.put("list", mapList); 26 | ST hello = 27 | new ST( 28 | "[, name: \\},fields: { value: \\}\\}}; separator=\",\">]"); 29 | hello.add("json", map); 30 | System.out.println(hello.render()); 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /mmq-broker/src/test/java/org/monkey/mmq/config/driver/KafkaDriverTest.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.driver; 2 | 3 | import io.netty.handler.codec.string.StringEncoder; 4 | import org.apache.kafka.clients.producer.*; 5 | import org.apache.kafka.common.serialization.StringSerializer; 6 | import org.junit.Test; 7 | 8 | import java.util.Properties; 9 | import java.util.concurrent.Future; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * @ClassNameKafkaDriverTest 15 | * @Description 16 | * @Author Solley 17 | * @Date2021/10/10 14:46 18 | * @Version V1.0 19 | **/ 20 | public class KafkaDriverTest { 21 | @Test 22 | public void testKafka() throws InterruptedException { 23 | Properties prop = new Properties(); 24 | prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "10.154.20.191:9093,10.154.20.192:9093,10.154.20.193:9093"); 25 | prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); 26 | prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); 27 | Producer producer = new KafkaProducer<>(prop); 28 | int i = 0; 29 | for (i = 0; i < 100; i++) { 30 | Future recordMetadataFuture = producer.send(new ProducerRecord("test", "msg:" + i++)); 31 | Thread.sleep(1000); 32 | } 33 | 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.config; 17 | 18 | import org.springframework.boot.SpringApplication; 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | import org.springframework.boot.web.servlet.ServletComponentScan; 21 | 22 | /** 23 | * Health Controller. 24 | * 25 | * @author solley 26 | */ 27 | @SpringBootApplication(scanBasePackages = "org.monkey.mmq.config") 28 | @ServletComponentScan 29 | public class Config { 30 | public static void main(String[] args) { 31 | SpringApplication.run(Config.class, args); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/config/Loggers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.config.config; 18 | 19 | import ch.qos.logback.classic.Level; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | /** 24 | * Loggers for core. 25 | * 26 | * @author solley 27 | * @since 1.2.0 28 | */ 29 | public class Loggers { 30 | 31 | public static final Logger CONFIG_SERVER = LoggerFactory.getLogger("org.monkey.mmq.config"); 32 | 33 | public static void setLogLevel(String logName, String level) { 34 | 35 | switch (logName) { 36 | case "broker-config": 37 | ((ch.qos.logback.classic.Logger) CONFIG_SERVER).setLevel(Level.valueOf(level)); 38 | break; 39 | default: 40 | break; 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/driver/ResourceDriver.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.driver; 2 | 3 | import org.monkey.mmq.config.matedata.ResourcesMateData; 4 | import org.monkey.mmq.core.exception.MmqException; 5 | 6 | import java.util.Map; 7 | 8 | public interface ResourceDriver { 9 | 10 | void addDriver(String resourceId, Map resource); 11 | 12 | void deleteDriver(String resourceId); 13 | 14 | T getDriver(String resourceId) throws Exception; 15 | 16 | boolean testConnect(ResourcesMateData resourcesMateData); 17 | 18 | void handle(Map property, ResourcesMateData resourcesMateData, 19 | String topic, int qos, String address, String username) throws MmqException; 20 | } 21 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/matedata/DriverMessage.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.matedata; 2 | 3 | import org.monkey.mmq.core.actor.ActorMsg; 4 | import org.monkey.mmq.core.actor.MsgType; 5 | 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * @ClassNameDriverEvent 11 | * @Description 12 | * @Author Solley 13 | * @Date2021/12/16 15:13 14 | * @Version V1.0 15 | **/ 16 | public class DriverMessage implements ActorMsg { 17 | 18 | public RuleEngineMessage ruleEngineMessage; 19 | 20 | public ResourcesMateData resourcesMateData; 21 | 22 | Map property; 23 | 24 | public RuleEngineMessage getRuleEngineMessage() { 25 | return ruleEngineMessage; 26 | } 27 | 28 | public void setRuleEngineMessage(RuleEngineMessage ruleEngineMessage) { 29 | this.ruleEngineMessage = ruleEngineMessage; 30 | } 31 | 32 | public ResourcesMateData getResourcesMateData() { 33 | return resourcesMateData; 34 | } 35 | 36 | public void setResourcesMateData(ResourcesMateData resourcesMateData) { 37 | this.resourcesMateData = resourcesMateData; 38 | } 39 | 40 | public Map getProperty() { 41 | return property; 42 | } 43 | 44 | public void setProperty(Map property) { 45 | this.property = property; 46 | } 47 | 48 | @Override 49 | public MsgType getMsgType() { 50 | return MsgType.DRIVER_BRIDGE; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/matedata/ModelEnum.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.matedata; 2 | 3 | /** 4 | * @ClassNameModelEnum 5 | * @Description 6 | * @Author Solley 7 | * @Date2022/1/13 21:23 8 | * @Version V1.0 9 | **/ 10 | public enum ModelEnum { 11 | AUTH(org.monkey.mmq.config.modules.auth.AuthModule.class), 12 | API(org.monkey.mmq.config.modules.api.ApiModule.class), 13 | ACL(org.monkey.mmq.config.modules.acl.AclModule.class); 14 | 15 | private Class name; 16 | 17 | public Class getName() { 18 | return name; 19 | } 20 | 21 | ModelEnum(Class name) { 22 | this.name = name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/matedata/ResourceEnum.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.matedata; 2 | 3 | public enum ResourceEnum { 4 | MYSQL(org.monkey.mmq.config.driver.MysqlDriver.class), 5 | KAFKA(org.monkey.mmq.config.driver.KafkaDriver.class), 6 | SQLSERVER(org.monkey.mmq.config.driver.SqlServerDriver.class), 7 | POSTGRESQL(org.monkey.mmq.config.driver.PostgresqlDriver.class), 8 | MQTT_BROKER(org.monkey.mmq.config.driver.MQTTDriver.class), 9 | TDENGINE(org.monkey.mmq.config.driver.TDengineDriver.class), 10 | INFLUXDB(org.monkey.mmq.config.driver.InfluxDBDriver.class), 11 | INFLUX1XDB(org.monkey.mmq.config.driver.InfluxDB1XDriver.class), 12 | RABBITMQ(org.monkey.mmq.config.driver.RabbitMQDriver.class),; 13 | 14 | private Class name; 15 | 16 | public Class getName() { 17 | return name; 18 | } 19 | 20 | ResourceEnum(Class name) { 21 | this.name = name; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/matedata/UpdateRuleEngineMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.config.matedata; 17 | 18 | import org.monkey.mmq.core.actor.ActorMsg; 19 | import org.monkey.mmq.core.actor.MsgType; 20 | import org.monkey.mmq.core.entity.InternalMessage; 21 | 22 | /** 23 | * @author solley 24 | */ 25 | public class UpdateRuleEngineMessage implements ActorMsg { 26 | 27 | 28 | RuleEngineMateData ruleEngineMateData; 29 | 30 | public RuleEngineMateData getRuleEngineMateData() { 31 | return ruleEngineMateData; 32 | } 33 | 34 | public void setRuleEngineMateData(RuleEngineMateData ruleEngineMateData) { 35 | this.ruleEngineMateData = ruleEngineMateData; 36 | } 37 | 38 | @Override 39 | public MsgType getMsgType() { 40 | return MsgType.UPDATE_RULE_ENGINE; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/matedata/UtilsAndCommons.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.config.matedata; 18 | 19 | 20 | import org.monkey.mmq.core.env.EnvUtil; 21 | 22 | import java.io.File; 23 | 24 | /** 25 | * Naming utils and common values. 26 | * 27 | * @author solley 28 | */ 29 | @SuppressWarnings("PMD.ThreadPoolCreationle") 30 | public class UtilsAndCommons { 31 | 32 | public static final String RESOURCES_STORE = "00-00---000-RESOURCES_STORE-000---00-00"; 33 | 34 | public static final String RULE_ENGINE_STORE = "00-00---000-RULE_ENGINE_STORE-000---00-00"; 35 | 36 | public static final String MODULES_STORE = "00-00---000-MODULES_STORE-000---00-00"; 37 | 38 | public static final String DATA_BASE_DIR = 39 | EnvUtil.getMmqHome() + File.separator + "data" + File.separator + "config"; 40 | } 41 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/modules/BaseModule.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.modules; 2 | 3 | import org.monkey.mmq.core.utils.StringUtils; 4 | 5 | /** 6 | * @ClassNameBaseModule 7 | * @Description 8 | * @Author Solley 9 | * @Date2022/1/18 23:00 10 | * @Version V1.0 11 | **/ 12 | public abstract class BaseModule implements IModule { 13 | 14 | protected ModelMateData modelMateData; 15 | 16 | @Override 17 | public void update(ModelMateData modelMateData) { 18 | if (modelMateData == null) return; 19 | if (StringUtils.isEmpty(modelMateData.getDescription())) return; 20 | if (StringUtils.isEmpty(modelMateData.getIcon())) return; 21 | if (StringUtils.isEmpty(modelMateData.getModuleName())) return; 22 | this.modelMateData = modelMateData; 23 | } 24 | 25 | @Override 26 | public ModelMateData getConfig() { 27 | return this.modelMateData; 28 | } 29 | 30 | @Override 31 | public boolean getEnable() { 32 | return this.modelMateData.getEnable(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/modules/IModule.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.modules; 2 | 3 | import org.monkey.mmq.core.exception.MmqException; 4 | 5 | /** 6 | * @ClassNameIModule 7 | * @Description 8 | * @Author Solley 9 | * @Date2022/1/13 20:48 10 | * @Version V1.0 11 | **/ 12 | public interface IModule { 13 | 14 | void update(ModelMateData config); 15 | 16 | boolean handle(Param param) throws MmqException; 17 | 18 | ModelMateData getConfig(); 19 | 20 | boolean getEnable(); 21 | } 22 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/modules/ModuleFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.config.modules; 17 | 18 | import org.monkey.mmq.config.matedata.ModelEnum; 19 | import org.monkey.mmq.core.utils.ApplicationUtils; 20 | 21 | /** 22 | * @author solley 23 | */ 24 | public class ModuleFactory { 25 | public static IModule getResourceDriverByEnum(ModelEnum modelEnum) { 26 | return (IModule) ApplicationUtils.getBean(modelEnum.getName()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/modules/api/ApiParam.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.modules.api; 2 | 3 | /** 4 | * @ClassNameApiParam 5 | * @Description 6 | * @Author Solley 7 | * @Date2022/1/18 22:54 8 | * @Version V1.0 9 | **/ 10 | public class ApiParam { 11 | 12 | private String appId; 13 | 14 | private String appSecret; 15 | 16 | public String getAppId() { 17 | return appId; 18 | } 19 | 20 | public void setAppId(String appId) { 21 | this.appId = appId; 22 | } 23 | 24 | public String getAppSecret() { 25 | return appSecret; 26 | } 27 | 28 | public void setAppSecret(String appSecret) { 29 | this.appSecret = appSecret; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /mmq-config/src/main/java/org/monkey/mmq/config/modules/auth/AuthParam.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.config.modules.auth; 2 | 3 | /** 4 | * @ClassNameAuthParam 5 | * @Description 6 | * @Author Solley 7 | * @Date2022/1/13 20:53 8 | * @Version V1.0 9 | **/ 10 | public class AuthParam { 11 | private String username; 12 | private String password; 13 | 14 | public String getUsername() { 15 | return username; 16 | } 17 | 18 | public void setUsername(String username) { 19 | this.username = username; 20 | } 21 | 22 | public String getPassword() { 23 | return password; 24 | } 25 | 26 | public void setPassword(String password) { 27 | this.password = password; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/actor/ActorMsg.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.actor; 2 | 3 | /** 4 | * @ClassNameActorMsg 5 | * @Description 6 | * @Author Solley 7 | * @Date2022/3/16 22:12 8 | * @Version V1.0 9 | **/ 10 | public interface ActorMsg { 11 | MsgType getMsgType(); 12 | } 13 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/actor/StopMessage.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.actor; 2 | 3 | /** 4 | * @ClassName:StopMessage 5 | * @Auther: Solley 6 | * @Description: 停止消息 7 | * @Date: 2022/7/21 08:30 8 | * @Version: v1.0 9 | */ 10 | 11 | public class StopMessage implements ActorMsg { 12 | @Override 13 | public MsgType getMsgType() { 14 | return MsgType.STOP; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/actor/message/ClientPutMessage.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.actor.message; 2 | 3 | import org.monkey.mmq.core.actor.ActorMsg; 4 | import org.monkey.mmq.core.actor.MsgType; 5 | import org.monkey.mmq.core.actor.metadata.message.ClientMateData; 6 | 7 | /** 8 | * @ClassNameClientEvent 9 | * @Description 10 | * @Author Solley 11 | * @Date2021/12/15 21:48 12 | * @Version V1.0 13 | **/ 14 | public class ClientPutMessage implements ActorMsg { 15 | 16 | public ClientMateData clientMateData; 17 | 18 | public ClientMateData getClientMateData() { 19 | return clientMateData; 20 | } 21 | 22 | public void setClientMateData(ClientMateData clientMateData) { 23 | this.clientMateData = clientMateData; 24 | } 25 | 26 | @Override 27 | public MsgType getMsgType() { 28 | return MsgType.CLIENT_PUT; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/actor/message/ClientRemoveMessage.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.actor.message; 2 | 3 | 4 | import org.monkey.mmq.core.actor.ActorMsg; 5 | import org.monkey.mmq.core.actor.MsgType; 6 | import org.monkey.mmq.core.actor.metadata.message.ClientMateData; 7 | 8 | /** 9 | * @ClassNameClientEvent 10 | * @Description 11 | * @Author Solley 12 | * @Date2021/12/15 21:48 13 | * @Version V1.0 14 | **/ 15 | public class ClientRemoveMessage implements ActorMsg { 16 | 17 | public ClientMateData clientMateData; 18 | 19 | public ClientMateData getClientMateData() { 20 | return clientMateData; 21 | } 22 | 23 | public void setClientMateData(ClientMateData clientMateData) { 24 | this.clientMateData = clientMateData; 25 | } 26 | 27 | @Override 28 | public MsgType getMsgType() { 29 | return MsgType.CLIENT_REMOVE; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/actor/metadata/message/PublishInOutType.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.actor.metadata.message; 2 | 3 | /** 4 | * @ClassNamePublishInOutType 5 | * @Description 6 | * @Author Solley 7 | * @Date2022/5/30 16:50 8 | * @Version V1.0 9 | **/ 10 | public enum PublishInOutType { 11 | IN, 12 | OUT 13 | } 14 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/common/Commons.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.common; 18 | 19 | /** 20 | * Constants. 21 | * 22 | * @author solley 23 | */ 24 | public final class Commons { 25 | 26 | public static final String MMQ_SERVER_CONTEXT = "/mmq"; 27 | 28 | public static final String MMQ_SERVER_VERSION = "/v1"; 29 | 30 | public static final String DEFAULT_MMQ_CORE_CONTEXT = MMQ_SERVER_VERSION + "/core"; 31 | 32 | public static final String MMQ_CORE_CONTEXT = DEFAULT_MMQ_CORE_CONTEXT; 33 | } 34 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/CommandOperations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.consistency; 18 | 19 | import org.monkey.mmq.core.consistency.model.RestResult; 20 | import org.monkey.mmq.core.consistency.model.RestResultUtils; 21 | 22 | import java.util.Map; 23 | 24 | /** 25 | * Operation and maintenance command interface. 26 | * 27 | * @author solley 28 | */ 29 | public interface CommandOperations { 30 | 31 | /** 32 | * Operation and maintenance interface operation entry. 33 | * 34 | * @param commands commands 35 | * @return execute success 36 | */ 37 | default RestResult execute(Map commands) { 38 | return RestResultUtils.success(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/DataOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.core.consistency; 17 | 18 | /** 19 | * Apply action. 20 | * 21 | * @author solley 22 | */ 23 | public enum DataOperation { 24 | /** 25 | * Data add. 26 | */ 27 | ADD, 28 | /** 29 | * Data changed. 30 | */ 31 | CHANGE, 32 | /** 33 | * Data deleted. 34 | */ 35 | DELETE, 36 | /** 37 | * Data verify. 38 | */ 39 | VERIFY, 40 | /** 41 | * Data Snapshot. 42 | */ 43 | SNAPSHOT, 44 | /** 45 | * Data Notify. 46 | */ 47 | NOTIFY, 48 | /** 49 | * Data query. 50 | */ 51 | QUERY; 52 | } 53 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/ap/APProtocol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.consistency.ap; 18 | 19 | import org.monkey.mmq.core.consistency.Config; 20 | import org.monkey.mmq.core.consistency.ConsistencyProtocol; 21 | 22 | /** 23 | * ap protocol. 24 | * 25 | * @author solley 26 | */ 27 | @SuppressWarnings("all") 28 | public interface APProtocol extends ConsistencyProtocol { 29 | 30 | } 31 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/ap/RequestProcessor4AP.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.consistency.ap; 18 | 19 | 20 | import org.monkey.mmq.core.consistency.RequestProcessor; 21 | 22 | /** 23 | * log processor for ap. 24 | * 25 | * @author solley 26 | */ 27 | @SuppressWarnings("all") 28 | public abstract class RequestProcessor4AP extends RequestProcessor { 29 | 30 | } 31 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/cp/CPProtocol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.consistency.cp; 18 | 19 | import org.monkey.mmq.core.consistency.Config; 20 | import org.monkey.mmq.core.consistency.ConsistencyProtocol; 21 | 22 | /** 23 | * cp protocol. 24 | * 25 | * @author solley 26 | */ 27 | @SuppressWarnings("all") 28 | public interface CPProtocol extends ConsistencyProtocol { 29 | 30 | /** 31 | * Returns whether this node is a leader node 32 | * 33 | * @param group business module info 34 | * @return is leader 35 | */ 36 | boolean isLeader(String group); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/cp/MetadataKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.consistency.cp; 18 | 19 | /** 20 | * Key value of metadata information of CP protocol. 21 | * 22 | * @author solley 23 | */ 24 | public class MetadataKey { 25 | 26 | public static final String LEADER_META_DATA = "leader"; 27 | 28 | public static final String TERM_META_DATA = "term"; 29 | 30 | public static final String RAFT_GROUP_MEMBER = "raftGroupMember"; 31 | 32 | public static final String ERR_MSG = "errMsg"; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/matedata/Record.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.consistency.matedata; 18 | 19 | import java.io.Serializable; 20 | 21 | /** 22 | * Record to transfer and store in MMQ cluster. 23 | * 24 | * @author solley 25 | * @since 1.0.0 26 | */ 27 | public interface Record extends Serializable { 28 | 29 | } 30 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/model/IResultCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.consistency.model; 18 | 19 | /** 20 | * IResultCode. 21 | * 22 | * @author klw 23 | * @ClassName: IResultCode 24 | * @Description: result code enum needs to be implemented this interface 25 | * @date 2019/6/28 14:44 26 | */ 27 | @Deprecated 28 | public interface IResultCode { 29 | 30 | /** 31 | * Get the result code. 32 | * 33 | * @return code value. 34 | */ 35 | int getCode(); 36 | 37 | /** 38 | * Get the result code's message. 39 | * 40 | * @return code's message. 41 | */ 42 | String getCodeMsg(); 43 | } 44 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/consistency/persistent/PersistentConsistencyService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.core.consistency.persistent; 17 | 18 | /** 19 | * A consistency service that guarantee CP consistency for the published data. 20 | * 21 | *

CP consistency is hereby defined as follows: 22 | * 23 | *

Once the writing operation returned client a success, the data within the operation is guaranteed to be 24 | * successfully written to the cluster. And the data should be consistent between servers after some time without any 25 | * outside interfere. 26 | * 27 | * @author solley 28 | */ 29 | public interface PersistentConsistencyService extends ConsistencyService { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/distributed/id/IdGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.distributed.id; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * Id generator. 23 | * 24 | * @author solley 25 | */ 26 | public interface IdGenerator { 27 | 28 | /** 29 | * Perform the corresponding initialization operation. 30 | */ 31 | void init(); 32 | 33 | /** 34 | * current id info. 35 | * 36 | * @return current id 37 | */ 38 | long currentId(); 39 | 40 | /** 41 | * Get next id. 42 | * 43 | * @return next id 44 | */ 45 | long nextId(); 46 | 47 | /** 48 | * Returns information for the current IDGenerator. 49 | * 50 | * @return {@link Map} 51 | */ 52 | Map info(); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/distributed/raft/RaftErrorEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.distributed.raft; 18 | 19 | 20 | import org.monkey.mmq.core.notify.Event; 21 | 22 | /** 23 | * The RAFT protocol runs an exception event. If this event is published, it means that the current raft Group cannot 24 | * continue to run normally 25 | * 26 | * @author solley 27 | */ 28 | public class RaftErrorEvent extends Event { 29 | 30 | private static final long serialVersionUID = 3016514657754158167L; 31 | 32 | private String groupName; 33 | 34 | public String getGroupName() { 35 | return groupName; 36 | } 37 | 38 | public void setGroupName(String groupName) { 39 | this.groupName = groupName; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/distributed/raft/exception/DuplicateRaftGroupException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.distributed.raft.exception; 18 | 19 | /** 20 | * Duplicate groupId when creating Raft Group throws this exception. 21 | * 22 | * @author solley 23 | */ 24 | public class DuplicateRaftGroupException extends RuntimeException { 25 | 26 | private static final long serialVersionUID = -6276695537457486790L; 27 | 28 | public DuplicateRaftGroupException(String group) { 29 | super("The Raft Group [" + group + "] is already used"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/distributed/raft/utils/FailoverClosure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.distributed.raft.utils; 18 | 19 | import com.alipay.sofa.jraft.Closure; 20 | import org.monkey.mmq.core.entity.Response; 21 | 22 | /** 23 | * Failure callback based on Closure. 24 | * 25 | * @author solley 26 | */ 27 | public interface FailoverClosure extends Closure { 28 | 29 | /** 30 | * Set the return interface if needed. 31 | * 32 | * @param response {@link Response} data 33 | */ 34 | void setResponse(Response response); 35 | 36 | /** 37 | * Catch exception. 38 | * 39 | * @param throwable {@link Throwable} 40 | */ 41 | void setThrowable(Throwable throwable); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/distributed/raft/utils/JRaftLogOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.distributed.raft.utils; 18 | 19 | /** 20 | * JRaft for additional information on logging operations. 21 | * 22 | * @author solley 23 | */ 24 | @SuppressWarnings("PMD.ClassNamingShouldBeCamelRule") 25 | public class JRaftLogOperation { 26 | 27 | public static final String MODIFY_OPERATION = "modify"; 28 | 29 | public static final String READ_OPERATION = "read"; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/exception/ServiceLoaderException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.exception; 18 | 19 | /** 20 | * MMQ service loader exception. 21 | * 22 | * @author xiweng.yy 23 | */ 24 | public class ServiceLoaderException extends RuntimeException { 25 | 26 | private static final long serialVersionUID = -4133484884875183141L; 27 | 28 | private final Class clazz; 29 | 30 | public ServiceLoaderException(Class clazz, Exception caused) { 31 | super(String.format("Can not load class `%s` by SPI ", clazz.getName()), caused); 32 | this.clazz = clazz; 33 | } 34 | 35 | public Class getClazz() { 36 | return clazz; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/lifecycle/Closeable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.lifecycle; 18 | 19 | import org.monkey.mmq.core.exception.MmqException; 20 | 21 | /** 22 | * An interface is used to define the resource's close and shutdown, such as IO Connection and ThreadPool. 23 | * 24 | * @author solley 25 | */ 26 | public interface Closeable { 27 | 28 | /** 29 | * Shutdown the Resources, such as Thread Pool. 30 | * 31 | * @throws MmqException exception. 32 | */ 33 | void shutdown() throws MmqException; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/notify/EventPublisherFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.notify; 18 | 19 | 20 | import org.monkey.mmq.core.utils.BiFunction; 21 | 22 | /** 23 | * Event publisher factory. 24 | * 25 | * @author solley 26 | */ 27 | public interface EventPublisherFactory extends BiFunction, Integer, EventPublisher> { 28 | 29 | /** 30 | * Build an new {@link EventPublisher}. 31 | * 32 | * @param eventType eventType for {@link EventPublisher} 33 | * @param maxQueueSize max queue size for {@link EventPublisher} 34 | * @return new {@link EventPublisher} 35 | */ 36 | @Override 37 | EventPublisher apply(Class eventType, Integer maxQueueSize); 38 | } 39 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/notify/SlowEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package org.monkey.mmq.core.notify; 19 | 20 | /** 21 | * This event share one event-queue. 22 | * 23 | * @author solley 24 | */ 25 | @SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule") 26 | public abstract class SlowEvent extends Event { 27 | 28 | @Override 29 | public long sequence() { 30 | return 0; 31 | } 32 | } -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/tls/FileChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.core.tls; 17 | 18 | /** 19 | * 20 | * @author solley 21 | */ 22 | public interface FileChangeListener { 23 | 24 | /** 25 | * listener onChanged event. 26 | * 27 | * @param filePath Path of changed file 28 | */ 29 | void onChanged(String filePath); 30 | } -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/BiFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.utils; 18 | 19 | /** 20 | * Represents a function that accepts two arguments and produces a result. The following utility functions are extracted 21 | * from org.apache.commons.lang3. 22 | * 23 | *

This is a functional interface 24 | * whose functional method is {@link #apply(Object, Object)}. 25 | * 26 | * @author solley 27 | */ 28 | public interface BiFunction { 29 | 30 | /** 31 | * Applies this function to the two given arguments. 32 | * 33 | * @param t the first function argument 34 | * @param u the second function argument 35 | * @return the function result 36 | */ 37 | R apply(T t, U u); 38 | } 39 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.utils; 2 | 3 | import java.io.File; 4 | import java.lang.reflect.Method; 5 | import java.net.URL; 6 | import java.net.URLClassLoader; 7 | 8 | /** 9 | * @ClassName:ClassUtil 10 | * @Auther: Solley 11 | * @Description: 12 | * @Date: 2022/8/4 13:16 13 | * @Version: v1.0 14 | */ 15 | 16 | public class ClassUtil { 17 | public static void loadJar(String jarPath) { 18 | File jarFile = new File(jarPath); 19 | // 从URLClassLoader类中获取类所在文件夹的方法,jar也可以认为是一个文件夹 20 | Method method = null; 21 | try { 22 | method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); 23 | } catch (NoSuchMethodException | SecurityException e) { 24 | Loggers.CORE.info("load class error ", e); 25 | } 26 | //获取方法的访问权限以便写回 27 | boolean accessible = method.isAccessible(); 28 | try { 29 | method.setAccessible(true); 30 | // 获取系统类加载器 31 | URLClassLoader classLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); 32 | URL url = jarFile.toURI().toURL(); 33 | method.invoke(classLoader, url); 34 | } catch (Exception e) { 35 | Loggers.CORE.info("load class error ", e); 36 | } finally { 37 | method.setAccessible(accessible); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/GenericType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.utils; 18 | 19 | import com.google.common.reflect.TypeToken; 20 | 21 | /** 22 | * Encapsulates third party tools for generics acquisition. 23 | * 24 | * @author solley 25 | */ 26 | public class GenericType extends TypeToken { 27 | 28 | private static final long serialVersionUID = -2103808581228167629L; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/NumberUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.utils; 18 | 19 | /** 20 | * MMQ number util. 21 | * 22 | * @author solley 23 | */ 24 | public class NumberUtil { 25 | 26 | /** 27 | * Whether all chars of input string is digit. 28 | * 29 | * @param input {@code String} checked 30 | * @return {@code true} if all chars is digit, otherwise false 31 | */ 32 | public static boolean isDigits(String input) { 33 | if (StringUtils.isEmpty(input)) { 34 | return false; 35 | } 36 | for (int i = 0; i < input.length(); i++) { 37 | if (!Character.isDigit(input.charAt(i))) { 38 | return false; 39 | } 40 | } 41 | return true; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/Observer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.utils; 18 | 19 | /** 20 | * Obeserver. 21 | * 22 | * @author solley 23 | */ 24 | public interface Observer { 25 | 26 | /** 27 | * This method is called whenever the observed object is changed. An application calls an {@code Observable} 28 | * object's {@code notifyObservers} method to have all the object's observers notified of the change. 29 | * 30 | * @param o the observable object. 31 | */ 32 | void update(Observable o); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/PasswordEncoderUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2018 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.core.utils; 18 | 19 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 20 | 21 | /** 22 | * Password encoder tool. 23 | * 24 | * @author solley 25 | */ 26 | public class PasswordEncoderUtil { 27 | 28 | public static Boolean matches(String raw, String encoded) { 29 | return new BCryptPasswordEncoder().matches(raw, encoded); 30 | } 31 | 32 | public static String encode(String raw) { 33 | return new BCryptPasswordEncoder().encode(raw); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/PwdUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020, Solley (hkk@yanboo.com.cn) All rights reserved. 3 | */ 4 | 5 | package org.monkey.mmq.core.utils; 6 | 7 | import cn.hutool.core.io.IoUtil; 8 | import cn.hutool.crypto.asymmetric.KeyType; 9 | import cn.hutool.crypto.asymmetric.RSA; 10 | 11 | import java.io.IOException; 12 | import java.security.interfaces.RSAPrivateKey; 13 | import java.util.Scanner; 14 | 15 | /** 16 | * 密码 17 | * @author Solley 18 | */ 19 | public class PwdUtil { 20 | 21 | /** 22 | * 通过用户名和私钥生成密码 23 | */ 24 | public static void main(String[] args) throws IOException { 25 | System.out.println(); 26 | System.out.print("输入需要获取密码的用户名: "); 27 | Scanner scanner = new Scanner(System.in); 28 | String value = scanner.nextLine(); 29 | RSAPrivateKey privateKey = IoUtil.readObj(PwdUtil.class.getClassLoader().getResourceAsStream("keystore/auth-private.key")); 30 | RSA rsa = new RSA(privateKey, null); 31 | System.out.println("用户名: " + value + " 对应生成的密码为: " + rsa.encryptBcd(value, KeyType.PrivateKey)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /mmq-core/src/main/java/org/monkey/mmq/core/utils/RsaKeyUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020, Solley (hkk@yanboo.com.cn) All rights reserved. 3 | */ 4 | 5 | package org.monkey.mmq.core.utils; 6 | 7 | import cn.hutool.core.io.FileUtil; 8 | import cn.hutool.core.io.IoUtil; 9 | import cn.hutool.crypto.SecureUtil; 10 | 11 | import java.security.KeyPair; 12 | import java.security.interfaces.RSAPrivateKey; 13 | import java.time.LocalDateTime; 14 | import java.util.Scanner; 15 | 16 | /** 17 | * 私钥 18 | * @author Solley 19 | */ 20 | public class RsaKeyUtil { 21 | 22 | /** 23 | * 生成私钥文件 24 | */ 25 | public static void main(String[] args) { 26 | System.out.println(); 27 | System.out.print("输入保存密钥文件的路径(如: D:/keystore/ ): "); 28 | Scanner scanner = new Scanner(System.in); 29 | String path = scanner.nextLine(); 30 | KeyPair keyPair = SecureUtil.generateKeyPair("RSA", 512, LocalDateTime.now().toString().getBytes()); 31 | RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 32 | String privatePath = path + "auth-private.key"; 33 | IoUtil.writeObjects(FileUtil.getOutputStream(privatePath), true, privateKey); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /mmq-core/src/main/proto/Data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | syntax = "proto3"; 18 | 19 | option java_multiple_files = true; 20 | option java_package = "org.monkey.mmq.core.entity"; 21 | 22 | //Deprecated 23 | message Log { 24 | string group = 1; 25 | string key = 2; 26 | bytes data = 3; 27 | string type = 4; 28 | string operation = 5; 29 | map extendInfo = 6; 30 | } 31 | 32 | //Deprecated 33 | message GetRequest { 34 | string group = 1; 35 | bytes data = 2; 36 | map extendInfo = 3; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /mmq-core/src/main/resources/META-INF/services/org.monkey.mmq.core.consistency.Serializer: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 1999-2018 Alibaba Group Holding Ltd. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | org.monkey.mmq.core.consistency.serialize.JacksonSerializer 18 | -------------------------------------------------------------------------------- /mmq-core/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # SpringApplicationRunListener 2 | org.springframework.boot.SpringApplicationRunListener=\ 3 | org.monkey.mmq.core.code.SpringApplicationRunListener 4 | # ApplicationListener 5 | org.springframework.context.ApplicationListener=\ 6 | org.monkey.mmq.core.code.StandaloneProfileApplicationListener 7 | # ApplicationContextInitializer 8 | org.springframework.context.ApplicationContextInitializer=\ 9 | org.monkey.mmq.core.utils.ApplicationUtils 10 | -------------------------------------------------------------------------------- /mmq-core/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | ____ 3 | ,' , `. ____ 4 | ,-+-,.' _ | ,' , `. ,----. Mmq ${application.version} 5 | ,-+-. ; , || ,-+-,.' _ | / / \-. Running in ${mmq.mode} mode, ${mmq.function.mode} function modules 6 | ,--.'|' | ;| ,-+-. ; , ||| : :| Port: ${server.port} 7 | | | ,', | ': ,--.'|' | ||| | .\ . Pid: ${pid} 8 | | | / | | ||| | ,', | |,. ; |: | Console: http://${mmq.local.ip}:${server.port}/dashboard/monitor 9 | ' | : | : |,| | / | |--' ' . \ | MQTT Port: ${mmq.broker.port} 10 | ; . | ; |--' | : | | , \ `. | MQTT WebsocketPort: ${mmq.broker.websocketPort} 11 | | : | | , | : | |/ `--'""| | MQTT SSL Port: ${mmq.broker.ssl.port} 12 | | : ' |/ | | |`-' | | | MQTT SSL WebsocketPort: ${mmq.broker.ssl.websocketPort} 13 | ; | |`-' | ;/ | | : User Home: ${mmq.home} 14 | | ;/ '---' `---'.| 15 | '---' `---` 16 | -------------------------------------------------------------------------------- /mmq-core/src/test/java/org/monkey/mmq/core/notify/DefaultPublisherTest.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.notify; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * @ClassNameDefaultPublisherTest 9 | * @Description 10 | * @Author Solley 11 | * @Date2022/1/22 10:30 12 | * @Version V1.0 13 | **/ 14 | public class DefaultPublisherTest { 15 | 16 | @Test 17 | public void notifySubscriber() { 18 | final Runnable job = () -> { 19 | System.out.println("sss"); 20 | Double ss = null; 21 | Double tt = 100 / ss; 22 | }; 23 | try { 24 | job.run(); 25 | } catch (Throwable e) { 26 | System.out.println(e.getMessage()); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /mmq-core/src/test/java/org/monkey/mmq/core/utils/PasswordEncoderUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.core.utils; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class PasswordEncoderUtilTest { 8 | 9 | @Test 10 | public void Test() { 11 | System.out.println(PasswordEncoderUtil.encode("aaaaaa")); 12 | } 13 | } -------------------------------------------------------------------------------- /mmq-plugs/src/main/java/org/monkey/mmq/plugs/Constants.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.plugs; 2 | 3 | /** 4 | * Constants. 5 | * 6 | * @author solley 7 | */ 8 | public class Constants { 9 | 10 | public static final String NULL = ""; 11 | 12 | public static final String DOT = "."; 13 | 14 | public static final String ENCODE = "UTF-8"; 15 | 16 | public static final String LOCAL_MAC_PROPERTY_KEY = "license.local.mac"; 17 | 18 | public static final String LOCAL_IP_PROPERTY_KEY = "license.local.ip"; 19 | } 20 | -------------------------------------------------------------------------------- /mmq-plugs/src/main/java/org/monkey/mmq/plugs/IMmqPlugs.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.plugs; 2 | 3 | import org.monkey.mmq.plugs.view.MmqPlugsView; 4 | 5 | public interface IMmqPlugs { 6 | 7 | MmqPlugsView getMmqPlugsView(); 8 | 9 | String getPlugsCode(); 10 | 11 | void update(MmqPlugsView mmqPlugsView); 12 | 13 | void setLocalMqttPort(int port); 14 | } 15 | -------------------------------------------------------------------------------- /mmq-plugs/src/main/java/org/monkey/mmq/plugs/utils/Loggers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.plugs.utils; 18 | 19 | import ch.qos.logback.classic.Level; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | /** 24 | * Loggers for core. 25 | * 26 | * @author solley 27 | * @since 1.2.0 28 | */ 29 | public class Loggers { 30 | 31 | public static final Logger PLUGS = LoggerFactory.getLogger("org.monkey.mmq.plugs"); 32 | 33 | public static void setLogLevel(String logName, String level) { 34 | 35 | switch (logName) { 36 | case "mmq-plugs": 37 | ((ch.qos.logback.classic.Logger) PLUGS).setLevel(Level.valueOf(level)); 38 | break; 39 | default: 40 | break; 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mmq-plugs/src/main/java/org/monkey/mmq/plugs/view/ComponentType.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.plugs.view; 2 | 3 | public enum ComponentType { 4 | SELECT, 5 | INPUT 6 | } 7 | -------------------------------------------------------------------------------- /mmq-plugs/src/main/java/org/monkey/mmq/plugs/view/KeyValue.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.plugs.view; 2 | 3 | /** 4 | * @ClassName:Option 5 | * @Auther: Solley 6 | * @Description: 7 | * @Date: 2022/8/4 23:44 8 | * @Version: v1.0 9 | */ 10 | 11 | public class KeyValue { 12 | String key; 13 | String value; 14 | public KeyValue() { 15 | 16 | } 17 | public KeyValue(String key, String value) { 18 | this.key = key; 19 | this.value = value; 20 | } 21 | public String getKey() { 22 | return key; 23 | } 24 | 25 | public void setKey(String key) { 26 | this.key = key; 27 | } 28 | 29 | public String getValue() { 30 | return value; 31 | } 32 | 33 | public void setValue(String value) { 34 | this.value = value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /mmq-plugs/src/main/java/org/monkey/mmq/plugs/view/MmqPlugsView.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.plugs.view; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | /** 7 | * @ClassName:LicenseView 8 | * @Auther: Solley 9 | * @Description: 10 | * @Date: 2022/8/4 23:05 11 | * @Version: v1.0 12 | */ 13 | 14 | public class MmqPlugsView { 15 | /** 16 | * 插件名称 17 | */ 18 | String plugsName; 19 | /** 20 | * 插件代码 21 | */ 22 | String plugsCode; 23 | /** 24 | * is enable 25 | */ 26 | boolean enable; 27 | /** 28 | * 属性 29 | */ 30 | List propertyItems; 31 | 32 | public String getPlugsName() { 33 | return plugsName; 34 | } 35 | 36 | public void setPlugsName(String plugsName) { 37 | this.plugsName = plugsName; 38 | } 39 | 40 | public boolean isEnable() { 41 | return enable; 42 | } 43 | 44 | public void setEnable(boolean enable) { 45 | this.enable = enable; 46 | } 47 | 48 | public List getPropertyItems() { 49 | return propertyItems; 50 | } 51 | 52 | public void setPropertyItems(List propertyItems) { 53 | this.propertyItems = propertyItems; 54 | } 55 | 56 | public String getPlugsCode() { 57 | return plugsCode; 58 | } 59 | 60 | public void setPlugsCode(String plugsCode) { 61 | this.plugsCode = plugsCode; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/feature/DistinctFeature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.feature; 18 | 19 | import net.sf.jsqlparser.statement.select.Distinct; 20 | import org.monkey.mmq.rule.engine.ReactorQLMetadata; 21 | import org.monkey.mmq.rule.engine.ReactorQLRecord; 22 | import reactor.core.publisher.Flux; 23 | 24 | import java.util.function.Function; 25 | 26 | public interface DistinctFeature extends Feature { 27 | 28 | Function, Flux> createDistinctMapper(Distinct distinct, ReactorQLMetadata metadata); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/feature/Feature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.feature; 18 | 19 | /** 20 | * QL特性接口,表示支持到某个功能,如函数,聚合等 21 | * 22 | * @author solley 23 | * @see FeatureId 24 | * @see FilterFeature 25 | * @see ValueMapFeature 26 | * @see GroupFeature 27 | * @since 1.0 28 | */ 29 | public interface Feature { 30 | 31 | /** 32 | * 特性ID 33 | * 34 | * @return ID 35 | */ 36 | String getId(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/feature/GroupFeature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.feature; 18 | 19 | import net.sf.jsqlparser.expression.Expression; 20 | import org.monkey.mmq.rule.engine.ReactorQLMetadata; 21 | import org.monkey.mmq.rule.engine.ReactorQLRecord; 22 | import reactor.core.publisher.Flux; 23 | 24 | import java.util.function.Function; 25 | 26 | /** 27 | * 分组支持,用来创建对Flux进行分组的函数 28 | * 29 | * @author solley 30 | * @since 1.0 31 | */ 32 | public interface GroupFeature extends Feature { 33 | 34 | Function, Flux>> createGroupMapper(Expression expression, ReactorQLMetadata metadata); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/feature/PropertyFeature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.feature; 18 | 19 | import java.util.Optional; 20 | 21 | public interface PropertyFeature extends Feature { 22 | 23 | 24 | String ID_STR = "property-resolver"; 25 | 26 | FeatureId ID = FeatureId.of(ID_STR); 27 | 28 | Optional getProperty(Object property, Object value); 29 | 30 | @Override 31 | default String getId() { 32 | return ID_STR; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/feature/ValueAggMapFeature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.feature; 18 | 19 | import net.sf.jsqlparser.expression.Expression; 20 | import org.monkey.mmq.rule.engine.ReactorQLMetadata; 21 | import org.monkey.mmq.rule.engine.ReactorQLRecord; 22 | import reactor.core.publisher.Flux; 23 | 24 | import java.util.function.Function; 25 | 26 | public interface ValueAggMapFeature extends Feature { 27 | 28 | 29 | Function, Flux> createMapper(Expression expression, ReactorQLMetadata metadata); 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/supports/group/GroupByCalculateBinaryFeature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.supports.group; 18 | 19 | 20 | import org.monkey.mmq.rule.engine.utils.CastUtils; 21 | 22 | import java.util.function.BiFunction; 23 | 24 | /** 25 | * 根据数学运算来分组 26 | * 27 | * @author solley 28 | * @since 1.0 29 | */ 30 | public class GroupByCalculateBinaryFeature extends GroupByBinaryFeature { 31 | 32 | public GroupByCalculateBinaryFeature(String type, BiFunction mapper) { 33 | 34 | super(type, (left, right) -> mapper.apply(CastUtils.castNumber(left), CastUtils.castNumber(right))); 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/supports/map/BinaryCalculateMapFeature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.supports.map; 18 | 19 | 20 | import org.monkey.mmq.rule.engine.utils.CastUtils; 21 | 22 | import java.util.function.BiFunction; 23 | 24 | public class BinaryCalculateMapFeature extends BinaryMapFeature { 25 | 26 | public BinaryCalculateMapFeature(String type, BiFunction calculator) { 27 | super(type,(left,right)-> calculator.apply(CastUtils.castNumber(left), CastUtils.castNumber(right))); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /mmq-rule-engine/src/main/java/org/monkey/mmq/rule/engine/utils/SqlUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.monkey.mmq.rule.engine.utils; 18 | 19 | public class SqlUtils { 20 | 21 | public static String getCleanStr(String str) { 22 | if (str == null) { 23 | return null; 24 | } 25 | if (str.startsWith("\"")) { 26 | str = str.substring(1); 27 | } 28 | if (str.endsWith("\"")) { 29 | str = str.substring(0, str.length() - 1); 30 | } 31 | return str; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /mmq-ui/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 10 4 | -------------------------------------------------------------------------------- /mmq-ui/.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=false 5 | indent_style=space 6 | indent_size=2 7 | 8 | [{*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}] 9 | indent_style=space 10 | indent_size=2 11 | 12 | [{*.jhm,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.tld,*.fxml,*.jrxml,*.xml,*.jnlp,*.wsdl}] 13 | indent_style=space 14 | indent_size=2 15 | 16 | [{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] 17 | indent_style=space 18 | indent_size=2 19 | 20 | [*.svg] 21 | indent_style=space 22 | indent_size=2 23 | 24 | [*.js.map] 25 | indent_style=space 26 | indent_size=2 27 | 28 | [*.less] 29 | indent_style=space 30 | indent_size=2 31 | 32 | [*.vue] 33 | indent_style=space 34 | indent_size=2 35 | 36 | [{.analysis_options,*.yml,*.yaml}] 37 | indent_style=space 38 | indent_size=2 39 | 40 | -------------------------------------------------------------------------------- /mmq-ui/.env: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | VUE_APP_PREVIEW=false 3 | VUE_APP_API_BASE_URL=/ -------------------------------------------------------------------------------- /mmq-ui/.env.development: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | VUE_APP_PREVIEW=true 3 | VUE_APP_API_BASE_URL=http://127.0.0.1:8888 -------------------------------------------------------------------------------- /mmq-ui/.env.preview: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | VUE_APP_PREVIEW=true 3 | VUE_APP_API_BASE_URL=/ -------------------------------------------------------------------------------- /mmq-ui/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "space-before-function-paren": 0 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/.gitattributes: -------------------------------------------------------------------------------- 1 | public/* linguist-vendored -------------------------------------------------------------------------------- /mmq-ui/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | package-lock.json 23 | -------------------------------------------------------------------------------- /mmq-ui/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "semi": false, 4 | "singleQuote": true, 5 | "prettier.spaceBeforeFunctionParen": true 6 | } 7 | -------------------------------------------------------------------------------- /mmq-ui/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10.15.0 4 | cache: yarn 5 | script: 6 | - yarn 7 | - yarn run lint --no-fix && yarn run build 8 | -------------------------------------------------------------------------------- /mmq-ui/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Anan Yang 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. -------------------------------------------------------------------------------- /mmq-ui/babel.config.js: -------------------------------------------------------------------------------- 1 | const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) 2 | const IS_PREVIEW = process.env.VUE_APP_PREVIEW === 'true' 3 | 4 | const plugins = [] 5 | if (IS_PROD && !IS_PREVIEW) { 6 | // 去除日志的插件, 7 | plugins.push('transform-remove-console') 8 | } 9 | 10 | // lazy load ant-design-vue 11 | // if your use import on Demand, Use this code 12 | plugins.push(['import', { 13 | 'libraryName': 'ant-design-vue', 14 | 'libraryDirectory': 'es', 15 | 'style': true // `style: true` 会加载 less 文件 16 | }]) 17 | 18 | module.exports = { 19 | presets: [ 20 | '@vue/cli-plugin-babel/preset', 21 | [ 22 | '@babel/preset-env', 23 | { 24 | 'useBuiltIns': 'entry', 25 | 'corejs': 3 26 | } 27 | ] 28 | ], 29 | plugins 30 | } 31 | -------------------------------------------------------------------------------- /mmq-ui/docs/add-page-loading-animate.md: -------------------------------------------------------------------------------- 1 | 为首屏增加 加载动画 2 | ==== 3 | 4 | 5 | 6 | ## 需求 7 | 8 | > 为了缓解用户第一次访问时,加载 JS 过大所导致用户等待白屏时间过长导致的用户体验不好,进行的一个优化动效。 9 | 10 | 11 | 12 | ## 实现方案 13 | 14 | 1. 将 动画加载 dom 元素放在 #app 内,Vue 生命周期开始时,会自动清掉 #app 下的所有元素。 15 | 2. 将 动画加载 dom 元素放在 body 下,Vue 生命周期开始时 App.vue (created, mounted) 调用 `@/utils/utll` 下的 removeLoadingAnimate(#id, timeout) 则会移除加载动画 16 | 17 | 最后一步: 18 | ​ 将样式插入到 `public/index.html` 文件的 `` 最好写成内联 `` 19 | 20 | 21 | 22 | ---- 23 | 24 | 目前提供有两个样式,均在 `public/loading` 文件夹内。且 pro 已经默认使用了一套 loading 动画方案,可以直接参考 `public/index.html` 25 | 26 | 27 | ## 写在最后 28 | 29 | 目前 pro 有页面 overflow 显示出浏览器滚动条时,页面会抖动一下的问题。 30 | 31 | 欢迎各位提供能解决的方案和实现 demo。如果在条件允许的情况下,建议请直接使用 pro 进行改造,也欢迎直接 PR 到 pro 的仓库 32 | -------------------------------------------------------------------------------- /mmq-ui/docs/webpack-bundle-analyzer.md: -------------------------------------------------------------------------------- 1 | 先增加依赖 2 | 3 | ```bash 4 | // npm 5 | $ npm install --save-dev webpack-bundle-analyzer 6 | 7 | // or yarn 8 | $ yarn add webpack-bundle-analyzer -D 9 | ``` 10 | 11 | 配置文件 `vue.config.js` 增加 `configureWebpack.plugins` 参数 12 | 13 | ``` 14 | const path = require('path') 15 | const webpack = require('webpack') 16 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 17 | 18 | function resolve (dir) { 19 | return path.join(__dirname, dir) 20 | } 21 | 22 | // vue.config.js 23 | module.exports = { 24 | configureWebpack: { 25 | plugins: [ 26 | // Ignore all locale files of moment.js 27 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), 28 | // 依赖大小分析工具 29 | new BundleAnalyzerPlugin(), 30 | ] 31 | }, 32 | 33 | 34 | ... 35 | } 36 | ``` 37 | 38 | 39 | 40 | 启动 `cli` 的 `build` 命令进行项目编译,编译完成时,会自动运行一个 http://localhost:8888 的地址,完整显示了支持库依赖 -------------------------------------------------------------------------------- /mmq-ui/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: [ 3 | 'js', 4 | 'jsx', 5 | 'json', 6 | 'vue' 7 | ], 8 | transform: { 9 | '^.+\\.vue$': 'vue-jest', 10 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', 11 | '^.+\\.jsx?$': 'babel-jest' 12 | }, 13 | moduleNameMapper: { 14 | '^@/(.*)$': '/src/$1' 15 | }, 16 | snapshotSerializers: [ 17 | 'jest-serializer-vue' 18 | ], 19 | testMatch: [ 20 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 21 | ], 22 | testURL: 'http://localhost/' 23 | } 24 | -------------------------------------------------------------------------------- /mmq-ui/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": [ 7 | "src/*" 8 | ] 9 | } 10 | }, 11 | "exclude": [ 12 | "node_modules", 13 | "dist" 14 | ], 15 | "include": [ 16 | "src/**/*" 17 | ] 18 | } -------------------------------------------------------------------------------- /mmq-ui/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/public/avatar2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/mmq-ui/public/avatar2.jpg -------------------------------------------------------------------------------- /mmq-ui/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/mmq-ui/public/logo.png -------------------------------------------------------------------------------- /mmq-ui/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 29 | -------------------------------------------------------------------------------- /mmq-ui/src/api/system.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | const systemApi = { 4 | Syteminfo: '/v1/system/info', 5 | Clients: '/v1/system/clients', 6 | Subscribes: '/v1/system/subscribes', 7 | Nodes: '/v1/system/nodes' 8 | } 9 | 10 | export function getSystemInfo () { 11 | return request({ 12 | url: systemApi.Syteminfo, 13 | method: 'get' 14 | }) 15 | } 16 | 17 | export function getClients (parameter) { 18 | return request({ 19 | url: systemApi.Clients, 20 | method: 'get', 21 | params: parameter 22 | }) 23 | } 24 | 25 | export function getNodes () { 26 | return request({ 27 | url: systemApi.Nodes, 28 | method: 'get' 29 | }) 30 | } 31 | 32 | export function getSubscribes (parameter) { 33 | return request({ 34 | url: systemApi.Subscribes, 35 | method: 'get', 36 | params: parameter 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /mmq-ui/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/mmq-ui/src/assets/logo.png -------------------------------------------------------------------------------- /mmq-ui/src/components/ArticleListContent/index.js: -------------------------------------------------------------------------------- 1 | import ArticleListContent from './ArticleListContent' 2 | 3 | export default ArticleListContent 4 | -------------------------------------------------------------------------------- /mmq-ui/src/components/AvatarList/Item.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'ant-design-vue/es/_util/vue-types' 2 | import { Tooltip, Avatar } from 'ant-design-vue' 3 | import { getSlotOptions } from 'ant-design-vue/lib/_util/props-util' 4 | import { warning } from 'ant-design-vue/lib/vc-util/warning' 5 | 6 | export const AvatarListItemProps = { 7 | tips: PropTypes.string.def(null), 8 | src: PropTypes.string.def('') 9 | } 10 | 11 | const Item = { 12 | __ANT_AVATAR_CHILDREN: true, 13 | name: 'AvatarListItem', 14 | props: AvatarListItemProps, 15 | created () { 16 | warning(getSlotOptions(this.$parent).__ANT_AVATAR_LIST, 'AvatarListItem must be a subcomponent of AvatarList') 17 | }, 18 | render () { 19 | const AvatarDom = 20 | return this.tips && {AvatarDom} || 21 | } 22 | } 23 | 24 | export default Item 25 | -------------------------------------------------------------------------------- /mmq-ui/src/components/AvatarList/index.js: -------------------------------------------------------------------------------- 1 | import AvatarList from './List' 2 | import Item from './Item' 3 | 4 | export { 5 | AvatarList, 6 | Item as AvatarListItem 7 | } 8 | 9 | export default AvatarList 10 | -------------------------------------------------------------------------------- /mmq-ui/src/components/AvatarList/index.less: -------------------------------------------------------------------------------- 1 | @import "../index"; 2 | 3 | @avatar-list-prefix-cls: ~"@{ant-pro-prefix}-avatar-list"; 4 | @avatar-list-item-prefix-cls: ~"@{ant-pro-prefix}-avatar-list-item"; 5 | 6 | .@{avatar-list-prefix-cls} { 7 | display: inline-block; 8 | 9 | ul { 10 | list-style: none; 11 | display: inline-block; 12 | padding: 0; 13 | margin: 0 0 0 8px; 14 | font-size: 0; 15 | } 16 | } 17 | 18 | .@{avatar-list-item-prefix-cls} { 19 | display: inline-block; 20 | font-size: @font-size-base; 21 | margin-left: -8px; 22 | width: @avatar-size-base; 23 | height: @avatar-size-base; 24 | 25 | :global { 26 | .ant-avatar { 27 | border: 1px solid #fff; 28 | cursor: pointer; 29 | } 30 | } 31 | 32 | &.large { 33 | width: @avatar-size-lg; 34 | height: @avatar-size-lg; 35 | } 36 | 37 | &.small { 38 | width: @avatar-size-sm; 39 | height: @avatar-size-sm; 40 | } 41 | 42 | &.mini { 43 | width: 20px; 44 | height: 20px; 45 | 46 | :global { 47 | .ant-avatar { 48 | width: 20px; 49 | height: 20px; 50 | line-height: 20px; 51 | 52 | .ant-avatar-string { 53 | font-size: 12px; 54 | line-height: 18px; 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Charts/Bar.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 63 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Charts/MiniArea.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 53 | 54 | 57 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Charts/MiniBar.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 54 | 55 | 58 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Charts/MiniSmoothArea.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 37 | 38 | 41 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Charts/TransferBar.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 65 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Charts/chart.less: -------------------------------------------------------------------------------- 1 | .antv-chart-mini { 2 | position: relative; 3 | width: 100%; 4 | 5 | .chart-wrapper { 6 | position: absolute; 7 | bottom: -28px; 8 | width: 100%; 9 | 10 | /* margin: 0 -5px; 11 | overflow: hidden;*/ 12 | } 13 | } -------------------------------------------------------------------------------- /mmq-ui/src/components/Charts/smooth.area.less: -------------------------------------------------------------------------------- 1 | @import "../index"; 2 | 3 | @smoothArea-prefix-cls: ~"@{ant-pro-prefix}-smooth-area"; 4 | 5 | .@{smoothArea-prefix-cls} { 6 | position: relative; 7 | width: 100%; 8 | 9 | .chart-wrapper { 10 | position: absolute; 11 | bottom: -28px; 12 | width: 100%; 13 | } 14 | } -------------------------------------------------------------------------------- /mmq-ui/src/components/Editor/WangEditor.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 50 | 51 | 58 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Ellipsis/index.js: -------------------------------------------------------------------------------- 1 | import Ellipsis from './Ellipsis' 2 | 3 | export default Ellipsis 4 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Ellipsis/index.md: -------------------------------------------------------------------------------- 1 | # Ellipsis 文本自动省略号 2 | 3 | 文本过长自动处理省略号,支持按照文本长度和最大行数两种方式截取。 4 | 5 | 6 | 7 | 引用方式: 8 | 9 | ```javascript 10 | import Ellipsis from '@/components/Ellipsis' 11 | 12 | export default { 13 | components: { 14 | Ellipsis 15 | } 16 | } 17 | ``` 18 | 19 | 20 | 21 | ## 代码演示 [demo](https://pro.loacg.com/test/home) 22 | 23 | ```html 24 | 25 | There were injuries alleged in three cases in 2015, and a 26 | fourth incident in September, according to the safety recall report. After meeting with US regulators in October, the firm decided to issue a voluntary recall. 27 | 28 | ``` 29 | 30 | 31 | 32 | ## API 33 | 34 | 35 | 参数 | 说明 | 类型 | 默认值 36 | ----|------|-----|------ 37 | tooltip | 移动到文本展示完整内容的提示 | boolean | - 38 | length | 在按照长度截取下的文本最大字符数,超过则截取省略 | number | - -------------------------------------------------------------------------------- /mmq-ui/src/components/FooterToolbar/FooterToolBar.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 44 | 45 | 48 | -------------------------------------------------------------------------------- /mmq-ui/src/components/FooterToolbar/index.js: -------------------------------------------------------------------------------- 1 | import FooterToolBar from './FooterToolBar' 2 | import './index.less' 3 | 4 | export default FooterToolBar 5 | -------------------------------------------------------------------------------- /mmq-ui/src/components/FooterToolbar/index.less: -------------------------------------------------------------------------------- 1 | @import "../index"; 2 | 3 | @footer-toolbar-prefix-cls: ~"@{ant-pro-prefix}-footer-toolbar"; 4 | 5 | .@{footer-toolbar-prefix-cls} { 6 | position: fixed; 7 | width: 100%; 8 | bottom: 0; 9 | right: 0; 10 | height: 56px; 11 | line-height: 56px; 12 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.03); 13 | background: #fff; 14 | border-top: 1px solid #e8e8e8; 15 | padding: 0 24px; 16 | z-index: 9; 17 | 18 | &:after { 19 | content: ""; 20 | display: block; 21 | clear: both; 22 | } 23 | } -------------------------------------------------------------------------------- /mmq-ui/src/components/FooterToolbar/index.md: -------------------------------------------------------------------------------- 1 | # FooterToolbar 底部工具栏 2 | 3 | 固定在底部的工具栏。 4 | 5 | 6 | 7 | ## 何时使用 8 | 9 | 固定在内容区域的底部,不随滚动条移动,常用于长页面的数据搜集和提交工作。 10 | 11 | 12 | 13 | 引用方式: 14 | 15 | ```javascript 16 | import FooterToolBar from '@/components/FooterToolbar' 17 | 18 | export default { 19 | components: { 20 | FooterToolBar 21 | } 22 | } 23 | ``` 24 | 25 | 26 | 27 | ## 代码演示 28 | 29 | ```html 30 | 31 | 提交 32 | 33 | ``` 34 | 或 35 | ```html 36 | 37 | 提交 38 | 39 | ``` 40 | 41 | 42 | ## API 43 | 44 | 参数 | 说明 | 类型 | 默认值 45 | ----|------|-----|------ 46 | children (slot) | 工具栏内容,向右对齐 | - | - 47 | extra | 额外信息,向左对齐 | String, Object | - 48 | 49 | -------------------------------------------------------------------------------- /mmq-ui/src/components/GlobalFooter/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | -------------------------------------------------------------------------------- /mmq-ui/src/components/GlobalHeader/RightContent.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 59 | -------------------------------------------------------------------------------- /mmq-ui/src/components/IconSelector/README.md: -------------------------------------------------------------------------------- 1 | IconSelector 2 | ==== 3 | 4 | > 图标选择组件,常用于为某一个数据设定一个图标时使用 5 | > eg: 设定菜单列表时,为每个菜单设定一个图标 6 | 7 | 该组件由 [@Saraka](https://github.com/saraka-tsukai) 封装 8 | 9 | 10 | 11 | ### 使用方式 12 | 13 | ```vue 14 | 19 | 20 | 39 | ``` 40 | 41 | 42 | 43 | ### 事件 44 | 45 | 46 | | 名称 | 说明 | 类型 | 默认值 | 47 | | ------ | -------------------------- | ------ | ------ | 48 | | change | 当改变了 `icon` 选中项触发 | String | - | 49 | -------------------------------------------------------------------------------- /mmq-ui/src/components/IconSelector/index.js: -------------------------------------------------------------------------------- 1 | import IconSelector from './IconSelector' 2 | export default IconSelector 3 | -------------------------------------------------------------------------------- /mmq-ui/src/components/MultiTab/events.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | export default new Vue() 3 | -------------------------------------------------------------------------------- /mmq-ui/src/components/MultiTab/index.js: -------------------------------------------------------------------------------- 1 | import events from './events' 2 | import MultiTab from './MultiTab' 3 | import './index.less' 4 | 5 | const api = { 6 | /** 7 | * open new tab on route fullPath 8 | * @param config 9 | */ 10 | open: function (config) { 11 | events.$emit('open', config) 12 | }, 13 | rename: function (key, name) { 14 | events.$emit('rename', { key: key, name: name }) 15 | }, 16 | /** 17 | * close current page 18 | */ 19 | closeCurrentPage: function () { 20 | this.close() 21 | }, 22 | /** 23 | * close route fullPath tab 24 | * @param config 25 | */ 26 | close: function (config) { 27 | events.$emit('close', config) 28 | } 29 | } 30 | 31 | MultiTab.install = function (Vue) { 32 | if (Vue.prototype.$multiTab) { 33 | return 34 | } 35 | api.instance = events 36 | Vue.prototype.$multiTab = api 37 | Vue.component('multi-tab', MultiTab) 38 | } 39 | 40 | export default MultiTab 41 | -------------------------------------------------------------------------------- /mmq-ui/src/components/MultiTab/index.less: -------------------------------------------------------------------------------- 1 | @import '../index'; 2 | 3 | @multi-tab-prefix-cls: ~"@{ant-pro-prefix}-multi-tab"; 4 | @multi-tab-wrapper-prefix-cls: ~"@{ant-pro-prefix}-multi-tab-wrapper"; 5 | 6 | /* 7 | .topmenu .@{multi-tab-prefix-cls} { 8 | max-width: 1200px; 9 | margin: -23px auto 24px auto; 10 | } 11 | */ 12 | .@{multi-tab-prefix-cls} { 13 | margin: -23px -24px 24px -24px; 14 | background: #fff; 15 | } 16 | 17 | .topmenu .@{multi-tab-wrapper-prefix-cls} { 18 | max-width: 1200px; 19 | margin: 0 auto; 20 | } 21 | 22 | .topmenu.content-width-Fluid .@{multi-tab-wrapper-prefix-cls} { 23 | max-width: 100%; 24 | margin: 0 auto; 25 | } 26 | -------------------------------------------------------------------------------- /mmq-ui/src/components/NoticeIcon/index.js: -------------------------------------------------------------------------------- 1 | import NoticeIcon from './NoticeIcon' 2 | export default NoticeIcon 3 | -------------------------------------------------------------------------------- /mmq-ui/src/components/NumberInfo/NumberInfo.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 51 | 52 | 55 | -------------------------------------------------------------------------------- /mmq-ui/src/components/NumberInfo/index.js: -------------------------------------------------------------------------------- 1 | import NumberInfo from './NumberInfo' 2 | 3 | export default NumberInfo 4 | -------------------------------------------------------------------------------- /mmq-ui/src/components/NumberInfo/index.less: -------------------------------------------------------------------------------- 1 | @import "../index"; 2 | 3 | @numberInfo-prefix-cls: ~"@{ant-pro-prefix}-number-info"; 4 | 5 | .@{numberInfo-prefix-cls} { 6 | 7 | .ant-pro-number-info-subtitle { 8 | color: @text-color-secondary; 9 | font-size: @font-size-base; 10 | height: 22px; 11 | line-height: 22px; 12 | overflow: hidden; 13 | text-overflow: ellipsis; 14 | word-break: break-all; 15 | white-space: nowrap; 16 | } 17 | 18 | .number-info-value { 19 | margin-top: 4px; 20 | font-size: 0; 21 | overflow: hidden; 22 | text-overflow: ellipsis; 23 | word-break: break-all; 24 | white-space: nowrap; 25 | 26 | & > span { 27 | color: @heading-color; 28 | display: inline-block; 29 | line-height: 32px; 30 | height: 32px; 31 | font-size: 24px; 32 | margin-right: 32px; 33 | } 34 | 35 | .sub-total { 36 | color: @text-color-secondary; 37 | font-size: @font-size-lg; 38 | vertical-align: top; 39 | margin-right: 0; 40 | i { 41 | font-size: 12px; 42 | transform: scale(0.82); 43 | margin-left: 4px; 44 | } 45 | :global { 46 | .anticon-caret-up { 47 | color: @red-6; 48 | } 49 | .anticon-caret-down { 50 | color: @green-6; 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /mmq-ui/src/components/NumberInfo/index.md: -------------------------------------------------------------------------------- 1 | # NumberInfo 数据文本 2 | 3 | 常用在数据卡片中,用于突出展示某个业务数据。 4 | 5 | 6 | 7 | 引用方式: 8 | 9 | ```javascript 10 | import NumberInfo from '@/components/NumberInfo' 11 | 12 | export default { 13 | components: { 14 | NumberInfo 15 | } 16 | } 17 | ``` 18 | 19 | 20 | 21 | ## 代码演示 [demo](https://pro.loacg.com/test/home) 22 | 23 | ```html 24 | 29 | ``` 30 | 31 | 32 | 33 | ## API 34 | 35 | 参数 | 说明 | 类型 | 默认值 36 | ----|------|-----|------ 37 | title | 标题 | ReactNode\|string | - 38 | subTitle | 子标题 | ReactNode\|string | - 39 | total | 总量 | ReactNode\|string | - 40 | subTotal | 子总量 | ReactNode\|string | - 41 | status | 增加状态 | 'up \| down' | - 42 | theme | 状态样式 | string | 'light' 43 | gap | 设置数字和描述之间的间距(像素)| number | 8 44 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Search/index.less: -------------------------------------------------------------------------------- 1 | @import "~ant-design-vue/es/style/themes/default"; 2 | 3 | .global-search-wrapper { 4 | position: fixed; 5 | top: 0; 6 | left: 0; 7 | right: 0; 8 | bottom: 0; 9 | z-index: @zindex-modal-mask; 10 | background: @modal-mask-bg; 11 | 12 | .global-search-box { 13 | position: absolute; 14 | top: 20%; 15 | left: 50%; 16 | width: 450px; 17 | transform: translate(-50%, -50%); 18 | 19 | .global-search-tips { 20 | color: @white; 21 | font-size: @font-size-lg; 22 | text-align: right; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /mmq-ui/src/components/SelectLang/index.less: -------------------------------------------------------------------------------- 1 | @import "~ant-design-vue/es/style/themes/default"; 2 | 3 | @header-menu-prefix-cls: ~'@{ant-prefix}-pro-header-menu'; 4 | @header-drop-down-prefix-cls: ~'@{ant-prefix}-pro-drop-down'; 5 | 6 | .@{header-menu-prefix-cls} { 7 | 8 | .anticon { 9 | margin-right: 8px; 10 | } 11 | .ant-dropdown-menu-item { 12 | min-width: 160px; 13 | } 14 | } 15 | 16 | .@{header-drop-down-prefix-cls} { 17 | 18 | line-height: @layout-header-height; 19 | vertical-align: top; 20 | cursor: pointer; 21 | 22 | > i { 23 | font-size: 16px !important; 24 | transform: none !important; 25 | 26 | svg { 27 | position: relative; 28 | top: -1px; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /mmq-ui/src/components/SettingDrawer/SettingItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 24 | 25 | 39 | -------------------------------------------------------------------------------- /mmq-ui/src/components/SettingDrawer/index.js: -------------------------------------------------------------------------------- 1 | import SettingDrawer from './SettingDrawer' 2 | export default SettingDrawer 3 | -------------------------------------------------------------------------------- /mmq-ui/src/components/SettingDrawer/settingConfig.js: -------------------------------------------------------------------------------- 1 | import message from 'ant-design-vue/es/message' 2 | // import defaultSettings from '../defaultSettings'; 3 | import themeColor from './themeColor.js' 4 | 5 | // let lessNodesAppended 6 | const colorList = [ 7 | { 8 | key: '薄暮', color: '#F5222D' 9 | }, 10 | { 11 | key: '火山', color: '#FA541C' 12 | }, 13 | { 14 | key: '日暮', color: '#FAAD14' 15 | }, 16 | { 17 | key: '明青', color: '#13C2C2' 18 | }, 19 | { 20 | key: '极光绿', color: '#52C41A' 21 | }, 22 | { 23 | key: '拂晓蓝(默认)', color: '#1890FF' 24 | }, 25 | { 26 | key: '极客蓝', color: '#2F54EB' 27 | }, 28 | { 29 | key: '酱紫', color: '#722ED1' 30 | } 31 | ] 32 | 33 | const updateTheme = newPrimaryColor => { 34 | const hideMessage = message.loading('正在切换主题!', 0) 35 | themeColor.changeColor(newPrimaryColor).finally(() => { 36 | setTimeout(() => { 37 | hideMessage() 38 | }, 10) 39 | }) 40 | } 41 | 42 | const updateColorWeak = colorWeak => { 43 | // document.body.className = colorWeak ? 'colorWeak' : ''; 44 | const app = document.body.querySelector('#app') 45 | colorWeak ? app.classList.add('colorWeak') : app.classList.remove('colorWeak') 46 | } 47 | 48 | export { updateTheme, colorList, updateColorWeak } 49 | -------------------------------------------------------------------------------- /mmq-ui/src/components/SettingDrawer/themeColor.js: -------------------------------------------------------------------------------- 1 | import client from 'webpack-theme-color-replacer/client' 2 | import generate from '@ant-design/colors/lib/generate' 3 | 4 | export default { 5 | getAntdSerials (color) { 6 | // 淡化(即less的tint) 7 | const lightens = new Array(9).fill().map((t, i) => { 8 | return client.varyColor.lighten(color, i / 10) 9 | }) 10 | // colorPalette变换得到颜色值 11 | const colorPalettes = generate(color) 12 | const rgb = client.varyColor.toNum3(color.replace('#', '')).join(',') 13 | return lightens.concat(colorPalettes).concat(rgb) 14 | }, 15 | changeColor (newColor) { 16 | var options = { 17 | newColors: this.getAntdSerials(newColor), // new colors array, one-to-one corresponde with `matchColors` 18 | changeUrl (cssUrl) { 19 | return `/${cssUrl}` // while router is not `hash` mode, it needs absolute path 20 | } 21 | } 22 | return client.changer.changeColor(options, Promise) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mmq-ui/src/components/StandardFormRow/index.js: -------------------------------------------------------------------------------- 1 | import StandardFormRow from './StandardFormRow' 2 | 3 | export default StandardFormRow 4 | -------------------------------------------------------------------------------- /mmq-ui/src/components/TagSelect/TagSelectOption.jsx: -------------------------------------------------------------------------------- 1 | import { Tag } from 'ant-design-vue' 2 | const { CheckableTag } = Tag 3 | 4 | export default { 5 | name: 'TagSelectOption', 6 | props: { 7 | prefixCls: { 8 | type: String, 9 | default: 'ant-pro-tag-select-option' 10 | }, 11 | value: { 12 | type: [String, Number, Object], 13 | default: '' 14 | }, 15 | checked: { 16 | type: Boolean, 17 | default: false 18 | } 19 | }, 20 | data () { 21 | return { 22 | localChecked: this.checked || false 23 | } 24 | }, 25 | watch: { 26 | 'checked' (val) { 27 | this.localChecked = val 28 | }, 29 | '$parent.items': { 30 | handler: function (val) { 31 | this.value && val.hasOwnProperty(this.value) && (this.localChecked = val[this.value]) 32 | }, 33 | deep: true 34 | } 35 | }, 36 | render () { 37 | const { $slots, value } = this 38 | const onChange = (checked) => { 39 | this.$emit('change', { value, checked }) 40 | } 41 | return ( 42 | {$slots.default} 43 | ) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /mmq-ui/src/components/TextArea/style.less: -------------------------------------------------------------------------------- 1 | .ant-textarea-limit { 2 | position: relative; 3 | 4 | .limit { 5 | position: absolute; 6 | color: #909399; 7 | background: #fff; 8 | font-size: 12px; 9 | bottom: 5px; 10 | right: 10px; 11 | } 12 | } -------------------------------------------------------------------------------- /mmq-ui/src/components/Trend/Trend.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 38 | 39 | 42 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Trend/index.js: -------------------------------------------------------------------------------- 1 | import Trend from './Trend.vue' 2 | 3 | export default Trend 4 | -------------------------------------------------------------------------------- /mmq-ui/src/components/Trend/index.less: -------------------------------------------------------------------------------- 1 | @import "../index"; 2 | 3 | @trend-prefix-cls: ~"@{ant-pro-prefix}-trend"; 4 | 5 | .@{trend-prefix-cls} { 6 | display: inline-block; 7 | font-size: @font-size-base; 8 | line-height: 22px; 9 | 10 | .up, 11 | .down { 12 | margin-left: 4px; 13 | position: relative; 14 | top: 1px; 15 | 16 | i { 17 | font-size: 12px; 18 | transform: scale(0.83); 19 | } 20 | } 21 | 22 | .item-text { 23 | display: inline-block; 24 | margin-left: 8px; 25 | color: rgba(0,0,0,.85); 26 | } 27 | 28 | .up { 29 | color: @red-6; 30 | } 31 | .down { 32 | color: @green-6; 33 | top: -1px; 34 | } 35 | 36 | &.reverse-color .up { 37 | color: @green-6; 38 | } 39 | &.reverse-color .down { 40 | color: @red-6; 41 | } 42 | } -------------------------------------------------------------------------------- /mmq-ui/src/components/Trend/index.md: -------------------------------------------------------------------------------- 1 | # Trend 趋势标记 2 | 3 | 趋势符号,标记上升和下降趋势。通常用绿色代表“好”,红色代表“不好”,股票涨跌场景除外。 4 | 5 | 6 | 7 | 引用方式: 8 | 9 | ```javascript 10 | import Trend from '@/components/Trend' 11 | 12 | export default { 13 | components: { 14 | Trend 15 | } 16 | } 17 | ``` 18 | 19 | 20 | 21 | ## 代码演示 [demo](https://pro.loacg.com/test/home) 22 | 23 | ```html 24 | 5% 25 | ``` 26 | 或 27 | ```html 28 | 29 | 工资 30 | 5% 31 | 32 | ``` 33 | 或 34 | ```html 35 | 5% 36 | ``` 37 | 38 | 39 | ## API 40 | 41 | | 参数 | 说明 | 类型 | 默认值 | 42 | |----------|------------------------------------------|-------------|-------| 43 | | flag | 上升下降标识:`up|down` | string | - | 44 | | reverseColor | 颜色反转 | Boolean | false | 45 | 46 | -------------------------------------------------------------------------------- /mmq-ui/src/components/_util/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * components util 3 | */ 4 | 5 | /** 6 | * 清理空值,对象 7 | * @param children 8 | * @returns {*[]} 9 | */ 10 | export function filterEmpty (children = []) { 11 | return children.filter(c => c.tag || (c.text && c.text.trim() !== '')) 12 | } 13 | 14 | /** 15 | * 获取字符串长度,英文字符 长度1,中文字符长度2 16 | * @param {*} str 17 | */ 18 | export const getStrFullLength = (str = '') => 19 | str.split('').reduce((pre, cur) => { 20 | const charCode = cur.charCodeAt(0) 21 | if (charCode >= 0 && charCode <= 128) { 22 | return pre + 1 23 | } 24 | return pre + 2 25 | }, 0) 26 | 27 | /** 28 | * 截取字符串,根据 maxLength 截取后返回 29 | * @param {*} str 30 | * @param {*} maxLength 31 | */ 32 | export const cutStrByFullLength = (str = '', maxLength) => { 33 | let showLength = 0 34 | return str.split('').reduce((pre, cur) => { 35 | const charCode = cur.charCodeAt(0) 36 | if (charCode >= 0 && charCode <= 128) { 37 | showLength += 1 38 | } else { 39 | showLength += 2 40 | } 41 | if (showLength <= maxLength) { 42 | return pre + cur 43 | } 44 | return pre 45 | }, '') 46 | } 47 | -------------------------------------------------------------------------------- /mmq-ui/src/components/index.less: -------------------------------------------------------------------------------- 1 | @import "~ant-design-vue/lib/style/index"; 2 | 3 | // The prefix to use on all css classes from ant-pro. 4 | @ant-pro-prefix : ant-pro; 5 | @ant-global-sider-zindex : 106; 6 | @ant-global-header-zindex : 105; -------------------------------------------------------------------------------- /mmq-ui/src/config/defaultSettings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 项目默认配置项 3 | * primaryColor - 默认主题色, 如果修改颜色不生效,请清理 localStorage 4 | * navTheme - sidebar theme ['dark', 'light'] 两种主题 5 | * colorWeak - 色盲模式 6 | * layout - 整体布局方式 ['sidemenu', 'topmenu'] 两种布局 7 | * fixedHeader - 固定 Header : boolean 8 | * fixSiderbar - 固定左侧菜单栏 : boolean 9 | * contentWidth - 内容区布局: 流式 | 固定 10 | * 11 | * storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage) 12 | * 13 | */ 14 | 15 | export default { 16 | navTheme: 'dark', // theme for nav menu 17 | primaryColor: '#F5222D', // primary color of ant design 18 | layout: 'sidemenu', // nav menu position: `sidemenu` or `topmenu` 19 | contentWidth: 'Fluid', // layout of content: `Fluid` or `Fixed`, only works when layout is topmenu 20 | fixedHeader: false, // sticky header 21 | fixSiderbar: false, // sticky siderbar 22 | colorWeak: false, 23 | menu: { 24 | locale: true 25 | }, 26 | title: 'MMQ Broker', 27 | pwa: false, 28 | iconfontUrl: '', 29 | production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true' 30 | } 31 | -------------------------------------------------------------------------------- /mmq-ui/src/core/directives/action.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from '@/store' 3 | 4 | /** 5 | * Action 权限指令 6 | * 指令用法: 7 | * - 在需要控制 action 级别权限的组件上使用 v-action:[method] , 如下: 8 | * 添加用户 9 | * 删除用户 10 | * 修改 11 | * 12 | * - 当前用户没有权限时,组件上使用了该指令则会被隐藏 13 | * - 当后台权限跟 pro 提供的模式不同时,只需要针对这里的权限过滤进行修改即可 14 | * 15 | * @see https://github.com/vueComponent/ant-design-vue-pro/pull/53 16 | */ 17 | const action = Vue.directive('action', { 18 | inserted: function (el, binding, vnode) { 19 | const actionName = binding.arg 20 | const roles = store.getters.roles 21 | const elVal = vnode.context.$route.meta.permission 22 | const permissionId = elVal instanceof String && [elVal] || elVal 23 | roles.permissions.forEach(p => { 24 | if (!permissionId.includes(p.permissionId)) { 25 | return 26 | } 27 | if (p.actionList && !p.actionList.includes(actionName)) { 28 | el.parentNode && el.parentNode.removeChild(el) || (el.style.display = 'none') 29 | } 30 | }) 31 | } 32 | }) 33 | 34 | export default action 35 | -------------------------------------------------------------------------------- /mmq-ui/src/core/icons.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom icon list 3 | * All icons are loaded here for easy management 4 | * @see https://vue.ant.design/components/icon/#Custom-Font-Icon 5 | * 6 | * 自定义图标加载表 7 | * 所有图标均从这里加载,方便管理 8 | */ 9 | import bxAnaalyse from '@/assets/icons/bx-analyse.svg?inline' // path to your '*.svg?inline' file. 10 | 11 | export { bxAnaalyse } 12 | -------------------------------------------------------------------------------- /mmq-ui/src/core/use.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | // base library 4 | import Antd from 'ant-design-vue' 5 | import Viser from 'viser-vue' 6 | import VueCropper from 'vue-cropper' 7 | import 'ant-design-vue/dist/antd.less' 8 | 9 | // ext library 10 | import VueClipboard from 'vue-clipboard2' 11 | import MultiTab from '@/components/MultiTab' 12 | import PageLoading from '@/components/PageLoading' 13 | import PermissionHelper from '@/core/permission/permission' 14 | // import '@/components/use' 15 | import './directives/action' 16 | 17 | VueClipboard.config.autoSetContainer = true 18 | 19 | Vue.use(Antd) 20 | Vue.use(Viser) 21 | Vue.use(MultiTab) 22 | Vue.use(PageLoading) 23 | Vue.use(VueClipboard) 24 | Vue.use(PermissionHelper) 25 | Vue.use(VueCropper) 26 | 27 | process.env.NODE_ENV !== 'production' && console.warn('[antd-pro] WARNING: Antd now use fulled imported.') 28 | -------------------------------------------------------------------------------- /mmq-ui/src/layouts/BasicLayout.less: -------------------------------------------------------------------------------- 1 | @import "~ant-design-vue/es/style/themes/default.less"; 2 | 3 | .ant-pro-global-header-index-right { 4 | margin-right: 8px; 5 | 6 | &.ant-pro-global-header-index-dark { 7 | .ant-pro-global-header-index-action { 8 | color: hsla(0, 0%, 100%, .85); 9 | 10 | &:hover { 11 | background: #1890ff; 12 | } 13 | } 14 | } 15 | 16 | .ant-pro-account-avatar { 17 | .antd-pro-global-header-index-avatar { 18 | margin: ~'calc((@{layout-header-height} - 24px) / 2)' 0; 19 | margin-right: 8px; 20 | color: @primary-color; 21 | vertical-align: top; 22 | background: rgba(255, 255, 255, 0.85); 23 | } 24 | } 25 | 26 | .menu { 27 | .anticon { 28 | margin-right: 8px; 29 | } 30 | 31 | .ant-dropdown-menu-item { 32 | min-width: 100px; 33 | } 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /mmq-ui/src/layouts/BlankLayout.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 17 | -------------------------------------------------------------------------------- /mmq-ui/src/layouts/PageView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /mmq-ui/src/layouts/RouteView.vue: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /mmq-ui/src/layouts/index.js: -------------------------------------------------------------------------------- 1 | import UserLayout from './UserLayout' 2 | import BlankLayout from './BlankLayout' 3 | import BasicLayout from './BasicLayout' 4 | import RouteView from './RouteView' 5 | import PageView from './PageView' 6 | 7 | export { UserLayout, BasicLayout, BlankLayout, RouteView, PageView } 8 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US.js: -------------------------------------------------------------------------------- 1 | import antdEnUS from 'ant-design-vue/es/locale-provider/en_US' 2 | import momentEU from 'moment/locale/eu' 3 | import global from './en-US/global' 4 | 5 | import menu from './en-US/menu' 6 | import setting from './en-US/setting' 7 | import user from './en-US/user' 8 | import overview from './en-US/overview' 9 | 10 | import dashboard from './en-US/dashboard' 11 | import form from './en-US/form' 12 | import result from './en-US/result' 13 | import account from './en-US/account' 14 | 15 | const components = { 16 | antLocale: antdEnUS, 17 | momentName: 'eu', 18 | momentLocale: momentEU 19 | } 20 | 21 | export default { 22 | message: '-', 23 | 24 | 'layouts.usermenu.dialog.title': 'Message', 25 | 'layouts.usermenu.dialog.content': 'Are you sure you would like to logout?', 26 | 'layouts.userLayout.title': 'MQTT Broker System', 27 | ...components, 28 | ...global, 29 | ...menu, 30 | ...setting, 31 | ...user, 32 | ...dashboard, 33 | ...form, 34 | ...result, 35 | overview, 36 | ...account 37 | } 38 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/account.js: -------------------------------------------------------------------------------- 1 | import settings from './account/settings' 2 | 3 | export default { 4 | ...settings 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/dashboard.js: -------------------------------------------------------------------------------- 1 | import analysis from './dashboard/analysis' 2 | 3 | export default { 4 | ...analysis 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/form.js: -------------------------------------------------------------------------------- 1 | import basicForm from './form/basicForm' 2 | 3 | export default { 4 | ...basicForm 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/global.js: -------------------------------------------------------------------------------- 1 | export default { 2 | submit: 'Submit', 3 | save: 'Save', 4 | 'submit.ok': 'Submit successfully', 5 | 'save.ok': 'Saved successfully' 6 | } 7 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/menu.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'menu.welcome': 'Welcome', 3 | 'menu.home': 'Home', 4 | 'menu.dashboard': 'Monitor', 5 | 'menu.dashboard.monitor': 'Overview', 6 | 'menu.dashboard.topics': 'Topics', 7 | 'menu.dashboard.clients': 'Client', 8 | 'menu.dashboard.subscription': 'Subscription', 9 | 'menu.ruleEngine': 'RuleEngine', 10 | 'menu.ruleEngine.resources': 'Resources', 11 | 'menu.ruleEngine.ruleEngine': 'RuleEngine', 12 | 'menu.modules': 'Modules', 13 | 'menu.modules.modules': 'Modules', 14 | 'menu.account.logout': 'Logout', 15 | 'menu.account.settings': 'Settings', 16 | 'menu.plugs': 'Plugs', 17 | 'menu.plugs.plugs': 'Plugs' 18 | } 19 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/overview.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'overview.systemName': 'System Name' 3 | } 4 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/result.js: -------------------------------------------------------------------------------- 1 | import success from './result/success' 2 | import fail from './result/fail' 3 | 4 | export default { 5 | ...success, 6 | ...fail 7 | } 8 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/result/fail.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'result.fail.error.title': 'Submission Failed', 3 | 'result.fail.error.description': 4 | 'Please check and modify the following information before resubmitting.', 5 | 'result.fail.error.hint-title': 'The content you submitted has the following error:', 6 | 'result.fail.error.hint-text1': 'Your account has been frozen', 7 | 'result.fail.error.hint-btn1': 'Thaw immediately', 8 | 'result.fail.error.hint-text2': 'Your account is not yet eligible to apply', 9 | 'result.fail.error.hint-btn2': 'Upgrade immediately', 10 | 'result.fail.error.btn-text': 'Return to modify' 11 | } 12 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/en-US/result/success.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'result.success.title': 'Submission Success', 3 | 'result.success.description': 4 | 'The submission results page is used to feed back the results of a series of operational tasks. If it is a simple operation, use the Message global prompt feedback. This text area can show a simple supplementary explanation. If there is a similar requirement for displaying “documents”, the following gray area can present more complicated content.', 5 | 'result.success.operate-title': 'Project Name', 6 | 'result.success.operate-id': 'Project ID', 7 | 'result.success.principal': 'Principal', 8 | 'result.success.operate-time': 'Effective time', 9 | 'result.success.step1-title': 'Create project', 10 | 'result.success.step1-operator': 'Qu Lili', 11 | 'result.success.step2-title': 'Departmental preliminary review', 12 | 'result.success.step2-operator': 'Zhou Maomao', 13 | 'result.success.step2-extra': 'Urge', 14 | 'result.success.step3-title': 'Financial review', 15 | 'result.success.step4-title': 'Finish', 16 | 'result.success.btn-return': 'Back List', 17 | 'result.success.btn-project': 'View Project', 18 | 'result.success.btn-print': 'Print' 19 | } 20 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN.js: -------------------------------------------------------------------------------- 1 | import antd from 'ant-design-vue/es/locale-provider/zh_CN' 2 | import momentCN from 'moment/locale/zh-cn' 3 | import global from './zh-CN/global' 4 | 5 | import menu from './zh-CN/menu' 6 | import setting from './zh-CN/setting' 7 | import user from './zh-CN/user' 8 | import dashboard from './zh-CN/dashboard' 9 | import form from './zh-CN/form' 10 | import result from './zh-CN/result' 11 | import account from './zh-CN/account' 12 | import overview from './zh-CN/overview' 13 | 14 | const components = { 15 | antLocale: antd, 16 | momentName: 'zh-cn', 17 | momentLocale: momentCN 18 | } 19 | 20 | export default { 21 | message: '-', 22 | 23 | 'layouts.usermenu.dialog.title': '信息', 24 | 'layouts.usermenu.dialog.content': '您确定要注销吗?', 25 | 'layouts.userLayout.title': 'MQTT Broker System', 26 | ...components, 27 | ...global, 28 | ...menu, 29 | ...setting, 30 | ...user, 31 | ...dashboard, 32 | ...form, 33 | ...result, 34 | overview, 35 | ...account 36 | } 37 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/account.js: -------------------------------------------------------------------------------- 1 | import settings from './account/settings' 2 | 3 | export default { 4 | ...settings 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/dashboard.js: -------------------------------------------------------------------------------- 1 | import analysis from './dashboard/analysis' 2 | 3 | export default { 4 | ...analysis 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/form.js: -------------------------------------------------------------------------------- 1 | import basicForm from './form/basicForm' 2 | 3 | export default { 4 | ...basicForm 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/global.js: -------------------------------------------------------------------------------- 1 | export default { 2 | submit: '提交', 3 | save: '保存', 4 | 'submit.ok': '提交成功', 5 | 'save.ok': '保存成功' 6 | } 7 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/menu.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'menu.welcome': '欢迎', 3 | 'menu.home': '主页', 4 | 'menu.dashboard': '监控', 5 | 'menu.dashboard.monitor': '概述', 6 | 'menu.dashboard.clients': '客户端', 7 | 'menu.dashboard.topics': '主题', 8 | 'menu.dashboard.subscription': '订阅', 9 | 'menu.ruleEngine': '规则引擎', 10 | 'menu.ruleEngine.resources': '资源', 11 | 'menu.ruleEngine.ruleEngine': '规则引擎', 12 | 'menu.modules': '模块', 13 | 'menu.modules.modules': '模块', 14 | 'menu.account.logout': '登出', 15 | 'menu.account.settings': '设置', 16 | 'menu.plugs': '插件', 17 | 'menu.plugs.plugs': '插件' 18 | } 19 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/overview.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'overview.systemName': '系统名' 3 | } 4 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/result.js: -------------------------------------------------------------------------------- 1 | import success from './result/success' 2 | import fail from './result/fail' 3 | 4 | export default { 5 | ...success, 6 | ...fail 7 | } 8 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/result/fail.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'result.fail.error.title': '提交失败', 3 | 'result.fail.error.description': '请核对并修改以下信息后,再重新提交。', 4 | 'result.fail.error.hint-title': '您提交的内容有如下错误:', 5 | 'result.fail.error.hint-text1': '您的账户已被冻结', 6 | 'result.fail.error.hint-btn1': '立即解冻', 7 | 'result.fail.error.hint-text2': '您的账户还不具备申请资格', 8 | 'result.fail.error.hint-btn2': '立即升级', 9 | 'result.fail.error.btn-text': '返回修改' 10 | } 11 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/result/success.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'result.success.title': '提交成功', 3 | 'result.success.description': 4 | '提交结果页用于反馈一系列操作任务的处理结果, 如果仅是简单操作,使用 Message 全局提示反馈即可。 本文字区域可以展示简单的补充说明,如果有类似展示 “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。', 5 | 'result.success.operate-title': '项目名称', 6 | 'result.success.operate-id': '项目 ID', 7 | 'result.success.principal': '负责人', 8 | 'result.success.operate-time': '生效时间', 9 | 'result.success.step1-title': '创建项目', 10 | 'result.success.step1-operator': '曲丽丽', 11 | 'result.success.step2-title': '部门初审', 12 | 'result.success.step2-operator': '周毛毛', 13 | 'result.success.step2-extra': '催一下', 14 | 'result.success.step3-title': '财务复核', 15 | 'result.success.step4-title': '完成', 16 | 'result.success.btn-return': '返回列表', 17 | 'result.success.btn-project': '查看项目', 18 | 'result.success.btn-print': '打印' 19 | } 20 | -------------------------------------------------------------------------------- /mmq-ui/src/locales/lang/zh-CN/setting.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'app.setting.pagestyle': '整体风格设置', 3 | 'app.setting.pagestyle.light': '亮色菜单风格', 4 | 'app.setting.pagestyle.dark': '暗色菜单风格', 5 | 'app.setting.pagestyle.realdark': '暗黑模式', 6 | 'app.setting.themecolor': '主题色', 7 | 'app.setting.navigationmode': '导航模式', 8 | 'app.setting.content-width': '内容区域宽度', 9 | 'app.setting.fixedheader': '固定 Header', 10 | 'app.setting.fixedsidebar': '固定侧边栏', 11 | 'app.setting.sidemenu': '侧边菜单布局', 12 | 'app.setting.topmenu': '顶部菜单布局', 13 | 'app.setting.content-width.fixed': 'Fixed', 14 | 'app.setting.content-width.fluid': 'Fluid', 15 | 'app.setting.othersettings': '其他设置', 16 | 'app.setting.weakmode': '色弱模式', 17 | 'app.setting.copy': '拷贝设置', 18 | 'app.setting.loading': '加载主题中', 19 | 'app.setting.copyinfo': '拷贝设置成功 src/config/defaultSettings.js', 20 | 'app.setting.production.hint': '配置栏只在开发环境用于预览,生产环境不会展现,请拷贝后手动修改配置文件', 21 | 'app.setting.themecolor.daybreak': '拂晓蓝', 22 | 'app.setting.themecolor.dust': '薄暮', 23 | 'app.setting.themecolor.volcano': '火山', 24 | 'app.setting.themecolor.sunset': '日暮', 25 | 'app.setting.themecolor.cyan': '明青', 26 | 'app.setting.themecolor.green': '极光绿', 27 | 'app.setting.themecolor.geekblue': '极客蓝', 28 | 'app.setting.themecolor.purple': '酱紫' 29 | } 30 | -------------------------------------------------------------------------------- /mmq-ui/src/main.js: -------------------------------------------------------------------------------- 1 | // with polyfills 2 | import 'core-js/stable' 3 | import 'regenerator-runtime/runtime' 4 | 5 | import Vue from 'vue' 6 | import App from './App.vue' 7 | import router from './router' 8 | import store from './store/' 9 | import i18n from './locales' 10 | import { VueAxios } from './utils/request' 11 | import ProLayout, { PageHeaderWrapper } from '@ant-design-vue/pro-layout' 12 | import themePluginConfig from '../config/themePluginConfig' 13 | 14 | // mock 15 | // WARNING: `mockjs` NOT SUPPORT `IE` PLEASE DO NOT USE IN `production` ENV. 16 | import './mock' 17 | 18 | import bootstrap from './core/bootstrap' 19 | import './core/lazy_use' // use lazy load components 20 | import './permission' // permission control 21 | import './utils/filter' // global filter 22 | import './global.less' // global style 23 | 24 | Vue.config.productionTip = false 25 | 26 | // mount axios to `Vue.$http` and `this.$http` 27 | Vue.use(VueAxios) 28 | // use pro-layout components 29 | Vue.component('pro-layout', ProLayout) 30 | Vue.component('page-container', PageHeaderWrapper) 31 | Vue.component('page-header-wrapper', PageHeaderWrapper) 32 | 33 | window.umi_plugin_ant_themeVar = themePluginConfig.theme 34 | 35 | new Vue({ 36 | router, 37 | store, 38 | i18n, 39 | // init localstorage, vuex, Logo message 40 | created: bootstrap, 41 | render: h => h(App) 42 | }).$mount('#app') 43 | -------------------------------------------------------------------------------- /mmq-ui/src/mock/index.js: -------------------------------------------------------------------------------- 1 | import { isIE } from '@/utils/util' 2 | 3 | // 判断环境不是 prod 或者 preview 是 true 时,加载 mock 服务 4 | if (process.env.NODE_ENV !== 'production' || process.env.VUE_APP_PREVIEW === 'true') { 5 | if (isIE()) { 6 | console.error('[antd-pro] ERROR: `mockjs` NOT SUPPORT `IE` PLEASE DO NOT USE IN `production` ENV.') 7 | } 8 | // 使用同步加载依赖 9 | // 防止 vuex 中的 GetInfo 早于 mock 运行,导致无法 mock 请求返回结果 10 | console.log('[antd-pro] mock mounting') 11 | const Mock = require('mockjs2') 12 | require('./services/auth') 13 | require('./services/user') 14 | require('./services/manage') 15 | require('./services/other') 16 | require('./services/tagCloud') 17 | require('./services/article') 18 | 19 | Mock.setup({ 20 | timeout: 800 // setter delay time 21 | }) 22 | console.log('[antd-pro] mock mounted') 23 | } 24 | -------------------------------------------------------------------------------- /mmq-ui/src/mock/util.js: -------------------------------------------------------------------------------- 1 | const responseBody = { 2 | message: '', 3 | timestamp: 0, 4 | result: null, 5 | code: 0 6 | } 7 | 8 | export const builder = (data, message, code = 0, headers = {}) => { 9 | responseBody.result = data 10 | if (message !== undefined && message !== null) { 11 | responseBody.message = message 12 | } 13 | if (code !== undefined && code !== 0) { 14 | responseBody.code = code 15 | responseBody._status = code 16 | } 17 | if (headers !== null && typeof headers === 'object' && Object.keys(headers).length > 0) { 18 | responseBody._headers = headers 19 | } 20 | responseBody.timestamp = new Date().getTime() 21 | return responseBody 22 | } 23 | 24 | export const getQueryParameters = (options) => { 25 | const url = options.url 26 | const search = url.split('?')[1] 27 | if (!search) { 28 | return {} 29 | } 30 | return JSON.parse('{"' + decodeURIComponent(search) 31 | .replace(/"/g, '\\"') 32 | .replace(/&/g, '","') 33 | .replace(/=/g, '":"') + '"}') 34 | } 35 | 36 | export const getBody = (options) => { 37 | return options.body && JSON.parse(options.body) 38 | } 39 | -------------------------------------------------------------------------------- /mmq-ui/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import { constantRouterMap } from '@/config/router.config' 4 | 5 | // hack router push callback 6 | const originalPush = Router.prototype.push 7 | Router.prototype.push = function push (location, onResolve, onReject) { 8 | if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject) 9 | return originalPush.call(this, location).catch(err => err) 10 | } 11 | 12 | Vue.use(Router) 13 | 14 | export default new Router({ 15 | mode: 'history', 16 | routes: constantRouterMap 17 | }) 18 | -------------------------------------------------------------------------------- /mmq-ui/src/store/app-mixin.js: -------------------------------------------------------------------------------- 1 | import { mapState } from 'vuex' 2 | 3 | const baseMixin = { 4 | computed: { 5 | ...mapState({ 6 | layout: state => state.app.layout, 7 | navTheme: state => state.app.theme, 8 | primaryColor: state => state.app.color, 9 | colorWeak: state => state.app.weak, 10 | fixedHeader: state => state.app.fixedHeader, 11 | fixedSidebar: state => state.app.fixedSidebar, 12 | contentWidth: state => state.app.contentWidth, 13 | autoHideHeader: state => state.app.autoHideHeader, 14 | 15 | isMobile: state => state.app.isMobile, 16 | sideCollapsed: state => state.app.sideCollapsed, 17 | multiTab: state => state.app.multiTab 18 | }), 19 | isTopMenu () { 20 | return this.layout === 'topmenu' 21 | } 22 | }, 23 | methods: { 24 | isSideMenu () { 25 | return !this.isTopMenu 26 | } 27 | } 28 | } 29 | 30 | export { 31 | baseMixin 32 | } 33 | -------------------------------------------------------------------------------- /mmq-ui/src/store/device-mixin.js: -------------------------------------------------------------------------------- 1 | import { mapState } from 'vuex' 2 | 3 | const deviceMixin = { 4 | computed: { 5 | ...mapState({ 6 | isMobile: state => state.app.isMobile 7 | }) 8 | } 9 | } 10 | 11 | export { deviceMixin } 12 | -------------------------------------------------------------------------------- /mmq-ui/src/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | isMobile: state => state.app.isMobile, 3 | lang: state => state.app.lang, 4 | theme: state => state.app.theme, 5 | color: state => state.app.color, 6 | token: state => state.user.token, 7 | avatar: state => state.user.avatar, 8 | nickname: state => state.user.name, 9 | welcome: state => state.user.welcome, 10 | roles: state => state.user.roles, 11 | userInfo: state => state.user.info, 12 | addRouters: state => state.permission.addRouters, 13 | multiTab: state => state.app.multiTab 14 | } 15 | 16 | export default getters 17 | -------------------------------------------------------------------------------- /mmq-ui/src/store/i18n-mixin.js: -------------------------------------------------------------------------------- 1 | import { mapState } from 'vuex' 2 | 3 | const i18nMixin = { 4 | computed: { 5 | ...mapState({ 6 | currentLang: state => state.app.lang 7 | }) 8 | }, 9 | methods: { 10 | setLang (lang) { 11 | this.$store.dispatch('setLang', lang) 12 | } 13 | } 14 | } 15 | 16 | export default i18nMixin 17 | -------------------------------------------------------------------------------- /mmq-ui/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import app from './modules/app' 5 | import user from './modules/user' 6 | 7 | // default router permission control 8 | import permission from './modules/permission' 9 | 10 | // dynamic router permission control (Experimental) 11 | // import permission from './modules/async-router' 12 | import getters from './getters' 13 | 14 | Vue.use(Vuex) 15 | 16 | export default new Vuex.Store({ 17 | modules: { 18 | app, 19 | user, 20 | permission 21 | }, 22 | state: { 23 | 24 | }, 25 | mutations: { 26 | 27 | }, 28 | actions: { 29 | 30 | }, 31 | getters 32 | }) 33 | -------------------------------------------------------------------------------- /mmq-ui/src/store/modules/async-router.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 向后端请求用户的菜单,动态生成路由 3 | */ 4 | import { constantRouterMap } from '@/config/router.config' 5 | import { generatorDynamicRouter } from '@/router/generator-routers' 6 | 7 | const permission = { 8 | state: { 9 | routers: constantRouterMap, 10 | addRouters: [] 11 | }, 12 | mutations: { 13 | SET_ROUTERS: (state, routers) => { 14 | state.addRouters = routers 15 | state.routers = constantRouterMap.concat(routers) 16 | } 17 | }, 18 | actions: { 19 | GenerateRoutes ({ commit }, data) { 20 | return new Promise(resolve => { 21 | const { token } = data 22 | generatorDynamicRouter(token).then(routers => { 23 | commit('SET_ROUTERS', routers) 24 | resolve() 25 | }) 26 | resolve() 27 | }) 28 | } 29 | } 30 | } 31 | 32 | export default permission 33 | -------------------------------------------------------------------------------- /mmq-ui/src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const ACCESS_TOKEN = 'Access-Token' 2 | 3 | export const SIDEBAR_TYPE = 'sidebar_type' 4 | export const TOGGLE_MOBILE_TYPE = 'is_mobile' 5 | export const TOGGLE_NAV_THEME = 'nav_theme' 6 | export const TOGGLE_LAYOUT = 'layout' 7 | export const TOGGLE_FIXED_HEADER = 'fixed_header' 8 | export const TOGGLE_FIXED_SIDEBAR = 'fixed_sidebar' 9 | export const TOGGLE_CONTENT_WIDTH = 'content_width' 10 | export const TOGGLE_HIDE_HEADER = 'auto_hide_header' 11 | export const TOGGLE_COLOR = 'color' 12 | export const TOGGLE_WEAK = 'weak' 13 | export const TOGGLE_MULTI_TAB = 'multi_tab' 14 | export const APP_LANGUAGE = 'app_language' 15 | 16 | export const CONTENT_WIDTH_TYPE = { 17 | Fluid: 'Fluid', 18 | Fixed: 'Fixed' 19 | } 20 | 21 | export const NAV_THEME = { 22 | LIGHT: 'light', 23 | DARK: 'dark' 24 | } 25 | -------------------------------------------------------------------------------- /mmq-ui/src/utils/axios.js: -------------------------------------------------------------------------------- 1 | const VueAxios = { 2 | vm: {}, 3 | // eslint-disable-next-line no-unused-vars 4 | install (Vue, instance) { 5 | if (this.installed) { 6 | return 7 | } 8 | this.installed = true 9 | 10 | if (!instance) { 11 | // eslint-disable-next-line no-console 12 | console.error('You have to install axios') 13 | return 14 | } 15 | 16 | Vue.axios = instance 17 | 18 | Object.defineProperties(Vue.prototype, { 19 | axios: { 20 | get: function get () { 21 | return instance 22 | } 23 | }, 24 | $http: { 25 | get: function get () { 26 | return instance 27 | } 28 | } 29 | }) 30 | } 31 | } 32 | 33 | export { 34 | VueAxios 35 | } 36 | -------------------------------------------------------------------------------- /mmq-ui/src/utils/domUtil.js: -------------------------------------------------------------------------------- 1 | import config from '@/config/defaultSettings' 2 | 3 | export const setDocumentTitle = function (title) { 4 | document.title = title 5 | const ua = navigator.userAgent 6 | // eslint-disable-next-line 7 | const regex = /\bMicroMessenger\/([\d\.]+)/ 8 | if (regex.test(ua) && /ip(hone|od|ad)/i.test(ua)) { 9 | const i = document.createElement('iframe') 10 | i.src = '/favicon.ico' 11 | i.style.display = 'none' 12 | i.onload = function () { 13 | setTimeout(function () { 14 | i.remove() 15 | }, 9) 16 | } 17 | document.body.appendChild(i) 18 | } 19 | } 20 | 21 | export const domTitle = config.title 22 | -------------------------------------------------------------------------------- /mmq-ui/src/utils/filter.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import moment from 'moment' 3 | import 'moment/locale/zh-cn' 4 | moment.locale('zh-cn') 5 | 6 | Vue.filter('NumberFormat', function (value) { 7 | if (!value) { 8 | return '0' 9 | } 10 | const intPartFormat = value.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') // 将整数部分逢三一断 11 | return intPartFormat 12 | }) 13 | 14 | Vue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { 15 | return moment(dataStr).format(pattern) 16 | }) 17 | 18 | Vue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { 19 | return moment(dataStr).format(pattern) 20 | }) 21 | -------------------------------------------------------------------------------- /mmq-ui/src/utils/routeConvert.js: -------------------------------------------------------------------------------- 1 | import cloneDeep from 'lodash.clonedeep' 2 | 3 | export function convertRoutes (nodes) { 4 | if (!nodes) return null 5 | 6 | nodes = cloneDeep(nodes) 7 | 8 | let queue = Array.isArray(nodes) ? nodes.concat() : [nodes] 9 | 10 | while (queue.length) { 11 | const levelSize = queue.length 12 | 13 | for (let i = 0; i < levelSize; i++) { 14 | const node = queue.shift() 15 | 16 | if (!node.children || !node.children.length) continue 17 | 18 | node.children.forEach(child => { 19 | // 转化相对路径 20 | if (child.path[0] !== '/' && !child.path.startsWith('http')) { 21 | child.path = node.path.replace(/(\w*)[/]*$/, `$1/${child.path}`) 22 | } 23 | }) 24 | 25 | queue = queue.concat(node.children) 26 | } 27 | } 28 | 29 | return nodes 30 | } 31 | -------------------------------------------------------------------------------- /mmq-ui/src/utils/screenLog.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export const printANSI = () => { 3 | // console.clear() 4 | console.log('[antd pro] created()') 5 | // ASCII - ANSI Shadow 6 | let text = ` 7 | __ __ __ __ ___ 8 | | \/ || \/ | / _ \ 9 | | |\/| || |\/| || (_) | 10 | |_|__|_||_|__|_| \__\_\ 11 | _|"""""|_|"""""|_|"""""| 12 | \t\t\t\t\tPublished ${APP_VERSION}-${GIT_HASH} @ antdv.com 13 | \t\t\t\t\tBuild date: ${BUILD_DATE}` 14 | console.log(`%c${text}`, 'color: #fc4d50') 15 | console.log('%c感谢使用 MMQ!', 'color: #000; font-size: 14px; font-family: Hiragino Sans GB,Microsoft YaHei,\\\\5FAE\\8F6F\\96C5\\9ED1,Droid Sans Fallback,Source Sans,Wenquanyi Micro Hei,WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei,Apple LiGothic Medium,SimHei,ST Heiti,WenQuanYi Zen Hei Sharp,sans-serif;') 16 | console.log('%cThanks for using MMQ!', 'color: #fff; font-size: 14px; font-weight: 300; text-shadow:#000 1px 0 0,#000 0 1px 0,#000 -1px 0 0,#000 0 -1px 0;') 17 | } 18 | -------------------------------------------------------------------------------- /mmq-ui/src/utils/utils.less: -------------------------------------------------------------------------------- 1 | .textOverflow() { 2 | overflow: hidden; 3 | white-space: nowrap; 4 | text-overflow: ellipsis; 5 | word-break: break-all; 6 | } 7 | 8 | .textOverflowMulti(@line: 3, @bg: #fff) { 9 | position: relative; 10 | max-height: @line * 1.5em; 11 | margin-right: -1em; 12 | padding-right: 1em; 13 | overflow: hidden; 14 | line-height: 1.5em; 15 | text-align: justify; 16 | &::before { 17 | position: absolute; 18 | right: 14px; 19 | bottom: 0; 20 | padding: 0 1px; 21 | background: @bg; 22 | content: '...'; 23 | } 24 | &::after { 25 | position: absolute; 26 | right: 14px; 27 | width: 1em; 28 | height: 1em; 29 | margin-top: 0.2em; 30 | background: white; 31 | content: ''; 32 | } 33 | } 34 | 35 | // mixins for clearfix 36 | // ------------------------ 37 | .clearfix() { 38 | zoom: 1; 39 | &::before, 40 | &::after { 41 | display: table; 42 | content: ' '; 43 | } 44 | &::after { 45 | clear: both; 46 | height: 0; 47 | font-size: 0; 48 | visibility: hidden; 49 | } 50 | } -------------------------------------------------------------------------------- /mmq-ui/src/views/404.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /mmq-ui/src/views/exception/403.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /mmq-ui/src/views/exception/404.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /mmq-ui/src/views/exception/500.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /mmq-ui/src/views/user/RegisterResult.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 41 | 42 | 45 | -------------------------------------------------------------------------------- /mmq-ui/tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /mmq-ui/webstorm.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const webpackConfig = require('@vue/cli-service/webpack.config.js') 3 | module.exports = webpackConfig 4 | -------------------------------------------------------------------------------- /mmq-web/src/main/java/org/monkey/mmq/web/Mmq.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.web; 17 | 18 | import org.monkey.mmq.core.env.EnvUtil; 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | import org.springframework.boot.web.servlet.ServletComponentScan; 22 | 23 | import java.util.TimeZone; 24 | 25 | /** 26 | * Health Controller. 27 | * 28 | * @author solley 29 | */ 30 | @SpringBootApplication(scanBasePackages = "org.monkey.mmq") 31 | @ServletComponentScan 32 | public class Mmq { 33 | public static void main(String[] args) { 34 | // EnvUtil.setIsStandalone(true); 35 | SpringApplication.run(Mmq.class, args); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /mmq-web/src/main/java/org/monkey/mmq/web/config/BasicApi.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.web.config; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @ClassNameBasicApi 7 | * @Description HTTP API 使用Basic认证方式,id 和 password 须分别填写 AppID 和 AppSecret 8 | * @Author Solley 9 | * @Date2022/1/19 12:43 10 | * @Version V1.0 11 | **/ 12 | @Documented 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(ElementType.METHOD) 15 | public @interface BasicApi { 16 | } 17 | -------------------------------------------------------------------------------- /mmq-web/src/main/java/org/monkey/mmq/web/config/NotWrap.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.web.config; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 对spring mvc controller返回的结果不进行封装,直接以原生结果返回 7 | * @author solley 8 | * @date 2018年4月3日 上午9:10:41 123123123 9 | * @version 1.0.0 10 | */ 11 | @Documented 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.METHOD) 14 | public @interface NotWrap { 15 | String value() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /mmq-web/src/main/java/org/monkey/mmq/web/controller/HealthController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 Monkey Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.monkey.mmq.web.controller; 17 | 18 | import org.springframework.http.ResponseEntity; 19 | import org.springframework.web.bind.annotation.GetMapping; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RestController; 22 | 23 | /** 24 | * Health Controller. 25 | * 26 | * @author solley 27 | */ 28 | @RestController 29 | @RequestMapping("/v1/console/health") 30 | public class HealthController { 31 | @GetMapping("/liveness") 32 | public ResponseEntity liveness() { 33 | return ResponseEntity.ok().body("OK"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mmq-web/src/main/java/org/monkey/mmq/web/util/BaseContextUtil.java: -------------------------------------------------------------------------------- 1 | package org.monkey.mmq.web.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class BaseContextUtil { 7 | 8 | public static final String USER_NAME = "username"; 9 | 10 | public static ThreadLocal> threadLocal = new ThreadLocal>(); 11 | 12 | public static void set(String key, Object value) { 13 | Map map = threadLocal.get(); 14 | if (map == null) { 15 | map = new HashMap(); 16 | threadLocal.set(map); 17 | } 18 | map.put(key, value); 19 | } 20 | 21 | public static Object get(String key){ 22 | Map map = threadLocal.get(); 23 | if (map == null) { 24 | map = new HashMap(); 25 | threadLocal.set(map); 26 | } 27 | return map.get(key) == null ? "" : map.get(key); 28 | } 29 | 30 | private static String returnObjectValue(Object value) { 31 | return value==null?null:value.toString(); 32 | } 33 | 34 | public static void remove(){ 35 | threadLocal.remove(); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /mmq-web/src/main/resources/mmq-version.txt: -------------------------------------------------------------------------------- 1 | version=${project.version} 2 | -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/avatar2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/mmq-web/src/main/resources/static/avatar2.jpg -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/css/user.7020778c.css: -------------------------------------------------------------------------------- 1 | .step-form-wrapper[data-v-4a462ef6]{margin:0 auto;width:80%;max-width:400px}.user-layout-login label[data-v-13d99ba0]{font-size:14px}.user-layout-login .getCaptcha[data-v-13d99ba0]{display:block;width:100%;height:40px}.user-layout-login .forge-password[data-v-13d99ba0]{font-size:14px}.user-layout-login button.login-button[data-v-13d99ba0]{padding:0 15px;font-size:16px;height:40px;width:100%}.user-layout-login .user-login-other[data-v-13d99ba0]{text-align:left;margin-top:24px;line-height:22px}.user-layout-login .user-login-other .item-icon[data-v-13d99ba0]{font-size:24px;color:rgba(0,0,0,.2);margin-left:16px;vertical-align:middle;cursor:pointer;-webkit-transition:color .3s;transition:color .3s}.user-layout-login .user-login-other .item-icon[data-v-13d99ba0]:hover{color:#1890ff}.user-layout-login .user-login-other .register[data-v-13d99ba0]{float:right}.user-register.error{color:red}.user-register.warning{color:#ff7e05}.user-register.success{color:#52c41a}.user-layout-register .ant-input-group-addon:first-child{background-color:#fff}.user-layout-register>h3[data-v-3f0943cc]{font-size:16px;margin-bottom:20px}.user-layout-register .getCaptcha[data-v-3f0943cc]{display:block;width:100%;height:40px}.user-layout-register .register-button[data-v-3f0943cc]{width:50%}.user-layout-register .login[data-v-3f0943cc]{float:right;line-height:40px} -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/fail.e5dc8464.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["fail"],{cc89:function(t,e,o){"use strict";o.r(e);var n=function(){var t=this,e=t.$createElement,o=t._self._c||e;return o("a-result",{attrs:{status:"404",title:"404","sub-title":"Sorry, the page you visited does not exist."},scopedSlots:t._u([{key:"extra",fn:function(){return[o("a-button",{attrs:{type:"primary"},on:{click:t.toHome}},[t._v(" Back Home ")])]},proxy:!0}])})},s=[],r={name:"Exception404",methods:{toHome:function(){this.$router.push({path:"/"})}}},u=r,a=o("2877"),i=Object(a["a"])(u,n,s,!1,null,null,null);e["default"]=i.exports}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/lang-zh-CN-global.2ab19788.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["lang-zh-CN-global"],{1858:function(s,o,a){"use strict";a.r(o),o["default"]={submit:"提交",save:"保存","submit.ok":"提交成功","save.ok":"保存成功"}}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/lang-zh-CN-menu.a4978041.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["lang-zh-CN-menu"],{"1dec":function(e,n,u){"use strict";u.r(n),n["default"]={"menu.welcome":"欢迎","menu.home":"主页","menu.dashboard":"监控","menu.dashboard.monitor":"概述","menu.dashboard.clients":"客户端","menu.dashboard.topics":"主题","menu.dashboard.subscription":"订阅","menu.ruleEngine":"规则引擎","menu.ruleEngine.resources":"资源","menu.ruleEngine.ruleEngine":"规则引擎","menu.modules":"模块","menu.modules.modules":"模块","menu.account.logout":"登出","menu.account.settings":"设置","menu.plugs":"插件","menu.plugs.plugs":"插件"}}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/lang-zh-CN-overview.5670809e.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["lang-zh-CN-overview"],{ce35:function(e,w,n){"use strict";n.r(w),w["default"]={"overview.systemName":"系统名"}}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/lang-zh-CN-result-fail.e3747840.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["lang-zh-CN-result-fail"],{d5c8:function(r,t,e){"use strict";e.r(t),t["default"]={"result.fail.error.title":"提交失败","result.fail.error.description":"请核对并修改以下信息后,再重新提交。","result.fail.error.hint-title":"您提交的内容有如下错误:","result.fail.error.hint-text1":"您的账户已被冻结","result.fail.error.hint-btn1":"立即解冻","result.fail.error.hint-text2":"您的账户还不具备申请资格","result.fail.error.hint-btn2":"立即升级","result.fail.error.btn-text":"返回修改"}}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/lang-zh-CN-result-success.349556c5.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["lang-zh-CN-result-success"],{"4fd4":function(s,e,t){"use strict";t.r(e),e["default"]={"result.success.title":"提交成功","result.success.description":"提交结果页用于反馈一系列操作任务的处理结果, 如果仅是简单操作,使用 Message 全局提示反馈即可。 本文字区域可以展示简单的补充说明,如果有类似展示 “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。","result.success.operate-title":"项目名称","result.success.operate-id":"项目 ID","result.success.principal":"负责人","result.success.operate-time":"生效时间","result.success.step1-title":"创建项目","result.success.step1-operator":"曲丽丽","result.success.step2-title":"部门初审","result.success.step2-operator":"周毛毛","result.success.step2-extra":"催一下","result.success.step3-title":"财务复核","result.success.step4-title":"完成","result.success.btn-return":"返回列表","result.success.btn-project":"查看项目","result.success.btn-print":"打印"}}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/lang-zh-CN-result.1a9c63f2.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["lang-zh-CN-result","lang-zh-CN-result-fail","lang-zh-CN-result-success"],{"4fd4":function(e,s,t){"use strict";t.r(s),s["default"]={"result.success.title":"提交成功","result.success.description":"提交结果页用于反馈一系列操作任务的处理结果, 如果仅是简单操作,使用 Message 全局提示反馈即可。 本文字区域可以展示简单的补充说明,如果有类似展示 “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。","result.success.operate-title":"项目名称","result.success.operate-id":"项目 ID","result.success.principal":"负责人","result.success.operate-time":"生效时间","result.success.step1-title":"创建项目","result.success.step1-operator":"曲丽丽","result.success.step2-title":"部门初审","result.success.step2-operator":"周毛毛","result.success.step2-extra":"催一下","result.success.step3-title":"财务复核","result.success.step4-title":"完成","result.success.btn-return":"返回列表","result.success.btn-project":"查看项目","result.success.btn-print":"打印"}},8176:function(e,s,t){"use strict";t.r(s);var r=t("5530"),u=t("4fd4"),l=t("d5c8");s["default"]=Object(r["a"])(Object(r["a"])({},u["default"]),l["default"])},d5c8:function(e,s,t){"use strict";t.r(s),s["default"]={"result.fail.error.title":"提交失败","result.fail.error.description":"请核对并修改以下信息后,再重新提交。","result.fail.error.hint-title":"您提交的内容有如下错误:","result.fail.error.hint-text1":"您的账户已被冻结","result.fail.error.hint-btn1":"立即解冻","result.fail.error.hint-text2":"您的账户还不具备申请资格","result.fail.error.hint-btn2":"立即升级","result.fail.error.btn-text":"返回修改"}}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/js/lang-zh-CN-setting.78d9e9d1.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["lang-zh-CN-setting"],{5436:function(t,e,p){"use strict";p.r(e),e["default"]={"app.setting.pagestyle":"整体风格设置","app.setting.pagestyle.light":"亮色菜单风格","app.setting.pagestyle.dark":"暗色菜单风格","app.setting.pagestyle.realdark":"暗黑模式","app.setting.themecolor":"主题色","app.setting.navigationmode":"导航模式","app.setting.content-width":"内容区域宽度","app.setting.fixedheader":"固定 Header","app.setting.fixedsidebar":"固定侧边栏","app.setting.sidemenu":"侧边菜单布局","app.setting.topmenu":"顶部菜单布局","app.setting.content-width.fixed":"Fixed","app.setting.content-width.fluid":"Fluid","app.setting.othersettings":"其他设置","app.setting.weakmode":"色弱模式","app.setting.copy":"拷贝设置","app.setting.loading":"加载主题中","app.setting.copyinfo":"拷贝设置成功 src/config/defaultSettings.js","app.setting.production.hint":"配置栏只在开发环境用于预览,生产环境不会展现,请拷贝后手动修改配置文件","app.setting.themecolor.daybreak":"拂晓蓝","app.setting.themecolor.dust":"薄暮","app.setting.themecolor.volcano":"火山","app.setting.themecolor.sunset":"日暮","app.setting.themecolor.cyan":"明青","app.setting.themecolor.green":"极光绿","app.setting.themecolor.geekblue":"极客蓝","app.setting.themecolor.purple":"酱紫"}}}]); -------------------------------------------------------------------------------- /mmq-web/src/main/resources/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrHKing/mmqtt/2fc9b0bc7ea67fa98dc85952483e75fb5595af3d/mmq-web/src/main/resources/static/logo.png -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_05292e21_2a71_46d6_b121_0882c2a1c42a_00000000.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_05292e21_2a71_46d6_b121_0882c2a1c42a_00000001.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_15d13a7b_1be2_4f8a_9950_5ec8ca58aea0_00000001.tmp: -------------------------------------------------------------------------------- 1 | paho1640921025845000001 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_15d13a7b_1be2_4f8a_9950_5ec8ca58aea0_00000002.tmp: -------------------------------------------------------------------------------- 1 | paho1640921025845000001 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_15d13a7b_1be2_4f8a_9950_5ec8ca58aea0_00000003.tmp: -------------------------------------------------------------------------------- 1 | paho1640921025845000001 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_22746656_c18e_4aca_b13c_6a18c1ea678f_00000000.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_22746656_c18e_4aca_b13c_6a18c1ea678f_00000001.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_240142ee_ddd8_4b72_8866_5e3d473415c8_00000000.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_240142ee_ddd8_4b72_8866_5e3d473415c8_00000001.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_46a4c671_c368_42ba_83ce_fdb7b6f827d4_00000000.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_46a4c671_c368_42ba_83ce_fdb7b6f827d4_00000001.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000000.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000001.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000004.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000005.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000006.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_4c2e9355_452a_4546_86af_a0d83b9c5e84_00000007.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_56b26020_9cdb_4e07_9a01_b0f5f533df6f_00000000.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_56b26020_9cdb_4e07_9a01_b0f5f533df6f_00000001.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_5cd7a0d8_b12d_4a1a_aa62_0e011aa387df_00000000.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_5cd7a0d8_b12d_4a1a_aa62_0e011aa387df_00000001.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000002.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000003.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000004.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_6d79732e_0954_4621_a445_ebc8d2793e99_00000005.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_98bb9a31_589f_4f58_9d02_9dea13a6b634_00000004.tmp: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_98bb9a31_589f_4f58_9d02_9dea13a6b634_00000005.tmp: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /work/Tomcat/localhost/ROOT/upload_99c060d3_6ed9_4ca3_ba74_5c2ce4c25a0f_00000000.tmp: -------------------------------------------------------------------------------- 1 | paho1640921025845000001 --------------------------------------------------------------------------------