Repository: 2014shijina2014/open-capacity-platform Branch: master Commit: 2edfb17e330c Files: 2815 Total size: 22.9 MB Directory structure: gitextract_7yrrkpra/ ├── .gitee/ │ ├── ISSUE_TEMPLATE.zh-CN.md │ └── PULL_REQUEST_TEMPLATE.zh-CN.md ├── .gitignore ├── .tgitconfig ├── LICENSE ├── README.md ├── open-api-gateway/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── docker/ │ │ └── Dockerfile │ ├── java/ │ │ └── com/ │ │ └── open/ │ │ └── capacity/ │ │ ├── GatewayApp.java │ │ ├── client/ │ │ │ └── oauth2/ │ │ │ ├── OAuth2ClientConfig.java │ │ │ ├── authorize/ │ │ │ │ ├── AuthorizeConfigManager.java │ │ │ │ ├── AuthorizeConfigProvider.java │ │ │ │ ├── OpenAuthorizeConfigManager.java │ │ │ │ └── provider/ │ │ │ │ └── AuthAuthorizeConfigProvider.java │ │ │ ├── config/ │ │ │ │ ├── DocumentationConfig.java │ │ │ │ ├── SecurityHandlerConfig.java │ │ │ │ └── SwaggerConfig.java │ │ │ ├── dao/ │ │ │ │ └── ServiceDao.java │ │ │ ├── filter/ │ │ │ │ ├── AccessFilter.java │ │ │ │ └── IPFilter.java │ │ │ ├── service/ │ │ │ │ ├── RbacService.java │ │ │ │ └── impl/ │ │ │ │ └── RbacServiceImpl.java │ │ │ └── token/ │ │ │ ├── TokenStoreConfig.java │ │ │ └── store/ │ │ │ └── RedisTemplateTokenStore.java │ │ └── controller/ │ │ ├── TestController.java │ │ └── UserController.java │ └── resources/ │ ├── application.yml │ └── bootstrap.yml ├── open-commons/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── open/ │ └── capacity/ │ └── security/ │ ├── dto/ │ │ ├── LoginUser.java │ │ ├── ResponseInfo.java │ │ ├── RoleDto.java │ │ └── UserDto.java │ └── model/ │ ├── BaseEntity.java │ ├── Permission.java │ ├── Role.java │ ├── SysLogs.java │ ├── SysUser.java │ └── TokenModel.java ├── open-config-center/ │ ├── apollo/ │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── apollo-adminservice/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── assembly/ │ │ │ │ └── assembly-descriptor.xml │ │ │ ├── main/ │ │ │ │ ├── config/ │ │ │ │ │ ├── apollo-adminservice.conf │ │ │ │ │ └── app.properties │ │ │ │ ├── docker/ │ │ │ │ │ └── Dockerfile │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── ctrip/ │ │ │ │ │ └── framework/ │ │ │ │ │ └── apollo/ │ │ │ │ │ └── adminservice/ │ │ │ │ │ ├── AdminServiceApplication.java │ │ │ │ │ ├── AdminServiceHealthIndicator.java │ │ │ │ │ ├── aop/ │ │ │ │ │ │ ├── NamespaceAcquireLockAspect.java │ │ │ │ │ │ ├── NamespaceUnlockAspect.java │ │ │ │ │ │ └── PreAcquireNamespaceLock.java │ │ │ │ │ └── controller/ │ │ │ │ │ ├── AppController.java │ │ │ │ │ ├── AppNamespaceController.java │ │ │ │ │ ├── ClusterController.java │ │ │ │ │ ├── CommitController.java │ │ │ │ │ ├── IndexController.java │ │ │ │ │ ├── InstanceConfigController.java │ │ │ │ │ ├── ItemController.java │ │ │ │ │ ├── ItemSetController.java │ │ │ │ │ ├── NamespaceBranchController.java │ │ │ │ │ ├── NamespaceController.java │ │ │ │ │ ├── NamespaceLockController.java │ │ │ │ │ ├── ReleaseController.java │ │ │ │ │ └── ReleaseHistoryController.java │ │ │ │ ├── resources/ │ │ │ │ │ ├── META-INF/ │ │ │ │ │ │ └── app.properties │ │ │ │ │ ├── adminservice.properties │ │ │ │ │ ├── application.yml │ │ │ │ │ ├── bootstrap.yml │ │ │ │ │ └── logback.xml │ │ │ │ └── scripts/ │ │ │ │ ├── shutdown.sh │ │ │ │ └── startup.sh │ │ │ └── test/ │ │ │ └── resources/ │ │ │ ├── application.properties │ │ │ ├── application.yml │ │ │ ├── bootstrap.yml │ │ │ ├── controller/ │ │ │ │ ├── cleanup.sql │ │ │ │ ├── test-itemset.sql │ │ │ │ └── test-release.sql │ │ │ ├── data.sql │ │ │ └── logback-test.xml │ │ ├── apollo-biz/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── main/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── ctrip/ │ │ │ │ └── framework/ │ │ │ │ └── apollo/ │ │ │ │ └── biz/ │ │ │ │ ├── ApolloBizConfig.java │ │ │ │ ├── auth/ │ │ │ │ │ └── WebSecurityConfig.java │ │ │ │ ├── config/ │ │ │ │ │ └── BizConfig.java │ │ │ │ ├── customize/ │ │ │ │ │ ├── BizLoggingCustomizer.java │ │ │ │ │ └── package-info.java │ │ │ │ ├── entity/ │ │ │ │ │ ├── Audit.java │ │ │ │ │ ├── Cluster.java │ │ │ │ │ ├── Commit.java │ │ │ │ │ ├── GrayReleaseRule.java │ │ │ │ │ ├── Instance.java │ │ │ │ │ ├── InstanceConfig.java │ │ │ │ │ ├── Item.java │ │ │ │ │ ├── Namespace.java │ │ │ │ │ ├── NamespaceLock.java │ │ │ │ │ ├── Privilege.java │ │ │ │ │ ├── Release.java │ │ │ │ │ ├── ReleaseHistory.java │ │ │ │ │ ├── ReleaseMessage.java │ │ │ │ │ └── ServerConfig.java │ │ │ │ ├── eureka/ │ │ │ │ │ └── ApolloEurekaClientConfig.java │ │ │ │ ├── grayReleaseRule/ │ │ │ │ │ ├── GrayReleaseRuleCache.java │ │ │ │ │ └── GrayReleaseRulesHolder.java │ │ │ │ ├── message/ │ │ │ │ │ ├── DatabaseMessageSender.java │ │ │ │ │ ├── MessageSender.java │ │ │ │ │ ├── ReleaseMessageListener.java │ │ │ │ │ ├── ReleaseMessageScanner.java │ │ │ │ │ └── Topics.java │ │ │ │ ├── repository/ │ │ │ │ │ ├── AppNamespaceRepository.java │ │ │ │ │ ├── AppRepository.java │ │ │ │ │ ├── AuditRepository.java │ │ │ │ │ ├── ClusterRepository.java │ │ │ │ │ ├── CommitRepository.java │ │ │ │ │ ├── GrayReleaseRuleRepository.java │ │ │ │ │ ├── InstanceConfigRepository.java │ │ │ │ │ ├── InstanceRepository.java │ │ │ │ │ ├── ItemRepository.java │ │ │ │ │ ├── NamespaceLockRepository.java │ │ │ │ │ ├── NamespaceRepository.java │ │ │ │ │ ├── PrivilegeRepository.java │ │ │ │ │ ├── ReleaseHistoryRepository.java │ │ │ │ │ ├── ReleaseMessageRepository.java │ │ │ │ │ ├── ReleaseRepository.java │ │ │ │ │ └── ServerConfigRepository.java │ │ │ │ ├── service/ │ │ │ │ │ ├── AdminService.java │ │ │ │ │ ├── AppNamespaceService.java │ │ │ │ │ ├── AppService.java │ │ │ │ │ ├── AuditService.java │ │ │ │ │ ├── BizDBPropertySource.java │ │ │ │ │ ├── ClusterService.java │ │ │ │ │ ├── CommitService.java │ │ │ │ │ ├── InstanceService.java │ │ │ │ │ ├── ItemService.java │ │ │ │ │ ├── ItemSetService.java │ │ │ │ │ ├── NamespaceBranchService.java │ │ │ │ │ ├── NamespaceLockService.java │ │ │ │ │ ├── NamespaceService.java │ │ │ │ │ ├── ReleaseHistoryService.java │ │ │ │ │ ├── ReleaseMessageService.java │ │ │ │ │ └── ReleaseService.java │ │ │ │ └── utils/ │ │ │ │ ├── ConfigChangeContentBuilder.java │ │ │ │ ├── EntityManagerUtil.java │ │ │ │ ├── ReleaseKeyGenerator.java │ │ │ │ └── ReleaseMessageKeyGenerator.java │ │ │ └── test/ │ │ │ └── resources/ │ │ │ ├── application.properties │ │ │ ├── data.sql │ │ │ ├── logback-test.xml │ │ │ └── sql/ │ │ │ ├── clean.sql │ │ │ ├── namespace-branch-test.sql │ │ │ ├── namespace-test.sql │ │ │ └── release-creation-test.sql │ │ ├── apollo-client/ │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── main/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── ctrip/ │ │ │ │ │ └── framework/ │ │ │ │ │ └── apollo/ │ │ │ │ │ ├── Config.java │ │ │ │ │ ├── ConfigChangeListener.java │ │ │ │ │ ├── ConfigFile.java │ │ │ │ │ ├── ConfigFileChangeListener.java │ │ │ │ │ ├── ConfigService.java │ │ │ │ │ ├── build/ │ │ │ │ │ │ └── ApolloInjector.java │ │ │ │ │ ├── enums/ │ │ │ │ │ │ └── PropertyChangeType.java │ │ │ │ │ ├── exceptions/ │ │ │ │ │ │ ├── ApolloConfigException.java │ │ │ │ │ │ └── ApolloConfigStatusCodeException.java │ │ │ │ │ ├── internals/ │ │ │ │ │ │ ├── AbstractConfig.java │ │ │ │ │ │ ├── AbstractConfigFile.java │ │ │ │ │ │ ├── AbstractConfigRepository.java │ │ │ │ │ │ ├── ConfigManager.java │ │ │ │ │ │ ├── ConfigRepository.java │ │ │ │ │ │ ├── ConfigServiceLocator.java │ │ │ │ │ │ ├── DefaultConfig.java │ │ │ │ │ │ ├── DefaultConfigManager.java │ │ │ │ │ │ ├── DefaultInjector.java │ │ │ │ │ │ ├── Injector.java │ │ │ │ │ │ ├── JsonConfigFile.java │ │ │ │ │ │ ├── LocalFileConfigRepository.java │ │ │ │ │ │ ├── PlainTextConfigFile.java │ │ │ │ │ │ ├── PropertiesConfigFile.java │ │ │ │ │ │ ├── RemoteConfigLongPollService.java │ │ │ │ │ │ ├── RemoteConfigRepository.java │ │ │ │ │ │ ├── RepositoryChangeListener.java │ │ │ │ │ │ ├── SimpleConfig.java │ │ │ │ │ │ ├── XmlConfigFile.java │ │ │ │ │ │ ├── YamlConfigFile.java │ │ │ │ │ │ └── YmlConfigFile.java │ │ │ │ │ ├── model/ │ │ │ │ │ │ ├── ConfigChange.java │ │ │ │ │ │ ├── ConfigChangeEvent.java │ │ │ │ │ │ └── ConfigFileChangeEvent.java │ │ │ │ │ ├── spi/ │ │ │ │ │ │ ├── ConfigFactory.java │ │ │ │ │ │ ├── ConfigFactoryManager.java │ │ │ │ │ │ ├── ConfigRegistry.java │ │ │ │ │ │ ├── DefaultConfigFactory.java │ │ │ │ │ │ ├── DefaultConfigFactoryManager.java │ │ │ │ │ │ └── DefaultConfigRegistry.java │ │ │ │ │ ├── spring/ │ │ │ │ │ │ ├── annotation/ │ │ │ │ │ │ │ ├── ApolloAnnotationProcessor.java │ │ │ │ │ │ │ ├── ApolloConfig.java │ │ │ │ │ │ │ ├── ApolloConfigChangeListener.java │ │ │ │ │ │ │ ├── ApolloConfigRegistrar.java │ │ │ │ │ │ │ ├── EnableApolloConfig.java │ │ │ │ │ │ │ └── SpringValueProcessor.java │ │ │ │ │ │ ├── boot/ │ │ │ │ │ │ │ ├── ApolloApplicationContextInitializer.java │ │ │ │ │ │ │ └── ApolloAutoConfiguration.java │ │ │ │ │ │ ├── config/ │ │ │ │ │ │ │ ├── ConfigPropertySource.java │ │ │ │ │ │ │ ├── ConfigPropertySourceFactory.java │ │ │ │ │ │ │ ├── ConfigPropertySourcesProcessor.java │ │ │ │ │ │ │ ├── NamespaceHandler.java │ │ │ │ │ │ │ ├── PropertySourcesConstants.java │ │ │ │ │ │ │ └── PropertySourcesProcessor.java │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── property/ │ │ │ │ │ │ │ ├── PlaceholderHelper.java │ │ │ │ │ │ │ ├── SpringValue.java │ │ │ │ │ │ │ ├── SpringValueDefinition.java │ │ │ │ │ │ │ └── SpringValueDefinitionProcessor.java │ │ │ │ │ │ └── util/ │ │ │ │ │ │ └── BeanRegistrationUtil.java │ │ │ │ │ └── util/ │ │ │ │ │ ├── ConfigUtil.java │ │ │ │ │ ├── ExceptionUtil.java │ │ │ │ │ ├── function/ │ │ │ │ │ │ └── Functions.java │ │ │ │ │ ├── http/ │ │ │ │ │ │ ├── HttpRequest.java │ │ │ │ │ │ ├── HttpResponse.java │ │ │ │ │ │ └── HttpUtil.java │ │ │ │ │ └── parser/ │ │ │ │ │ ├── ParserException.java │ │ │ │ │ └── Parsers.java │ │ │ │ └── resources/ │ │ │ │ └── META-INF/ │ │ │ │ ├── apollo-1.0.0.xsd │ │ │ │ ├── services/ │ │ │ │ │ └── com.ctrip.framework.apollo.internals.Injector │ │ │ │ ├── spring.factories │ │ │ │ ├── spring.handlers │ │ │ │ └── spring.schemas │ │ │ └── test/ │ │ │ └── resources/ │ │ │ ├── META-INF/ │ │ │ │ └── services/ │ │ │ │ └── com.ctrip.framework.apollo.internals.Injector │ │ │ ├── log4j2.xml │ │ │ └── spring/ │ │ │ ├── XmlConfigAnnotationTest1.xml │ │ │ ├── XmlConfigAnnotationTest2.xml │ │ │ ├── XmlConfigAnnotationTest3.xml │ │ │ ├── XmlConfigAnnotationTest4.xml │ │ │ ├── XmlConfigAnnotationTest5.xml │ │ │ ├── XmlConfigPlaceholderTest1.xml │ │ │ ├── XmlConfigPlaceholderTest10.xml │ │ │ ├── XmlConfigPlaceholderTest2.xml │ │ │ ├── XmlConfigPlaceholderTest3.xml │ │ │ ├── XmlConfigPlaceholderTest4.xml │ │ │ ├── XmlConfigPlaceholderTest5.xml │ │ │ ├── XmlConfigPlaceholderTest6.xml │ │ │ ├── XmlConfigPlaceholderTest7.xml │ │ │ ├── XmlConfigPlaceholderTest8.xml │ │ │ └── XmlConfigPlaceholderTest9.xml │ │ ├── apollo-common/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── main/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── ctrip/ │ │ │ │ │ └── framework/ │ │ │ │ │ └── apollo/ │ │ │ │ │ └── common/ │ │ │ │ │ ├── ApolloCommonConfig.java │ │ │ │ │ ├── aop/ │ │ │ │ │ │ └── RepositoryAspect.java │ │ │ │ │ ├── condition/ │ │ │ │ │ │ ├── ConditionalOnMissingProfile.java │ │ │ │ │ │ ├── ConditionalOnProfile.java │ │ │ │ │ │ └── OnProfileCondition.java │ │ │ │ │ ├── config/ │ │ │ │ │ │ ├── RefreshableConfig.java │ │ │ │ │ │ └── RefreshablePropertySource.java │ │ │ │ │ ├── constants/ │ │ │ │ │ │ ├── GsonType.java │ │ │ │ │ │ ├── NamespaceBranchStatus.java │ │ │ │ │ │ ├── ReleaseOperation.java │ │ │ │ │ │ └── ReleaseOperationContext.java │ │ │ │ │ ├── controller/ │ │ │ │ │ │ ├── ApolloInfoController.java │ │ │ │ │ │ ├── CharacterEncodingFilterConfiguration.java │ │ │ │ │ │ ├── GlobalDefaultExceptionHandler.java │ │ │ │ │ │ ├── HttpMessageConverterConfiguration.java │ │ │ │ │ │ └── WebMvcConfig.java │ │ │ │ │ ├── customize/ │ │ │ │ │ │ ├── LoggingCustomizer.java │ │ │ │ │ │ ├── TomcatContainerCustomizer.java │ │ │ │ │ │ └── package-info.java │ │ │ │ │ ├── datasource/ │ │ │ │ │ │ ├── TitanCondition.java │ │ │ │ │ │ ├── TitanEntityManager.java │ │ │ │ │ │ ├── TitanSettings.java │ │ │ │ │ │ └── package-info.java │ │ │ │ │ ├── dto/ │ │ │ │ │ │ ├── AppDTO.java │ │ │ │ │ │ ├── AppNamespaceDTO.java │ │ │ │ │ │ ├── BaseDTO.java │ │ │ │ │ │ ├── ClusterDTO.java │ │ │ │ │ │ ├── CommitDTO.java │ │ │ │ │ │ ├── GrayReleaseRuleDTO.java │ │ │ │ │ │ ├── GrayReleaseRuleItemDTO.java │ │ │ │ │ │ ├── InstanceConfigDTO.java │ │ │ │ │ │ ├── InstanceDTO.java │ │ │ │ │ │ ├── ItemChangeSets.java │ │ │ │ │ │ ├── ItemDTO.java │ │ │ │ │ │ ├── NamespaceDTO.java │ │ │ │ │ │ ├── NamespaceLockDTO.java │ │ │ │ │ │ ├── PageDTO.java │ │ │ │ │ │ ├── ReleaseDTO.java │ │ │ │ │ │ └── ReleaseHistoryDTO.java │ │ │ │ │ ├── entity/ │ │ │ │ │ │ ├── App.java │ │ │ │ │ │ ├── AppNamespace.java │ │ │ │ │ │ ├── BaseEntity.java │ │ │ │ │ │ └── EntityPair.java │ │ │ │ │ ├── exception/ │ │ │ │ │ │ ├── AbstractApolloHttpException.java │ │ │ │ │ │ ├── BadRequestException.java │ │ │ │ │ │ ├── BeanUtilsException.java │ │ │ │ │ │ ├── NotFoundException.java │ │ │ │ │ │ └── ServiceException.java │ │ │ │ │ ├── http/ │ │ │ │ │ │ ├── MultiResponseEntity.java │ │ │ │ │ │ └── RichResponseEntity.java │ │ │ │ │ └── utils/ │ │ │ │ │ ├── BeanUtils.java │ │ │ │ │ ├── ExceptionUtils.java │ │ │ │ │ ├── GrayReleaseRuleItemTransformer.java │ │ │ │ │ ├── InputValidator.java │ │ │ │ │ ├── RequestPrecondition.java │ │ │ │ │ └── UniqueKeyGenerator.java │ │ │ │ └── resources/ │ │ │ │ ├── application-ctrip.properties │ │ │ │ ├── application-github.properties │ │ │ │ ├── application.properties │ │ │ │ └── datasource.xml │ │ │ └── test/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── ctrip/ │ │ │ └── framework/ │ │ │ └── apollo/ │ │ │ └── common/ │ │ │ ├── AllTests.java │ │ │ ├── conditional/ │ │ │ │ └── ConditionalOnProfileTest.java │ │ │ └── utils/ │ │ │ └── InputValidatorTest.java │ │ ├── apollo-configservice/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── assembly/ │ │ │ │ └── assembly-descriptor.xml │ │ │ ├── main/ │ │ │ │ ├── config/ │ │ │ │ │ ├── apollo-configservice.conf │ │ │ │ │ └── app.properties │ │ │ │ ├── docker/ │ │ │ │ │ └── Dockerfile │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── ctrip/ │ │ │ │ │ └── framework/ │ │ │ │ │ └── apollo/ │ │ │ │ │ ├── configservice/ │ │ │ │ │ │ ├── ConfigServiceApplication.java │ │ │ │ │ │ ├── ConfigServiceAutoConfiguration.java │ │ │ │ │ │ ├── ConfigServiceHealthIndicator.java │ │ │ │ │ │ ├── ServletInitializer.java │ │ │ │ │ │ ├── controller/ │ │ │ │ │ │ │ ├── ConfigController.java │ │ │ │ │ │ │ ├── ConfigFileController.java │ │ │ │ │ │ │ ├── NotificationController.java │ │ │ │ │ │ │ └── NotificationControllerV2.java │ │ │ │ │ │ ├── service/ │ │ │ │ │ │ │ ├── AppNamespaceServiceWithCache.java │ │ │ │ │ │ │ ├── ReleaseMessageServiceWithCache.java │ │ │ │ │ │ │ └── config/ │ │ │ │ │ │ │ ├── AbstractConfigService.java │ │ │ │ │ │ │ ├── ConfigService.java │ │ │ │ │ │ │ ├── ConfigServiceWithCache.java │ │ │ │ │ │ │ └── DefaultConfigService.java │ │ │ │ │ │ ├── util/ │ │ │ │ │ │ │ ├── InstanceConfigAuditUtil.java │ │ │ │ │ │ │ ├── NamespaceUtil.java │ │ │ │ │ │ │ └── WatchKeysUtil.java │ │ │ │ │ │ └── wrapper/ │ │ │ │ │ │ ├── CaseInsensitiveMapWrapper.java │ │ │ │ │ │ └── DeferredResultWrapper.java │ │ │ │ │ └── metaservice/ │ │ │ │ │ ├── ApolloMetaServiceConfig.java │ │ │ │ │ ├── controller/ │ │ │ │ │ │ └── ServiceController.java │ │ │ │ │ └── service/ │ │ │ │ │ └── DiscoveryService.java │ │ │ │ ├── resources/ │ │ │ │ │ ├── META-INF/ │ │ │ │ │ │ └── app.properties │ │ │ │ │ ├── application.yml │ │ │ │ │ ├── bootstrap.yml │ │ │ │ │ ├── configservice.properties │ │ │ │ │ └── logback.xml │ │ │ │ └── scripts/ │ │ │ │ ├── shutdown.sh │ │ │ │ └── startup.sh │ │ │ └── test/ │ │ │ └── resources/ │ │ │ ├── application.properties │ │ │ ├── application.yml │ │ │ ├── bootstrap.yml │ │ │ ├── data.sql │ │ │ ├── integration-test/ │ │ │ │ ├── cleanup.sql │ │ │ │ ├── test-gray-release.sql │ │ │ │ ├── test-release-message.sql │ │ │ │ ├── test-release-public-dc-override.sql │ │ │ │ ├── test-release-public-default-override.sql │ │ │ │ └── test-release.sql │ │ │ └── logback-test.xml │ │ ├── apollo-core/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── main/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── ctrip/ │ │ │ │ │ └── framework/ │ │ │ │ │ ├── apollo/ │ │ │ │ │ │ ├── Apollo.java │ │ │ │ │ │ ├── core/ │ │ │ │ │ │ │ ├── ConfigConsts.java │ │ │ │ │ │ │ ├── MetaDomainConsts.java │ │ │ │ │ │ │ ├── ServiceNameConsts.java │ │ │ │ │ │ │ ├── dto/ │ │ │ │ │ │ │ │ ├── ApolloConfig.java │ │ │ │ │ │ │ │ ├── ApolloConfigNotification.java │ │ │ │ │ │ │ │ ├── ApolloNotificationMessages.java │ │ │ │ │ │ │ │ └── ServiceDTO.java │ │ │ │ │ │ │ ├── enums/ │ │ │ │ │ │ │ │ ├── ConfigFileFormat.java │ │ │ │ │ │ │ │ ├── Env.java │ │ │ │ │ │ │ │ └── EnvUtils.java │ │ │ │ │ │ │ ├── schedule/ │ │ │ │ │ │ │ │ ├── ExponentialSchedulePolicy.java │ │ │ │ │ │ │ │ └── SchedulePolicy.java │ │ │ │ │ │ │ └── utils/ │ │ │ │ │ │ │ ├── ApolloThreadFactory.java │ │ │ │ │ │ │ ├── ByteUtil.java │ │ │ │ │ │ │ ├── ClassLoaderUtil.java │ │ │ │ │ │ │ ├── DNSUtil.java │ │ │ │ │ │ │ ├── MachineUtil.java │ │ │ │ │ │ │ ├── PropertiesUtil.java │ │ │ │ │ │ │ ├── ResourceUtils.java │ │ │ │ │ │ │ └── StringUtils.java │ │ │ │ │ │ └── tracer/ │ │ │ │ │ │ ├── Tracer.java │ │ │ │ │ │ ├── internals/ │ │ │ │ │ │ │ ├── DefaultMessageProducerManager.java │ │ │ │ │ │ │ ├── NullMessageProducer.java │ │ │ │ │ │ │ ├── NullMessageProducerManager.java │ │ │ │ │ │ │ ├── NullTransaction.java │ │ │ │ │ │ │ └── cat/ │ │ │ │ │ │ │ ├── CatMessageProducer.java │ │ │ │ │ │ │ ├── CatNames.java │ │ │ │ │ │ │ └── CatTransaction.java │ │ │ │ │ │ └── spi/ │ │ │ │ │ │ ├── MessageProducer.java │ │ │ │ │ │ ├── MessageProducerManager.java │ │ │ │ │ │ └── Transaction.java │ │ │ │ │ └── foundation/ │ │ │ │ │ ├── Foundation.java │ │ │ │ │ ├── internals/ │ │ │ │ │ │ ├── DefaultProviderManager.java │ │ │ │ │ │ ├── NetworkInterfaceManager.java │ │ │ │ │ │ ├── NullProviderManager.java │ │ │ │ │ │ ├── ServiceBootstrap.java │ │ │ │ │ │ ├── Utils.java │ │ │ │ │ │ ├── io/ │ │ │ │ │ │ │ ├── BOMInputStream.java │ │ │ │ │ │ │ ├── ByteOrderMark.java │ │ │ │ │ │ │ ├── IOUtils.java │ │ │ │ │ │ │ └── ProxyInputStream.java │ │ │ │ │ │ └── provider/ │ │ │ │ │ │ ├── DefaultApplicationProvider.java │ │ │ │ │ │ ├── DefaultNetworkProvider.java │ │ │ │ │ │ ├── DefaultServerProvider.java │ │ │ │ │ │ └── NullProvider.java │ │ │ │ │ └── spi/ │ │ │ │ │ ├── ProviderManager.java │ │ │ │ │ └── provider/ │ │ │ │ │ ├── ApplicationProvider.java │ │ │ │ │ ├── NetworkProvider.java │ │ │ │ │ ├── Provider.java │ │ │ │ │ └── ServerProvider.java │ │ │ │ └── resources/ │ │ │ │ ├── META-INF/ │ │ │ │ │ └── services/ │ │ │ │ │ ├── com.ctrip.framework.apollo.tracer.spi.MessageProducerManager │ │ │ │ │ └── com.ctrip.framework.foundation.spi.ProviderManager │ │ │ │ └── apollo-env.properties │ │ │ └── test/ │ │ │ └── resources/ │ │ │ ├── META-INF/ │ │ │ │ ├── app-with-utf8bom.properties │ │ │ │ ├── app.properties │ │ │ │ ├── services/ │ │ │ │ │ ├── com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1 │ │ │ │ │ ├── com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface3 │ │ │ │ │ ├── com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface4 │ │ │ │ │ ├── com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface5 │ │ │ │ │ └── com.ctrip.framework.apollo.tracer.spi.MessageProducerManager │ │ │ │ └── some-invalid-app.properties │ │ │ ├── apollo-env.properties │ │ │ ├── log4j2.xml │ │ │ └── properties/ │ │ │ ├── server-with-utf8bom.properties │ │ │ └── server.properties │ │ ├── apollo-portal/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── assembly/ │ │ │ │ └── assembly-descriptor.xml │ │ │ ├── main/ │ │ │ │ ├── config/ │ │ │ │ │ ├── apollo-portal.conf │ │ │ │ │ └── app.properties │ │ │ │ ├── docker/ │ │ │ │ │ └── Dockerfile │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── ctrip/ │ │ │ │ │ └── framework/ │ │ │ │ │ └── apollo/ │ │ │ │ │ ├── openapi/ │ │ │ │ │ │ ├── PortalOpenApiConfig.java │ │ │ │ │ │ ├── auth/ │ │ │ │ │ │ │ └── ConsumerPermissionValidator.java │ │ │ │ │ │ ├── dto/ │ │ │ │ │ │ │ ├── OpenAppNamespaceDTO.java │ │ │ │ │ │ │ ├── OpenEnvClusterDTO.java │ │ │ │ │ │ │ ├── OpenItemDTO.java │ │ │ │ │ │ │ ├── OpenNamespaceDTO.java │ │ │ │ │ │ │ ├── OpenNamespaceLockDTO.java │ │ │ │ │ │ │ └── OpenReleaseDTO.java │ │ │ │ │ │ ├── entity/ │ │ │ │ │ │ │ ├── Consumer.java │ │ │ │ │ │ │ ├── ConsumerAudit.java │ │ │ │ │ │ │ ├── ConsumerRole.java │ │ │ │ │ │ │ └── ConsumerToken.java │ │ │ │ │ │ ├── filter/ │ │ │ │ │ │ │ └── ConsumerAuthenticationFilter.java │ │ │ │ │ │ ├── repository/ │ │ │ │ │ │ │ ├── ConsumerAuditRepository.java │ │ │ │ │ │ │ ├── ConsumerRepository.java │ │ │ │ │ │ │ ├── ConsumerRoleRepository.java │ │ │ │ │ │ │ └── ConsumerTokenRepository.java │ │ │ │ │ │ ├── service/ │ │ │ │ │ │ │ ├── ConsumerRolePermissionService.java │ │ │ │ │ │ │ └── ConsumerService.java │ │ │ │ │ │ ├── util/ │ │ │ │ │ │ │ ├── ConsumerAuditUtil.java │ │ │ │ │ │ │ ├── ConsumerAuthUtil.java │ │ │ │ │ │ │ └── OpenApiBeanUtils.java │ │ │ │ │ │ └── v1/ │ │ │ │ │ │ └── controller/ │ │ │ │ │ │ ├── AppController.java │ │ │ │ │ │ ├── ItemController.java │ │ │ │ │ │ ├── NamespaceController.java │ │ │ │ │ │ └── ReleaseController.java │ │ │ │ │ └── portal/ │ │ │ │ │ ├── PortalApplication.java │ │ │ │ │ ├── api/ │ │ │ │ │ │ ├── API.java │ │ │ │ │ │ └── AdminServiceAPI.java │ │ │ │ │ ├── component/ │ │ │ │ │ │ ├── AdminServiceAddressLocator.java │ │ │ │ │ │ ├── ItemsComparator.java │ │ │ │ │ │ ├── PermissionValidator.java │ │ │ │ │ │ ├── PortalSettings.java │ │ │ │ │ │ ├── RestTemplateFactory.java │ │ │ │ │ │ ├── RetryableRestTemplate.java │ │ │ │ │ │ ├── config/ │ │ │ │ │ │ │ └── PortalConfig.java │ │ │ │ │ │ ├── emailbuilder/ │ │ │ │ │ │ │ ├── ConfigPublishEmailBuilder.java │ │ │ │ │ │ │ ├── GrayPublishEmailBuilder.java │ │ │ │ │ │ │ ├── MergeEmailBuilder.java │ │ │ │ │ │ │ ├── NormalPublishEmailBuilder.java │ │ │ │ │ │ │ └── RollbackEmailBuilder.java │ │ │ │ │ │ └── txtresolver/ │ │ │ │ │ │ ├── ConfigTextResolver.java │ │ │ │ │ │ ├── FileTextResolver.java │ │ │ │ │ │ └── PropertyResolver.java │ │ │ │ │ ├── constant/ │ │ │ │ │ │ ├── PermissionType.java │ │ │ │ │ │ ├── RoleType.java │ │ │ │ │ │ └── TracerEventType.java │ │ │ │ │ ├── controller/ │ │ │ │ │ │ ├── AppController.java │ │ │ │ │ │ ├── ClusterController.java │ │ │ │ │ │ ├── CommitController.java │ │ │ │ │ │ ├── ConsumerController.java │ │ │ │ │ │ ├── EnvController.java │ │ │ │ │ │ ├── FavoriteController.java │ │ │ │ │ │ ├── InstanceController.java │ │ │ │ │ │ ├── ItemController.java │ │ │ │ │ │ ├── NamespaceBranchController.java │ │ │ │ │ │ ├── NamespaceController.java │ │ │ │ │ │ ├── NamespaceLockController.java │ │ │ │ │ │ ├── OrganizationController.java │ │ │ │ │ │ ├── PageSettingController.java │ │ │ │ │ │ ├── PermissionController.java │ │ │ │ │ │ ├── ReleaseController.java │ │ │ │ │ │ ├── ReleaseHistoryController.java │ │ │ │ │ │ ├── ServerConfigController.java │ │ │ │ │ │ ├── SignInController.java │ │ │ │ │ │ ├── SsoHeartbeatController.java │ │ │ │ │ │ └── UserInfoController.java │ │ │ │ │ ├── entity/ │ │ │ │ │ │ ├── bo/ │ │ │ │ │ │ │ ├── Email.java │ │ │ │ │ │ │ ├── ItemBO.java │ │ │ │ │ │ │ ├── KVEntity.java │ │ │ │ │ │ │ ├── NamespaceBO.java │ │ │ │ │ │ │ ├── ReleaseBO.java │ │ │ │ │ │ │ ├── ReleaseHistoryBO.java │ │ │ │ │ │ │ └── UserInfo.java │ │ │ │ │ │ ├── model/ │ │ │ │ │ │ │ ├── AppModel.java │ │ │ │ │ │ │ ├── NamespaceCreationModel.java │ │ │ │ │ │ │ ├── NamespaceReleaseModel.java │ │ │ │ │ │ │ ├── NamespaceSyncModel.java │ │ │ │ │ │ │ ├── NamespaceTextModel.java │ │ │ │ │ │ │ └── Verifiable.java │ │ │ │ │ │ ├── po/ │ │ │ │ │ │ │ ├── Favorite.java │ │ │ │ │ │ │ ├── Permission.java │ │ │ │ │ │ │ ├── Role.java │ │ │ │ │ │ │ ├── RolePermission.java │ │ │ │ │ │ │ ├── ServerConfig.java │ │ │ │ │ │ │ ├── UserPO.java │ │ │ │ │ │ │ └── UserRole.java │ │ │ │ │ │ └── vo/ │ │ │ │ │ │ ├── AppRolesAssignedUsers.java │ │ │ │ │ │ ├── Change.java │ │ │ │ │ │ ├── EnvClusterInfo.java │ │ │ │ │ │ ├── ItemDiffs.java │ │ │ │ │ │ ├── LockInfo.java │ │ │ │ │ │ ├── NamespaceIdentifier.java │ │ │ │ │ │ ├── NamespaceRolesAssignedUsers.java │ │ │ │ │ │ ├── Number.java │ │ │ │ │ │ ├── Organization.java │ │ │ │ │ │ ├── PageSetting.java │ │ │ │ │ │ ├── PermissionCondition.java │ │ │ │ │ │ └── ReleaseCompareResult.java │ │ │ │ │ ├── enums/ │ │ │ │ │ │ └── ChangeType.java │ │ │ │ │ ├── listener/ │ │ │ │ │ │ ├── AppCreationEvent.java │ │ │ │ │ │ ├── AppInfoChangedEvent.java │ │ │ │ │ │ ├── AppInfoChangedListener.java │ │ │ │ │ │ ├── AppNamespaceCreationEvent.java │ │ │ │ │ │ ├── ConfigPublishEvent.java │ │ │ │ │ │ ├── ConfigPublishListener.java │ │ │ │ │ │ └── CreationListener.java │ │ │ │ │ ├── repository/ │ │ │ │ │ │ ├── AppNamespaceRepository.java │ │ │ │ │ │ ├── AppRepository.java │ │ │ │ │ │ ├── FavoriteRepository.java │ │ │ │ │ │ ├── PermissionRepository.java │ │ │ │ │ │ ├── RolePermissionRepository.java │ │ │ │ │ │ ├── RoleRepository.java │ │ │ │ │ │ ├── ServerConfigRepository.java │ │ │ │ │ │ ├── UserRepository.java │ │ │ │ │ │ └── UserRoleRepository.java │ │ │ │ │ ├── service/ │ │ │ │ │ │ ├── AppNamespaceService.java │ │ │ │ │ │ ├── AppService.java │ │ │ │ │ │ ├── ClusterService.java │ │ │ │ │ │ ├── CommitService.java │ │ │ │ │ │ ├── FavoriteService.java │ │ │ │ │ │ ├── InstanceService.java │ │ │ │ │ │ ├── ItemService.java │ │ │ │ │ │ ├── NamespaceBranchService.java │ │ │ │ │ │ ├── NamespaceLockService.java │ │ │ │ │ │ ├── NamespaceService.java │ │ │ │ │ │ ├── PortalDBPropertySource.java │ │ │ │ │ │ ├── ReleaseHistoryService.java │ │ │ │ │ │ ├── ReleaseService.java │ │ │ │ │ │ ├── RoleInitializationService.java │ │ │ │ │ │ └── RolePermissionService.java │ │ │ │ │ ├── spi/ │ │ │ │ │ │ ├── EmailService.java │ │ │ │ │ │ ├── LogoutHandler.java │ │ │ │ │ │ ├── MQService.java │ │ │ │ │ │ ├── SsoHeartbeatHandler.java │ │ │ │ │ │ ├── UserInfoHolder.java │ │ │ │ │ │ ├── UserService.java │ │ │ │ │ │ ├── configuration/ │ │ │ │ │ │ │ ├── AuthConfiguration.java │ │ │ │ │ │ │ ├── AuthFilterConfiguration.java │ │ │ │ │ │ │ ├── EmailConfiguration.java │ │ │ │ │ │ │ ├── MQConfiguration.java │ │ │ │ │ │ │ └── RoleConfiguration.java │ │ │ │ │ │ ├── ctrip/ │ │ │ │ │ │ │ ├── BizLoggingCustomizer.java │ │ │ │ │ │ │ ├── CtripEmailRequestBuilder.java │ │ │ │ │ │ │ ├── CtripEmailService.java │ │ │ │ │ │ │ ├── CtripLogoutHandler.java │ │ │ │ │ │ │ ├── CtripMQService.java │ │ │ │ │ │ │ ├── CtripSsoHeartbeatHandler.java │ │ │ │ │ │ │ ├── CtripUserInfoHolder.java │ │ │ │ │ │ │ ├── CtripUserService.java │ │ │ │ │ │ │ ├── WebContextConfiguration.java │ │ │ │ │ │ │ └── filters/ │ │ │ │ │ │ │ └── UserAccessFilter.java │ │ │ │ │ │ ├── defaultimpl/ │ │ │ │ │ │ │ ├── DefaultEmailService.java │ │ │ │ │ │ │ ├── DefaultLogoutHandler.java │ │ │ │ │ │ │ ├── DefaultMQService.java │ │ │ │ │ │ │ ├── DefaultRoleInitializationService.java │ │ │ │ │ │ │ ├── DefaultRolePermissionService.java │ │ │ │ │ │ │ ├── DefaultSsoHeartbeatHandler.java │ │ │ │ │ │ │ ├── DefaultUserInfoHolder.java │ │ │ │ │ │ │ └── DefaultUserService.java │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ └── springsecurity/ │ │ │ │ │ │ ├── SpringSecurityUserInfoHolder.java │ │ │ │ │ │ └── SpringSecurityUserService.java │ │ │ │ │ └── util/ │ │ │ │ │ ├── RelativeDateFormat.java │ │ │ │ │ └── RoleUtils.java │ │ │ │ ├── resources/ │ │ │ │ │ ├── META-INF/ │ │ │ │ │ │ └── app.properties │ │ │ │ │ ├── application-ctrip.yml │ │ │ │ │ ├── application.yml │ │ │ │ │ ├── logback.xml │ │ │ │ │ ├── portal.properties │ │ │ │ │ └── static/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ └── setting.html │ │ │ │ │ ├── app.html │ │ │ │ │ ├── cluster.html │ │ │ │ │ ├── config/ │ │ │ │ │ │ ├── history.html │ │ │ │ │ │ └── sync.html │ │ │ │ │ ├── config.html │ │ │ │ │ ├── ctrip_sso_heartbeat.html │ │ │ │ │ ├── default_sso_heartbeat.html │ │ │ │ │ ├── index.html │ │ │ │ │ ├── java/ │ │ │ │ │ │ └── com/ │ │ │ │ │ │ └── example/ │ │ │ │ │ │ └── demo/ │ │ │ │ │ │ └── EcvoicesystemDemoApplicationTests.java │ │ │ │ │ ├── login.html │ │ │ │ │ ├── namespace/ │ │ │ │ │ │ └── role.html │ │ │ │ │ ├── namespace.html │ │ │ │ │ ├── open/ │ │ │ │ │ │ └── manage.html │ │ │ │ │ ├── scripts/ │ │ │ │ │ │ ├── AppUtils.js │ │ │ │ │ │ ├── PageCommon.js │ │ │ │ │ │ ├── app.js │ │ │ │ │ │ ├── controller/ │ │ │ │ │ │ │ ├── AppController.js │ │ │ │ │ │ │ ├── ClusterController.js │ │ │ │ │ │ │ ├── IndexController.js │ │ │ │ │ │ │ ├── LoginController.js │ │ │ │ │ │ │ ├── NamespaceController.js │ │ │ │ │ │ │ ├── ServerConfigController.js │ │ │ │ │ │ │ ├── SettingController.js │ │ │ │ │ │ │ ├── UserController.js │ │ │ │ │ │ │ ├── config/ │ │ │ │ │ │ │ │ ├── ConfigBaseInfoController.js │ │ │ │ │ │ │ │ ├── ConfigNamespaceController.js │ │ │ │ │ │ │ │ ├── ReleaseHistoryController.js │ │ │ │ │ │ │ │ └── SyncConfigController.js │ │ │ │ │ │ │ ├── open/ │ │ │ │ │ │ │ │ └── OpenManageController.js │ │ │ │ │ │ │ └── role/ │ │ │ │ │ │ │ └── NamespaceRoleController.js │ │ │ │ │ │ ├── directive/ │ │ │ │ │ │ │ ├── delete-namespace-modal-directive.js │ │ │ │ │ │ │ ├── diff-directive.js │ │ │ │ │ │ │ ├── directive.js │ │ │ │ │ │ │ ├── gray-release-rules-modal-directive.js │ │ │ │ │ │ │ ├── item-modal-directive.js │ │ │ │ │ │ │ ├── merge-and-publish-modal-directive.js │ │ │ │ │ │ │ ├── namespace-panel-directive.js │ │ │ │ │ │ │ ├── publish-deny-modal-directive.js │ │ │ │ │ │ │ ├── release-modal-directive.js │ │ │ │ │ │ │ ├── rollback-modal-directive.js │ │ │ │ │ │ │ └── show-text-modal-directive.js │ │ │ │ │ │ ├── services/ │ │ │ │ │ │ │ ├── AppService.js │ │ │ │ │ │ │ ├── ClusterService.js │ │ │ │ │ │ │ ├── CommitService.js │ │ │ │ │ │ │ ├── CommonService.js │ │ │ │ │ │ │ ├── ConfigService.js │ │ │ │ │ │ │ ├── ConsumerService.js │ │ │ │ │ │ │ ├── EnvService.js │ │ │ │ │ │ │ ├── EventManager.js │ │ │ │ │ │ │ ├── FavoriteService.js │ │ │ │ │ │ │ ├── InstanceService.js │ │ │ │ │ │ │ ├── NamespaceBranchService.js │ │ │ │ │ │ │ ├── NamespaceLockService.js │ │ │ │ │ │ │ ├── NamespaceService.js │ │ │ │ │ │ │ ├── OrganizationService.js │ │ │ │ │ │ │ ├── PermissionService.js │ │ │ │ │ │ │ ├── ReleaseHistoryService.js │ │ │ │ │ │ │ ├── ReleaseService.js │ │ │ │ │ │ │ ├── ServerConfigService.js │ │ │ │ │ │ │ └── UserService.js │ │ │ │ │ │ └── valdr.js │ │ │ │ │ ├── server_config.html │ │ │ │ │ ├── styles/ │ │ │ │ │ │ └── common-style.css │ │ │ │ │ ├── user-manage.html │ │ │ │ │ ├── vendor/ │ │ │ │ │ │ └── ui-ace/ │ │ │ │ │ │ ├── ace.js │ │ │ │ │ │ ├── mode-json.js │ │ │ │ │ │ ├── mode-properties.js │ │ │ │ │ │ ├── mode-xml.js │ │ │ │ │ │ ├── mode-yaml.js │ │ │ │ │ │ ├── theme-eclipse.js │ │ │ │ │ │ ├── worker-json.js │ │ │ │ │ │ └── worker-xml.js │ │ │ │ │ └── views/ │ │ │ │ │ ├── common/ │ │ │ │ │ │ ├── footer.html │ │ │ │ │ │ └── nav.html │ │ │ │ │ └── component/ │ │ │ │ │ ├── confirm-dialog.html │ │ │ │ │ ├── delete-namespace-modal.html │ │ │ │ │ ├── diff.html │ │ │ │ │ ├── entrance.html │ │ │ │ │ ├── env-selector.html │ │ │ │ │ ├── gray-release-rules-modal.html │ │ │ │ │ ├── item-modal.html │ │ │ │ │ ├── merge-and-publish-modal.html │ │ │ │ │ ├── multiple-user-selector.html │ │ │ │ │ ├── namespace-panel-branch-tab.html │ │ │ │ │ ├── namespace-panel-header.html │ │ │ │ │ ├── namespace-panel-master-tab.html │ │ │ │ │ ├── namespace-panel.html │ │ │ │ │ ├── publish-deny-modal.html │ │ │ │ │ ├── release-modal.html │ │ │ │ │ ├── rollback-modal.html │ │ │ │ │ ├── show-text-modal.html │ │ │ │ │ └── user-selector.html │ │ │ │ └── scripts/ │ │ │ │ ├── shutdown.sh │ │ │ │ └── startup.sh │ │ │ └── test/ │ │ │ └── resources/ │ │ │ ├── application.properties │ │ │ ├── application.yml │ │ │ ├── logback-test.xml │ │ │ └── sql/ │ │ │ ├── appnamespaceservice/ │ │ │ │ └── init-appnamespace.sql │ │ │ ├── cleanup.sql │ │ │ ├── favorites/ │ │ │ │ └── favorites.sql │ │ │ └── permission/ │ │ │ ├── insert-test-consumerroles.sql │ │ │ ├── insert-test-permissions.sql │ │ │ ├── insert-test-rolepermissions.sql │ │ │ ├── insert-test-roles.sql │ │ │ └── insert-test-userroles.sql │ │ ├── pom.xml │ │ └── scripts/ │ │ ├── build.bat │ │ ├── build.sh │ │ ├── docker-quick-start/ │ │ │ ├── docker-compose.yml │ │ │ └── sql/ │ │ │ ├── apolloconfigdb.sql │ │ │ └── apolloportaldb.sql │ │ └── sql/ │ │ ├── apolloconfigdb.sql │ │ └── apolloportaldb.sql │ ├── apollo-gateway/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── ApiGateWayApp.java │ │ │ └── config/ │ │ │ ├── ZuulConfig.java │ │ │ └── ZuulConfigRreshConfig.java │ │ └── resources/ │ │ ├── META-INF/ │ │ │ └── app.properties │ │ └── bootstrap.yml │ └── pom.xml ├── open-db-core/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ ├── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── db/ │ │ │ │ └── config/ │ │ │ │ ├── DruidConfig.java │ │ │ │ └── dynamic/ │ │ │ │ ├── annotation/ │ │ │ │ │ └── DataSource.java │ │ │ │ ├── aop/ │ │ │ │ │ └── DataSourceAspect.java │ │ │ │ └── config/ │ │ │ │ ├── DynamicDataSourceConfig.java │ │ │ │ └── util/ │ │ │ │ ├── DataSourceHolder.java │ │ │ │ ├── DataSourceKey.java │ │ │ │ └── DynamicDataSource.java │ │ │ └── redis/ │ │ │ └── config/ │ │ │ ├── RedisConfig.java │ │ │ └── util/ │ │ │ ├── FastJson2JsonRedisSerializer.java │ │ │ └── RedisObjectSerializer.java │ │ └── mybatis.cfg.xml │ └── resources/ │ └── jdbc.bcv.properties ├── open-eureka-center/ │ ├── README.md │ ├── open-eureka-client/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── docker/ │ │ │ └── Dockerfile │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── EurekaClientApplication.java │ │ │ ├── config/ │ │ │ │ └── SwaggerConfig.java │ │ │ ├── controller/ │ │ │ │ ├── EurekaController.java │ │ │ │ ├── EurekaManageController.java │ │ │ │ └── HelloController.java │ │ │ └── health/ │ │ │ ├── EurekaClientHealthIndicator.java │ │ │ └── EurekaHealthCheckHandler.java │ │ └── resources/ │ │ ├── application.yml │ │ └── logback.xml │ ├── open-eureka-server/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── docker/ │ │ │ └── Dockerfile │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── EurekaServerApp.java │ │ │ ├── controller/ │ │ │ │ └── EurekaController.java │ │ │ └── listener/ │ │ │ └── EurekaInstanceCanceledListener.java │ │ └── resources/ │ │ ├── application.yml │ │ └── templates/ │ │ ├── .keep │ │ └── eureka/ │ │ ├── .keep │ │ ├── header.ftl │ │ ├── lastn.ftl │ │ ├── navbar.ftl │ │ └── status.ftl │ └── pom.xml ├── open-layui-web/ │ ├── .gitignore │ ├── pom.xml │ └── src/ │ └── main/ │ ├── docker/ │ │ └── Dockerfile │ ├── java/ │ │ └── com/ │ │ └── open/ │ │ └── capacity/ │ │ ├── SecurityApplication.java │ │ ├── activiti/ │ │ │ ├── config/ │ │ │ │ ├── ActPropertiesConfig.java │ │ │ │ └── ActivitiConfig.java │ │ │ ├── controller/ │ │ │ │ └── ActivitiController.java │ │ │ ├── entity/ │ │ │ │ ├── ActAssignee.java │ │ │ │ ├── ActDeployment.java │ │ │ │ ├── ActModel.java │ │ │ │ ├── LeaveOpinion.java │ │ │ │ ├── ProcessDefinition.java │ │ │ │ ├── Task.java │ │ │ │ └── UserLeave.java │ │ │ ├── mapper/ │ │ │ │ ├── ActAssigneeMapper.java │ │ │ │ ├── ActAssigneeMapper.xml │ │ │ │ ├── UserLeaveMapper.java │ │ │ │ └── UserLeaveMapper.xml │ │ │ ├── rest/ │ │ │ │ └── editor/ │ │ │ │ ├── main/ │ │ │ │ │ └── StencilsetRestResource.java │ │ │ │ └── model/ │ │ │ │ ├── ModelEditorJsonRestResource.java │ │ │ │ └── ModelSaveRestResource.java │ │ │ ├── service/ │ │ │ │ ├── ActAssigneeService.java │ │ │ │ ├── UserLeaveService.java │ │ │ │ └── impl/ │ │ │ │ ├── ActAssigneeServiceImpl.java │ │ │ │ └── UserLeaveServiceImpl.java │ │ │ └── util/ │ │ │ ├── AssigneeType.java │ │ │ ├── Checkbox.java │ │ │ ├── JsonUtil.java │ │ │ └── ResultType.java │ │ └── security/ │ │ ├── advice/ │ │ │ ├── ExceptionHandlerAdvice.java │ │ │ └── LogAdvice.java │ │ ├── annotation/ │ │ │ └── LogAnnotation.java │ │ ├── config/ │ │ │ ├── AsycTaskExecutorConfig.java │ │ │ ├── LoginPageConfig.java │ │ │ ├── SecurityConfig.java │ │ │ ├── SecurityHandlerConfig.java │ │ │ ├── SwaggerConfig.java │ │ │ └── WebMvcConfig.java │ │ ├── controller/ │ │ │ ├── ClientController.java │ │ │ ├── DictController.java │ │ │ ├── EurekaController.java │ │ │ ├── ExcelController.java │ │ │ ├── FileController.java │ │ │ ├── GenerateController.java │ │ │ ├── MailController.java │ │ │ ├── NoticeController.java │ │ │ ├── PermissionController.java │ │ │ ├── RoleController.java │ │ │ ├── ServiceController.java │ │ │ ├── SysLogsController.java │ │ │ └── UserController.java │ │ ├── dao/ │ │ │ ├── ClientDao.java │ │ │ ├── ClientDao.xml │ │ │ ├── DictDao.java │ │ │ ├── DictDaoxml │ │ │ ├── FileDao.xml │ │ │ ├── FileInfoDao.java │ │ │ ├── MailDao.java │ │ │ ├── MailDao.xml │ │ │ ├── NoticeDao.java │ │ │ ├── NoticeDao.xml │ │ │ ├── PermissionDao.java │ │ │ ├── RoleDao.java │ │ │ ├── RoleDao.xml │ │ │ ├── ServiceDao.java │ │ │ ├── SysLogsDao.java │ │ │ ├── SysLogsDao.xml │ │ │ ├── TokenDao.java │ │ │ ├── UserDao.java │ │ │ └── UserDao.xml │ │ ├── dto/ │ │ │ ├── BeanField.java │ │ │ ├── ClientDto.java │ │ │ ├── GenerateDetail.java │ │ │ ├── GenerateInput.java │ │ │ ├── LayuiFile.java │ │ │ ├── LoginUser.java │ │ │ ├── NoticeReadVO.java │ │ │ ├── NoticeVO.java │ │ │ ├── ResponseInfo.java │ │ │ ├── RoleDto.java │ │ │ ├── Token.java │ │ │ └── UserDto.java │ │ ├── filter/ │ │ │ └── TokenFilter.java │ │ ├── model/ │ │ │ ├── BaseEntity.java │ │ │ ├── Client.java │ │ │ ├── Dict.java │ │ │ ├── FileInfo.java │ │ │ ├── Mail.java │ │ │ ├── MailTo.java │ │ │ ├── Notice.java │ │ │ ├── Permission.java │ │ │ ├── Role.java │ │ │ ├── SysLogs.java │ │ │ ├── SysUser.java │ │ │ └── TokenModel.java │ │ ├── page/ │ │ │ └── table/ │ │ │ ├── PageTableArgumentResolver.java │ │ │ ├── PageTableHandler.java │ │ │ ├── PageTableRequest.java │ │ │ └── PageTableResponse.java │ │ ├── service/ │ │ │ ├── ClientService.java │ │ │ ├── FileService.java │ │ │ ├── GenerateService.java │ │ │ ├── MailService.java │ │ │ ├── MicroServiceService.java │ │ │ ├── PermissionService.java │ │ │ ├── RoleService.java │ │ │ ├── SendMailSevice.java │ │ │ ├── SysLogService.java │ │ │ ├── TokenService.java │ │ │ ├── UserService.java │ │ │ └── impl/ │ │ │ ├── ClientServiceImpl.java │ │ │ ├── FileServiceImpl.java │ │ │ ├── GenerateServiceImpl.java │ │ │ ├── MailServiceImpl.java │ │ │ ├── MicroServicesServiceImpl.java │ │ │ ├── PermissionServiceImpl.java │ │ │ ├── RoleServiceImpl.java │ │ │ ├── SendMailSeviceImpl.java │ │ │ ├── SysLogServiceImpl.java │ │ │ ├── TokenServiceImpl.java │ │ │ ├── UserDetailsServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ └── utils/ │ │ ├── ExcelUtil.java │ │ ├── FileUtil.java │ │ ├── ResponseUtil.java │ │ ├── SpringUtil.java │ │ ├── StrUtil.java │ │ ├── TemplateUtil.java │ │ └── UserUtil.java │ ├── resources/ │ │ ├── activiti.properties │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ ├── bpmn/ │ │ │ ├── demo.xml │ │ │ ├── leave.bpmn │ │ │ ├── leave2.bpmn │ │ │ └── vacationRequest.bpmn │ │ ├── db/ │ │ │ └── boot_security.sql │ │ ├── generate/ │ │ │ ├── controller.ftl │ │ │ ├── dao.ftl │ │ │ ├── htmlAdd.ftl │ │ │ ├── htmlList.ftl │ │ │ ├── htmlUpdate.ftl │ │ │ ├── java.ftl │ │ │ └── mapper.ftl │ │ ├── logback-admin.xml │ │ ├── mybatis.cfg.xml │ │ └── stencilset.json │ └── view/ │ └── static/ │ ├── admin.html │ ├── assets/ │ │ ├── css/ │ │ │ ├── admin.css │ │ │ ├── amazeui.css │ │ │ ├── amazeui.flat.css │ │ │ ├── app.css │ │ │ └── login.css │ │ ├── fonts/ │ │ │ └── FontAwesome.otf │ │ └── js/ │ │ ├── amazeui.ie8polyfill.js │ │ ├── amazeui.js │ │ ├── amazeui.widgets.helper.js │ │ ├── app.js │ │ ├── area.js │ │ ├── config.js │ │ ├── iscroll.js │ │ ├── login.js │ │ └── summernote.js │ ├── base-component/ │ │ ├── amazeui/ │ │ │ ├── css/ │ │ │ │ ├── admin.css │ │ │ │ ├── amazeui.css │ │ │ │ ├── amazeui.flat.css │ │ │ │ └── app.css │ │ │ ├── fonts/ │ │ │ │ └── FontAwesome.otf │ │ │ └── js/ │ │ │ ├── amazeui.ie8polyfill.js │ │ │ ├── amazeui.js │ │ │ ├── amazeui.widgets.helper.js │ │ │ ├── app.js │ │ │ ├── area.js │ │ │ ├── config.js │ │ │ ├── iscroll.js │ │ │ └── summernote.js │ │ └── layer/ │ │ ├── layer.js │ │ └── skin/ │ │ └── layer.css │ ├── css/ │ │ ├── bootstrap-treeview.css │ │ ├── font-awesome/ │ │ │ ├── css/ │ │ │ │ └── font-awesome.css │ │ │ └── fonts/ │ │ │ └── FontAwesome.otf │ │ ├── login.css │ │ ├── simple-line-icons/ │ │ │ └── css/ │ │ │ └── simple-line-icons.css │ │ ├── style.css │ │ ├── treetable/ │ │ │ ├── jquery.treetable.css │ │ │ ├── jquery.treetable.theme.default.css │ │ │ └── screen.css │ │ ├── your_style.css │ │ └── ztree/ │ │ ├── awesomeStyle/ │ │ │ ├── awesome.css │ │ │ ├── awesome.less │ │ │ └── fa.less │ │ ├── demo.css │ │ ├── metroStyle/ │ │ │ └── metroStyle.css │ │ └── zTreeStyle/ │ │ └── zTreeStyle.css │ ├── editor-app/ │ │ ├── app.js │ │ ├── editor/ │ │ │ ├── css/ │ │ │ │ └── editor.css │ │ │ └── oryx.debug.js │ │ └── libs/ │ │ ├── angular-dragdrop.min-1.0.3.js │ │ ├── angular-mocks_1.2.13/ │ │ │ └── angular-mocks.js │ │ ├── angular-resource_1.2.13/ │ │ │ └── angular-resource.js │ │ ├── angular-route_1.2.13/ │ │ │ └── angular-route.js │ │ ├── angular-sanitize_1.2.13/ │ │ │ └── angular-sanitize.js │ │ ├── angular-translate-loader-static-files/ │ │ │ ├── .bower.json │ │ │ └── angular-translate-loader-static-files.js │ │ ├── angular-translate-storage-cookie/ │ │ │ ├── .bower.json │ │ │ └── angular-translate-storage-cookie.js │ │ ├── angular-translate_2.4.2/ │ │ │ └── angular-translate.js │ │ ├── bootstrap-daterangepicker_1.3.7/ │ │ │ ├── daterangepicker-bs3.css │ │ │ └── daterangepicker.js │ │ ├── jquery.autogrow-textarea.js │ │ ├── ng-grid-2.0.7-min.js │ │ └── ui-utils.min-0.0.4.js │ ├── img/ │ │ └── bg.jpg1 │ ├── index.html │ ├── index.html.aaa │ ├── index.html.bak1 │ ├── index.html.bak2 │ ├── js/ │ │ ├── app.js │ │ ├── bootstrap/ │ │ │ └── bootstrap-treeview.js │ │ ├── common.js │ │ ├── dict.js │ │ ├── index.js │ │ ├── jq.js │ │ ├── libs/ │ │ │ └── jquery.treetable.js │ │ ├── main.js │ │ ├── main2.js │ │ ├── my/ │ │ │ ├── job.js │ │ │ ├── permission.js │ │ │ ├── roles/ │ │ │ │ └── role.js │ │ │ ├── ztree-menu.js │ │ │ └── ztree-service.js │ │ ├── plugin/ │ │ │ └── datatables/ │ │ │ ├── Chinese.lang │ │ │ └── swf/ │ │ │ ├── copy_csv_xls.swf │ │ │ └── copy_csv_xls_pdf.swf │ │ └── util/ │ │ └── ajaxutils.js │ ├── layui/ │ │ ├── css/ │ │ │ ├── layui.css │ │ │ ├── layui.mobile.css │ │ │ └── modules/ │ │ │ ├── code.css │ │ │ ├── laydate/ │ │ │ │ └── default/ │ │ │ │ └── laydate.css │ │ │ └── layer/ │ │ │ └── default/ │ │ │ └── layer.css │ │ ├── lay/ │ │ │ └── modules/ │ │ │ ├── carousel.js │ │ │ ├── code.js │ │ │ ├── element.js │ │ │ ├── flow.js │ │ │ ├── form.js │ │ │ ├── jquery.js │ │ │ ├── laydate.js │ │ │ ├── layedit.js │ │ │ ├── layer.js │ │ │ ├── laypage.js │ │ │ ├── laytpl.js │ │ │ ├── mobile.js │ │ │ ├── rate.js │ │ │ ├── table.js │ │ │ ├── tree.js │ │ │ ├── upload.js │ │ │ └── util.js │ │ ├── layui.all.js │ │ └── layui.js │ ├── lib/ │ │ ├── bootstrap/ │ │ │ ├── css/ │ │ │ │ ├── bootstrap-grid.css │ │ │ │ ├── bootstrap-reboot.css │ │ │ │ └── bootstrap.css │ │ │ └── js/ │ │ │ ├── bootstrap.bundle.js │ │ │ └── bootstrap.js │ │ ├── font-awesome/ │ │ │ ├── css/ │ │ │ │ └── font-awesome.css │ │ │ └── fonts/ │ │ │ └── FontAwesome.otf │ │ ├── jquery/ │ │ │ ├── core.js │ │ │ ├── jquery.js │ │ │ └── jquery.slim.js │ │ ├── layer/ │ │ │ ├── layer.js │ │ │ ├── mobile/ │ │ │ │ ├── layer.js │ │ │ │ └── need/ │ │ │ │ └── layer.css │ │ │ └── theme/ │ │ │ └── default/ │ │ │ └── layer.css │ │ ├── layui/ │ │ │ ├── css/ │ │ │ │ ├── global.css │ │ │ │ ├── layui.css │ │ │ │ ├── layui.mobile.css │ │ │ │ └── modules/ │ │ │ │ ├── code.css │ │ │ │ ├── laydate/ │ │ │ │ │ └── default/ │ │ │ │ │ └── laydate.css │ │ │ │ └── layer/ │ │ │ │ └── default/ │ │ │ │ └── layer.css │ │ │ ├── lay/ │ │ │ │ └── modules/ │ │ │ │ ├── carousel.js │ │ │ │ ├── code.js │ │ │ │ ├── element.js │ │ │ │ ├── flow.js │ │ │ │ ├── form.js │ │ │ │ ├── jquery.js │ │ │ │ ├── laydate.js │ │ │ │ ├── layedit.js │ │ │ │ ├── layer.js │ │ │ │ ├── laypage.js │ │ │ │ ├── laytpl.js │ │ │ │ ├── mobile.js │ │ │ │ ├── table.js │ │ │ │ ├── tree.js │ │ │ │ ├── upload.js │ │ │ │ └── util.js │ │ │ ├── layui.all.js │ │ │ ├── layui.js │ │ │ └── layuiextend/ │ │ │ ├── treeSelect/ │ │ │ │ ├── css/ │ │ │ │ │ └── treeSelect.css │ │ │ │ └── treeselect.js │ │ │ ├── treegrid/ │ │ │ │ ├── css/ │ │ │ │ │ └── grid.css │ │ │ │ ├── grid.js │ │ │ │ └── treegrid.js │ │ │ └── ztree/ │ │ │ ├── css/ │ │ │ │ ├── treeselect.css │ │ │ │ └── ztree/ │ │ │ │ ├── awesome/ │ │ │ │ │ ├── fa.less │ │ │ │ │ ├── ztree.css │ │ │ │ │ └── ztree.less │ │ │ │ ├── default/ │ │ │ │ │ └── ztree.css │ │ │ │ └── metro/ │ │ │ │ └── ztree.css │ │ │ └── js/ │ │ │ ├── treeselect.js │ │ │ └── ztree.js │ │ ├── popper.js/ │ │ │ ├── popper-utils.js │ │ │ └── popper.js │ │ ├── simple-line-icons/ │ │ │ └── css/ │ │ │ └── simple-line-icons.css │ │ └── skin/ │ │ └── css/ │ │ ├── admin.css │ │ ├── console.css │ │ └── login.css │ ├── login.html │ ├── login.html.bak │ ├── login.html.bak1 │ ├── pages/ │ │ ├── activiti/ │ │ │ ├── actList.html │ │ │ ├── actModelList.html │ │ │ ├── deploy/ │ │ │ │ └── act-node.html │ │ │ ├── diagram-viewer/ │ │ │ │ ├── index.html │ │ │ │ ├── js/ │ │ │ │ │ ├── ActivitiRest.js │ │ │ │ │ ├── ActivityImpl.js │ │ │ │ │ ├── Color.js │ │ │ │ │ ├── LineBreakMeasurer.js │ │ │ │ │ ├── Polyline.js │ │ │ │ │ ├── ProcessDiagramCanvas.js │ │ │ │ │ ├── ProcessDiagramGenerator.js │ │ │ │ │ ├── jquery/ │ │ │ │ │ │ ├── jquery.asyncqueue.js │ │ │ │ │ │ ├── jquery.js │ │ │ │ │ │ └── jquery.progressbar.js │ │ │ │ │ ├── jstools.js │ │ │ │ │ ├── raphael.2.1.1.js │ │ │ │ │ ├── raphael.js │ │ │ │ │ ├── raphael_uncompressed.js │ │ │ │ │ └── textlayout.js │ │ │ │ └── style.css │ │ │ ├── editor-app/ │ │ │ │ ├── app-cfg.js │ │ │ │ ├── app.js │ │ │ │ ├── configuration/ │ │ │ │ │ ├── properties/ │ │ │ │ │ │ ├── assignment-display-template.html │ │ │ │ │ │ ├── assignment-popup.html │ │ │ │ │ │ ├── assignment-write-template.html │ │ │ │ │ │ ├── boolean-property-template.html │ │ │ │ │ │ ├── condition-expression-display-template.html │ │ │ │ │ │ ├── condition-expression-popup.html │ │ │ │ │ │ ├── condition-expression-write-template.html │ │ │ │ │ │ ├── default-value-display-template.html │ │ │ │ │ │ ├── event-listeners-display-template.html │ │ │ │ │ │ ├── event-listeners-popup.html │ │ │ │ │ │ ├── event-listeners-write-template.html │ │ │ │ │ │ ├── execution-listeners-display-template.html │ │ │ │ │ │ ├── execution-listeners-popup.html │ │ │ │ │ │ ├── execution-listeners-write-template.html │ │ │ │ │ │ ├── feedback-popup.html │ │ │ │ │ │ ├── fields-display-template.html │ │ │ │ │ │ ├── fields-popup.html │ │ │ │ │ │ ├── fields-write-template.html │ │ │ │ │ │ ├── form-properties-display-template.html │ │ │ │ │ │ ├── form-properties-popup.html │ │ │ │ │ │ ├── form-properties-write-template.html │ │ │ │ │ │ ├── in-parameters-display-template.html │ │ │ │ │ │ ├── in-parameters-popup.html │ │ │ │ │ │ ├── in-parameters-write-template.html │ │ │ │ │ │ ├── message-definitions-display-template.html │ │ │ │ │ │ ├── message-definitions-popup.html │ │ │ │ │ │ ├── message-definitions-write-template.html │ │ │ │ │ │ ├── message-property-write-template.html │ │ │ │ │ │ ├── multiinstance-property-write-template.html │ │ │ │ │ │ ├── out-parameters-display-template.html │ │ │ │ │ │ ├── out-parameters-popup.html │ │ │ │ │ │ ├── out-parameters-write-template.html │ │ │ │ │ │ ├── sequenceflow-order-display-template.html │ │ │ │ │ │ ├── sequenceflow-order-popup.html │ │ │ │ │ │ ├── sequenceflow-order-write-template.html │ │ │ │ │ │ ├── signal-definitions-display-template.html │ │ │ │ │ │ ├── signal-definitions-popup.html │ │ │ │ │ │ ├── signal-definitions-write-template.html │ │ │ │ │ │ ├── signal-property-write-template.html │ │ │ │ │ │ ├── string-property-write-mode-template.html │ │ │ │ │ │ ├── subprocess-reference-display-template.html │ │ │ │ │ │ ├── subprocess-reference-popup.html │ │ │ │ │ │ ├── subprocess-reference-write-template.html │ │ │ │ │ │ ├── task-listeners-display-template.html │ │ │ │ │ │ ├── task-listeners-popup.html │ │ │ │ │ │ ├── task-listeners-write-template.html │ │ │ │ │ │ ├── text-popup.html │ │ │ │ │ │ └── text-property-write-template.html │ │ │ │ │ ├── properties-assignment-controller.js │ │ │ │ │ ├── properties-condition-expression-controller.js │ │ │ │ │ ├── properties-custom-controllers.js │ │ │ │ │ ├── properties-default-controllers.js │ │ │ │ │ ├── properties-event-listeners-controller.js │ │ │ │ │ ├── properties-execution-listeners-controller.js │ │ │ │ │ ├── properties-fields-controller.js │ │ │ │ │ ├── properties-form-properties-controller.js │ │ │ │ │ ├── properties-in-parameters-controller.js │ │ │ │ │ ├── properties-message-definitions-controller.js │ │ │ │ │ ├── properties-message-scope-controller.js │ │ │ │ │ ├── properties-multiinstance-controller.js │ │ │ │ │ ├── properties-out-parameters-controller.js │ │ │ │ │ ├── properties-sequenceflow-order-controller.js │ │ │ │ │ ├── properties-signal-definitions-controller.js │ │ │ │ │ ├── properties-signal-scope-controller.js │ │ │ │ │ ├── properties-task-listeners-controller.js │ │ │ │ │ ├── properties.js │ │ │ │ │ ├── toolbar-custom-actions.js │ │ │ │ │ ├── toolbar-default-actions.js │ │ │ │ │ ├── toolbar.js │ │ │ │ │ └── url-config.js │ │ │ │ ├── css/ │ │ │ │ │ ├── style-common.css │ │ │ │ │ ├── style-editor.css │ │ │ │ │ └── style.css │ │ │ │ ├── editor/ │ │ │ │ │ ├── css/ │ │ │ │ │ │ └── editor.css │ │ │ │ │ ├── i18n/ │ │ │ │ │ │ ├── translation_de.js │ │ │ │ │ │ ├── translation_en_us.js │ │ │ │ │ │ ├── translation_signavio_de.js │ │ │ │ │ │ └── translation_signavio_en_us.js │ │ │ │ │ ├── oryx.debug.js │ │ │ │ │ └── oryx.js │ │ │ │ ├── editor-config.js │ │ │ │ ├── editor-controller.js │ │ │ │ ├── editor-utils.js │ │ │ │ ├── editor.html │ │ │ │ ├── eventbus.js │ │ │ │ ├── header-controller.js │ │ │ │ ├── i18n/ │ │ │ │ │ ├── en.json │ │ │ │ │ └── en.json_bak │ │ │ │ ├── libs/ │ │ │ │ │ ├── angular-dragdrop.min-1.0.3.js │ │ │ │ │ ├── angular-mocks_1.2.13/ │ │ │ │ │ │ └── angular-mocks.js │ │ │ │ │ ├── angular-resource_1.2.13/ │ │ │ │ │ │ └── angular-resource.js │ │ │ │ │ ├── angular-route_1.2.13/ │ │ │ │ │ │ └── angular-route.js │ │ │ │ │ ├── angular-sanitize_1.2.13/ │ │ │ │ │ │ └── angular-sanitize.js │ │ │ │ │ ├── angular-translate-loader-static-files/ │ │ │ │ │ │ ├── .bower.json │ │ │ │ │ │ └── angular-translate-loader-static-files.js │ │ │ │ │ ├── angular-translate-storage-cookie/ │ │ │ │ │ │ ├── .bower.json │ │ │ │ │ │ └── angular-translate-storage-cookie.js │ │ │ │ │ ├── angular-translate_2.4.2/ │ │ │ │ │ │ └── angular-translate.js │ │ │ │ │ ├── bootstrap-daterangepicker_1.3.7/ │ │ │ │ │ │ ├── daterangepicker-bs3.css │ │ │ │ │ │ └── daterangepicker.js │ │ │ │ │ ├── bootstrap_3.1.1/ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ ├── bootstrap-theme.css │ │ │ │ │ │ │ └── bootstrap.css │ │ │ │ │ │ └── js/ │ │ │ │ │ │ └── bootstrap.js │ │ │ │ │ ├── es5-shim-15.3.4.5/ │ │ │ │ │ │ ├── .bower.json │ │ │ │ │ │ ├── .gitignore │ │ │ │ │ │ ├── CHANGES │ │ │ │ │ │ ├── CONTRIBUTORS.md │ │ │ │ │ │ ├── LICENSE │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ ├── es5-sham.js │ │ │ │ │ │ ├── es5-shim.js │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ └── tests/ │ │ │ │ │ │ ├── helpers/ │ │ │ │ │ │ │ ├── h-kill.js │ │ │ │ │ │ │ ├── h-matchers.js │ │ │ │ │ │ │ └── h.js │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ ├── index.min.html │ │ │ │ │ │ ├── lib/ │ │ │ │ │ │ │ ├── jasmine-html.js │ │ │ │ │ │ │ ├── jasmine.css │ │ │ │ │ │ │ ├── jasmine.js │ │ │ │ │ │ │ └── json2.js │ │ │ │ │ │ └── spec/ │ │ │ │ │ │ ├── s-array.js │ │ │ │ │ │ ├── s-date.js │ │ │ │ │ │ ├── s-function.js │ │ │ │ │ │ ├── s-number.js │ │ │ │ │ │ ├── s-object.js │ │ │ │ │ │ └── s-string.js │ │ │ │ │ ├── jquery.autogrow-textarea.js │ │ │ │ │ ├── jquery_1.11.0/ │ │ │ │ │ │ └── jquery.js │ │ │ │ │ ├── json3_3.2.6/ │ │ │ │ │ │ ├── LICENSE │ │ │ │ │ │ └── lib/ │ │ │ │ │ │ └── json3.js │ │ │ │ │ ├── ng-grid-2.0.7-min.js │ │ │ │ │ ├── path_parser.js │ │ │ │ │ ├── prototype-1.5.1.js │ │ │ │ │ └── ui-utils.min-0.0.4.js │ │ │ │ ├── partials/ │ │ │ │ │ ├── root-stencil-item-template.html │ │ │ │ │ └── stencil-item-template.html │ │ │ │ ├── plugins.xml │ │ │ │ ├── popups/ │ │ │ │ │ ├── icon-template.html │ │ │ │ │ ├── save-model.html │ │ │ │ │ ├── select-shape.html │ │ │ │ │ └── unsaved-changes.html │ │ │ │ ├── select-shape-controller.js │ │ │ │ ├── stencil-controller.js │ │ │ │ └── toolbar-controller.js │ │ │ └── modeler.html │ │ ├── client/ │ │ │ ├── addClient.html │ │ │ └── clientList.html │ │ ├── dashboard.html │ │ ├── dict/ │ │ │ ├── addDict.html │ │ │ ├── dictList.html │ │ │ └── updateDict.html │ │ ├── euraka/ │ │ │ └── euraka.html │ │ ├── excel/ │ │ │ └── sql.html │ │ ├── file/ │ │ │ └── fileList.html │ │ ├── generate/ │ │ │ └── edit.html │ │ ├── job/ │ │ │ ├── addJob.html │ │ │ ├── jobList.html │ │ │ └── updateJob.html │ │ ├── log/ │ │ │ └── logList.html │ │ ├── mail/ │ │ │ ├── addMail.html │ │ │ ├── mailDetail.html │ │ │ └── mailList.html │ │ ├── menu/ │ │ │ ├── addMenu.html │ │ │ ├── icon.html │ │ │ ├── menuList.html │ │ │ └── updateMenu.html │ │ ├── notice/ │ │ │ ├── addNotice.html │ │ │ ├── detail.html │ │ │ ├── noticeList.html │ │ │ ├── noticePubList.html │ │ │ └── updateNotice.html │ │ ├── role/ │ │ │ ├── addRole.html │ │ │ └── roleList.html │ │ ├── service/ │ │ │ ├── addService.html │ │ │ ├── icon.html │ │ │ ├── serviceList.html │ │ │ └── updateService.html │ │ └── user/ │ │ ├── addUser.html │ │ ├── changePassword.html │ │ ├── updateHeadImg.html │ │ ├── updateMyself.html │ │ ├── updateUser.html │ │ └── userList.html │ └── public/ │ ├── css/ │ │ ├── index1.css │ │ └── main.css │ ├── fonts/ │ │ └── FontAwesome.otf │ ├── js/ │ │ ├── common.js │ │ ├── index.js │ │ ├── navtab.js │ │ └── sys/ │ │ ├── config.js │ │ ├── generator.js │ │ ├── log.js │ │ ├── menu.js │ │ ├── role.js │ │ ├── schedule.js │ │ ├── schedule_log.js │ │ └── user.js │ ├── libs/ │ │ ├── ajaxupload.js │ │ ├── app.js │ │ └── router.js │ └── plugins/ │ ├── jqgrid/ │ │ ├── grid.locale-cn.js │ │ ├── ui.jqgrid-bootstrap-ui.css │ │ ├── ui.jqgrid-bootstrap.css │ │ └── ui.jqgrid.css │ ├── layer/ │ │ ├── layer.js │ │ ├── mobile/ │ │ │ ├── layer.js │ │ │ └── need/ │ │ │ └── layer.css │ │ └── skin/ │ │ ├── default/ │ │ │ └── layer.css │ │ └── moon/ │ │ └── style.css │ ├── layui/ │ │ ├── css/ │ │ │ ├── layui.css │ │ │ └── modules/ │ │ │ ├── code.css │ │ │ ├── icheck/ │ │ │ │ ├── flat/ │ │ │ │ │ ├── _all.css │ │ │ │ │ ├── aero.css │ │ │ │ │ ├── blue.css │ │ │ │ │ ├── flat.css │ │ │ │ │ ├── green.css │ │ │ │ │ ├── grey.css │ │ │ │ │ ├── orange.css │ │ │ │ │ ├── pink.css │ │ │ │ │ ├── purple.css │ │ │ │ │ ├── red.css │ │ │ │ │ └── yellow.css │ │ │ │ ├── futurico/ │ │ │ │ │ └── futurico.css │ │ │ │ ├── icheck.css │ │ │ │ ├── line/ │ │ │ │ │ ├── _all.css │ │ │ │ │ ├── aero.css │ │ │ │ │ ├── blue.css │ │ │ │ │ ├── green.css │ │ │ │ │ ├── grey.css │ │ │ │ │ ├── line.css │ │ │ │ │ ├── orange.css │ │ │ │ │ ├── pink.css │ │ │ │ │ ├── purple.css │ │ │ │ │ ├── red.css │ │ │ │ │ └── yellow.css │ │ │ │ ├── minimal/ │ │ │ │ │ ├── _all.css │ │ │ │ │ ├── aero.css │ │ │ │ │ ├── blue.css │ │ │ │ │ ├── green.css │ │ │ │ │ ├── grey.css │ │ │ │ │ ├── minimal.css │ │ │ │ │ ├── orange.css │ │ │ │ │ ├── pink.css │ │ │ │ │ ├── purple.css │ │ │ │ │ ├── red.css │ │ │ │ │ └── yellow.css │ │ │ │ ├── polaris/ │ │ │ │ │ └── polaris.css │ │ │ │ └── square/ │ │ │ │ ├── _all.css │ │ │ │ ├── aero.css │ │ │ │ ├── blue.css │ │ │ │ ├── green.css │ │ │ │ ├── grey.css │ │ │ │ ├── orange.css │ │ │ │ ├── pink.css │ │ │ │ ├── purple.css │ │ │ │ ├── red.css │ │ │ │ ├── square.css │ │ │ │ └── yellow.css │ │ │ ├── laydate/ │ │ │ │ └── laydate.css │ │ │ └── layer/ │ │ │ └── default/ │ │ │ └── layer.css │ │ ├── lay/ │ │ │ ├── dest/ │ │ │ │ ├── layui.all.js │ │ │ │ └── layui.mod.js │ │ │ ├── lib/ │ │ │ │ └── jquery.js │ │ │ └── modules/ │ │ │ ├── code.js │ │ │ ├── element.js │ │ │ ├── flow.js │ │ │ ├── form.js │ │ │ ├── laydate.js │ │ │ ├── layedit.js │ │ │ ├── layer.js │ │ │ ├── laypage.js │ │ │ ├── laytpl.js │ │ │ ├── tree.js │ │ │ ├── upload.js │ │ │ └── util.js │ │ ├── layui.js │ │ └── modules/ │ │ ├── icheck.js │ │ └── pjax.js │ └── ztree/ │ └── css/ │ ├── awesomeStyle/ │ │ ├── awesome.css │ │ ├── awesome.less │ │ └── fa.less │ ├── metroStyle/ │ │ └── metroStyle.css │ └── zTreeStyle/ │ └── zTreeStyle.css ├── open-monitor-center/ │ ├── cachecloud/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── cachecloud-open-client/ │ │ │ ├── cachecloud-jedis/ │ │ │ │ ├── .gitignore │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ ├── main/ │ │ │ │ │ └── java/ │ │ │ │ │ └── redis/ │ │ │ │ │ └── clients/ │ │ │ │ │ ├── jedis/ │ │ │ │ │ │ ├── BinaryClient.java │ │ │ │ │ │ ├── BinaryJedis.java │ │ │ │ │ │ ├── BinaryJedisCluster.java │ │ │ │ │ │ ├── BinaryJedisPubSub.java │ │ │ │ │ │ ├── BinaryShardedJedis.java │ │ │ │ │ │ ├── BitOP.java │ │ │ │ │ │ ├── BitPosParams.java │ │ │ │ │ │ ├── Builder.java │ │ │ │ │ │ ├── BuilderFactory.java │ │ │ │ │ │ ├── Client.java │ │ │ │ │ │ ├── Connection.java │ │ │ │ │ │ ├── DebugParams.java │ │ │ │ │ │ ├── GeoCoordinate.java │ │ │ │ │ │ ├── GeoRadiusResponse.java │ │ │ │ │ │ ├── GeoUnit.java │ │ │ │ │ │ ├── HostAndPort.java │ │ │ │ │ │ ├── Jedis.java │ │ │ │ │ │ ├── JedisCluster.java │ │ │ │ │ │ ├── JedisClusterCommand.java │ │ │ │ │ │ ├── JedisClusterConnectionHandler.java │ │ │ │ │ │ ├── JedisClusterInfoCache.java │ │ │ │ │ │ ├── JedisFactory.java │ │ │ │ │ │ ├── JedisMonitor.java │ │ │ │ │ │ ├── JedisPool.java │ │ │ │ │ │ ├── JedisPoolAbstract.java │ │ │ │ │ │ ├── JedisPoolConfig.java │ │ │ │ │ │ ├── JedisPubSub.java │ │ │ │ │ │ ├── JedisSentinelPool.java │ │ │ │ │ │ ├── JedisShardInfo.java │ │ │ │ │ │ ├── JedisSlotBasedConnectionHandler.java │ │ │ │ │ │ ├── MultiKeyPipelineBase.java │ │ │ │ │ │ ├── Pipeline.java │ │ │ │ │ │ ├── PipelineBase.java │ │ │ │ │ │ ├── PipelineCluster.java │ │ │ │ │ │ ├── PipelineClusterCommand.java │ │ │ │ │ │ ├── Protocol.java │ │ │ │ │ │ ├── Queable.java │ │ │ │ │ │ ├── RedisPipeline.java │ │ │ │ │ │ ├── Response.java │ │ │ │ │ │ ├── ScanParams.java │ │ │ │ │ │ ├── ScanResult.java │ │ │ │ │ │ ├── ShardedJedis.java │ │ │ │ │ │ ├── ShardedJedisPipeline.java │ │ │ │ │ │ ├── ShardedJedisPool.java │ │ │ │ │ │ ├── SortingParams.java │ │ │ │ │ │ ├── SubPubClusterCommand.java │ │ │ │ │ │ ├── Transaction.java │ │ │ │ │ │ ├── Tuple.java │ │ │ │ │ │ ├── ZParams.java │ │ │ │ │ │ ├── commands/ │ │ │ │ │ │ │ ├── AdvancedBinaryJedisCommands.java │ │ │ │ │ │ │ ├── AdvancedJedisCommands.java │ │ │ │ │ │ │ ├── BasicCommands.java │ │ │ │ │ │ │ ├── BasicRedisPipeline.java │ │ │ │ │ │ │ ├── BinaryJedisClusterCommands.java │ │ │ │ │ │ │ ├── BinaryJedisCommands.java │ │ │ │ │ │ │ ├── BinaryRedisPipeline.java │ │ │ │ │ │ │ ├── BinaryScriptingCommands.java │ │ │ │ │ │ │ ├── BinaryScriptingCommandsPipeline.java │ │ │ │ │ │ │ ├── ClusterCommands.java │ │ │ │ │ │ │ ├── ClusterPipeline.java │ │ │ │ │ │ │ ├── Commands.java │ │ │ │ │ │ │ ├── JedisClusterBinaryScriptingCommands.java │ │ │ │ │ │ │ ├── JedisClusterCommands.java │ │ │ │ │ │ │ ├── JedisClusterScriptingCommands.java │ │ │ │ │ │ │ ├── JedisCommands.java │ │ │ │ │ │ │ ├── MultiKeyBinaryCommands.java │ │ │ │ │ │ │ ├── MultiKeyBinaryJedisClusterCommands.java │ │ │ │ │ │ │ ├── MultiKeyBinaryRedisPipeline.java │ │ │ │ │ │ │ ├── MultiKeyCommands.java │ │ │ │ │ │ │ ├── MultiKeyCommandsPipeline.java │ │ │ │ │ │ │ ├── MultiKeyJedisClusterCommands.java │ │ │ │ │ │ │ ├── ProtocolCommand.java │ │ │ │ │ │ │ ├── RedisPipeline.java │ │ │ │ │ │ │ ├── ScriptingCommands.java │ │ │ │ │ │ │ ├── ScriptingCommandsPipeline.java │ │ │ │ │ │ │ └── SentinelCommands.java │ │ │ │ │ │ ├── exceptions/ │ │ │ │ │ │ │ ├── InvalidURIException.java │ │ │ │ │ │ │ ├── JedisAskDataException.java │ │ │ │ │ │ │ ├── JedisClusterCrossSlotException.java │ │ │ │ │ │ │ ├── JedisClusterException.java │ │ │ │ │ │ │ ├── JedisClusterMaxRedirectionsException.java │ │ │ │ │ │ │ ├── JedisConnectionException.java │ │ │ │ │ │ │ ├── JedisDataException.java │ │ │ │ │ │ │ ├── JedisException.java │ │ │ │ │ │ │ ├── JedisMovedDataException.java │ │ │ │ │ │ │ └── JedisRedirectionException.java │ │ │ │ │ │ ├── params/ │ │ │ │ │ │ │ ├── Params.java │ │ │ │ │ │ │ ├── geo/ │ │ │ │ │ │ │ │ └── GeoRadiusParam.java │ │ │ │ │ │ │ ├── set/ │ │ │ │ │ │ │ │ └── SetParams.java │ │ │ │ │ │ │ └── sortedset/ │ │ │ │ │ │ │ ├── ZAddParams.java │ │ │ │ │ │ │ └── ZIncrByParams.java │ │ │ │ │ │ ├── serializable/ │ │ │ │ │ │ │ ├── ProtostuffSerializer.java │ │ │ │ │ │ │ └── VO.java │ │ │ │ │ │ └── valueobject/ │ │ │ │ │ │ ├── RangeScoreVO.java │ │ │ │ │ │ ├── ReshardProcess.java │ │ │ │ │ │ └── SortedSetVO.java │ │ │ │ │ └── util/ │ │ │ │ │ ├── ClusterNodeInformation.java │ │ │ │ │ ├── ClusterNodeInformationParser.java │ │ │ │ │ ├── Hashing.java │ │ │ │ │ ├── IOUtils.java │ │ │ │ │ ├── JedisByteHashMap.java │ │ │ │ │ ├── JedisClusterCRC16.java │ │ │ │ │ ├── JedisURIHelper.java │ │ │ │ │ ├── KeyMergeUtil.java │ │ │ │ │ ├── MurmurHash.java │ │ │ │ │ ├── Pool.java │ │ │ │ │ ├── RedisInputStream.java │ │ │ │ │ ├── RedisOutputStream.java │ │ │ │ │ ├── SafeEncoder.java │ │ │ │ │ ├── ShardInfo.java │ │ │ │ │ ├── Sharded.java │ │ │ │ │ └── Slowlog.java │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── redis/ │ │ │ │ └── clients/ │ │ │ │ └── jedis/ │ │ │ │ ├── PipelineClusterTest.java │ │ │ │ ├── TupleTest.java │ │ │ │ └── tests/ │ │ │ │ ├── BuilderFactoryTest.java │ │ │ │ ├── ConnectionCloseTest.java │ │ │ │ ├── ConnectionTest.java │ │ │ │ ├── FragmentedByteArrayInputStream.java │ │ │ │ ├── HostAndPortUtil.java │ │ │ │ ├── JedisClusterNodeInformationParserTest.java │ │ │ │ ├── JedisClusterTest.java │ │ │ │ ├── JedisPoolTest.java │ │ │ │ ├── JedisSentinelPoolTest.java │ │ │ │ ├── JedisSentinelTest.java │ │ │ │ ├── JedisTest.java │ │ │ │ ├── JedisTestBase.java │ │ │ │ ├── KeyMergeUtilTest.java │ │ │ │ ├── PipeliningTest.java │ │ │ │ ├── ProtocolTest.java │ │ │ │ ├── ShardedJedisPipelineTest.java │ │ │ │ ├── ShardedJedisPoolTest.java │ │ │ │ ├── ShardedJedisTest.java │ │ │ │ ├── benchmark/ │ │ │ │ │ ├── CRC16Benchmark.java │ │ │ │ │ ├── GetSetBenchmark.java │ │ │ │ │ ├── HashingBenchmark.java │ │ │ │ │ ├── PipelinedGetSetBenchmark.java │ │ │ │ │ ├── PoolBenchmark.java │ │ │ │ │ ├── ProtocolBenchmark.java │ │ │ │ │ ├── SafeEncoderBenchmark.java │ │ │ │ │ └── ShardedBenchmark.java │ │ │ │ ├── collections/ │ │ │ │ │ └── SetFromListTest.java │ │ │ │ ├── commands/ │ │ │ │ │ ├── AllKindOfValuesCommandsTest.java │ │ │ │ │ ├── BinaryValuesCommandsTest.java │ │ │ │ │ ├── BitCommandsTest.java │ │ │ │ │ ├── ClusterBinaryJedisCommandsTest.java │ │ │ │ │ ├── ClusterCommandsTest.java │ │ │ │ │ ├── ClusterScriptingCommandsTest.java │ │ │ │ │ ├── ConnectionHandlingCommandsTest.java │ │ │ │ │ ├── ControlCommandsTest.java │ │ │ │ │ ├── GeoCommandsTest.java │ │ │ │ │ ├── HashesCommandsTest.java │ │ │ │ │ ├── HyperLogLogCommandsTest.java │ │ │ │ │ ├── JedisCommandTestBase.java │ │ │ │ │ ├── ListCommandsTest.java │ │ │ │ │ ├── ObjectCommandsTest.java │ │ │ │ │ ├── PublishSubscribeCommandsTest.java │ │ │ │ │ ├── ScriptingCommandsTest.java │ │ │ │ │ ├── SetCommandsTest.java │ │ │ │ │ ├── SlowlogCommandsTest.java │ │ │ │ │ ├── SortedSetCommandsTest.java │ │ │ │ │ ├── SortingCommandsTest.java │ │ │ │ │ ├── StringValuesCommandsTest.java │ │ │ │ │ ├── TransactionCommandsTest.java │ │ │ │ │ └── VariadicCommandsTest.java │ │ │ │ └── utils/ │ │ │ │ ├── ClientKillerUtil.java │ │ │ │ ├── FailoverAbortedException.java │ │ │ │ ├── JedisClusterCRC16Test.java │ │ │ │ ├── JedisClusterTestUtil.java │ │ │ │ ├── JedisSentinelTestUtil.java │ │ │ │ └── JedisURIHelperTest.java │ │ │ ├── cachecloud-open-client-basic/ │ │ │ │ ├── .gitignore │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ ├── main/ │ │ │ │ │ ├── java/ │ │ │ │ │ │ └── com/ │ │ │ │ │ │ └── sohu/ │ │ │ │ │ │ └── tv/ │ │ │ │ │ │ ├── cache/ │ │ │ │ │ │ │ └── client/ │ │ │ │ │ │ │ └── common/ │ │ │ │ │ │ │ └── jmx/ │ │ │ │ │ │ │ ├── CachecloudDataWatcher.java │ │ │ │ │ │ │ └── CachecloudDataWatcherMBean.java │ │ │ │ │ │ ├── cachecloud/ │ │ │ │ │ │ │ └── client/ │ │ │ │ │ │ │ └── basic/ │ │ │ │ │ │ │ ├── component/ │ │ │ │ │ │ │ │ ├── EmailComponent.java │ │ │ │ │ │ │ │ ├── EmailComponentImpl.java │ │ │ │ │ │ │ │ ├── MobileAlertComponent.java │ │ │ │ │ │ │ │ └── MobileAlertComponentImpl.java │ │ │ │ │ │ │ ├── exception/ │ │ │ │ │ │ │ │ └── CacheCloudClientHttpUtilsException.java │ │ │ │ │ │ │ ├── heartbeat/ │ │ │ │ │ │ │ │ ├── ClientStatusEnum.java │ │ │ │ │ │ │ │ └── HeartbeatInfo.java │ │ │ │ │ │ │ └── util/ │ │ │ │ │ │ │ ├── ConstUtils.java │ │ │ │ │ │ │ ├── DateUtils.java │ │ │ │ │ │ │ ├── HttpUtils.java │ │ │ │ │ │ │ ├── JsonUtil.java │ │ │ │ │ │ │ ├── NamedThreadFactory.java │ │ │ │ │ │ │ ├── NetUtils.java │ │ │ │ │ │ │ └── StringUtil.java │ │ │ │ │ │ └── jedis/ │ │ │ │ │ │ └── stat/ │ │ │ │ │ │ ├── constant/ │ │ │ │ │ │ │ └── ClientReportConstant.java │ │ │ │ │ │ ├── data/ │ │ │ │ │ │ │ └── UsefulDataCollector.java │ │ │ │ │ │ ├── enums/ │ │ │ │ │ │ │ ├── ClientCollectDataTypeEnum.java │ │ │ │ │ │ │ ├── ClientExceptionType.java │ │ │ │ │ │ │ ├── CostTimeDistriEnum.java │ │ │ │ │ │ │ └── ValueSizeDistriEnum.java │ │ │ │ │ │ ├── model/ │ │ │ │ │ │ │ ├── ClientReportBean.java │ │ │ │ │ │ │ ├── CostTimeDetailStatKey.java │ │ │ │ │ │ │ ├── CostTimeDetailStatModel.java │ │ │ │ │ │ │ ├── CostTimeModel.java │ │ │ │ │ │ │ ├── ExceptionModel.java │ │ │ │ │ │ │ ├── UsefulDataModel.java │ │ │ │ │ │ │ └── ValueLengthModel.java │ │ │ │ │ │ └── utils/ │ │ │ │ │ │ ├── AtomicLongMap.java │ │ │ │ │ │ ├── NamedThreadFactory.java │ │ │ │ │ │ └── NumberUtil.java │ │ │ │ │ └── resources/ │ │ │ │ │ └── cacheCloudClient.properties │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── sohu/ │ │ │ │ └── tv/ │ │ │ │ └── base/ │ │ │ │ └── test/ │ │ │ │ └── BaseTest.java │ │ │ ├── cachecloud-open-client-redis/ │ │ │ │ ├── .gitignore │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ ├── main/ │ │ │ │ │ └── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── sohu/ │ │ │ │ │ └── tv/ │ │ │ │ │ ├── builder/ │ │ │ │ │ │ ├── ClientBuilder.java │ │ │ │ │ │ ├── RedisClusterBuilder.java │ │ │ │ │ │ ├── RedisSentinelBuilder.java │ │ │ │ │ │ └── RedisStandaloneBuilder.java │ │ │ │ │ └── cachecloud/ │ │ │ │ │ └── client/ │ │ │ │ │ └── jedis/ │ │ │ │ │ └── stat/ │ │ │ │ │ ├── ClientDataCollectReportExecutor.java │ │ │ │ │ └── ClientReportDataCenter.java │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── sohu/ │ │ │ │ └── tv/ │ │ │ │ └── test/ │ │ │ │ ├── base/ │ │ │ │ │ └── BaseTest.java │ │ │ │ └── client/ │ │ │ │ ├── RedisClusterTest.java │ │ │ │ ├── RedisSentinelTest.java │ │ │ │ └── RedisStandaloneTest.java │ │ │ ├── cachecloud-open-jedis-stat/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ ├── main/ │ │ │ │ │ └── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── sohu/ │ │ │ │ │ └── tv/ │ │ │ │ │ ├── cache/ │ │ │ │ │ │ └── client/ │ │ │ │ │ │ └── common/ │ │ │ │ │ │ └── jmx/ │ │ │ │ │ │ ├── CachecloudDataWatcher.java │ │ │ │ │ │ └── CachecloudDataWatcherMBean.java │ │ │ │ │ └── jedis/ │ │ │ │ │ └── stat/ │ │ │ │ │ ├── constant/ │ │ │ │ │ │ └── ClientReportConstant.java │ │ │ │ │ ├── data/ │ │ │ │ │ │ └── UsefulDataCollector.java │ │ │ │ │ ├── enums/ │ │ │ │ │ │ ├── ClientCollectDataTypeEnum.java │ │ │ │ │ │ ├── ClientExceptionType.java │ │ │ │ │ │ ├── CostTimeDistriEnum.java │ │ │ │ │ │ └── ValueSizeDistriEnum.java │ │ │ │ │ ├── model/ │ │ │ │ │ │ ├── ClientReportBean.java │ │ │ │ │ │ ├── CostTimeDetailStatKey.java │ │ │ │ │ │ ├── CostTimeDetailStatModel.java │ │ │ │ │ │ ├── CostTimeModel.java │ │ │ │ │ │ ├── ExceptionModel.java │ │ │ │ │ │ ├── UsefulDataModel.java │ │ │ │ │ │ └── ValueLengthModel.java │ │ │ │ │ └── utils/ │ │ │ │ │ ├── AtomicLongMap.java │ │ │ │ │ ├── DateUtils.java │ │ │ │ │ ├── NamedThreadFactory.java │ │ │ │ │ └── NumberUtil.java │ │ │ │ └── test/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── sohu/ │ │ │ │ │ └── tv/ │ │ │ │ │ └── jedis/ │ │ │ │ │ └── stat/ │ │ │ │ │ └── data/ │ │ │ │ │ └── test/ │ │ │ │ │ └── UsefulDataCollectorTest.java │ │ │ │ └── resources/ │ │ │ │ └── logback-test.xml │ │ │ └── pom.xml │ │ ├── cachecloud-open-common/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── sohu/ │ │ │ └── cache/ │ │ │ ├── util/ │ │ │ │ ├── ConstUtils.java │ │ │ │ └── DemoCodeUtil.java │ │ │ └── web/ │ │ │ ├── component/ │ │ │ │ ├── EmailComponent.java │ │ │ │ ├── EmailComponentImpl.java │ │ │ │ ├── MobileAlertComponent.java │ │ │ │ └── MobileAlertComponentImpl.java │ │ │ └── util/ │ │ │ ├── HttpRequestUtil.java │ │ │ └── LoginUtil.java │ │ ├── cachecloud-open-web/ │ │ │ ├── .gitignore │ │ │ ├── nmon/ │ │ │ │ └── linux/ │ │ │ │ ├── x86/ │ │ │ │ │ ├── centos6 │ │ │ │ │ ├── centos7 │ │ │ │ │ ├── debian5 │ │ │ │ │ ├── debian50 │ │ │ │ │ ├── debian6 │ │ │ │ │ ├── debian60 │ │ │ │ │ ├── debian7 │ │ │ │ │ ├── debian8 │ │ │ │ │ ├── fedora14 │ │ │ │ │ ├── fedora15 │ │ │ │ │ ├── fedora16 │ │ │ │ │ ├── fedora17 │ │ │ │ │ ├── fedora18 │ │ │ │ │ ├── fedora19 │ │ │ │ │ ├── fedora20 │ │ │ │ │ ├── fedora21 │ │ │ │ │ ├── fedora22 │ │ │ │ │ ├── fedoracore4 │ │ │ │ │ ├── knoppix4 │ │ │ │ │ ├── knoppix5 │ │ │ │ │ ├── knoppix6 │ │ │ │ │ ├── knoppix7 │ │ │ │ │ ├── linux │ │ │ │ │ ├── linux_old │ │ │ │ │ ├── mint12 │ │ │ │ │ ├── mint14 │ │ │ │ │ ├── mint15 │ │ │ │ │ ├── mint16 │ │ │ │ │ ├── mint17 │ │ │ │ │ ├── mint7 │ │ │ │ │ ├── mint8 │ │ │ │ │ ├── opensuse11 │ │ │ │ │ ├── opensuse12 │ │ │ │ │ ├── opensuse13 │ │ │ │ │ ├── rhel5 │ │ │ │ │ ├── rhel52 │ │ │ │ │ ├── rhel54 │ │ │ │ │ ├── rhel6 │ │ │ │ │ ├── rhel65 │ │ │ │ │ ├── rhel7 │ │ │ │ │ ├── rhel71 │ │ │ │ │ ├── rhel72 │ │ │ │ │ ├── sles11 │ │ │ │ │ ├── sles12 │ │ │ │ │ ├── sles13 │ │ │ │ │ ├── ubuntu10 │ │ │ │ │ ├── ubuntu1004 │ │ │ │ │ ├── ubuntu1104 │ │ │ │ │ ├── ubuntu1110 │ │ │ │ │ ├── ubuntu13 │ │ │ │ │ ├── ubuntu14 │ │ │ │ │ ├── ubuntu1404 │ │ │ │ │ ├── ubuntu15 │ │ │ │ │ ├── ubuntu1504 │ │ │ │ │ ├── ubuntu1510 │ │ │ │ │ ├── ubuntu6 │ │ │ │ │ ├── ubuntu7 │ │ │ │ │ ├── ubuntu8 │ │ │ │ │ ├── ubuntu810 │ │ │ │ │ ├── ubuntu9 │ │ │ │ │ └── ubuntu910 │ │ │ │ └── x86_64/ │ │ │ │ ├── centos6 │ │ │ │ ├── centos7 │ │ │ │ ├── debian5 │ │ │ │ ├── debian50 │ │ │ │ ├── debian6 │ │ │ │ ├── debian60 │ │ │ │ ├── debian7 │ │ │ │ ├── debian8 │ │ │ │ ├── fedora14 │ │ │ │ ├── fedora15 │ │ │ │ ├── fedora16 │ │ │ │ ├── fedora17 │ │ │ │ ├── fedora18 │ │ │ │ ├── fedora19 │ │ │ │ ├── fedora20 │ │ │ │ ├── fedora21 │ │ │ │ ├── fedora22 │ │ │ │ ├── linux │ │ │ │ ├── linux_old │ │ │ │ ├── mint12 │ │ │ │ ├── mint14 │ │ │ │ ├── mint15 │ │ │ │ ├── mint16 │ │ │ │ ├── mint17 │ │ │ │ ├── opensuse11 │ │ │ │ ├── opensuse12 │ │ │ │ ├── opensuse13 │ │ │ │ ├── rhel4 │ │ │ │ ├── rhel45 │ │ │ │ ├── rhel5 │ │ │ │ ├── rhel54 │ │ │ │ ├── rhel6 │ │ │ │ ├── rhel7 │ │ │ │ ├── sles11 │ │ │ │ ├── sles12 │ │ │ │ ├── sles13 │ │ │ │ ├── ubuntu1004 │ │ │ │ ├── ubuntu1010 │ │ │ │ ├── ubuntu1104 │ │ │ │ ├── ubuntu1110 │ │ │ │ ├── ubuntu13 │ │ │ │ ├── ubuntu14 │ │ │ │ ├── ubuntu1404 │ │ │ │ ├── ubuntu1410 │ │ │ │ ├── ubuntu15 │ │ │ │ ├── ubuntu6 │ │ │ │ ├── ubuntu7 │ │ │ │ ├── ubuntu810 │ │ │ │ └── ubuntu910 │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── main/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── sohu/ │ │ │ │ │ └── cache/ │ │ │ │ │ ├── alert/ │ │ │ │ │ │ ├── AppAlertService.java │ │ │ │ │ │ ├── InstanceAlertService.java │ │ │ │ │ │ ├── bean/ │ │ │ │ │ │ │ └── AlertConfigBaseData.java │ │ │ │ │ │ ├── impl/ │ │ │ │ │ │ │ ├── AppAlertServiceImpl.java │ │ │ │ │ │ │ ├── BaseAlertService.java │ │ │ │ │ │ │ └── InstanceAlertServiceImpl.java │ │ │ │ │ │ └── strategy/ │ │ │ │ │ │ ├── AlertConfigStrategy.java │ │ │ │ │ │ ├── AofCurrentSizeAlertStrategy.java │ │ │ │ │ │ ├── ClientBiggestInputBufAlertStrategy.java │ │ │ │ │ │ ├── ClientLongestOutputListAlertStrategy.java │ │ │ │ │ │ ├── ClusterSlotsOkAlertStrategy.java │ │ │ │ │ │ ├── ClusterStateAlertStrategy.java │ │ │ │ │ │ ├── InstantaneousOpsPerSecAlertStrategy.java │ │ │ │ │ │ ├── LatestForkUsecAlertStrategy.java │ │ │ │ │ │ ├── MasterSlaveOffsetAlertStrategy.java │ │ │ │ │ │ ├── MemFragmentationRatioAlertStrategy.java │ │ │ │ │ │ ├── MinuteAofDelayedFsyncAlertStrategy.java │ │ │ │ │ │ ├── MinuteRejectedConnectionsAlertStrategy.java │ │ │ │ │ │ ├── MinuteSyncFullAlertStrategy.java │ │ │ │ │ │ ├── MinuteSyncPartialErrAlertStrategy.java │ │ │ │ │ │ ├── MinuteSyncPartialOkAlertStrategy.java │ │ │ │ │ │ ├── MinuteTotalNetInputMBytesAlertStrategy.java │ │ │ │ │ │ ├── MinuteTotalNetOutputMBytesAlertStrategy.java │ │ │ │ │ │ └── RdbLastBgsaveStatusAlertStrategy.java │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── AliasesResourceSqlSessionFactoryBean.java │ │ │ │ │ │ ├── ApplicationStarter.java │ │ │ │ │ │ └── JvmConfiger.java │ │ │ │ │ ├── async/ │ │ │ │ │ │ ├── AsyncService.java │ │ │ │ │ │ ├── AsyncThreadPoolFactory.java │ │ │ │ │ │ ├── KeyCallable.java │ │ │ │ │ │ ├── KeyFuture.java │ │ │ │ │ │ ├── NamedThreadFactory.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ └── AsyncServiceImpl.java │ │ │ │ │ ├── client/ │ │ │ │ │ │ ├── heartbeat/ │ │ │ │ │ │ │ ├── RedisClientController.java │ │ │ │ │ │ │ └── RedisClientReportDataController.java │ │ │ │ │ │ └── service/ │ │ │ │ │ │ ├── AppInstanceClientRelationService.java │ │ │ │ │ │ ├── ClientReportCostDistriService.java │ │ │ │ │ │ ├── ClientReportDataService.java │ │ │ │ │ │ ├── ClientReportDataSizeService.java │ │ │ │ │ │ ├── ClientReportExceptionService.java │ │ │ │ │ │ ├── ClientReportInstanceService.java │ │ │ │ │ │ ├── ClientReportValueDistriService.java │ │ │ │ │ │ ├── ClientVersionService.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── AppInstanceClientRelationServiceImpl.java │ │ │ │ │ │ ├── ClientReportCostDistriServiceImpl.java │ │ │ │ │ │ ├── ClientReportDataServiceImpl.java │ │ │ │ │ │ ├── ClientReportDataSizeServiceImpl.java │ │ │ │ │ │ ├── ClientReportExceptionServiceImpl.java │ │ │ │ │ │ ├── ClientReportInstanceServiceImpl.java │ │ │ │ │ │ ├── ClientReportValueDistriServiceImplV2.java │ │ │ │ │ │ └── ClientVersionServiceImpl.java │ │ │ │ │ ├── constant/ │ │ │ │ │ │ ├── AppAuditLogTypeEnum.java │ │ │ │ │ │ ├── AppAuditType.java │ │ │ │ │ │ ├── AppCheckEnum.java │ │ │ │ │ │ ├── AppDataMigrateEnum.java │ │ │ │ │ │ ├── AppDataMigrateResult.java │ │ │ │ │ │ ├── AppDataMigrateStatusEnum.java │ │ │ │ │ │ ├── AppDescEnum.java │ │ │ │ │ │ ├── AppStatusEnum.java │ │ │ │ │ │ ├── AppTopology.java │ │ │ │ │ │ ├── AppUserTypeEnum.java │ │ │ │ │ │ ├── BaseConstant.java │ │ │ │ │ │ ├── ClientStatusEnum.java │ │ │ │ │ │ ├── ClusterOperateResult.java │ │ │ │ │ │ ├── CommandResult.java │ │ │ │ │ │ ├── DataFormatCheckResult.java │ │ │ │ │ │ ├── EmptyObjectConstant.java │ │ │ │ │ │ ├── ErrorMessageEnum.java │ │ │ │ │ │ ├── HorizontalResult.java │ │ │ │ │ │ ├── ImportAppResult.java │ │ │ │ │ │ ├── InstanceStatusEnum.java │ │ │ │ │ │ ├── MachineConstant.java │ │ │ │ │ │ ├── MachineInfoEnum.java │ │ │ │ │ │ ├── PipelineEnum.java │ │ │ │ │ │ ├── RedisConfigTemplateChangeEnum.java │ │ │ │ │ │ ├── RedisConstant.java │ │ │ │ │ │ ├── RedisExcludeCommand.java │ │ │ │ │ │ ├── RedisMigrateToolConstant.java │ │ │ │ │ │ ├── ReshardStatusEnum.java │ │ │ │ │ │ ├── SymbolConstant.java │ │ │ │ │ │ ├── TimeDimensionalityEnum.java │ │ │ │ │ │ └── UserLoginTypeEnum.java │ │ │ │ │ ├── dao/ │ │ │ │ │ │ ├── AppAuditDao.java │ │ │ │ │ │ ├── AppAuditLogDao.java │ │ │ │ │ │ ├── AppClientCostTimeStatDao.java │ │ │ │ │ │ ├── AppClientCostTimeTotalStatDao.java │ │ │ │ │ │ ├── AppClientExceptionStatDao.java │ │ │ │ │ │ ├── AppClientReportDataSizeDao.java │ │ │ │ │ │ ├── AppClientValueStatDao.java │ │ │ │ │ │ ├── AppClientVersionDao.java │ │ │ │ │ │ ├── AppDailyDao.java │ │ │ │ │ │ ├── AppDao.java │ │ │ │ │ │ ├── AppDataMigrateStatusDao.java │ │ │ │ │ │ ├── AppInstanceClientRelationDao.java │ │ │ │ │ │ ├── AppStatsDao.java │ │ │ │ │ │ ├── AppToUserDao.java │ │ │ │ │ │ ├── AppUserDao.java │ │ │ │ │ │ ├── ConfigDao.java │ │ │ │ │ │ ├── InstanceAlertConfigDao.java │ │ │ │ │ │ ├── InstanceConfigDao.java │ │ │ │ │ │ ├── InstanceDao.java │ │ │ │ │ │ ├── InstanceFaultDao.java │ │ │ │ │ │ ├── InstanceReshardProcessDao.java │ │ │ │ │ │ ├── InstanceSlowLogDao.java │ │ │ │ │ │ ├── InstanceStatsDao.java │ │ │ │ │ │ ├── MachineDao.java │ │ │ │ │ │ ├── MachineStatsDao.java │ │ │ │ │ │ ├── MemFaultDao.java │ │ │ │ │ │ ├── QuartzDao.java │ │ │ │ │ │ └── ServerStatusDao.java │ │ │ │ │ ├── entity/ │ │ │ │ │ │ ├── AppAudit.java │ │ │ │ │ │ ├── AppAuditLog.java │ │ │ │ │ │ ├── AppClientCostTimeStat.java │ │ │ │ │ │ ├── AppClientCostTimeTotalStat.java │ │ │ │ │ │ ├── AppClientDataSizeStat.java │ │ │ │ │ │ ├── AppClientExceptionStat.java │ │ │ │ │ │ ├── AppClientValueDistriSimple.java │ │ │ │ │ │ ├── AppClientValueDistriStat.java │ │ │ │ │ │ ├── AppClientValueDistriStatTotal.java │ │ │ │ │ │ ├── AppClientVersion.java │ │ │ │ │ │ ├── AppCommandGroup.java │ │ │ │ │ │ ├── AppCommandStats.java │ │ │ │ │ │ ├── AppDailyData.java │ │ │ │ │ │ ├── AppDataMigrateSearch.java │ │ │ │ │ │ ├── AppDataMigrateStatus.java │ │ │ │ │ │ ├── AppDesc.java │ │ │ │ │ │ ├── AppInstanceClientRelation.java │ │ │ │ │ │ ├── AppSearch.java │ │ │ │ │ │ ├── AppStats.java │ │ │ │ │ │ ├── AppToUser.java │ │ │ │ │ │ ├── AppUser.java │ │ │ │ │ │ ├── ClientInstanceException.java │ │ │ │ │ │ ├── InstanceAlertConfig.java │ │ │ │ │ │ ├── InstanceAlertValueResult.java │ │ │ │ │ │ ├── InstanceCommandStats.java │ │ │ │ │ │ ├── InstanceConfig.java │ │ │ │ │ │ ├── InstanceFault.java │ │ │ │ │ │ ├── InstanceInfo.java │ │ │ │ │ │ ├── InstanceReshardProcess.java │ │ │ │ │ │ ├── InstanceSlotModel.java │ │ │ │ │ │ ├── InstanceSlowLog.java │ │ │ │ │ │ ├── InstanceStats.java │ │ │ │ │ │ ├── LoginResult.java │ │ │ │ │ │ ├── MachineInfo.java │ │ │ │ │ │ ├── MachineMemInfo.java │ │ │ │ │ │ ├── MachineStats.java │ │ │ │ │ │ ├── ServerInfo.java │ │ │ │ │ │ ├── ServerStatus.java │ │ │ │ │ │ ├── StandardStats.java │ │ │ │ │ │ ├── SystemConfig.java │ │ │ │ │ │ ├── TimeBetween.java │ │ │ │ │ │ ├── TimeDimensionality.java │ │ │ │ │ │ └── TriggerInfo.java │ │ │ │ │ ├── exception/ │ │ │ │ │ │ ├── IllegalParamException.java │ │ │ │ │ │ └── SSHException.java │ │ │ │ │ ├── init/ │ │ │ │ │ │ ├── AsyncLoad.java │ │ │ │ │ │ ├── MachineInitLoad.java │ │ │ │ │ │ └── RedisInitLoad.java │ │ │ │ │ ├── inspect/ │ │ │ │ │ │ ├── InspectHandler.java │ │ │ │ │ │ ├── InspectParamEnum.java │ │ │ │ │ │ ├── Inspector.java │ │ │ │ │ │ ├── InspectorJob.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── AbstractInspectHandler.java │ │ │ │ │ │ ├── AppClientConnInspector.java │ │ │ │ │ │ ├── AppInspectHandler.java │ │ │ │ │ │ ├── AppMemInspector.java │ │ │ │ │ │ ├── HostInspectHandler.java │ │ │ │ │ │ ├── InstanceRunInspector.java │ │ │ │ │ │ └── RedisIsolationPersistenceInspector.java │ │ │ │ │ ├── interceptor/ │ │ │ │ │ │ ├── AppAndInstanceAuthorityInterceptor.java │ │ │ │ │ │ ├── FrontUserLoginInterceptor.java │ │ │ │ │ │ ├── LoginInterceptorUtil.java │ │ │ │ │ │ └── ManageUserLoginInterceptor.java │ │ │ │ │ ├── jmx/ │ │ │ │ │ │ ├── ErrorLoggerWatcher.java │ │ │ │ │ │ ├── ErrorLoggerWatcherMBean.java │ │ │ │ │ │ ├── ThreadPoolStatisticsImpl.java │ │ │ │ │ │ └── ThreadPoolStatisticsMBean.java │ │ │ │ │ ├── log/ │ │ │ │ │ │ └── statistic/ │ │ │ │ │ │ └── ErrorStatisticsAppender.java │ │ │ │ │ ├── machine/ │ │ │ │ │ │ ├── MachineCenter.java │ │ │ │ │ │ ├── MachineDeployCenter.java │ │ │ │ │ │ ├── MachineProperty.java │ │ │ │ │ │ ├── PortGenerator.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── MachineCenterImpl.java │ │ │ │ │ │ └── MachineDeployCenterImpl.java │ │ │ │ │ ├── protocol/ │ │ │ │ │ │ ├── MachineProtocol.java │ │ │ │ │ │ └── RedisProtocol.java │ │ │ │ │ ├── redis/ │ │ │ │ │ │ ├── RedisCenter.java │ │ │ │ │ │ ├── RedisClusterNode.java │ │ │ │ │ │ ├── RedisClusterReshard.java │ │ │ │ │ │ ├── RedisConfigTemplateService.java │ │ │ │ │ │ ├── RedisDeployCenter.java │ │ │ │ │ │ ├── enums/ │ │ │ │ │ │ │ ├── InstanceAlertCheckCycleEnum.java │ │ │ │ │ │ │ ├── InstanceAlertCompareTypeEnum.java │ │ │ │ │ │ │ ├── InstanceAlertStatusEnum.java │ │ │ │ │ │ │ ├── InstanceAlertTypeEnum.java │ │ │ │ │ │ │ ├── RedisAlertConfigEnum.java │ │ │ │ │ │ │ ├── RedisClusterConfigEnum.java │ │ │ │ │ │ │ ├── RedisClusterInfoEnum.java │ │ │ │ │ │ │ ├── RedisConfigEnum.java │ │ │ │ │ │ │ ├── RedisInfoEnum.java │ │ │ │ │ │ │ ├── RedisReadOnlyCommandEnum.java │ │ │ │ │ │ │ └── RedisSentinelConfigEnum.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── RedisCenterImpl.java │ │ │ │ │ │ ├── RedisConfigTemplateServiceImpl.java │ │ │ │ │ │ └── RedisDeployCenterImpl.java │ │ │ │ │ ├── schedule/ │ │ │ │ │ │ ├── SchedulerCenter.java │ │ │ │ │ │ ├── TriggerCenter.java │ │ │ │ │ │ ├── impl/ │ │ │ │ │ │ │ ├── SchedulerCenterImpl.java │ │ │ │ │ │ │ └── TriggerCenterImpl.java │ │ │ │ │ │ └── jobs/ │ │ │ │ │ │ ├── AppDailyJob.java │ │ │ │ │ │ ├── CacheBaseJob.java │ │ │ │ │ │ ├── CleanUpStatisticsJob.java │ │ │ │ │ │ ├── ErrorStatisticsJob.java │ │ │ │ │ │ ├── InstanceAlertValueJob.java │ │ │ │ │ │ ├── MachineJob.java │ │ │ │ │ │ ├── MachineMonitorJob.java │ │ │ │ │ │ ├── RedisJob.java │ │ │ │ │ │ ├── RedisSlowLogJob.java │ │ │ │ │ │ ├── ServerJob.java │ │ │ │ │ │ └── SystemConfigRefreshJob.java │ │ │ │ │ ├── server/ │ │ │ │ │ │ ├── ServerStatusCollector.java │ │ │ │ │ │ ├── data/ │ │ │ │ │ │ │ ├── CPU.java │ │ │ │ │ │ │ ├── Connection.java │ │ │ │ │ │ │ ├── Disk.java │ │ │ │ │ │ │ ├── LineParser.java │ │ │ │ │ │ │ ├── Load.java │ │ │ │ │ │ │ ├── Memory.java │ │ │ │ │ │ │ ├── Net.java │ │ │ │ │ │ │ ├── OS.java │ │ │ │ │ │ │ ├── OSInfo.java │ │ │ │ │ │ │ └── Server.java │ │ │ │ │ │ └── nmon/ │ │ │ │ │ │ └── NMONService.java │ │ │ │ │ ├── ssh/ │ │ │ │ │ │ ├── SSHTemplate.java │ │ │ │ │ │ └── SSHUtil.java │ │ │ │ │ ├── stats/ │ │ │ │ │ │ ├── app/ │ │ │ │ │ │ │ ├── AppDailyDataCenter.java │ │ │ │ │ │ │ ├── AppDataMigrateCenter.java │ │ │ │ │ │ │ ├── AppDeployCenter.java │ │ │ │ │ │ │ ├── AppStatsCenter.java │ │ │ │ │ │ │ ├── ImportAppCenter.java │ │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ │ ├── AppDailyDataCenterImpl.java │ │ │ │ │ │ │ ├── AppDataMigrateCenterImpl.java │ │ │ │ │ │ │ ├── AppDeployCenterImpl.java │ │ │ │ │ │ │ ├── AppStatsCenterImpl.java │ │ │ │ │ │ │ └── ImportAppCenterImpl.java │ │ │ │ │ │ └── instance/ │ │ │ │ │ │ ├── InstanceAlertConfigService.java │ │ │ │ │ │ ├── InstanceDeployCenter.java │ │ │ │ │ │ ├── InstanceStatsCenter.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── InstanceAlertConfigServiceImpl.java │ │ │ │ │ │ ├── InstanceDeployCenterImpl.java │ │ │ │ │ │ └── InstanceStatsCenterImpl.java │ │ │ │ │ ├── util/ │ │ │ │ │ │ ├── AppKeyUtil.java │ │ │ │ │ │ ├── IdempotentConfirmer.java │ │ │ │ │ │ ├── IntegerUtil.java │ │ │ │ │ │ ├── JsonUtil.java │ │ │ │ │ │ ├── NMONFileFactory.java │ │ │ │ │ │ ├── OSFactory.java │ │ │ │ │ │ ├── ObjectConvert.java │ │ │ │ │ │ ├── ScheduleUtil.java │ │ │ │ │ │ ├── StringUtil.java │ │ │ │ │ │ └── TypeUtil.java │ │ │ │ │ └── web/ │ │ │ │ │ ├── chart/ │ │ │ │ │ │ ├── key/ │ │ │ │ │ │ │ └── ChartKeysUtil.java │ │ │ │ │ │ └── model/ │ │ │ │ │ │ ├── AreaChartEntity.java │ │ │ │ │ │ ├── ChartEntity.java │ │ │ │ │ │ ├── HighchartPoint.java │ │ │ │ │ │ ├── SimpleChartData.java │ │ │ │ │ │ └── SplineChartEntity.java │ │ │ │ │ ├── controller/ │ │ │ │ │ │ ├── AppClientDataShowController.java │ │ │ │ │ │ ├── AppController.java │ │ │ │ │ │ ├── AppDataMigrateController.java │ │ │ │ │ │ ├── AppManageController.java │ │ │ │ │ │ ├── BaseController.java │ │ │ │ │ │ ├── ClientManageController.java │ │ │ │ │ │ ├── ConfigManageController.java │ │ │ │ │ │ ├── FaultController.java │ │ │ │ │ │ ├── ImportAppController.java │ │ │ │ │ │ ├── IndexController.java │ │ │ │ │ │ ├── InstanceAlertValueController.java │ │ │ │ │ │ ├── InstanceController.java │ │ │ │ │ │ ├── InstanceManageController.java │ │ │ │ │ │ ├── JobController.java │ │ │ │ │ │ ├── LoginController.java │ │ │ │ │ │ ├── MachineManageController.java │ │ │ │ │ │ ├── NoticeManageController.java │ │ │ │ │ │ ├── QuartzManageController.java │ │ │ │ │ │ ├── RedisConfigTemplateController.java │ │ │ │ │ │ ├── ServerController.java │ │ │ │ │ │ ├── TotalManageController.java │ │ │ │ │ │ ├── TriggerController.java │ │ │ │ │ │ ├── UserController.java │ │ │ │ │ │ └── UserManageController.java │ │ │ │ │ ├── enums/ │ │ │ │ │ │ ├── AdminEnum.java │ │ │ │ │ │ ├── AppOrderByEnum.java │ │ │ │ │ │ ├── LoginEnum.java │ │ │ │ │ │ ├── RedisOperateEnum.java │ │ │ │ │ │ └── SuccessEnum.java │ │ │ │ │ ├── factory/ │ │ │ │ │ │ └── UserLoginStatusFactory.java │ │ │ │ │ ├── service/ │ │ │ │ │ │ ├── AppService.java │ │ │ │ │ │ ├── ConfigService.java │ │ │ │ │ │ ├── MemFaultService.java │ │ │ │ │ │ ├── ServerDataService.java │ │ │ │ │ │ ├── UserLoginStatusService.java │ │ │ │ │ │ ├── UserService.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── AppServiceImpl.java │ │ │ │ │ │ ├── ConfigServiceImpl.java │ │ │ │ │ │ ├── MemFaultServiceImpl.java │ │ │ │ │ │ ├── ServerDataServiceImpl.java │ │ │ │ │ │ ├── UserLoginStatusCookieServiceImpl.java │ │ │ │ │ │ ├── UserLoginStatusSessionServiceImpl.java │ │ │ │ │ │ └── UserServiceImpl.java │ │ │ │ │ ├── util/ │ │ │ │ │ │ ├── AppEmailUtil.java │ │ │ │ │ │ ├── DateUtil.java │ │ │ │ │ │ ├── IpUtil.java │ │ │ │ │ │ ├── Page.java │ │ │ │ │ │ ├── SimpleFileUtil.java │ │ │ │ │ │ └── VelocityUtils.java │ │ │ │ │ └── vo/ │ │ │ │ │ ├── AppDetailVO.java │ │ │ │ │ └── RedisSlowLog.java │ │ │ │ ├── resources/ │ │ │ │ │ ├── application.properties │ │ │ │ │ ├── cachecloud-web.conf │ │ │ │ │ ├── logback.xml │ │ │ │ │ ├── mapper/ │ │ │ │ │ │ ├── AppAuditDao.xml │ │ │ │ │ │ ├── AppAuditLogDao.xml │ │ │ │ │ │ ├── AppClientCostTimeStatDao.xml │ │ │ │ │ │ ├── AppClientCostTimeTotalStatDao.xml │ │ │ │ │ │ ├── AppClientExceptionStatDao.xml │ │ │ │ │ │ ├── AppClientReportDataSizeDao.xml │ │ │ │ │ │ ├── AppClientValueStatDao.xml │ │ │ │ │ │ ├── AppClientVersionDao.xml │ │ │ │ │ │ ├── AppDailyDao.xml │ │ │ │ │ │ ├── AppDao.xml │ │ │ │ │ │ ├── AppDataMigrateStatusDao.xml │ │ │ │ │ │ ├── AppInstanceClientRelationDao.xml │ │ │ │ │ │ ├── AppStatsDao.xml │ │ │ │ │ │ ├── AppToUserDao.xml │ │ │ │ │ │ ├── AppUserDao.xml │ │ │ │ │ │ ├── ConfigDao.xml │ │ │ │ │ │ ├── InstanceAlertConfigDao.xml │ │ │ │ │ │ ├── InstanceConfigDao.xml │ │ │ │ │ │ ├── InstanceDao.xml │ │ │ │ │ │ ├── InstanceFaultDao.xml │ │ │ │ │ │ ├── InstanceReshardProcessDao.xml │ │ │ │ │ │ ├── InstanceSlowLogDao.xml │ │ │ │ │ │ ├── InstanceStatsDao.xml │ │ │ │ │ │ ├── MachineDao.xml │ │ │ │ │ │ ├── MachineStatsDao.xml │ │ │ │ │ │ ├── QuartzDao.xml │ │ │ │ │ │ └── ServerStatusDao.xml │ │ │ │ │ ├── mybatis-config.xml │ │ │ │ │ ├── spring/ │ │ │ │ │ │ ├── spring-alert.xml │ │ │ │ │ │ ├── spring-client-report.xml │ │ │ │ │ │ ├── spring-config.xml │ │ │ │ │ │ ├── spring-data.xml │ │ │ │ │ │ ├── spring-inspector.xml │ │ │ │ │ │ ├── spring-jmx.xml │ │ │ │ │ │ ├── spring-load.xml │ │ │ │ │ │ ├── spring-local.xml │ │ │ │ │ │ ├── spring-manage.xml │ │ │ │ │ │ ├── spring-mvc.xml │ │ │ │ │ │ ├── spring-mybatis.xml │ │ │ │ │ │ ├── spring-online.xml │ │ │ │ │ │ ├── spring-quartz.xml │ │ │ │ │ │ ├── spring-service.xml │ │ │ │ │ │ └── spring.xml │ │ │ │ │ └── templates/ │ │ │ │ │ ├── appAudit.vm │ │ │ │ │ ├── appDaily.vm │ │ │ │ │ └── instanceAlert.vm │ │ │ │ ├── swap/ │ │ │ │ │ ├── local.properties │ │ │ │ │ └── online.properties │ │ │ │ └── webapp/ │ │ │ │ ├── WEB-INF/ │ │ │ │ │ ├── include/ │ │ │ │ │ │ ├── contact.jsp │ │ │ │ │ │ ├── foot.jsp │ │ │ │ │ │ ├── head.jsp │ │ │ │ │ │ ├── headAdmin.jsp │ │ │ │ │ │ └── headMenu.jsp │ │ │ │ │ ├── jsp/ │ │ │ │ │ │ ├── app/ │ │ │ │ │ │ │ ├── appCommand.jsp │ │ │ │ │ │ │ ├── appCommandAnalysis.jsp │ │ │ │ │ │ │ ├── appDaily.jsp │ │ │ │ │ │ │ ├── appDemo.jsp │ │ │ │ │ │ │ ├── appDetail.jsp │ │ │ │ │ │ │ ├── appInit.jsp │ │ │ │ │ │ │ ├── appInstanceNetStat.jsp │ │ │ │ │ │ │ ├── appList.jsp │ │ │ │ │ │ │ ├── appMachineInstancesTopology.jsp │ │ │ │ │ │ │ ├── appScaleApply.jsp │ │ │ │ │ │ │ ├── appStat.jsp │ │ │ │ │ │ │ ├── appTopology.jsp │ │ │ │ │ │ │ ├── initBecomeContributor.jsp │ │ │ │ │ │ │ ├── manageUser.jsp │ │ │ │ │ │ │ ├── slowLog.jsp │ │ │ │ │ │ │ └── userAppsIndex.jsp │ │ │ │ │ │ ├── client/ │ │ │ │ │ │ │ ├── appClientIndex.jsp │ │ │ │ │ │ │ ├── clientCostDistribute.jsp │ │ │ │ │ │ │ ├── clientException.jsp │ │ │ │ │ │ │ └── clientValueDistribute.jsp │ │ │ │ │ │ ├── import/ │ │ │ │ │ │ │ └── init.jsp │ │ │ │ │ │ ├── instance/ │ │ │ │ │ │ │ ├── instanceAdvancedAnalysis.jsp │ │ │ │ │ │ │ ├── instanceClientList.jsp │ │ │ │ │ │ │ ├── instanceCommand.jsp │ │ │ │ │ │ │ ├── instanceConfigSelect.jsp │ │ │ │ │ │ │ ├── instanceFault.jsp │ │ │ │ │ │ │ ├── instanceIndex.jsp │ │ │ │ │ │ │ ├── instanceSlowSelect.jsp │ │ │ │ │ │ │ └── instanceStat.jsp │ │ │ │ │ │ ├── manage/ │ │ │ │ │ │ │ ├── appAudit/ │ │ │ │ │ │ │ │ ├── addAudit.jsp │ │ │ │ │ │ │ │ ├── appAuditList.jsp │ │ │ │ │ │ │ │ ├── appConfigChangeDetail.jsp │ │ │ │ │ │ │ │ ├── appDeploy.jsp │ │ │ │ │ │ │ │ ├── appDeployDetail.jsp │ │ │ │ │ │ │ │ ├── appIntanceReferList.jsp │ │ │ │ │ │ │ │ ├── appScaleApplyDetail.jsp │ │ │ │ │ │ │ │ ├── handleHorizontalScale.jsp │ │ │ │ │ │ │ │ ├── handleHorizontalScaleDetail.jsp │ │ │ │ │ │ │ │ ├── horizontalScaleApplyDetail.jsp │ │ │ │ │ │ │ │ ├── horizontalScaleProcessList.jsp │ │ │ │ │ │ │ │ ├── initAppConfigChange.jsp │ │ │ │ │ │ │ │ ├── initAppDeploy.jsp │ │ │ │ │ │ │ │ ├── initAppScaleApply.jsp │ │ │ │ │ │ │ │ ├── initHorizontalScaleApply.jsp │ │ │ │ │ │ │ │ ├── initInstanceConfigChange.jsp │ │ │ │ │ │ │ │ ├── instanceConfig.jsp │ │ │ │ │ │ │ │ ├── instanceConfigChangeDetail.jsp │ │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ │ ├── machineForHorizontalScaleList.jsp │ │ │ │ │ │ │ │ └── machineReferList.jsp │ │ │ │ │ │ │ ├── appOps/ │ │ │ │ │ │ │ │ ├── appInfoAndAudit.jsp │ │ │ │ │ │ │ │ ├── appInstance.jsp │ │ │ │ │ │ │ │ ├── appMachine.jsp │ │ │ │ │ │ │ │ └── appOpsIndex.jsp │ │ │ │ │ │ │ ├── client/ │ │ │ │ │ │ │ │ ├── exception/ │ │ │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ │ │ └── statList.jsp │ │ │ │ │ │ │ │ └── version/ │ │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ │ └── statList.jsp │ │ │ │ │ │ │ ├── commons/ │ │ │ │ │ │ │ │ ├── appConstants.jsp │ │ │ │ │ │ │ │ └── taglibs.jsp │ │ │ │ │ │ │ ├── config/ │ │ │ │ │ │ │ │ ├── init.jsp │ │ │ │ │ │ │ │ └── initConfigDetail.jsp │ │ │ │ │ │ │ ├── fault/ │ │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ │ └── memFaultList.jsp │ │ │ │ │ │ │ ├── include/ │ │ │ │ │ │ │ │ ├── cache_cloud_main_css.jsp │ │ │ │ │ │ │ │ ├── cache_cloud_main_js.jsp │ │ │ │ │ │ │ │ ├── foot.jsp │ │ │ │ │ │ │ │ ├── head.jsp │ │ │ │ │ │ │ │ └── left.jsp │ │ │ │ │ │ │ ├── instance/ │ │ │ │ │ │ │ │ └── log.jsp │ │ │ │ │ │ │ ├── instanceAlert/ │ │ │ │ │ │ │ │ ├── init.jsp │ │ │ │ │ │ │ │ └── initConfigDetail.jsp │ │ │ │ │ │ │ ├── login.jsp │ │ │ │ │ │ │ ├── machine/ │ │ │ │ │ │ │ │ ├── addMachine.jsp │ │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ │ ├── machineInstances.jsp │ │ │ │ │ │ │ │ ├── machineInstancesDetail.jsp │ │ │ │ │ │ │ │ └── machineList.jsp │ │ │ │ │ │ │ ├── notice/ │ │ │ │ │ │ │ │ ├── initNotice.jsp │ │ │ │ │ │ │ │ └── initNoticeDetail.jsp │ │ │ │ │ │ │ ├── quartz/ │ │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ │ └── quartzList.jsp │ │ │ │ │ │ │ ├── redisConfig/ │ │ │ │ │ │ │ │ ├── init.jsp │ │ │ │ │ │ │ │ ├── initConfigDetail.jsp │ │ │ │ │ │ │ │ └── preview.jsp │ │ │ │ │ │ │ ├── total/ │ │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ │ └── totalList.jsp │ │ │ │ │ │ │ └── user/ │ │ │ │ │ │ │ ├── addUser.jsp │ │ │ │ │ │ │ ├── initUser.jsp │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ └── userList.jsp │ │ │ │ │ │ ├── migrate/ │ │ │ │ │ │ │ ├── checkData.jsp │ │ │ │ │ │ │ ├── config.jsp │ │ │ │ │ │ │ ├── init.jsp │ │ │ │ │ │ │ ├── list.jsp │ │ │ │ │ │ │ ├── log.jsp │ │ │ │ │ │ │ └── process.jsp │ │ │ │ │ │ ├── server/ │ │ │ │ │ │ │ ├── cpu.jsp │ │ │ │ │ │ │ ├── disk.jsp │ │ │ │ │ │ │ ├── index.jsp │ │ │ │ │ │ │ ├── net.jsp │ │ │ │ │ │ │ └── overview.jsp │ │ │ │ │ │ └── user/ │ │ │ │ │ │ └── userRegister.jsp │ │ │ │ │ ├── resources/ │ │ │ │ │ │ ├── My97DatePicker/ │ │ │ │ │ │ │ ├── My97DatePicker.htm │ │ │ │ │ │ │ ├── WdatePicker.js │ │ │ │ │ │ │ ├── calendar.js │ │ │ │ │ │ │ ├── config.js │ │ │ │ │ │ │ ├── lang/ │ │ │ │ │ │ │ │ ├── en.js │ │ │ │ │ │ │ │ ├── zh-cn.js │ │ │ │ │ │ │ │ └── zh-tw.js │ │ │ │ │ │ │ ├── skin/ │ │ │ │ │ │ │ │ ├── WdatePicker.css │ │ │ │ │ │ │ │ ├── default/ │ │ │ │ │ │ │ │ │ └── datepicker.css │ │ │ │ │ │ │ │ └── whyGreen/ │ │ │ │ │ │ │ │ └── datepicker.css │ │ │ │ │ │ │ └── test_02.html │ │ │ │ │ │ ├── assets/ │ │ │ │ │ │ │ └── flash/ │ │ │ │ │ │ │ └── ZeroClipboard.swf │ │ │ │ │ │ ├── bootstrap/ │ │ │ │ │ │ │ ├── bootstrap3/ │ │ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ │ │ ├── bootstrap-theme.css │ │ │ │ │ │ │ │ │ └── bootstrap.css │ │ │ │ │ │ │ │ └── js/ │ │ │ │ │ │ │ │ └── bootstrap.js │ │ │ │ │ │ │ ├── jquery/ │ │ │ │ │ │ │ │ └── jquery-1.11.0.js │ │ │ │ │ │ │ ├── paginator/ │ │ │ │ │ │ │ │ ├── bootstrap-paginator.js │ │ │ │ │ │ │ │ └── custom-pagenitor.js │ │ │ │ │ │ │ └── res/ │ │ │ │ │ │ │ ├── respond.matchmedia.addListener.src.js │ │ │ │ │ │ │ └── respond.src.js │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ ├── login.css │ │ │ │ │ │ │ └── mem-cloud.css │ │ │ │ │ │ ├── error/ │ │ │ │ │ │ │ └── noPower.jsp │ │ │ │ │ │ ├── highchart3/ │ │ │ │ │ │ │ └── js/ │ │ │ │ │ │ │ ├── adapters/ │ │ │ │ │ │ │ │ ├── mootools-adapter.js │ │ │ │ │ │ │ │ ├── mootools-adapter.src.js │ │ │ │ │ │ │ │ ├── prototype-adapter.js │ │ │ │ │ │ │ │ └── prototype-adapter.src.js │ │ │ │ │ │ │ ├── highcharts-more.js │ │ │ │ │ │ │ ├── highcharts-more.src.js │ │ │ │ │ │ │ ├── highcharts.js │ │ │ │ │ │ │ ├── highcharts.src.js │ │ │ │ │ │ │ ├── modules/ │ │ │ │ │ │ │ │ ├── annotations.js │ │ │ │ │ │ │ │ ├── annotations.src.js │ │ │ │ │ │ │ │ ├── canvas-tools.js │ │ │ │ │ │ │ │ ├── canvas-tools.src.js │ │ │ │ │ │ │ │ ├── data.js │ │ │ │ │ │ │ │ ├── data.src.js │ │ │ │ │ │ │ │ ├── exporting.js │ │ │ │ │ │ │ │ ├── exporting.src.js │ │ │ │ │ │ │ │ ├── funnel.js │ │ │ │ │ │ │ │ ├── funnel.src.js │ │ │ │ │ │ │ │ ├── heatmap.js │ │ │ │ │ │ │ │ ├── heatmap.src.js │ │ │ │ │ │ │ │ ├── map.js │ │ │ │ │ │ │ │ └── map.src.js │ │ │ │ │ │ │ └── themes/ │ │ │ │ │ │ │ ├── dark-blue.js │ │ │ │ │ │ │ ├── dark-green.js │ │ │ │ │ │ │ ├── gray.js │ │ │ │ │ │ │ ├── grid.js │ │ │ │ │ │ │ └── skies.js │ │ │ │ │ │ ├── js/ │ │ │ │ │ │ │ ├── appClient.js │ │ │ │ │ │ │ ├── appDetail.js │ │ │ │ │ │ │ ├── appInit.js │ │ │ │ │ │ │ ├── appStat.js │ │ │ │ │ │ │ ├── chart.js │ │ │ │ │ │ │ ├── instanceExecute.js │ │ │ │ │ │ │ ├── jquery-console.js │ │ │ │ │ │ │ ├── mem-cloud.js │ │ │ │ │ │ │ ├── myPopover.js │ │ │ │ │ │ │ ├── myhighchart.js │ │ │ │ │ │ │ ├── prettify.css │ │ │ │ │ │ │ ├── prettify.js │ │ │ │ │ │ │ └── run_prettify.js │ │ │ │ │ │ ├── manage/ │ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ │ ├── animate.css │ │ │ │ │ │ │ │ ├── custom.css │ │ │ │ │ │ │ │ ├── pages/ │ │ │ │ │ │ │ │ │ ├── about-us.css │ │ │ │ │ │ │ │ │ ├── blog.css │ │ │ │ │ │ │ │ │ ├── coming-soon.css │ │ │ │ │ │ │ │ │ ├── email.css │ │ │ │ │ │ │ │ │ ├── error.css │ │ │ │ │ │ │ │ │ ├── image-crop.css │ │ │ │ │ │ │ │ │ ├── inbox.css │ │ │ │ │ │ │ │ │ ├── invoice.css │ │ │ │ │ │ │ │ │ ├── lock.css │ │ │ │ │ │ │ │ │ ├── login-soft.css │ │ │ │ │ │ │ │ │ ├── login.css │ │ │ │ │ │ │ │ │ ├── news.css │ │ │ │ │ │ │ │ │ ├── portfolio.css │ │ │ │ │ │ │ │ │ ├── pricing-tables.css │ │ │ │ │ │ │ │ │ ├── profile.css │ │ │ │ │ │ │ │ │ ├── promo.css │ │ │ │ │ │ │ │ │ ├── search.css │ │ │ │ │ │ │ │ │ ├── tasks.css │ │ │ │ │ │ │ │ │ └── timeline.css │ │ │ │ │ │ │ │ ├── plugins.css │ │ │ │ │ │ │ │ ├── print.css │ │ │ │ │ │ │ │ ├── style-metronic.css │ │ │ │ │ │ │ │ ├── style-non-responsive.css │ │ │ │ │ │ │ │ ├── style-responsive.css │ │ │ │ │ │ │ │ ├── style.css │ │ │ │ │ │ │ │ └── themes/ │ │ │ │ │ │ │ │ ├── blue.css │ │ │ │ │ │ │ │ ├── brown.css │ │ │ │ │ │ │ │ ├── default.css │ │ │ │ │ │ │ │ ├── grey.css │ │ │ │ │ │ │ │ ├── light.css │ │ │ │ │ │ │ │ └── purple.css │ │ │ │ │ │ │ ├── fonts/ │ │ │ │ │ │ │ │ └── font.css │ │ │ │ │ │ │ ├── manage/ │ │ │ │ │ │ │ │ ├── auditManage.js │ │ │ │ │ │ │ │ ├── machineManage.js │ │ │ │ │ │ │ │ └── userManage.js │ │ │ │ │ │ │ ├── oldMemResource/ │ │ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ │ │ ├── invalid.css │ │ │ │ │ │ │ │ │ ├── reset.css │ │ │ │ │ │ │ │ │ └── style.css │ │ │ │ │ │ │ │ └── scripts/ │ │ │ │ │ │ │ │ ├── facebox.js │ │ │ │ │ │ │ │ ├── jquery.wysiwyg.js │ │ │ │ │ │ │ │ ├── session-create.js │ │ │ │ │ │ │ │ └── simpla.jquery.configuration.js │ │ │ │ │ │ │ ├── plugins/ │ │ │ │ │ │ │ │ ├── bootstrap/ │ │ │ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ │ │ │ └── bootstrap.css │ │ │ │ │ │ │ │ │ └── js/ │ │ │ │ │ │ │ │ │ ├── bootstrap.js │ │ │ │ │ │ │ │ │ └── bootstrap2-typeahead.js │ │ │ │ │ │ │ │ ├── data-tables/ │ │ │ │ │ │ │ │ │ ├── DT_bootstrap.css │ │ │ │ │ │ │ │ │ ├── DT_bootstrap.js │ │ │ │ │ │ │ │ │ └── jquery.dataTables.js │ │ │ │ │ │ │ │ └── font-awesome/ │ │ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ │ │ └── font-awesome.css │ │ │ │ │ │ │ │ ├── fonts/ │ │ │ │ │ │ │ │ │ └── FontAwesome.otf │ │ │ │ │ │ │ │ ├── less/ │ │ │ │ │ │ │ │ │ ├── bordered-pulled.less │ │ │ │ │ │ │ │ │ ├── core.less │ │ │ │ │ │ │ │ │ ├── fixed-width.less │ │ │ │ │ │ │ │ │ ├── font-awesome.less │ │ │ │ │ │ │ │ │ ├── icons.less │ │ │ │ │ │ │ │ │ ├── larger.less │ │ │ │ │ │ │ │ │ ├── list.less │ │ │ │ │ │ │ │ │ ├── mixins.less │ │ │ │ │ │ │ │ │ ├── path.less │ │ │ │ │ │ │ │ │ ├── rotated-flipped.less │ │ │ │ │ │ │ │ │ ├── spinning.less │ │ │ │ │ │ │ │ │ ├── stacked.less │ │ │ │ │ │ │ │ │ └── variables.less │ │ │ │ │ │ │ │ └── scss/ │ │ │ │ │ │ │ │ ├── _bordered-pulled.scss │ │ │ │ │ │ │ │ ├── _core.scss │ │ │ │ │ │ │ │ ├── _fixed-width.scss │ │ │ │ │ │ │ │ ├── _icons.scss │ │ │ │ │ │ │ │ ├── _larger.scss │ │ │ │ │ │ │ │ ├── _list.scss │ │ │ │ │ │ │ │ ├── _mixins.scss │ │ │ │ │ │ │ │ ├── _path.scss │ │ │ │ │ │ │ │ ├── _rotated-flipped.scss │ │ │ │ │ │ │ │ ├── _spinning.scss │ │ │ │ │ │ │ │ ├── _stacked.scss │ │ │ │ │ │ │ │ ├── _variables.scss │ │ │ │ │ │ │ │ └── font-awesome.scss │ │ │ │ │ │ │ └── scripts/ │ │ │ │ │ │ │ ├── app.js │ │ │ │ │ │ │ ├── calendar.js │ │ │ │ │ │ │ ├── charts.js │ │ │ │ │ │ │ ├── coming-soon.js │ │ │ │ │ │ │ ├── contact-us.js │ │ │ │ │ │ │ ├── custom.js │ │ │ │ │ │ │ ├── form-components.js │ │ │ │ │ │ │ ├── form-dropzone.js │ │ │ │ │ │ │ ├── form-editable.js │ │ │ │ │ │ │ ├── form-fileupload.js │ │ │ │ │ │ │ ├── form-image-crop.js │ │ │ │ │ │ │ ├── form-samples.js │ │ │ │ │ │ │ ├── form-validation.js │ │ │ │ │ │ │ ├── form-wizard.js │ │ │ │ │ │ │ ├── idle-timeout.js │ │ │ │ │ │ │ ├── inbox.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── lock.js │ │ │ │ │ │ │ ├── login-soft.js │ │ │ │ │ │ │ ├── login.js │ │ │ │ │ │ │ ├── maps-google.js │ │ │ │ │ │ │ ├── maps-vector.js │ │ │ │ │ │ │ ├── portfolio.js │ │ │ │ │ │ │ ├── portlet-draggable.js │ │ │ │ │ │ │ ├── search.js │ │ │ │ │ │ │ ├── table-advanced.js │ │ │ │ │ │ │ ├── table-ajax.js │ │ │ │ │ │ │ ├── table-editable.js │ │ │ │ │ │ │ ├── table-managed.js │ │ │ │ │ │ │ ├── tasks.js │ │ │ │ │ │ │ ├── ui-bootbox.js │ │ │ │ │ │ │ ├── ui-datepaginator.js │ │ │ │ │ │ │ ├── ui-extended-modals.js │ │ │ │ │ │ │ ├── ui-general.js │ │ │ │ │ │ │ ├── ui-ion-sliders.js │ │ │ │ │ │ │ ├── ui-jqueryui-sliders.js │ │ │ │ │ │ │ ├── ui-knob.js │ │ │ │ │ │ │ ├── ui-nestable.js │ │ │ │ │ │ │ ├── ui-nouisliders.js │ │ │ │ │ │ │ ├── ui-toastr.js │ │ │ │ │ │ │ └── ui-tree.js │ │ │ │ │ │ └── widgets/ │ │ │ │ │ │ └── jscalendar/ │ │ │ │ │ │ ├── calendar-setup.js │ │ │ │ │ │ ├── calendar-setup_stripped.js │ │ │ │ │ │ ├── calendar.js │ │ │ │ │ │ ├── calendar_stripped.js │ │ │ │ │ │ ├── lang/ │ │ │ │ │ │ │ ├── calendar-af.js │ │ │ │ │ │ │ ├── calendar-al.js │ │ │ │ │ │ │ ├── calendar-bg.js │ │ │ │ │ │ │ ├── calendar-big5-utf8.js │ │ │ │ │ │ │ ├── calendar-big5.js │ │ │ │ │ │ │ ├── calendar-br.js │ │ │ │ │ │ │ ├── calendar-ca.js │ │ │ │ │ │ │ ├── calendar-cs-utf8.js │ │ │ │ │ │ │ ├── calendar-cs-win.js │ │ │ │ │ │ │ ├── calendar-da.js │ │ │ │ │ │ │ ├── calendar-de.js │ │ │ │ │ │ │ ├── calendar-du.js │ │ │ │ │ │ │ ├── calendar-el.js │ │ │ │ │ │ │ ├── calendar-en.js │ │ │ │ │ │ │ ├── calendar-es.js │ │ │ │ │ │ │ ├── calendar-fi.js │ │ │ │ │ │ │ ├── calendar-fr.js │ │ │ │ │ │ │ ├── calendar-he-utf8.js │ │ │ │ │ │ │ ├── calendar-hr-utf8.js │ │ │ │ │ │ │ ├── calendar-hr.js │ │ │ │ │ │ │ ├── calendar-hu.js │ │ │ │ │ │ │ ├── calendar-it.js │ │ │ │ │ │ │ ├── calendar-jp.js │ │ │ │ │ │ │ ├── calendar-ko-utf8.js │ │ │ │ │ │ │ ├── calendar-ko.js │ │ │ │ │ │ │ ├── calendar-lt-utf8.js │ │ │ │ │ │ │ ├── calendar-lt.js │ │ │ │ │ │ │ ├── calendar-lv.js │ │ │ │ │ │ │ ├── calendar-nl.js │ │ │ │ │ │ │ ├── calendar-no.js │ │ │ │ │ │ │ ├── calendar-pl-utf8.js │ │ │ │ │ │ │ ├── calendar-pl.js │ │ │ │ │ │ │ ├── calendar-pt.js │ │ │ │ │ │ │ ├── calendar-ro.js │ │ │ │ │ │ │ ├── calendar-ru.js │ │ │ │ │ │ │ ├── calendar-ru_win_.js │ │ │ │ │ │ │ ├── calendar-si.js │ │ │ │ │ │ │ ├── calendar-sk.js │ │ │ │ │ │ │ ├── calendar-sp.js │ │ │ │ │ │ │ ├── calendar-sv.js │ │ │ │ │ │ │ ├── calendar-tr.js │ │ │ │ │ │ │ ├── calendar-zh.js │ │ │ │ │ │ │ └── cn_utf8.js │ │ │ │ │ │ └── skins/ │ │ │ │ │ │ └── aqua/ │ │ │ │ │ │ └── theme.css │ │ │ │ │ └── web.xml │ │ │ │ ├── daily.jsp │ │ │ │ ├── error.jsp │ │ │ │ ├── index.jsp │ │ │ │ └── test.jsp │ │ │ └── test/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── sohu/ │ │ │ │ ├── cache/ │ │ │ │ │ ├── dao/ │ │ │ │ │ │ ├── InstanceDaoTest.java │ │ │ │ │ │ ├── InstanceFaultDaoTest.java │ │ │ │ │ │ ├── InstanceReshardProcessDaoTest.java │ │ │ │ │ │ └── MachineDaoTest.java │ │ │ │ │ └── stats/ │ │ │ │ │ └── app/ │ │ │ │ │ ├── AppDataMigrateCenterTest.java │ │ │ │ │ └── ImportAppCenterTest.java │ │ │ │ └── test/ │ │ │ │ ├── BaseTest.java │ │ │ │ ├── SimpleBaseTest.java │ │ │ │ ├── alert/ │ │ │ │ │ └── AppServiceAlertImplTest.java │ │ │ │ ├── app/ │ │ │ │ │ └── AppStatsCenterImplTest.java │ │ │ │ ├── cache/ │ │ │ │ │ └── inspect/ │ │ │ │ │ └── AppClientConnInspectorTest.java │ │ │ │ ├── dao/ │ │ │ │ │ ├── AppAuditDaoTest.java │ │ │ │ │ ├── AppAuditLogDaoTest.java │ │ │ │ │ ├── AppClientReportDataSizeDaoTest.java │ │ │ │ │ ├── AppClientVersionDaoTest.java │ │ │ │ │ ├── AppDaoTest.java │ │ │ │ │ ├── AppDataMigrateStatusDaoTest.java │ │ │ │ │ ├── AppStatsDaoTest.java │ │ │ │ │ ├── AppToUserDaoTest.java │ │ │ │ │ ├── AppUserDaoTest.java │ │ │ │ │ ├── InstanceConfigDaoTest.java │ │ │ │ │ └── QuartzDaoTest.java │ │ │ │ ├── init/ │ │ │ │ │ └── MachineInitTest.java │ │ │ │ ├── inspect/ │ │ │ │ │ └── InspectHandlerTest.java │ │ │ │ ├── instance/ │ │ │ │ │ └── InstanceStatsCenterTest.java │ │ │ │ ├── machine/ │ │ │ │ │ └── PortGeneratorTest.java │ │ │ │ ├── misc/ │ │ │ │ │ └── MiscTest.java │ │ │ │ ├── protocol/ │ │ │ │ │ └── RedisProtocolTest.java │ │ │ │ ├── redis/ │ │ │ │ │ ├── Node.java │ │ │ │ │ ├── RedisConfigTemplateTest.java │ │ │ │ │ └── RedisImportantDataDeal.java │ │ │ │ ├── schedule/ │ │ │ │ │ ├── ScheduleUtilTestTest.java │ │ │ │ │ └── SchedulerCenterTest.java │ │ │ │ ├── stats/ │ │ │ │ │ └── app/ │ │ │ │ │ └── AppCenterTest.java │ │ │ │ └── util/ │ │ │ │ ├── ObjectConvertTest.java │ │ │ │ ├── SSHUtilTest.java │ │ │ │ └── ScheduleUtilTest.java │ │ │ └── resources/ │ │ │ ├── logback-test.xml │ │ │ └── spring-test.xml │ │ ├── pom.xml │ │ └── script/ │ │ ├── cachecloud-init.sh │ │ ├── cachecloud.sql │ │ ├── deploy.sh │ │ ├── start.sh │ │ └── stop.sh │ ├── open-admin-server/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── Controller.java │ │ │ └── OpenAdminApp.java │ │ └── resources/ │ │ └── application.yml │ ├── open-zipkin-center/ │ │ ├── SPRING CLOUD微服务日志挖掘的应用研究.doc │ │ ├── open-zipkin-kafka-client/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── open/ │ │ │ │ └── capacity/ │ │ │ │ └── ZipKinClientApp.java │ │ │ └── resources/ │ │ │ └── application.yml │ │ ├── open-zipkin-kafka-server/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── open/ │ │ │ │ └── capacity/ │ │ │ │ └── OpenZipkinServer.java │ │ │ └── resources/ │ │ │ └── application.yml │ │ ├── open-zipkin-memery-client/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── open/ │ │ │ │ └── capacity/ │ │ │ │ ├── TestController.java │ │ │ │ └── ZipKinClientApp.java │ │ │ └── resources/ │ │ │ └── application.yml │ │ ├── open-zipkin-memery-server/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── open/ │ │ │ │ └── capacity/ │ │ │ │ └── OpenZipkinSerApp.java │ │ │ └── resources/ │ │ │ └── application.yml │ │ └── pom.xml │ └── pom.xml ├── open-oauth-center/ │ ├── README.md │ ├── db/ │ │ └── init.sql │ ├── open-oauth-client/ │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── UnieapAuthServerApp.java │ │ │ ├── client/ │ │ │ │ └── oauth2/ │ │ │ │ ├── OAuth2ClientConfig.java │ │ │ │ ├── authorize/ │ │ │ │ │ ├── AuthorizeConfigManager.java │ │ │ │ │ ├── AuthorizeConfigProvider.java │ │ │ │ │ ├── OpenAuthorizeConfigManager.java │ │ │ │ │ └── provider/ │ │ │ │ │ └── AuthAuthorizeConfigProvider.java │ │ │ │ ├── config/ │ │ │ │ │ └── SecurityHandlerConfig.java │ │ │ │ ├── service/ │ │ │ │ │ ├── RbacService.java │ │ │ │ │ └── impl/ │ │ │ │ │ └── RbacServiceImpl.java │ │ │ │ └── token/ │ │ │ │ ├── TokenStoreConfig.java │ │ │ │ └── store/ │ │ │ │ └── RedisTemplateTokenStore.java │ │ │ └── controller/ │ │ │ ├── TestController.java │ │ │ └── UserController.java │ │ └── resources/ │ │ └── application.yml │ ├── open-oauth-client-two/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── UnieapAuthServerApp.java │ │ │ ├── client/ │ │ │ │ └── oauth2/ │ │ │ │ ├── OAuth2ClientConfig.java │ │ │ │ ├── config/ │ │ │ │ │ └── SecurityHandlerConfig.java │ │ │ │ ├── controller/ │ │ │ │ │ └── UserController.java │ │ │ │ └── token/ │ │ │ │ ├── TokenStoreConfig.java │ │ │ │ └── store/ │ │ │ │ └── RedisTemplateTokenStore.java │ │ │ └── controller/ │ │ │ └── TestController.java │ │ └── resources/ │ │ └── application.yml │ ├── open-oauth-server/ │ │ ├── README.md │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── docker/ │ │ │ └── Dockerfile │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── OpenAuthServerApp.java │ │ │ ├── config/ │ │ │ │ ├── FeignConfig.java │ │ │ │ └── TokenStorePostProcessor.java │ │ │ ├── controller/ │ │ │ │ ├── PermissionController.java │ │ │ │ ├── TestController.java │ │ │ │ ├── UserController.java │ │ │ │ └── UserTokenController.java │ │ │ ├── fegin/ │ │ │ │ ├── PermissionClient.java │ │ │ │ ├── RoleClient.java │ │ │ │ └── UserClient.java │ │ │ ├── filter/ │ │ │ │ └── InspectHeaderFilter.java │ │ │ ├── httpclient/ │ │ │ │ └── HttpAuthInvoker.java │ │ │ ├── server/ │ │ │ │ └── oauth2/ │ │ │ │ ├── OAuth2ServerConfig.java │ │ │ │ ├── client/ │ │ │ │ │ └── RedisClientDetailsService.java │ │ │ │ ├── code/ │ │ │ │ │ └── RedisAuthorizationCodeServices.java │ │ │ │ ├── config/ │ │ │ │ │ ├── OauthLogoutHandler.java │ │ │ │ │ ├── PasswordConfig.java │ │ │ │ │ ├── SecurityConfig.java │ │ │ │ │ ├── SecurityHandlerConfig.java │ │ │ │ │ └── SwaggerConfig.java │ │ │ │ ├── dao/ │ │ │ │ │ └── UserDao.java │ │ │ │ ├── service/ │ │ │ │ │ └── UnieapUserDetailsService.java │ │ │ │ └── token/ │ │ │ │ ├── TokenStoreConfig.java │ │ │ │ └── store/ │ │ │ │ └── RedisTemplateTokenStore.java │ │ │ └── utils/ │ │ │ └── SpringUtil.java │ │ ├── resources/ │ │ │ └── application.yml │ │ └── view/ │ │ └── static/ │ │ ├── css/ │ │ │ ├── import_main.css │ │ │ ├── page_all.css │ │ │ └── saved_resource.html │ │ ├── hello.html │ │ ├── index.html │ │ ├── js/ │ │ │ ├── import_base_tan_802b7ff.js │ │ │ ├── login_4765ca5.js │ │ │ ├── page.login_c7313e6.js │ │ │ └── wrapper.js │ │ └── login.html │ ├── open-oauth-sso/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── open/ │ │ │ └── capacity/ │ │ │ ├── SsoClientApp.java │ │ │ ├── client/ │ │ │ │ ├── config/ │ │ │ │ │ └── OauthLogoutHandler.java │ │ │ │ └── web/ │ │ │ │ └── UnieapSecurityConfig.java │ │ │ ├── controller/ │ │ │ │ └── UserController.java │ │ │ ├── filter/ │ │ │ │ └── TokenFilter.java │ │ │ └── utils/ │ │ │ └── SpringUtil.java │ │ ├── resources/ │ │ │ └── application.yml │ │ └── view/ │ │ └── static/ │ │ └── index.html │ └── pom.xml ├── open-user-center/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── open/ │ │ └── capacity/ │ │ ├── UserCenterApp.java │ │ └── security/ │ │ ├── advice/ │ │ │ ├── ExceptionHandlerAdvice.java │ │ │ └── LogAdvice.java │ │ ├── annotation/ │ │ │ └── LogAnnotation.java │ │ ├── config/ │ │ │ ├── AsycTaskExecutorConfig.java │ │ │ ├── LoginPageConfig.java │ │ │ ├── SecurityConfig.java │ │ │ ├── SecurityHandlerConfig.java │ │ │ ├── SwaggerConfig.java │ │ │ └── WebMvcConfig.java │ │ ├── controller/ │ │ │ ├── PermissionController.java │ │ │ ├── RoleController.java │ │ │ └── UserController.java │ │ ├── dao/ │ │ │ ├── PermissionDao.java │ │ │ ├── RoleDao.java │ │ │ ├── RoleDao.xml │ │ │ ├── SysLogsDao.java │ │ │ ├── SysLogsDao.xml │ │ │ ├── TokenDao.java │ │ │ ├── UserDao.java │ │ │ └── UserDao.xml │ │ ├── dto/ │ │ │ └── Token.java │ │ ├── filter/ │ │ │ └── TokenFilter.java │ │ ├── page/ │ │ │ └── table/ │ │ │ ├── PageTableArgumentResolver.java │ │ │ ├── PageTableHandler.java │ │ │ ├── PageTableRequest.java │ │ │ └── PageTableResponse.java │ │ ├── service/ │ │ │ ├── MicroServiceService.java │ │ │ ├── PermissionService.java │ │ │ ├── RoleService.java │ │ │ ├── SysLogService.java │ │ │ ├── TokenService.java │ │ │ ├── UserService.java │ │ │ └── impl/ │ │ │ ├── PermissionServiceImpl.java │ │ │ ├── RoleServiceImpl.java │ │ │ ├── SysLogServiceImpl.java │ │ │ ├── TokenServiceImpl.java │ │ │ ├── UserDetailsServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ └── utils/ │ │ ├── FileUtil.java │ │ ├── ResponseUtil.java │ │ ├── SpringUtil.java │ │ ├── StrUtil.java │ │ └── UserUtil.java │ └── resources/ │ └── application.yml ├── open-xxl-job/ │ ├── README.md │ ├── db/ │ │ └── tables_xxl_job.sql │ ├── doc/ │ │ ├── 分布式任务调度平台XXL-JOB.html │ │ └── 分布式任务调度平台XXL-JOB_files/ │ │ ├── analytics.js │ │ ├── core.php │ │ ├── hm.js │ │ ├── vue.css │ │ └── z_stat.php │ ├── pom.xml │ ├── xxl-job-admin/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── xxl/ │ │ │ └── job/ │ │ │ └── admin/ │ │ │ ├── Application.java │ │ │ ├── component/ │ │ │ │ └── SpringJobFactory.java │ │ │ ├── config/ │ │ │ │ ├── MyWebMvcConfigurer.java │ │ │ │ ├── QuartzConfig.java │ │ │ │ └── Swagger2Config.java │ │ │ ├── controller/ │ │ │ │ ├── IndexController.java │ │ │ │ ├── JobApiController.java │ │ │ │ ├── JobCodeController.java │ │ │ │ ├── JobGroupController.java │ │ │ │ ├── JobInfoController.java │ │ │ │ ├── JobLogController.java │ │ │ │ ├── annotation/ │ │ │ │ │ └── PermessionLimit.java │ │ │ │ ├── interceptor/ │ │ │ │ │ ├── CookieInterceptor.java │ │ │ │ │ └── PermissionInterceptor.java │ │ │ │ └── resolver/ │ │ │ │ └── WebExceptionResolver.java │ │ │ ├── core/ │ │ │ │ ├── conf/ │ │ │ │ │ └── XxlJobAdminConfig.java │ │ │ │ ├── enums/ │ │ │ │ │ └── ExecutorFailStrategyEnum.java │ │ │ │ ├── jobbean/ │ │ │ │ │ └── RemoteHttpJobBean.java │ │ │ │ ├── model/ │ │ │ │ │ ├── XxlJobGroup.java │ │ │ │ │ ├── XxlJobInfo.java │ │ │ │ │ ├── XxlJobLog.java │ │ │ │ │ ├── XxlJobLogGlue.java │ │ │ │ │ └── XxlJobRegistry.java │ │ │ │ ├── route/ │ │ │ │ │ ├── ExecutorRouteStrategyEnum.java │ │ │ │ │ ├── ExecutorRouter.java │ │ │ │ │ └── strategy/ │ │ │ │ │ ├── ExecutorRouteBusyover.java │ │ │ │ │ ├── ExecutorRouteConsistentHash.java │ │ │ │ │ ├── ExecutorRouteFailover.java │ │ │ │ │ ├── ExecutorRouteFirst.java │ │ │ │ │ ├── ExecutorRouteLFU.java │ │ │ │ │ ├── ExecutorRouteLRU.java │ │ │ │ │ ├── ExecutorRouteLast.java │ │ │ │ │ ├── ExecutorRouteRandom.java │ │ │ │ │ └── ExecutorRouteRound.java │ │ │ │ ├── schedule/ │ │ │ │ │ └── XxlJobDynamicScheduler.java │ │ │ │ ├── thread/ │ │ │ │ │ ├── JobFailMonitorHelper.java │ │ │ │ │ └── JobRegistryMonitorHelper.java │ │ │ │ ├── trigger/ │ │ │ │ │ └── XxlJobTrigger.java │ │ │ │ └── util/ │ │ │ │ ├── CookieUtil.java │ │ │ │ ├── FtlUtil.java │ │ │ │ ├── I18nUtil.java │ │ │ │ ├── LocalCacheUtil.java │ │ │ │ ├── MailUtil.java │ │ │ │ └── PropertiesUtil.java │ │ │ ├── dao/ │ │ │ │ ├── XxlJobGroupDao.java │ │ │ │ ├── XxlJobGroupMapper.xml │ │ │ │ ├── XxlJobInfoDao.java │ │ │ │ ├── XxlJobInfoMapper.xml │ │ │ │ ├── XxlJobLogDao.java │ │ │ │ ├── XxlJobLogGlueDao.java │ │ │ │ ├── XxlJobLogGlueMapper.xml │ │ │ │ ├── XxlJobLogMapper.xml │ │ │ │ ├── XxlJobRegistryDao.java │ │ │ │ └── XxlJobRegistryMapper.xml │ │ │ └── service/ │ │ │ ├── XxlJobService.java │ │ │ └── impl/ │ │ │ ├── AdminBizImpl.java │ │ │ └── XxlJobServiceImpl.java │ │ ├── resources/ │ │ │ ├── application.yml │ │ │ ├── i18n/ │ │ │ │ ├── message.properties │ │ │ │ └── message_en.properties │ │ │ ├── log4j.properties │ │ │ ├── log4j.xml │ │ │ └── xxl-job-admin.properties │ │ └── view/ │ │ ├── 500.html │ │ ├── i18n/ │ │ │ ├── message.properties │ │ │ └── message_en.properties │ │ ├── static/ │ │ │ ├── adminlte/ │ │ │ │ ├── dist/ │ │ │ │ │ └── css/ │ │ │ │ │ └── google-local/ │ │ │ │ │ └── local.google.fonts.css │ │ │ │ └── plugins/ │ │ │ │ ├── datatables/ │ │ │ │ │ ├── dataTables.bootstrap.css │ │ │ │ │ └── jquery.dataTables_themeroller.css │ │ │ │ ├── daterangepicker/ │ │ │ │ │ ├── daterangepicker.css │ │ │ │ │ └── daterangepicker.js │ │ │ │ └── iCheck/ │ │ │ │ └── square/ │ │ │ │ ├── _all.css │ │ │ │ ├── aero.css │ │ │ │ ├── blue.css │ │ │ │ ├── green.css │ │ │ │ ├── grey.css │ │ │ │ ├── orange.css │ │ │ │ ├── pink.css │ │ │ │ ├── purple.css │ │ │ │ ├── red.css │ │ │ │ ├── square.css │ │ │ │ └── yellow.css │ │ │ ├── js/ │ │ │ │ ├── common.1.js │ │ │ │ ├── index.js │ │ │ │ ├── jobcode.index.1.js │ │ │ │ ├── jobgroup.index.1.js │ │ │ │ ├── jobinfo.index.1.js │ │ │ │ ├── joblog.detail.1.js │ │ │ │ ├── joblog.index.1.js │ │ │ │ └── login.1.js │ │ │ └── plugins/ │ │ │ ├── codemirror/ │ │ │ │ ├── addon/ │ │ │ │ │ └── hint/ │ │ │ │ │ ├── anyword-hint.js │ │ │ │ │ ├── show-hint.css │ │ │ │ │ └── show-hint.js │ │ │ │ ├── lib/ │ │ │ │ │ ├── codemirror.css │ │ │ │ │ └── codemirror.js │ │ │ │ └── mode/ │ │ │ │ ├── clike/ │ │ │ │ │ └── clike.js │ │ │ │ ├── python/ │ │ │ │ │ └── python.js │ │ │ │ └── shell/ │ │ │ │ └── shell.js │ │ │ ├── font-awesome-4.5.0/ │ │ │ │ └── fonts/ │ │ │ │ └── FontAwesome.otf │ │ │ ├── jquery/ │ │ │ │ └── jquery.cookie.js │ │ │ ├── layer/ │ │ │ │ ├── layer.js │ │ │ │ ├── mobile/ │ │ │ │ │ ├── layer.js │ │ │ │ │ └── need/ │ │ │ │ │ └── layer.css │ │ │ │ └── skin/ │ │ │ │ └── default/ │ │ │ │ └── layer.css │ │ │ └── pace/ │ │ │ └── themes/ │ │ │ ├── pace-theme-bounce.css │ │ │ └── pace-theme-flash.css │ │ └── templates/ │ │ ├── common/ │ │ │ ├── common.exception.ftl │ │ │ ├── common.macro.ftl │ │ │ └── common.result.ftl │ │ ├── index.ftl │ │ ├── jobcode/ │ │ │ └── jobcode.index.ftl │ │ ├── jobgroup/ │ │ │ └── jobgroup.index.ftl │ │ ├── jobinfo/ │ │ │ └── jobinfo.index.ftl │ │ ├── joblog/ │ │ │ ├── joblog.detail.ftl │ │ │ └── joblog.index.ftl │ │ └── login.ftl │ ├── xxl-job-core/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── com/ │ │ └── xxl/ │ │ └── job/ │ │ └── core/ │ │ ├── biz/ │ │ │ ├── AdminBiz.java │ │ │ ├── ExecutorBiz.java │ │ │ ├── impl/ │ │ │ │ └── ExecutorBizImpl.java │ │ │ └── model/ │ │ │ ├── HandleCallbackParam.java │ │ │ ├── LogResult.java │ │ │ ├── RegistryParam.java │ │ │ ├── ReturnT.java │ │ │ └── TriggerParam.java │ │ ├── enums/ │ │ │ ├── ExecutorBlockStrategyEnum.java │ │ │ └── RegistryConfig.java │ │ ├── executor/ │ │ │ └── XxlJobExecutor.java │ │ ├── glue/ │ │ │ ├── GlueFactory.java │ │ │ └── GlueTypeEnum.java │ │ ├── handler/ │ │ │ ├── IJobHandler.java │ │ │ ├── annotation/ │ │ │ │ └── JobHandler.java │ │ │ └── impl/ │ │ │ ├── GlueJobHandler.java │ │ │ └── ScriptJobHandler.java │ │ ├── log/ │ │ │ ├── XxlJobFileAppender.java │ │ │ └── XxlJobLogger.java │ │ ├── rpc/ │ │ │ ├── codec/ │ │ │ │ ├── RpcRequest.java │ │ │ │ └── RpcResponse.java │ │ │ ├── netcom/ │ │ │ │ ├── NetComClientProxy.java │ │ │ │ ├── NetComServerFactory.java │ │ │ │ └── jetty/ │ │ │ │ ├── client/ │ │ │ │ │ └── JettyClient.java │ │ │ │ └── server/ │ │ │ │ ├── JettyServer.java │ │ │ │ └── JettyServerHandler.java │ │ │ └── serialize/ │ │ │ └── HessianSerializer.java │ │ ├── thread/ │ │ │ ├── ExecutorRegistryThread.java │ │ │ ├── JobLogFileCleanThread.java │ │ │ ├── JobThread.java │ │ │ └── TriggerCallbackThread.java │ │ └── util/ │ │ ├── FileUtil.java │ │ ├── HttpClientUtil.java │ │ ├── IpUtil.java │ │ ├── JacksonUtil.java │ │ ├── NetUtil.java │ │ ├── ScriptUtil.java │ │ └── ShardingUtil.java │ └── xxl-job-demo/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── open/ │ │ └── capacity/ │ │ ├── Application.java │ │ ├── config/ │ │ │ └── XxlJobConfig.java │ │ └── jobhandler/ │ │ ├── DemoJobHandler.java │ │ └── ShardingJobHandler.java │ └── resources/ │ ├── application.properties │ └── logback.xml └── pom.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitee/ISSUE_TEMPLATE.zh-CN.md ================================================ ### 该问题是怎么引起的? ### 重现步骤 ### 报错信息 ================================================ FILE: .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md ================================================ ### 该Pull Request关联的Issue ### 修改描述 ### 测试用例 ### 修复效果的截屏 ================================================ FILE: .gitignore ================================================ # maven ignore target/ *.jar *.war *.zip *.tar *.tar.gz *.class *.project # eclipse ignore .settings/ .classpath target/ bin/ open-cxf-service/ open-elasticsearch/ # idea ignore .idea/ *.ipr *.iml *.iws # temp ignore *.log *.cache *.diff *.patch *.tmp # system ignore .DS_Store Thumbs.db # else .springBeans /open-layui-web/logs/ ================================================ FILE: .tgitconfig ================================================ ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2018 owen Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ #

open-capacity-platform 微服务能力开发平台

Build Status Coverage Status Downloads License

### 欢迎进群(群内领资料) `一键加群` open-capacity-platform交流 ![](https://i.imgur.com/kxpc628.png) ### 简介 ​ 简称ocp是基于layui+springcloud的企业级微服务框架(用户权限管理,配置中心管理,应用管理,....),其核心的设计目标是分离前后端,快速开发部署,学习简单,功能强大,提供快速接入核心接口能力,其目标是帮助企业搭建一套类似百度能力开放平台的框架。 ### 基于OCP的企业微服务体验地址 http://47.94.252.160:8066 用户名/密码:admin/admin ### 组织结构 open-capacity-platform ``` ├ open-db-core -- 数据库逻辑封装 ├ open-eureka-center -- eureka服务注册发现套件 ├ ├── open-eureka-server --服务注册中心[1111] ├ └── open-eureka-client --注册服务样例工程[7768] ├ open-config-center -- 配置中心 ├ ├── apollo -- 阿波罗配置中心 ├ ├ ├── apollo-adminservice --[8090] ├ ├ ├── apollo-assembly ├ ├ ├── apollo-biz ├ ├ ├── apollo-buildtools ├ ├ ├── apollo-client ├ ├ ├── apollo-common ├ ├ ├── apollo-configservice --[8080] ├ ├ ├── apollo-core ├ ├ └── apollo-demo ├ └ apollo-gateway -- 阿波罗整合网关样例工程[9000] ├ open-oauth-center --oauth2套件 ├ ├── open-oauth-server --oauth认证中心[8000] ├ ├── open-oauth-client --oauth资源服务器样例工程[8100] ├ ├── open-capacity-client-two --oauth资源服务器样例工程[8200] ├ └── open-oauth-sso --oauth sso样例工程[9997] ├ open-api-gateway -- 服务网关[9200] ├ open-layui-web -- 基于jwt spring security的layui后台管理系统 ├ open-xxl-job -- 分布式调度任务 ├ ├── xxl-job-core --核心库 ├ ├── xxl-job-admin --job管理器 ├ └── xxl-job-demo --job执行器 ├ open-monitor-center -- 监控中心 ├ ├── open-admin-server -- spring boot admin server[9998] ├ ├ cachecloud-open-parent -- 搜狐redis云平台 ├ ├ ├── cachecloud-open-client ├ ├ ├── cachecloud-open-common ├ ├ └── cachecloud-open-web ├ └─ open-zipkin-center -- zipkin链路跟踪[9412] ├ ├── open-zipkin-server-kafka --zipkin链路跟踪服务端 └ └── open-zipkin-client-kafka --zipkin链路跟踪客户端 ``` #### 开发工具: - MySql: 数据库 - Tomcat: 应用服务器 - SVN|Git: 版本管理 - Nginx: 反向代理服务器 - IntelliJ IDEA/STS-3.8.0.RELEASE : 开发IDE/STS - Navicat for MySQL: 数据库客户端 ### 开发环境 JDK8+ READIS 3.X MySQL 5.6 + MAVEN 3.3.9 ### 技术介绍 ![](https://i.imgur.com/29QKUkG.png) ### 框架设计 ![](https://i.imgur.com/vn03vIX.jpg) ## ocp项目演示 ![](http://img1.ph.126.net/WAraEeweVw2SyTUSG1dT6Q==/3887169428474612491.gif) ## 阿波罗配置中心演示 ![](http://img2.ph.126.net/-cKtj6Wia_q6YiZKV-IOsQ==/295548725646480248.gif) ## oauth认证方式 ![](https://i.imgur.com/MUCa4x6.gif) ## oauth单点登录 ![](https://i.imgur.com/PwcuvoC.gif) ## 一. open-capacity-platform能力开放平台管理 01.用户登录 02.用户管理 ![](https://i.imgur.com/Ud65k7j.png) 03.角色管理 ![](https://i.imgur.com/Vl4n8Wr.png) 04.菜单管理 ![](https://i.imgur.com/DXFAsUy.png) 05.注册中心 ![](https://i.imgur.com/L1RMEoq.png) ![](https://i.imgur.com/IKHAQ1c.png) 06.配置中心 ![](https://i.imgur.com/PrHbd6P.png) ![](https://i.imgur.com/Zyy4XjQ.png) 07.服务管理 ![](https://i.imgur.com/eDqMHBF.png) 08.应用管理 ![](https://i.imgur.com/BKN06Te.png) 09.定时任务 ![](https://i.imgur.com/boiJhNU.jpg) ## 部署 1.cd /root/sop/eureka-server/bin/ && ./start.sh 启动注册中心服务 2.cd /root/sop/config-center/configservice/bin/ && ./start.sh 启动配置中心configservice服务 3.cd /root/sop/config-center/adminservice/bin/ && ./start.sh 启动配置中心adminservice 服务 4.cd /root/sop/config-center/portalservice/bin/ && ./start.sh 启动配置中心portalservice服务 5.cd /root/sop/apollo-zuul/bin/ && ./start.sh 启动演示apollo-zuul项目 启动后效果预览 ![](https://i.imgur.com/H0CiqbD.jpg) ================================================ FILE: open-api-gateway/pom.xml ================================================ 4.0.0 com.open.capacity open-capacity-platform 0.0.1-SNAPSHOT open-api-gateway zuul oauth swagger集成 gitgeek com.open.capacity open-db-core ${core.version} org.springframework.boot spring-boot-starter-web org.springframework spring-context-support org.springframework.social spring-social-web org.springframework.cloud spring-cloud-starter-oauth2 org.springframework.security spring-security-jwt org.apache.commons commons-lang3 com.didispace swagger-butler-core 1.1.0 com.github.xiaoymin swagger-bootstrap-ui 1.6 com.zyplayer swagger-mg-ui 1.0.1 com.squareup.okhttp3 okhttp org.springframework.cloud spring-cloud-starter-zuul org.springframework.cloud spring-cloud-starter-eureka io.swagger swagger-core 1.5.8 io.springfox springfox-swagger2 2.4.0 io.springfox springfox-swagger-ui 2.4.0 org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-maven-plugin 1.3.3.RELEASE repackage com.spotify docker-maven-plugin 0.4.13 ${docker.image.prefix}/${project.artifactId} src/main/docker / ${project.build.directory} ${project.build.finalName}.jar open-api-gateway ================================================ FILE: open-api-gateway/src/main/docker/Dockerfile ================================================ FROM frolvlad/alpine-oraclejdk8 VOLUME /tmp ADD open-api-gateway.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/GatewayApp.java ================================================ package com.open.capacity; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月12日 上午22:57:51 类说明 */ @Configuration @EnableZuulProxy @EnableDiscoveryClient @SpringBootApplication public class GatewayApp { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } @Bean // 前后分离 ajax跨域调用处理 public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允许cookies跨域 config.addAllowedOrigin("*");// 允许向该服务器提交请求的URI,*表示全部允许。。这里尽量限制来源域,比如http://xxxx:8080 // ,以降低安全风险。。 config.addAllowedHeader("*");// 允许访问的头信息,*表示全部 config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许,也可以单独设置GET、PUT等 /* * config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET");// * 允许Get的请求方法 config.addAllowedMethod("PUT"); * config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); * config.addAllowedMethod("PATCH"); */ source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } public static void main(String[] args) { SpringApplication.run(GatewayApp.class, args); } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/OAuth2ClientConfig.java ================================================ package com.open.capacity.client.oauth2; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.context.SecurityContextPersistenceFilter; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; import com.open.capacity.client.oauth2.authorize.AuthorizeConfigManager; import com.open.capacity.client.oauth2.filter.IPFilter; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月12日 上午22:57:51 */ @Component @Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true) public class OAuth2ClientConfig extends ResourceServerConfigurerAdapter { @Resource private ObjectMapper objectMapper; // springmvc启动时自动装配json处理类 @Autowired(required = false) private TokenStore redisTokenStore; @Autowired(required = false) private JwtTokenStore jwtTokenStore; @Autowired(required = false) private JwtAccessTokenConverter jwtAccessTokenConverter; @Autowired private AuthenticationEntryPoint authenticationEntryPoint; @Autowired private AuthenticationFailureHandler authenticationFailureHandler; @Autowired private AuthorizeConfigManager authorizeConfigManager; @Autowired private OAuth2WebSecurityExpressionHandler expressionHandler; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/health"); } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { if (jwtTokenStore != null) { resources.tokenStore(jwtTokenStore); } else if (redisTokenStore != null) { resources.tokenStore(redisTokenStore); } resources.stateless(true); resources.authenticationEntryPoint(authenticationEntryPoint) ; resources.expressionHandler(expressionHandler); resources.accessDeniedHandler(oAuth2AccessDeniedHandler); } @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.headers().frameOptions().disable(); authorizeConfigManager.config(http.authorizeRequests()); IPFilter iPFilter = new IPFilter(); iPFilter.setAuthenticationFailureHandler(authenticationFailureHandler); iPFilter.afterPropertiesSet(); http.addFilterAfter(iPFilter, SecurityContextPersistenceFilter.class); } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/AuthorizeConfigManager.java ================================================ package com.open.capacity.client.oauth2.authorize; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年2月1日 下午9:47:00 * 类说明 */ public interface AuthorizeConfigManager { /** * @param config */ void config(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry config); } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/AuthorizeConfigProvider.java ================================================ package com.open.capacity.client.oauth2.authorize; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; /** * @author 作者 owen E-mail:624191343@qq.com * @version 创建时间:2018年2月1日 下午9:46:25 * 类说明 */ public interface AuthorizeConfigProvider { boolean config(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry config); } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/OpenAuthorizeConfigManager.java ================================================ package com.open.capacity.client.oauth2.authorize; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.stereotype.Component; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年2月1日 下午9:50:27 * 类说明 */ @Component public class OpenAuthorizeConfigManager implements AuthorizeConfigManager { @Autowired private List authorizeConfigProviders; /* (non-Javadoc) * @see com.imooc.security.core.authorize.AuthorizeConfigManager#config(org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry) */ @Override public void config(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry config) { //设置访问 for (AuthorizeConfigProvider authorizeConfigProvider : authorizeConfigProviders) { authorizeConfigProvider.config(config) ; } //token正确登录 config.anyRequest().authenticated() ; // 放开则全部可以不需要认证访问 // config // .anyRequest() // .access("@rbacService.hasPermission(request, authentication)"); } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/authorize/provider/AuthAuthorizeConfigProvider.java ================================================ package com.open.capacity.client.oauth2.authorize.provider; import com.open.capacity.client.oauth2.authorize.AuthorizeConfigProvider; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.stereotype.Component; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年1月31日 下午9:11:36 * 类说明 * 白名单 */ @Component @Order(Integer.MAX_VALUE - 1) public class AuthAuthorizeConfigProvider implements AuthorizeConfigProvider { @Override public boolean config(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry config) { //免token登录设置 config.antMatchers("/test163").permitAll(); config.antMatchers("/auth/**").permitAll(); config.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**").permitAll(); config.antMatchers("/**/v2/api-docs", "/**/configuration/ui", "/**/swagger-resources", "/**/configuration/security", "/**/swagger-ui.html", "/**/webjars/**").permitAll(); return true; } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/config/DocumentationConfig.java ================================================ package com.open.capacity.client.oauth2.config; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider; import java.util.ArrayList; import java.util.List; @Primary @Component public class DocumentationConfig implements SwaggerResourcesProvider { @Override public List get() { List resources = new ArrayList<>(); // zuul routes /client/ zuul 集中管理api文档 // 分布式文档集成 resources.add(swaggerResource("认证中心", "/auth/v2/api-docs", "2.0")); resources.add(swaggerResource("erukea客户端", "/client/v2/api-docs", "2.0")); return resources; } private SwaggerResource swaggerResource(String name, String location, String version) { SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setName(name); swaggerResource.setLocation(location); swaggerResource.setSwaggerVersion(version); return swaggerResource; } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/config/SecurityHandlerConfig.java ================================================ package com.open.capacity.client.oauth2.config; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.annotation.Resource; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年4月5日 下午7:52:21 * 类说明 */ @Component @Configuration public class SecurityHandlerConfig { @Resource private ObjectMapper objectMapper ; //springmvc启动时自动装配json处理类 /** * 登陆失败 * * @return */ @Bean public AuthenticationFailureHandler loginFailureHandler() { return new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { String msg = null; if (exception instanceof BadCredentialsException) { msg = "密码错误"; } else { msg = exception.getMessage(); } Map rsp = new HashMap<>(); response.setStatus(HttpStatus.UNAUTHORIZED.value()); rsp.put("resp_code", HttpStatus.UNAUTHORIZED.value() + ""); rsp.put("rsp_msg", msg); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(rsp)); response.getWriter().flush(); response.getWriter().close(); } }; } /** * 未登录,返回401 * * @return */ @Bean public AuthenticationEntryPoint authenticationEntryPoint() { return new AuthenticationEntryPoint() { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { Map rsp =new HashMap<>(); response.setStatus(HttpStatus.UNAUTHORIZED.value() ); rsp.put("resp_code", HttpStatus.UNAUTHORIZED.value() + "") ; rsp.put("resp_msg", authException.getMessage()) ; response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(rsp)); response.getWriter().flush(); response.getWriter().close(); } }; } @Bean public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) { OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler(); expressionHandler.setApplicationContext(applicationContext); return expressionHandler; } @Bean public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler(){ return new OAuth2AccessDeniedHandler(){ @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) throws IOException, ServletException { Map rsp =new HashMap<>(); response.setContentType("application/json;charset=UTF-8"); response.setStatus(HttpStatus.UNAUTHORIZED.value() ); rsp.put("resp_code", HttpStatus.UNAUTHORIZED.value() + "") ; rsp.put("resp_msg", authException.getMessage()) ; response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(rsp)); response.getWriter().flush(); response.getWriter().close(); } }; } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/config/SwaggerConfig.java ================================================ package com.open.capacity.client.oauth2.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Component @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.open.capacity")) .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/dao/ServiceDao.java ================================================ package com.open.capacity.client.oauth2.dao; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; import java.util.Map; @Mapper public interface ServiceDao { @Select("select p.* from sys_services p inner join sys_client_permission rp on p.id = rp.permissionId where rp.clientId = #{clientId} order by p.sort") List listByClientId(Long clientId); @Select("select * from oauth_client_details t where t.client_id = #{clientId}") Map getClient(String clientId); } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/filter/AccessFilter.java ================================================ package com.open.capacity.client.oauth2.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; /** * Created by owen on 2017/9/10. */ @Component public class AccessFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); try { //解决zuul token传递问题 Authentication user = SecurityContextHolder.getContext() .getAuthentication(); if (user != null) { if (user instanceof OAuth2Authentication) { Authentication athentication = (Authentication) user; OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) athentication.getDetails(); ctx.addZuulRequestHeader("Authorization", "bearer " + details.getTokenValue()); } } } catch (Exception e) { } return null; } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/filter/IPFilter.java ================================================ package com.open.capacity.client.oauth2.filter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.util.AntPathMatcher; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; /** * IP过滤器 * * @author owen 624191343@qq.com *

* 2017年10月14日 */ public class IPFilter extends OncePerRequestFilter implements InitializingBean { Logger logger = LoggerFactory.getLogger(getClass()); private AuthenticationFailureHandler authenticationFailureHandler; public AuthenticationFailureHandler getAuthenticationFailureHandler() { return authenticationFailureHandler; } public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) { this.authenticationFailureHandler = authenticationFailureHandler; } // 所有需要拦截的url private Set urls = new HashSet<>(); // url匹配器 private AntPathMatcher pathMatcher = new AntPathMatcher(); @Override public void afterPropertiesSet() throws ServletException { super.afterPropertiesSet(); // 初始化其他bean参数 } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String accessToken = null; accessToken = extractToken(request); // if(!pathMatcher.match("/auth/**", request.getRequestURI())){ // // if (accessToken == null) { // authenticationFailureHandler.onAuthenticationFailure(request, response, // new AuthenticationException("token 不存在") { // // private static final long serialVersionUID = 6154557943607468780L; // // }); // return; // } // } // String ipAddr = this.getIpAddr(req); // logger.info("请求IP地址为:[{}]", ipAddr); // // 配置本地IP白名单,生产环境可放入数据库或者redis中 // List ips = new ArrayList(); // ips.add("127.0.0.1"); // // if (!ips.contains(ipAddr)) { // logger.info("IP地址校验不通过!!!"); // ctx.setResponseStatusCode(401); // ctx.setSendZuulResponse(false); // ctx.setResponseBody("IpAddr is forbidden!"); // } // logger.info("IP校验通过。"); filterChain.doFilter(request, response); } protected String extractToken(HttpServletRequest request) { // first check the header... String token = extractHeaderToken(request); // bearer type allows a request parameter as well if (token == null) { logger.debug("Token not found in headers. Trying request parameters."); token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN); if (token == null) { logger.debug("Token not found in request parameters. Not an OAuth2 request."); } else { request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE); } } return token; } /** * Extract the OAuth bearer token from a header. * * @param request The request. * @return The token, or null if no OAuth authorization header was supplied. */ protected String extractHeaderToken(HttpServletRequest request) { Enumeration headers = request.getHeaders("Authorization"); while (headers.hasMoreElements()) { // typically there is only one (most // servers enforce that) String value = headers.nextElement(); if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) { String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim(); // Add this here for the auth details later. Would be better to // change the signature of this method. request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim()); int commaIndex = authHeaderValue.indexOf(','); if (commaIndex > 0) { authHeaderValue = authHeaderValue.substring(0, commaIndex); } return authHeaderValue; } } return null; } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/service/RbacService.java ================================================ package com.open.capacity.client.oauth2.service; import org.springframework.security.core.Authentication; import javax.servlet.http.HttpServletRequest; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年12月4日 下午5:32:29 * 类说明 */ public interface RbacService { boolean hasPermission(HttpServletRequest request, Authentication authentication); } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/service/impl/RbacServiceImpl.java ================================================ package com.open.capacity.client.oauth2.service.impl; import com.open.capacity.client.oauth2.dao.ServiceDao; import com.open.capacity.client.oauth2.service.RbacService; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.stereotype.Service; import org.springframework.util.AntPathMatcher; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.Iterator; import java.util.List; import java.util.Map; /** * API 级别权限认证 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年12月4日 下午5:32:29 * 类说明 */ @Service("rbacService") public class RbacServiceImpl implements RbacService { @Resource private ServiceDao serviceDao; private AntPathMatcher antPathMatcher = new AntPathMatcher(); /** * @param request HttpServletRequest * @param authentication 认证信息 * @return 是否有权限 */ @Override public boolean hasPermission(HttpServletRequest request, Authentication authentication) { Authentication user = SecurityContextHolder.getContext() .getAuthentication(); if (user != null) { if (user instanceof OAuth2Authentication) { OAuth2Authentication athentication = (OAuth2Authentication) user; String clientId = athentication.getOAuth2Request().getClientId(); Map map = serviceDao.getClient(clientId); if (map == null) { return false; } else { List list = serviceDao.listByClientId(Long.valueOf(String.valueOf(map.get("id")))); ; for (Iterator it = list.iterator(); it.hasNext(); ) { Map temp = it.next(); if (antPathMatcher.match(request.getRequestURI(), String.valueOf(temp.get("href")))) { return true; } } return false; } } } //TODO 目前都是true boolean hasPermission = true; return hasPermission; } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/token/TokenStoreConfig.java ================================================ package com.open.capacity.client.oauth2.token; import javax.annotation.Resource; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年12月18日 下午3:15:22 * 类说明 * redis存储token */ @Configuration public class TokenStoreConfig { @Resource private DataSource dataSource ; @Autowired(required=false) private RedisTemplate redisTemplate ; @Bean @ConditionalOnProperty(prefix="security.oauth2.token.store",name="type" ,havingValue="jdbc" ,matchIfMissing=true) public JdbcTokenStore jdbcTokenStore(){ // oauth_access_token oauth_refresh_token 创建两张表 // return new JdbcTokenStore( dataSource ) ; return new JdbcTokenStore( dataSource ) ; } @Bean @ConditionalOnProperty(prefix="security.oauth2.token.store",name="type" ,havingValue="redis" ,matchIfMissing=true) public RedisTemplateTokenStore redisTokenStore(){ // return new RedisTokenStore( redisTemplate.getConnectionFactory() ) ; //单台redis服务器 RedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore() ; redisTemplateStore.setRedisTemplate(redisTemplate); return redisTemplateStore ; } //使用jwt替换原有的uuid生成token方式 @Configuration @ConditionalOnProperty(prefix="security.oauth2.token.store",name="type" ,havingValue="jwt" ,matchIfMissing=true) public static class JWTTokenConfig { @Bean public JwtTokenStore jwtTokenStore(){ return new JwtTokenStore( jwtAccessTokenConverter() ) ; } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter(){ JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter(); accessTokenConverter.setSigningKey("neusoft"); return accessTokenConverter ; } } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/client/oauth2/token/store/RedisTemplateTokenStore.java ================================================ package com.open.capacity.client.oauth2.token.store; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator; import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; import org.springframework.security.oauth2.provider.token.TokenStore; /** * @author owen 624191343@qq.com * @version 创建时间:2017年11月12日 上午22:57:51 * 类说明 * redis集群存储token */ public class RedisTemplateTokenStore implements TokenStore { private static final String ACCESS = "access:"; private static final String AUTH_TO_ACCESS = "auth_to_access:"; private static final String AUTH = "auth:"; private static final String REFRESH_AUTH = "refresh_auth:"; private static final String ACCESS_TO_REFRESH = "access_to_refresh:"; private static final String REFRESH = "refresh:"; private static final String REFRESH_TO_ACCESS = "refresh_to_access:"; private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:"; private static final String UNAME_TO_ACCESS = "uname_to_access:"; private RedisTemplate redisTemplate ; public RedisTemplate getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { this.authenticationKeyGenerator = authenticationKeyGenerator; } public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { String key = authenticationKeyGenerator.extractKey(authentication); OAuth2AccessToken accessToken = (OAuth2AccessToken) redisTemplate.opsForValue().get(AUTH_TO_ACCESS+key); if (accessToken != null && !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) { // Keep the stores consistent (maybe the same user is represented by this authentication but the details // have changed) storeAccessToken(accessToken, authentication); } return accessToken; } public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { return readAuthentication(token.getValue()); } public OAuth2Authentication readAuthentication(String token) { return (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH + token); } public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { return readAuthenticationForRefreshToken(token.getValue()); } public OAuth2Authentication readAuthenticationForRefreshToken(String token) { return (OAuth2Authentication) this.redisTemplate.opsForValue().get( REFRESH_AUTH+token); } public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { OAuth2AccessToken existingAccessToken = this.getAccessToken(authentication); this.redisTemplate.opsForValue().set(ACCESS+ token.getValue(), token); this.redisTemplate.opsForValue().set(AUTH +token.getValue(), authentication); this.redisTemplate.opsForValue().set(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication), token); if (!authentication.isClientOnly()) { if (existingAccessToken != null) { if (!existingAccessToken.isExpired()) { int seconds = token.getExpiresIn(); redisTemplate.expire(UNAME_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ; }else{ redisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ; } }else{ redisTemplate.opsForList().rightPush(UNAME_TO_ACCESS+getApprovalKey(authentication), token) ; } } if (existingAccessToken != null) { if (!existingAccessToken.isExpired()) { int seconds = token.getExpiresIn(); redisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ; }else{ redisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ; } }else{ redisTemplate.opsForList().rightPush(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), token) ; } if (token.getExpiration() != null) { int seconds = token.getExpiresIn(); redisTemplate.expire(ACCESS+ token.getValue(), seconds, TimeUnit.SECONDS) ; redisTemplate.expire(AUTH+ token.getValue(), seconds, TimeUnit.SECONDS) ; redisTemplate.expire(AUTH_TO_ACCESS+ authenticationKeyGenerator.extractKey(authentication), seconds, TimeUnit.SECONDS) ; redisTemplate.expire(CLIENT_ID_TO_ACCESS+authentication.getOAuth2Request().getClientId(), seconds, TimeUnit.SECONDS) ; redisTemplate.expire(UNAME_TO_ACCESS+ getApprovalKey(authentication), seconds, TimeUnit.SECONDS) ; } OAuth2RefreshToken refreshToken = token.getRefreshToken(); if (token.getRefreshToken() != null && token.getRefreshToken().getValue() != null) { this.redisTemplate.opsForValue().set( REFRESH_TO_ACCESS+ token.getRefreshToken().getValue(), token.getValue()); this.redisTemplate.opsForValue().set(ACCESS_TO_REFRESH+token.getValue(), token.getRefreshToken().getValue()); if (refreshToken instanceof ExpiringOAuth2RefreshToken) { ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; Date expiration = expiringRefreshToken.getExpiration(); if (expiration != null) { int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L) .intValue(); redisTemplate.expire( REFRESH_TO_ACCESS+ token.getRefreshToken().getValue() , seconds, TimeUnit.SECONDS) ; redisTemplate.expire( ACCESS_TO_REFRESH+token.getValue(), seconds, TimeUnit.SECONDS) ; } } } } private String getApprovalKey(OAuth2Authentication authentication) { String userName = authentication.getUserAuthentication() == null ? "" : authentication.getUserAuthentication() .getName(); return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName); } private String getApprovalKey(String clientId, String userName) { return clientId + (userName==null ? "" : ":" + userName); } public void removeAccessToken(OAuth2AccessToken accessToken) { removeAccessToken(accessToken.getValue()); } public OAuth2AccessToken readAccessToken(String tokenValue) { return (OAuth2AccessToken) this.redisTemplate.opsForValue().get(ACCESS+tokenValue); } public void removeAccessToken(String tokenValue) { OAuth2AccessToken removed = (OAuth2AccessToken) redisTemplate.opsForValue().get(ACCESS+tokenValue); // Don't remove the refresh token - it's up to the caller to do that OAuth2Authentication authentication = (OAuth2Authentication) this.redisTemplate.opsForValue().get(AUTH+tokenValue); this.redisTemplate.delete(AUTH+tokenValue); redisTemplate.delete(ACCESS+tokenValue); this.redisTemplate.delete(ACCESS_TO_REFRESH +tokenValue); if (authentication != null) { this.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication)); String clientId = authentication.getOAuth2Request().getClientId(); // redisTemplate.opsForList().rightPush("UNAME_TO_ACCESS:"+getApprovalKey(authentication), token) ; redisTemplate.opsForList().leftPop(UNAME_TO_ACCESS+getApprovalKey(clientId, authentication.getName())); redisTemplate.opsForList().leftPop(CLIENT_ID_TO_ACCESS+clientId); this.redisTemplate.delete(AUTH_TO_ACCESS+authenticationKeyGenerator.extractKey(authentication)); } } public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { this.redisTemplate.opsForValue().set(REFRESH+refreshToken.getValue(), refreshToken); this.redisTemplate.opsForValue().set( REFRESH_AUTH + refreshToken.getValue(), authentication); } public OAuth2RefreshToken readRefreshToken(String tokenValue) { return (OAuth2RefreshToken) this.redisTemplate.opsForValue().get(REFRESH+tokenValue); } public void removeRefreshToken(OAuth2RefreshToken refreshToken) { removeRefreshToken(refreshToken.getValue()); } public void removeRefreshToken(String tokenValue) { this.redisTemplate.delete( REFRESH + tokenValue); this.redisTemplate.delete( REFRESH_AUTH + tokenValue); this.redisTemplate.delete(REFRESH_TO_ACCESS +tokenValue); } public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { removeAccessTokenUsingRefreshToken(refreshToken.getValue()); } private void removeAccessTokenUsingRefreshToken(String refreshToken) { String token = (String) this.redisTemplate.opsForValue().get( REFRESH_TO_ACCESS +refreshToken) ; if (token != null) { redisTemplate.delete(REFRESH_TO_ACCESS+ refreshToken); } } public Collection findTokensByClientIdAndUserName(String clientId, String userName) { List result = redisTemplate.opsForList().range(UNAME_TO_ACCESS+ getApprovalKey(clientId, userName), 0, -1); if (result == null || result.size() == 0) { return Collections. emptySet(); } List accessTokens = new ArrayList(result.size()); for(Iterator it = result.iterator();it.hasNext();){ OAuth2AccessToken accessToken = (OAuth2AccessToken) it.next(); accessTokens.add(accessToken); } return Collections. unmodifiableCollection(accessTokens); } public Collection findTokensByClientId(String clientId) { List result = redisTemplate.opsForList().range((CLIENT_ID_TO_ACCESS+clientId), 0, -1); if (result == null || result.size() == 0) { return Collections. emptySet(); } List accessTokens = new ArrayList(result.size()); for(Iterator it = result.iterator();it.hasNext();){ OAuth2AccessToken accessToken = (OAuth2AccessToken) it.next(); accessTokens.add(accessToken); } return Collections. unmodifiableCollection(accessTokens); } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/controller/TestController.java ================================================ package com.open.capacity.controller; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月12日 上午22:57:51 */ @RestController public class TestController { private static final Logger logger = LoggerFactory.getLogger(TestController.class); @Resource private RedisTemplate< String, Object> redisTemplate ; @GetMapping("/test111") public String hello() { return "hello"; } } ================================================ FILE: open-api-gateway/src/main/java/com/open/capacity/controller/UserController.java ================================================ package com.open.capacity.controller; import java.security.Principal; import java.util.HashMap; import java.util.Map; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.open.capacity.client.oauth2.token.store.RedisTemplateTokenStore; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月12日 上午22:57:51 */ @RestController public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Resource private RedisTemplate< String, Object> redisTemplate ; @GetMapping("/hello") public String hello() { redisTemplate.opsForValue().set("hello", "owen"); return "hello"; } @RequestMapping(value = { "/users" }, produces = "application/json") // 获取用户信息。/auth/user public Map user(OAuth2Authentication user) { Map userInfo = new HashMap<>(); userInfo.put("user", user.getUserAuthentication().getPrincipal()); logger.debug("认证详细信息:" + user.getUserAuthentication().getPrincipal().toString()); userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities())); return userInfo; } @RequestMapping(value = { "/user" }, produces = "application/json") // 获取用户信息。/auth/user public Principal user(Principal user) { return user; } @GetMapping("/del/{accessToken}/{refreshToken}") public String hello2(@PathVariable String accessToken,@PathVariable String refreshToken) { RedisTemplateTokenStore redisTemplateStore = new RedisTemplateTokenStore(); redisTemplateStore.setRedisTemplate(redisTemplate); redisTemplateStore.removeAccessToken(accessToken); redisTemplateStore.removeRefreshToken(refreshToken); return "delR"; } } ================================================ FILE: open-api-gateway/src/main/resources/application.yml ================================================ server: port: 9200 spring: application: name: open-auth-gateway datasource: type: com.alibaba.druid.pool.DruidDataSource # driver-class-name: oracle.jdbc.OracleDriver # url: jdbc:oracle:thin:@127.0.0.1:1521:orcl # username: crm_owner_user # password: bss_crm_test # filters: stat,wall ################## mysql start ############################ driver-class-name: com.mysql.jdbc.Driver # 192.168.3.150 130.75.131.211 134.224.249.39 47.94.252.160 url: jdbc:mysql://192.168.3.150:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false username: root password: root filters: stat,wall ################### mysq end l########################## redis: ################### redis 单机版 start ########################## host: 127.0.0.1 port: 6379 timeout: 3000 database: 1 ################### redis 单机版 end ########################## # cluster: # nodes: 192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001 ## #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 # #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001 # timeout: 1000 # 连接超时时间(毫秒) # pool: # max-active: 10 # 连接池最大连接数(使用负值表示没有限制) # max-idle: 8 # 连接池中的最大空闲连接 # min-idle: 2 # 连接池中的最小空闲连接 # max-wait: 100 # 连接池最大阻塞等待时间(使用负值表示没有限制) docker: ipAddress: 47.94.252.160 mybatis: config-location: classpath:mybatis.cfg.xml mapper-locations: classpath*:com/open/**/dao/*.xml security: oauth2: token: store: type: redis #设置最大超时时间 ribbon: httpclient: enabled: false okhttp: enabled: true ReadTimeout: 90000 ConnectTimeout: 90000 #设置最大容错超时时间 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 90000 hystrix: command: default: execution: timeout: enabled: false #设置熔断的超时时间开启 false关闭熔断功能,true开启熔断功能 isolation: thread: timeoutInMilliseconds: 90000 swagger: butler: api-docs-path: v2/api-docs auto-generate-from-zuul-routes: true zuul: retryable: false #关闭重试 sensitive-headers: #/oauth/token需要请求头处理 add-host-header: true routes: baidu: path: /test163/** url: http://www.163.com auth: path: /auth/** service-id: open-auth-server strip-prefix: true custom-sensitive-headers: true #http://blog.didispace.com/spring-cloud-zuul-cookie-redirect/ zuul授权码跳转问题 client: path: /client/** service-id: open-eureka-client strip-prefix: true auth_client: path: /auth-client/** service-id: open-auth-client strip-prefix: true eureka: client: serviceUrl: defaultZone: http://127.0.0.1:1111/eureka/ #http://192.168.3.170:1111/eureka,http://192.168.3.171:1111/eureka,http://192.168.3.173:1111/eureka #http://130.75.131.243:1111/eureka/,http://130.75.131.244:1111/eureka/,http://130.75.131.245:1111/eureka/ instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} # instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 5 #注册实例文档 status-page-url: http://${spring.cloud.client.ipAddress}:${server.port}/swagger-ui.html # ${server.port}为该服务的端口号 # status-page-url: http://${docker.ipAddress}:${server.port}/swagger-ui.html # ${server.port}为该服务的端口号 ================================================ FILE: open-api-gateway/src/main/resources/bootstrap.yml ================================================ management: security: enabled: false #spring: # cloud: # config: # discovery: # enabled: true # service-id: unieap-config-server # name: unieap-config-server # fail-fast: true # profile: dev # eureka-config-client-dev.yml ================================================ FILE: open-commons/pom.xml ================================================ 4.0.0 com.open.capacity open-capacity-platform 0.0.1-SNAPSHOT open-commons org.springframework.security spring-security-core org.apache.commons commons-lang3 org.apache.commons commons-collections4 4.0 ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/dto/LoginUser.java ================================================ package com.open.capacity.security.dto; import com.fasterxml.jackson.annotation.JsonIgnore; import com.open.capacity.security.model.Permission; import com.open.capacity.security.model.SysUser; import org.apache.commons.lang3.StringUtils; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; public class LoginUser extends SysUser implements UserDetails { private static final long serialVersionUID = -1379274258881257107L; private List permissions; private String jwtToken; private String token; /** * 登陆时间戳(毫秒) */ private Long loginTime; /** * 过期时间戳 */ private Long expireTime; public List getPermissions() { return permissions; } public void setPermissions(List permissions) { this.permissions = permissions; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } @Override @JsonIgnore public Collection getAuthorities() { List auths = new ArrayList(); for (Iterator it = permissions.iterator(); it.hasNext(); ) { Permission p = it.next(); if (!StringUtils.isEmpty(p.getPermission())) { auths.add(new SimpleGrantedAuthority(p.getPermission())); } } return auths; // return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission())) // .map(p -> new SimpleGrantedAuthority(p.getPermission())).collect(Collectors.toSet()); } public void setAuthorities(Collection authorities) { // do nothing } // 账户是否未过期 @JsonIgnore @Override public boolean isAccountNonExpired() { return true; } // 账户是否未锁定 @JsonIgnore @Override public boolean isAccountNonLocked() { return getStatus() != Status.LOCKED; } // 密码是否未过期 @JsonIgnore @Override public boolean isCredentialsNonExpired() { return true; } // 账户是否激活 @JsonIgnore @Override public boolean isEnabled() { return true; } public Long getLoginTime() { return loginTime; } public void setLoginTime(Long loginTime) { this.loginTime = loginTime; } public Long getExpireTime() { return expireTime; } public void setExpireTime(Long expireTime) { this.expireTime = expireTime; } @JsonIgnore public String getJwtToken() { return jwtToken; } public void setJwtToken(String jwtToken) { this.jwtToken = jwtToken; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/dto/ResponseInfo.java ================================================ package com.open.capacity.security.dto; import java.io.Serializable; public class ResponseInfo implements Serializable { private static final long serialVersionUID = -4417715614021482064L; private String code; private String message; public ResponseInfo(String code, String message) { super(); this.code = code; this.message = message; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/dto/RoleDto.java ================================================ package com.open.capacity.security.dto; import com.open.capacity.security.model.Role; import java.util.List; public class RoleDto extends Role { private static final long serialVersionUID = 4218495592167610193L; private List permissionIds; public List getPermissionIds() { return permissionIds; } public void setPermissionIds(List permissionIds) { this.permissionIds = permissionIds; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/dto/UserDto.java ================================================ package com.open.capacity.security.dto; import com.open.capacity.security.model.SysUser; import java.util.List; public class UserDto extends SysUser { private static final long serialVersionUID = -184009306207076712L; private List roleIds; public List getRoleIds() { return roleIds; } public void setRoleIds(List roleIds) { this.roleIds = roleIds; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/model/BaseEntity.java ================================================ package com.open.capacity.security.model; import java.io.Serializable; import java.util.Date; public abstract class BaseEntity implements Serializable { private static final long serialVersionUID = 2054813493011812469L; private ID id; private Date createTime = new Date(); private Date updateTime = new Date(); public ID getId() { return id; } public void setId(ID id) { this.id = id; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/model/Permission.java ================================================ package com.open.capacity.security.model; import java.util.List; public class Permission extends BaseEntity { private static final long serialVersionUID = 6180869216498363919L; private Long parentId; private String name; private String css; private String href; private Integer type; private String permission; private Integer sort; private List child; public Long getParentId() { return parentId; } public void setParentId(Long parentId) { this.parentId = parentId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCss() { return css; } public void setCss(String css) { this.css = css; } public String getHref() { return href; } public void setHref(String href) { this.href = href; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public String getPermission() { return permission; } public void setPermission(String permission) { this.permission = permission; } public Integer getSort() { return sort; } public void setSort(Integer sort) { this.sort = sort; } public List getChild() { return child; } public void setChild(List child) { this.child = child; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/model/Role.java ================================================ package com.open.capacity.security.model; public class Role extends BaseEntity { private static final long serialVersionUID = -3802292814767103648L; private String name; private String description; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/model/SysLogs.java ================================================ package com.open.capacity.security.model; public class SysLogs extends BaseEntity { private static final long serialVersionUID = -7809315432127036583L; private SysUser user; private String module; private Boolean flag; private String remark; public SysUser getUser() { return user; } public void setUser(SysUser user) { this.user = user; } public String getModule() { return module; } public void setModule(String module) { this.module = module; } public Boolean getFlag() { return flag; } public void setFlag(Boolean flag) { this.flag = flag; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/model/SysUser.java ================================================ package com.open.capacity.security.model; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; public class SysUser extends BaseEntity { private static final long serialVersionUID = -6525908145032868837L; private String username; private String password; private String nickname; private String headImgUrl; private String phone; private String telephone; private String email; @JsonFormat(pattern = "yyyy-MM-dd") private Date birthday; private Integer sex; private Integer status; private String intro; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getHeadImgUrl() { return headImgUrl; } public void setHeadImgUrl(String headImgUrl) { this.headImgUrl = headImgUrl; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getIntro() { return intro; } public void setIntro(String intro) { this.intro = intro; } public interface Status { int DISABLED = 0; int VALID = 1; int LOCKED = 2; } } ================================================ FILE: open-commons/src/main/java/com/open/capacity/security/model/TokenModel.java ================================================ package com.open.capacity.security.model; import java.util.Date; public class TokenModel extends BaseEntity { private static final long serialVersionUID = 4566334160572911795L; /** * 过期时间 */ private Date expireTime; /** * LoginUser的json串 */ private String val; public Date getExpireTime() { return expireTime; } public void setExpireTime(Date expireTime) { this.expireTime = expireTime; } public String getVal() { return val; } public void setVal(String val) { this.val = val; } } ================================================ FILE: open-config-center/apollo/.gitattributes ================================================ text=auto ================================================ FILE: open-config-center/apollo/.gitignore ================================================ *.class .DS_Store application.pid # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.ear # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* # Eclipse .classpath .project target .settings bin/ target/ # Idea .idea *.iml # git *.orig ================================================ FILE: open-config-center/apollo/.travis.yml ================================================ language: java jdk: - oraclejdk8 notification: email: recipients: - song_s@ctrip.com,zhanglea@ctrip.com on_success: always on_failure: always before_script: - echo "MAVEN_OPTS='-Xms1024m -Xmx3072m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m'" > ~/.mavenrc before_install: - pip install --user codecov after_success: - mvn clean test jacoco:report coveralls:report - codecov branches: only: - master env: global: - secure: "DYJkJ7ArGJuIyTJsmjvUAJRyUKXEaGFWYZFAGZq6vxbrMN3tThz7drfNhhvP2YE7hdS7YX7hZBWVQEnNR+pBN+ykQFx7TpLr311eEk2/Yy3G5qegeHMsgqYXfAp3FFpYlE6Kr3Dcf4kFSWtRi735kSo5oHicoaxbyWENgmKT+uQjYERKhDXEoenMaDpcf8WO8KARzxI1cXf69ECnYP2rzNOfkNW4IGjTcJnplXPZ9BNBRn3WfyPwEHlemETAMwJxJXolNM9qn1bDBTB/35yJrneQY/pYp9Q8PbQID2lNJu7PFKYaI9mvsKHUgxjbzsC29zlMY94pDr6sQtr7IA0dSuk+qO2tEqAStTwRI5JOcozLAslTMNnUn6HLvy0/Kkq1TL+JrIohoRD58F34SzjcnuB4w0/GCWGU4BMSbzPwHsgQZM4lkHDWv+w1OSwP3dgCFI/vYYr9xNV0zqTgyZ9ITkMZPL0wOh0DZ7Bxxm80wyHfJuRwywemMtzitgjPR4BKENbpcoGN4lcKWciksAuiyX+dedOPfGoOWfnIKh1g7yeVB84LMggCSad/9cqnYf2Sm8xSyVzNmyhSOy2Ocy40RDas2uHIK3/QPy56Le/t1LD2On/x1TZBIoSavedNYA5N54s/ZCDZOcepUMvlwtjgnx/SMjU85ZLKCcliPGdTWws=" - "MAVEN_OPTS=-Xms1024m -Xmx3072m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m" addons: coverity_scan: project: name: "ctripcorp/apollo" description: "Build submitted via Travis CI" notification_email: song_s@ctrip.com,zhanglea@ctrip.com build_command_prepend: "mvn clean" build_command: "mvn -DskipTests=true compile" branch_pattern: master cache: directories: - $HOME/.m2 ================================================ FILE: open-config-center/apollo/LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: open-config-center/apollo/apollo-adminservice/pom.xml ================================================ com.ctrip.framework.apollo apollo 0.10.0-SNAPSHOT 4.0.0 apollo-adminservice Apollo AdminService ${project.artifactId} com.ctrip.framework.apollo apollo-biz org.springframework.cloud spring-cloud-starter-eureka-server test spring-cloud-starter-archaius org.springframework.cloud spring-cloud-starter-ribbon org.springframework.cloud ribbon-eureka com.netflix.ribbon aws-java-sdk-core com.amazonaws aws-java-sdk-ec2 com.amazonaws aws-java-sdk-autoscaling com.amazonaws aws-java-sdk-sts com.amazonaws aws-java-sdk-route53 com.amazonaws com.h2database h2 test org.springframework.boot spring-boot-starter-jdbc mysql mysql-connector-java org.springframework.boot spring-boot-maven-plugin repackage apollo-adminservice ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/assembly/assembly-descriptor.xml ================================================ apollo-assembly zip false src/main/scripts scripts *.sh 0755 unix src/main/config config apollo-adminservice.conf unix src/main/config / apollo-adminservice.conf unix target / ${project.artifactId}-*.jar 0755 ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/config/apollo-adminservice.conf ================================================ MODE=service PID_FOLDER=. LOG_FOLDER=/opt/logs/100003172/ ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/config/app.properties ================================================ appId=100003172 jdkVersion=1.8 ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/docker/Dockerfile ================================================ # Dockerfile for apollo-adminservice # Build with: # docker build -t apollo-adminservice . # Run with: # docker run -p 8090:8090 -d -v /tmp/logs:/opt/logs --name apollo-adminservice apollo-adminservice FROM openjdk:8-jre-alpine MAINTAINER ameizi ENV VERSION 0.9.0 RUN echo "http://mirrors.aliyun.com/alpine/v3.6/main" > /etc/apk/repositories \ && echo "http://mirrors.aliyun.com/alpine/v3.6/community" >> /etc/apk/repositories \ && apk update upgrade \ && apk add --no-cache procps unzip curl bash tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone ADD apollo-adminservice-${VERSION}-github.zip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip RUN unzip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip -d /apollo-adminservice \ && rm -rf /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip \ && sed -i '$d' /apollo-adminservice/scripts/startup.sh \ && echo "tail -f /dev/null" >> /apollo-adminservice/scripts/startup.sh EXPOSE 8090 CMD ["/apollo-adminservice/scripts/startup.sh"] ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/AdminServiceApplication.java ================================================ package com.ctrip.framework.apollo.adminservice; import com.ctrip.framework.apollo.biz.ApolloBizConfig; import com.ctrip.framework.apollo.common.ApolloCommonConfig; import org.springframework.boot.actuate.system.ApplicationPidFileWriter; import org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; @EnableAspectJAutoProxy @EnableEurekaClient @Configuration @PropertySource(value = {"classpath:adminservice.properties"}) @EnableAutoConfiguration @EnableTransactionManagement @ComponentScan(basePackageClasses = {ApolloCommonConfig.class, ApolloBizConfig.class, AdminServiceApplication.class}) public class AdminServiceApplication { public static void main(String[] args) { ConfigurableApplicationContext context = new SpringApplicationBuilder(AdminServiceApplication.class).run(args); context.addApplicationListener(new ApplicationPidFileWriter()); context.addApplicationListener(new EmbeddedServerPortFileWriter()); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/AdminServiceHealthIndicator.java ================================================ package com.ctrip.framework.apollo.adminservice; import com.ctrip.framework.apollo.biz.service.AppService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Component; @Component public class AdminServiceHealthIndicator implements HealthIndicator { @Autowired private AppService appService; @Override public Health health() { int errorCode = check(); if (errorCode != 0) { return Health.down().withDetail("Error Code", errorCode).build(); } return Health.up().build(); } private int check() { PageRequest pageable = new PageRequest(0, 1); appService.findAll(pageable); return 0; } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceAcquireLockAspect.java ================================================ package com.ctrip.framework.apollo.adminservice.aop; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.NamespaceLock; import com.ctrip.framework.apollo.biz.service.ItemService; import com.ctrip.framework.apollo.biz.service.NamespaceLockService; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.ServiceException; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Component; /** * 一个namespace在一次发布中只能允许一个人修改配置 * 通过数据库lock表来实现 */ @Aspect @Component public class NamespaceAcquireLockAspect { private static final Logger logger = LoggerFactory.getLogger(NamespaceAcquireLockAspect.class); @Autowired private NamespaceLockService namespaceLockService; @Autowired private NamespaceService namespaceService; @Autowired private ItemService itemService; @Autowired private BizConfig bizConfig; //create item @Before("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, item, ..)") public void requireLockAdvice(String appId, String clusterName, String namespaceName, ItemDTO item) { acquireLock(appId, clusterName, namespaceName, item.getDataChangeLastModifiedBy()); } //update item @Before("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, itemId, item, ..)") public void requireLockAdvice(String appId, String clusterName, String namespaceName, long itemId, ItemDTO item) { acquireLock(appId, clusterName, namespaceName, item.getDataChangeLastModifiedBy()); } //update by change set @Before("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, changeSet, ..)") public void requireLockAdvice(String appId, String clusterName, String namespaceName, ItemChangeSets changeSet) { acquireLock(appId, clusterName, namespaceName, changeSet.getDataChangeLastModifiedBy()); } //delete item @Before("@annotation(PreAcquireNamespaceLock) && args(itemId, operator, ..)") public void requireLockAdvice(long itemId, String operator) { Item item = itemService.findOne(itemId); if (item == null){ throw new BadRequestException("item not exist."); } acquireLock(item.getNamespaceId(), operator); } void acquireLock(String appId, String clusterName, String namespaceName, String currentUser) { if (bizConfig.isNamespaceLockSwitchOff()) { return; } Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); acquireLock(namespace, currentUser); } void acquireLock(long namespaceId, String currentUser) { if (bizConfig.isNamespaceLockSwitchOff()) { return; } Namespace namespace = namespaceService.findOne(namespaceId); acquireLock(namespace, currentUser); } private void acquireLock(Namespace namespace, String currentUser) { if (namespace == null) { throw new BadRequestException("namespace not exist."); } long namespaceId = namespace.getId(); NamespaceLock namespaceLock = namespaceLockService.findLock(namespaceId); if (namespaceLock == null) { try { tryLock(namespaceId, currentUser); //lock success } catch (DataIntegrityViolationException e) { //lock fail namespaceLock = namespaceLockService.findLock(namespaceId); checkLock(namespace, namespaceLock, currentUser); } catch (Exception e) { logger.error("try lock error", e); throw e; } } else { //check lock owner is current user checkLock(namespace, namespaceLock, currentUser); } } private void tryLock(long namespaceId, String user) { NamespaceLock lock = new NamespaceLock(); lock.setNamespaceId(namespaceId); lock.setDataChangeCreatedBy(user); lock.setDataChangeLastModifiedBy(user); namespaceLockService.tryLock(lock); } private void checkLock(Namespace namespace, NamespaceLock namespaceLock, String currentUser) { if (namespaceLock == null) { throw new ServiceException( String.format("Check lock for %s failed, please retry.", namespace.getNamespaceName())); } String lockOwner = namespaceLock.getDataChangeCreatedBy(); if (!lockOwner.equals(currentUser)) { throw new BadRequestException( "namespace:" + namespace.getNamespaceName() + " is modified by " + lockOwner); } } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceUnlockAspect.java ================================================ package com.ctrip.framework.apollo.adminservice.aop; import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.service.ItemService; import com.ctrip.framework.apollo.biz.service.NamespaceLockService; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.biz.service.ReleaseService; import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; /** * unlock namespace if is redo operation. * -------------------------------------------- * For example: If namespace has a item K1 = v1 * -------------------------------------------- * First operate: change k1 = v2 (lock namespace) * Second operate: change k1 = v1 (unlock namespace) */ @Aspect @Component public class NamespaceUnlockAspect { private Gson gson = new Gson(); @Autowired private NamespaceLockService namespaceLockService; @Autowired private NamespaceService namespaceService; @Autowired private ItemService itemService; @Autowired private ReleaseService releaseService; @Autowired private BizConfig bizConfig; //create item @After("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, item, ..)") public void requireLockAdvice(String appId, String clusterName, String namespaceName, ItemDTO item) { tryUnlock(namespaceService.findOne(appId, clusterName, namespaceName)); } //update item @After("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, itemId, item, ..)") public void requireLockAdvice(String appId, String clusterName, String namespaceName, long itemId, ItemDTO item) { tryUnlock(namespaceService.findOne(appId, clusterName, namespaceName)); } //update by change set @After("@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, changeSet, ..)") public void requireLockAdvice(String appId, String clusterName, String namespaceName, ItemChangeSets changeSet) { tryUnlock(namespaceService.findOne(appId, clusterName, namespaceName)); } //delete item @After("@annotation(PreAcquireNamespaceLock) && args(itemId, operator, ..)") public void requireLockAdvice(long itemId, String operator) { Item item = itemService.findOne(itemId); if (item == null) { throw new BadRequestException("item not exist."); } tryUnlock(namespaceService.findOne(item.getNamespaceId())); } private void tryUnlock(Namespace namespace) { if (bizConfig.isNamespaceLockSwitchOff()) { return; } if (!isModified(namespace)) { namespaceLockService.unlock(namespace.getId()); } } boolean isModified(Namespace namespace) { Release release = releaseService.findLatestActiveRelease(namespace); List items = itemService.findItemsWithoutOrdered(namespace.getId()); if (release == null) { return hasNormalItems(items); } Map releasedConfiguration = gson.fromJson(release.getConfigurations(), GsonType.CONFIG); Map configurationFromItems = generateConfigurationFromItems(namespace, items); MapDifference difference = Maps.difference(releasedConfiguration, configurationFromItems); return !difference.areEqual(); } private boolean hasNormalItems(List items) { for (Item item : items) { if (!StringUtils.isEmpty(item.getKey())) { return true; } } return false; } private Map generateConfigurationFromItems(Namespace namespace, List namespaceItems) { Map configurationFromItems = Maps.newHashMap(); Namespace parentNamespace = namespaceService.findParentNamespace(namespace); //parent namespace if (parentNamespace == null) { generateMapFromItems(namespaceItems, configurationFromItems); } else {//child namespace Release parentRelease = releaseService.findLatestActiveRelease(parentNamespace); if (parentRelease != null) { configurationFromItems = gson.fromJson(parentRelease.getConfigurations(), GsonType.CONFIG); } generateMapFromItems(namespaceItems, configurationFromItems); } return configurationFromItems; } private Map generateMapFromItems(List items, Map configurationFromItems) { for (Item item : items) { String key = item.getKey(); if (StringUtils.isBlank(key)) { continue; } configurationFromItems.put(key, item.getValue()); } return configurationFromItems; } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/PreAcquireNamespaceLock.java ================================================ package com.ctrip.framework.apollo.adminservice.aop; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 标识方法需要获取到namespace的lock才能执行 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface PreAcquireNamespaceLock { } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.biz.service.AdminService; import com.ctrip.framework.apollo.biz.service.AppService; import com.ctrip.framework.apollo.common.dto.AppDTO; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.common.utils.InputValidator; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Objects; @RestController public class AppController { @Autowired private AppService appService; @Autowired private AdminService adminService; @RequestMapping(path = "/apps", method = RequestMethod.POST) public AppDTO create(@RequestBody AppDTO dto) { if (!InputValidator.isValidClusterNamespace(dto.getAppId())) { throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); } App entity = BeanUtils.transfrom(App.class, dto); App managedEntity = appService.findOne(entity.getAppId()); if (managedEntity != null) { throw new BadRequestException("app already exist."); } entity = adminService.createNewApp(entity); dto = BeanUtils.transfrom(AppDTO.class, entity); return dto; } @RequestMapping(value = "/apps/{appId:.+}", method = RequestMethod.DELETE) public void delete(@PathVariable("appId") String appId, @RequestParam String operator) { App entity = appService.findOne(appId); if (entity == null) { throw new NotFoundException("app not found for appId " + appId); } appService.delete(entity.getId(), operator); } @RequestMapping(value = "/apps/{appId:.+}", method = RequestMethod.PUT) public void update(@PathVariable String appId, @RequestBody App app) { if (!Objects.equals(appId, app.getAppId())) { throw new BadRequestException("The App Id of path variable and request body is different"); } appService.update(app); } @RequestMapping(value = "/apps", method = RequestMethod.GET) public List find(@RequestParam(value = "name", required = false) String name, Pageable pageable) { List app = null; if (StringUtils.isBlank(name)) { app = appService.findAll(pageable); } else { app = appService.findByName(name); } return BeanUtils.batchTransform(AppDTO.class, app); } @RequestMapping(value = "/apps/{appId:.+}", method = RequestMethod.GET) public AppDTO get(@PathVariable("appId") String appId) { App app = appService.findOne(appId); if (app == null) { throw new NotFoundException("app not found for appId " + appId); } return BeanUtils.transfrom(AppDTO.class, app); } @RequestMapping(value = "/apps/{appId}/unique", method = RequestMethod.GET) public boolean isAppIdUnique(@PathVariable("appId") String appId) { return appService.isAppIdUnique(appId); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppNamespaceController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.service.AppNamespaceService; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.common.dto.AppNamespaceDTO; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class AppNamespaceController { @Autowired private AppNamespaceService appNamespaceService; @Autowired private NamespaceService namespaceService; @RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST) public AppNamespaceDTO create(@RequestBody AppNamespaceDTO appNamespace) { AppNamespace entity = BeanUtils.transfrom(AppNamespace.class, appNamespace); AppNamespace managedEntity = appNamespaceService.findOne(entity.getAppId(), entity.getName()); if (managedEntity != null) { throw new BadRequestException("app namespaces already exist."); } if (StringUtils.isEmpty(entity.getFormat())){ entity.setFormat(ConfigFileFormat.Properties.getValue()); } entity = appNamespaceService.createAppNamespace(entity); return BeanUtils.transfrom(AppNamespaceDTO.class, entity); } @RequestMapping(value = "/appnamespaces/{publicNamespaceName}/namespaces", method = RequestMethod.GET) public List findPublicAppNamespaceAllNamespaces(@PathVariable String publicNamespaceName, Pageable pageable) { List namespaces = namespaceService.findPublicAppNamespaceAllNamespaces(publicNamespaceName, pageable); return BeanUtils.batchTransform(NamespaceDTO.class, namespaces); } @RequestMapping(value = "/appnamespaces/{publicNamespaceName}/associated-namespaces/count", method = RequestMethod.GET) public int countPublicAppNamespaceAssociatedNamespaces(@PathVariable String publicNamespaceName) { return namespaceService.countPublicAppNamespaceAssociatedNamespaces(publicNamespaceName); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ClusterController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.biz.entity.Cluster; import com.ctrip.framework.apollo.biz.service.ClusterService; import com.ctrip.framework.apollo.common.dto.ClusterDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.common.utils.InputValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class ClusterController { @Autowired private ClusterService clusterService; @RequestMapping(path = "/apps/{appId}/clusters", method = RequestMethod.POST) public ClusterDTO create(@PathVariable("appId") String appId, @RequestParam(value = "autoCreatePrivateNamespace", defaultValue = "true") boolean autoCreatePrivateNamespace, @RequestBody ClusterDTO dto) { if (!InputValidator.isValidClusterNamespace(dto.getName())) { throw new BadRequestException(String.format("Cluster格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); } Cluster entity = BeanUtils.transfrom(Cluster.class, dto); Cluster managedEntity = clusterService.findOne(appId, entity.getName()); if (managedEntity != null) { throw new BadRequestException("cluster already exist."); } if (autoCreatePrivateNamespace) { entity = clusterService.saveWithInstanceOfAppNamespaces(entity); } else { entity = clusterService.saveWithoutInstanceOfAppNamespaces(entity); } dto = BeanUtils.transfrom(ClusterDTO.class, entity); return dto; } @RequestMapping(path = "/apps/{appId}/clusters/{clusterName:.+}", method = RequestMethod.DELETE) public void delete(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @RequestParam String operator) { Cluster entity = clusterService.findOne(appId, clusterName); if (entity == null) { throw new NotFoundException("cluster not found for clusterName " + clusterName); } clusterService.delete(entity.getId(), operator); } @RequestMapping(value = "/apps/{appId}/clusters", method = RequestMethod.GET) public List find(@PathVariable("appId") String appId) { List clusters = clusterService.findParentClusters(appId); return BeanUtils.batchTransform(ClusterDTO.class, clusters); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName:.+}", method = RequestMethod.GET) public ClusterDTO get(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName) { Cluster cluster = clusterService.findOne(appId, clusterName); if (cluster == null) { throw new NotFoundException("cluster not found for name " + clusterName); } return BeanUtils.transfrom(ClusterDTO.class, cluster); } @RequestMapping(value = "/apps/{appId}/cluster/{clusterName}/unique", method = RequestMethod.GET) public boolean isAppIdUnique(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName) { return clusterService.isClusterNameUnique(appId, clusterName); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/CommitController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.biz.entity.Commit; import com.ctrip.framework.apollo.biz.service.CommitService; import com.ctrip.framework.apollo.common.dto.CommitDTO; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class CommitController { @Autowired private CommitService commitService; @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit", method = RequestMethod.GET) public List find(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName, Pageable pageable){ List commits = commitService.find(appId, clusterName, namespaceName, pageable); return BeanUtils.batchTransform(CommitDTO.class, commits); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/IndexController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(path = "/") public class IndexController { @RequestMapping(path = "", method = RequestMethod.GET) public String index() { return "apollo-adminservice"; } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/InstanceConfigController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.HashMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.biz.entity.Instance; import com.ctrip.framework.apollo.biz.entity.InstanceConfig; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.service.InstanceService; import com.ctrip.framework.apollo.biz.service.ReleaseService; import com.ctrip.framework.apollo.common.dto.InstanceConfigDTO; import com.ctrip.framework.apollo.common.dto.InstanceDTO; import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * @author Jason Song(song_s@ctrip.com) */ @RestController @RequestMapping("/instances") public class InstanceConfigController { private static final Splitter RELEASES_SPLITTER = Splitter.on(",").omitEmptyStrings() .trimResults(); @Autowired private ReleaseService releaseService; @Autowired private InstanceService instanceService; @RequestMapping(value = "/by-release", method = RequestMethod.GET) public PageDTO getByRelease(@RequestParam("releaseId") long releaseId, Pageable pageable) { Release release = releaseService.findOne(releaseId); if (release == null) { throw new NotFoundException(String.format("release not found for %s", releaseId)); } Page instanceConfigsPage = instanceService.findActiveInstanceConfigsByReleaseKey (release.getReleaseKey(), pageable); List instanceDTOs = Collections.emptyList(); if (instanceConfigsPage.hasContent()) { Multimap instanceConfigMap = HashMultimap.create(); Set otherReleaseKeys = Sets.newHashSet(); for (InstanceConfig instanceConfig : instanceConfigsPage.getContent()) { instanceConfigMap.put(instanceConfig.getInstanceId(), instanceConfig); otherReleaseKeys.add(instanceConfig.getReleaseKey()); } Set instanceIds = instanceConfigMap.keySet(); List instances = instanceService.findInstancesByIds(instanceIds); if (!CollectionUtils.isEmpty(instances)) { instanceDTOs = BeanUtils.batchTransform(InstanceDTO.class, instances); } for (InstanceDTO instanceDTO : instanceDTOs) { Collection configs = instanceConfigMap.get(instanceDTO.getId()); List configDTOs = configs.stream().map(instanceConfig -> { InstanceConfigDTO instanceConfigDTO = new InstanceConfigDTO(); //to save some space instanceConfigDTO.setRelease(null); instanceConfigDTO.setReleaseDeliveryTime(instanceConfig.getReleaseDeliveryTime()); instanceConfigDTO.setDataChangeLastModifiedTime(instanceConfig .getDataChangeLastModifiedTime()); return instanceConfigDTO; }).collect(Collectors.toList()); instanceDTO.setConfigs(configDTOs); } } return new PageDTO<>(instanceDTOs, pageable, instanceConfigsPage.getTotalElements()); } @RequestMapping(value = "/by-namespace-and-releases-not-in", method = RequestMethod.GET) public List getByReleasesNotIn(@RequestParam("appId") String appId, @RequestParam("clusterName") String clusterName, @RequestParam("namespaceName") String namespaceName, @RequestParam("releaseIds") String releaseIds) { Set releaseIdSet = RELEASES_SPLITTER.splitToList(releaseIds).stream().map(Long::parseLong) .collect(Collectors.toSet()); List releases = releaseService.findByReleaseIds(releaseIdSet); if (CollectionUtils.isEmpty(releases)) { throw new NotFoundException(String.format("releases not found for %s", releaseIds)); } Set releaseKeys = releases.stream().map(Release::getReleaseKey).collect(Collectors .toSet()); List instanceConfigs = instanceService .findInstanceConfigsByNamespaceWithReleaseKeysNotIn(appId, clusterName, namespaceName, releaseKeys); Multimap instanceConfigMap = HashMultimap.create(); Set otherReleaseKeys = Sets.newHashSet(); for (InstanceConfig instanceConfig : instanceConfigs) { instanceConfigMap.put(instanceConfig.getInstanceId(), instanceConfig); otherReleaseKeys.add(instanceConfig.getReleaseKey()); } List instances = instanceService.findInstancesByIds(instanceConfigMap.keySet()); if (CollectionUtils.isEmpty(instances)) { return Collections.emptyList(); } List instanceDTOs = BeanUtils.batchTransform(InstanceDTO.class, instances); List otherReleases = releaseService.findByReleaseKeys(otherReleaseKeys); Map releaseMap = Maps.newHashMap(); for (Release release : otherReleases) { //unset configurations to save space release.setConfigurations(null); ReleaseDTO releaseDTO = BeanUtils.transfrom(ReleaseDTO.class, release); releaseMap.put(release.getReleaseKey(), releaseDTO); } for (InstanceDTO instanceDTO : instanceDTOs) { Collection configs = instanceConfigMap.get(instanceDTO.getId()); List configDTOs = configs.stream().map(instanceConfig -> { InstanceConfigDTO instanceConfigDTO = new InstanceConfigDTO(); instanceConfigDTO.setRelease(releaseMap.get(instanceConfig.getReleaseKey())); instanceConfigDTO.setReleaseDeliveryTime(instanceConfig.getReleaseDeliveryTime()); instanceConfigDTO.setDataChangeLastModifiedTime(instanceConfig .getDataChangeLastModifiedTime()); return instanceConfigDTO; }).collect(Collectors.toList()); instanceDTO.setConfigs(configDTOs); } return instanceDTOs; } @RequestMapping(value = "/by-namespace", method = RequestMethod.GET) public PageDTO getInstancesByNamespace( @RequestParam("appId") String appId, @RequestParam("clusterName") String clusterName, @RequestParam("namespaceName") String namespaceName, @RequestParam(value = "instanceAppId", required = false) String instanceAppId, Pageable pageable) { Page instances; if (Strings.isNullOrEmpty(instanceAppId)) { instances = instanceService.findInstancesByNamespace(appId, clusterName, namespaceName, pageable); } else { instances = instanceService.findInstancesByNamespaceAndInstanceAppId(instanceAppId, appId, clusterName, namespaceName, pageable); } List instanceDTOs = BeanUtils.batchTransform(InstanceDTO.class, instances.getContent()); return new PageDTO<>(instanceDTOs, pageable, instances.getTotalElements()); } @RequestMapping(value = "/by-namespace/count", method = RequestMethod.GET) public long getInstancesCountByNamespace(@RequestParam("appId") String appId, @RequestParam("clusterName") String clusterName, @RequestParam("namespaceName") String namespaceName) { Page instances = instanceService.findInstancesByNamespace(appId, clusterName, namespaceName, new PageRequest(0, 1)); return instances.getTotalElements(); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.adminservice.aop.PreAcquireNamespaceLock; import com.ctrip.framework.apollo.biz.entity.Commit; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.service.CommitService; import com.ctrip.framework.apollo.biz.service.ItemService; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.biz.utils.ConfigChangeContentBuilder; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class ItemController { @Autowired private ItemService itemService; @Autowired private NamespaceService namespaceService; @Autowired private CommitService commitService; @PreAcquireNamespaceLock @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST) public ItemDTO create(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, @RequestBody ItemDTO dto) { Item entity = BeanUtils.transfrom(Item.class, dto); ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder(); Item managedEntity = itemService.findOne(appId, clusterName, namespaceName, entity.getKey()); if (managedEntity != null) { throw new BadRequestException("item already exist"); } else { entity = itemService.save(entity); builder.createItem(entity); } dto = BeanUtils.transfrom(ItemDTO.class, entity); Commit commit = new Commit(); commit.setAppId(appId); commit.setClusterName(clusterName); commit.setNamespaceName(namespaceName); commit.setChangeSets(builder.build()); commit.setDataChangeCreatedBy(dto.getDataChangeLastModifiedBy()); commit.setDataChangeLastModifiedBy(dto.getDataChangeLastModifiedBy()); commitService.save(commit); return dto; } @PreAcquireNamespaceLock @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", method = RequestMethod.PUT) public ItemDTO update(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, @PathVariable("itemId") long itemId, @RequestBody ItemDTO itemDTO) { Item entity = BeanUtils.transfrom(Item.class, itemDTO); ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder(); Item managedEntity = itemService.findOne(itemId); if (managedEntity == null) { throw new BadRequestException("item not exist"); } Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedEntity); //protect. only value,comment,lastModifiedBy can be modified managedEntity.setValue(entity.getValue()); managedEntity.setComment(entity.getComment()); managedEntity.setDataChangeLastModifiedBy(entity.getDataChangeLastModifiedBy()); entity = itemService.update(managedEntity); builder.updateItem(beforeUpdateItem, entity); itemDTO = BeanUtils.transfrom(ItemDTO.class, entity); if (builder.hasContent()) { Commit commit = new Commit(); commit.setAppId(appId); commit.setClusterName(clusterName); commit.setNamespaceName(namespaceName); commit.setChangeSets(builder.build()); commit.setDataChangeCreatedBy(itemDTO.getDataChangeLastModifiedBy()); commit.setDataChangeLastModifiedBy(itemDTO.getDataChangeLastModifiedBy()); commitService.save(commit); } return itemDTO; } @PreAcquireNamespaceLock @RequestMapping(path = "/items/{itemId}", method = RequestMethod.DELETE) public void delete(@PathVariable("itemId") long itemId, @RequestParam String operator) { Item entity = itemService.findOne(itemId); if (entity == null) { throw new NotFoundException("item not found for itemId " + itemId); } itemService.delete(entity.getId(), operator); Namespace namespace = namespaceService.findOne(entity.getNamespaceId()); Commit commit = new Commit(); commit.setAppId(namespace.getAppId()); commit.setClusterName(namespace.getClusterName()); commit.setNamespaceName(namespace.getNamespaceName()); commit.setChangeSets(new ConfigChangeContentBuilder().deleteItem(entity).build()); commit.setDataChangeCreatedBy(operator); commit.setDataChangeLastModifiedBy(operator); commitService.save(commit); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.GET) public List findItems(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName) { return BeanUtils.batchTransform(ItemDTO.class, itemService.findItemsWithOrdered(appId, clusterName, namespaceName)); } @RequestMapping(value = "/items/{itemId}", method = RequestMethod.GET) public ItemDTO get(@PathVariable("itemId") long itemId) { Item item = itemService.findOne(itemId); if (item == null) { throw new NotFoundException("item not found for itemId " + itemId); } return BeanUtils.transfrom(ItemDTO.class, item); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}", method = RequestMethod.GET) public ItemDTO get(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, @PathVariable("key") String key) { Item item = itemService.findOne(appId, clusterName, namespaceName, key); if (item == null) { throw new NotFoundException( String.format("item not found for %s %s %s %s", appId, clusterName, namespaceName, key)); } return BeanUtils.transfrom(ItemDTO.class, item); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemSetController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.adminservice.aop.PreAcquireNamespaceLock; import com.ctrip.framework.apollo.biz.service.ItemSetService; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class ItemSetController { @Autowired private ItemSetService itemSetService; @PreAcquireNamespaceLock @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset", method = RequestMethod.POST) public ResponseEntity create(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody ItemChangeSets changeSet) { itemSetService.updateSet(appId, clusterName, namespaceName, changeSet); return ResponseEntity.status(HttpStatus.OK).build(); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceBranchController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.message.MessageSender; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.service.NamespaceBranchService; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator; import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class NamespaceBranchController { @Autowired private MessageSender messageSender; @Autowired private NamespaceBranchService namespaceBranchService; @Autowired private NamespaceService namespaceService; @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches", method = RequestMethod.POST) public NamespaceDTO createBranch(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestParam("operator") String operator) { checkNamespace(appId, clusterName, namespaceName); Namespace createdBranch = namespaceBranchService.createBranch(appId, clusterName, namespaceName, operator); return BeanUtils.transfrom(NamespaceDTO.class, createdBranch); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", method = RequestMethod.GET) public GrayReleaseRuleDTO findBranchGrayRules(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName) { checkBranch(appId, clusterName, namespaceName, branchName); GrayReleaseRule rules = namespaceBranchService.findBranchGrayRules(appId, clusterName, namespaceName, branchName); if (rules == null) { return null; } GrayReleaseRuleDTO ruleDTO = new GrayReleaseRuleDTO(rules.getAppId(), rules.getClusterName(), rules.getNamespaceName(), rules.getBranchName()); ruleDTO.setReleaseId(rules.getReleaseId()); ruleDTO.setRuleItems(GrayReleaseRuleItemTransformer.batchTransformFromJSON(rules.getRules())); return ruleDTO; } @Transactional @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", method = RequestMethod.PUT) public void updateBranchGrayRules(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName, @RequestBody GrayReleaseRuleDTO newRuleDto) { checkBranch(appId, clusterName, namespaceName, branchName); GrayReleaseRule newRules = BeanUtils.transfrom(GrayReleaseRule.class, newRuleDto); newRules.setRules(GrayReleaseRuleItemTransformer.batchTransformToJSON(newRuleDto.getRuleItems())); newRules.setBranchStatus(NamespaceBranchStatus.ACTIVE); namespaceBranchService.updateBranchGrayRules(appId, clusterName, namespaceName, branchName, newRules); messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName), Topics.APOLLO_RELEASE_TOPIC); } @Transactional @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}", method = RequestMethod.DELETE) public void deleteBranch(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName, @RequestParam("operator") String operator) { checkBranch(appId, clusterName, namespaceName, branchName); namespaceBranchService .deleteBranch(appId, clusterName, namespaceName, branchName, NamespaceBranchStatus.DELETED, operator); messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName), Topics.APOLLO_RELEASE_TOPIC); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches", method = RequestMethod.GET) public NamespaceDTO loadNamespaceBranch(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName) { checkNamespace(appId, clusterName, namespaceName); Namespace childNamespace = namespaceBranchService.findBranch(appId, clusterName, namespaceName); if (childNamespace == null) { return null; } return BeanUtils.transfrom(NamespaceDTO.class, childNamespace); } private void checkBranch(String appId, String clusterName, String namespaceName, String branchName) { //1. check parent namespace checkNamespace(appId, clusterName, namespaceName); //2. check child namespace Namespace childNamespace = namespaceService.findOne(appId, branchName, namespaceName); if (childNamespace == null) { throw new BadRequestException(String.format("Namespace's branch not exist. AppId = %s, ClusterName = %s, " + "NamespaceName = %s, BranchName = %s", appId, clusterName, namespaceName, branchName)); } } private void checkNamespace(String appId, String clusterName, String namespaceName) { Namespace parentNamespace = namespaceService.findOne(appId, clusterName, namespaceName); if (parentNamespace == null) { throw new BadRequestException(String.format("Namespace not exist. AppId = %s, ClusterName = %s, NamespaceName = %s", appId, clusterName, namespaceName)); } } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.common.utils.InputValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; @RestController public class NamespaceController { @Autowired private NamespaceService namespaceService; @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces", method = RequestMethod.POST) public NamespaceDTO create(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @RequestBody NamespaceDTO dto) { if (!InputValidator.isValidClusterNamespace(dto.getNamespaceName())) { throw new BadRequestException(String.format("Namespace格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); } Namespace entity = BeanUtils.transfrom(Namespace.class, dto); Namespace managedEntity = namespaceService.findOne(appId, clusterName, entity.getNamespaceName()); if (managedEntity != null) { throw new BadRequestException("namespace already exist."); } entity = namespaceService.save(entity); dto = BeanUtils.transfrom(NamespaceDTO.class, entity); return dto; } @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}", method = RequestMethod.DELETE) public void delete(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, @RequestParam String operator) { Namespace entity = namespaceService.findOne(appId, clusterName, namespaceName); if (entity == null) throw new NotFoundException( String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName)); namespaceService.deleteNamespace(entity, operator); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces", method = RequestMethod.GET) public List find(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName) { List groups = namespaceService.findNamespaces(appId, clusterName); return BeanUtils.batchTransform(NamespaceDTO.class, groups); } @RequestMapping(value = "/namespaces/{namespaceId}", method = RequestMethod.GET) public NamespaceDTO get(@PathVariable("namespaceId") Long namespaceId) { Namespace namespace = namespaceService.findOne(namespaceId); if (namespace == null) throw new NotFoundException(String.format("namespace not found for %s", namespaceId)); return BeanUtils.transfrom(NamespaceDTO.class, namespace); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}", method = RequestMethod.GET) public NamespaceDTO get(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace == null) throw new NotFoundException( String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName)); return BeanUtils.transfrom(NamespaceDTO.class, namespace); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace", method = RequestMethod.GET) public NamespaceDTO findPublicNamespaceForAssociatedNamespace(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName) { Namespace namespace = namespaceService.findPublicNamespaceForAssociatedNamespace(clusterName, namespaceName); if (namespace == null) { throw new NotFoundException(String.format("public namespace not found. namespace:%s", namespaceName)); } return BeanUtils.transfrom(NamespaceDTO.class, namespace); } /** * cluster -> cluster has not published namespaces? */ @RequestMapping(value = "/apps/{appId}/namespaces/publish_info", method = RequestMethod.GET) public Map namespacePublishInfo(@PathVariable String appId) { return namespaceService.namespacePublishInfo(appId); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceLockController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.NamespaceLock; import com.ctrip.framework.apollo.biz.service.NamespaceLockService; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class NamespaceLockController { @Autowired private NamespaceLockService namespaceLockService; @Autowired private NamespaceService namespaceService; @Autowired private BizConfig bizConfig; @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock", method = RequestMethod.GET) public NamespaceLockDTO getNamespaceLockOwner(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace == null) { throw new BadRequestException("namespace not exist."); } if (bizConfig.isNamespaceLockSwitchOff()) { return null; } NamespaceLock lock = namespaceLockService.findLock(namespace.getId()); if (lock == null) { return null; } return BeanUtils.transfrom(NamespaceLockDTO.class, lock); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.google.common.base.Splitter; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.message.MessageSender; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.service.NamespaceBranchService; import com.ctrip.framework.apollo.biz.service.NamespaceService; import com.ctrip.framework.apollo.biz.service.ReleaseService; import com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator; import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @RestController public class ReleaseController { private static final Splitter RELEASES_SPLITTER = Splitter.on(",").omitEmptyStrings() .trimResults(); @Autowired private ReleaseService releaseService; @Autowired private NamespaceService namespaceService; @Autowired private MessageSender messageSender; @Autowired private NamespaceBranchService namespaceBranchService; @RequestMapping(value = "/releases/{releaseId}", method = RequestMethod.GET) public ReleaseDTO get(@PathVariable("releaseId") long releaseId) { Release release = releaseService.findOne(releaseId); if (release == null) { throw new NotFoundException(String.format("release not found for %s", releaseId)); } return BeanUtils.transfrom(ReleaseDTO.class, release); } @RequestMapping(value = "/releases", method = RequestMethod.GET) public List findReleaseByIds(@RequestParam("releaseIds") String releaseIds) { Set releaseIdSet = RELEASES_SPLITTER.splitToList(releaseIds).stream().map(Long::parseLong) .collect(Collectors.toSet()); List releases = releaseService.findByReleaseIds(releaseIdSet); return BeanUtils.batchTransform(ReleaseDTO.class, releases); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all", method = RequestMethod.GET) public List findAllReleases(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, Pageable page) { List releases = releaseService.findAllReleases(appId, clusterName, namespaceName, page); return BeanUtils.batchTransform(ReleaseDTO.class, releases); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active", method = RequestMethod.GET) public List findActiveReleases(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, Pageable page) { List releases = releaseService.findActiveReleases(appId, clusterName, namespaceName, page); return BeanUtils.batchTransform(ReleaseDTO.class, releases); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest", method = RequestMethod.GET) public ReleaseDTO getLatest(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName) { Release release = releaseService.findLatestActiveRelease(appId, clusterName, namespaceName); return BeanUtils.transfrom(ReleaseDTO.class, release); } @Transactional @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases", method = RequestMethod.POST) public ReleaseDTO publish(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, @RequestParam("name") String releaseName, @RequestParam(name = "comment", required = false) String releaseComment, @RequestParam("operator") String operator, @RequestParam(name = "isEmergencyPublish", defaultValue = "false") boolean isEmergencyPublish) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace == null) { throw new NotFoundException(String.format("Could not find namespace for %s %s %s", appId, clusterName, namespaceName)); } Release release = releaseService.publish(namespace, releaseName, releaseComment, operator, isEmergencyPublish); //send release message Namespace parentNamespace = namespaceService.findParentNamespace(namespace); String messageCluster; if (parentNamespace != null) { messageCluster = parentNamespace.getClusterName(); } else { messageCluster = clusterName; } messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, messageCluster, namespaceName), Topics.APOLLO_RELEASE_TOPIC); return BeanUtils.transfrom(ReleaseDTO.class, release); } /** * merge branch items to master and publish master * * @return published result */ @Transactional @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish", method = RequestMethod.POST) public ReleaseDTO updateAndPublish(@PathVariable("appId") String appId, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, @RequestParam("releaseName") String releaseName, @RequestParam("branchName") String branchName, @RequestParam(value = "deleteBranch", defaultValue = "true") boolean deleteBranch, @RequestParam(name = "releaseComment", required = false) String releaseComment, @RequestParam(name = "isEmergencyPublish", defaultValue = "false") boolean isEmergencyPublish, @RequestBody ItemChangeSets changeSets) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace == null) { throw new NotFoundException(String.format("Could not find namespace for %s %s %s", appId, clusterName, namespaceName)); } Release release = releaseService.mergeBranchChangeSetsAndRelease(namespace, branchName, releaseName, releaseComment, isEmergencyPublish, changeSets); if (deleteBranch) { namespaceBranchService.deleteBranch(appId, clusterName, namespaceName, branchName, NamespaceBranchStatus.MERGED, changeSets.getDataChangeLastModifiedBy()); } messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName), Topics.APOLLO_RELEASE_TOPIC); return BeanUtils.transfrom(ReleaseDTO.class, release); } @Transactional @RequestMapping(path = "/releases/{releaseId}/rollback", method = RequestMethod.PUT) public void rollback(@PathVariable("releaseId") long releaseId, @RequestParam("operator") String operator) { Release release = releaseService.rollback(releaseId, operator); String appId = release.getAppId(); String clusterName = release.getClusterName(); String namespaceName = release.getNamespaceName(); //send release message messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName), Topics.APOLLO_RELEASE_TOPIC); } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ReleaseHistoryController.java ================================================ package com.ctrip.framework.apollo.adminservice.controller; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.ctrip.framework.apollo.biz.entity.ReleaseHistory; import com.ctrip.framework.apollo.biz.service.ReleaseHistoryService; import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.common.dto.ReleaseHistoryDTO; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * @author Jason Song(song_s@ctrip.com) */ @RestController public class ReleaseHistoryController { private Gson gson = new Gson(); private Type configurationTypeReference = new TypeToken>() { }.getType(); @Autowired private ReleaseHistoryService releaseHistoryService; @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories", method = RequestMethod.GET) public PageDTO findReleaseHistoriesByNamespace( @PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespaceName, Pageable pageable) { Page result = releaseHistoryService.findReleaseHistoriesByNamespace(appId, clusterName, namespaceName, pageable); return transform2PageDTO(result, pageable); } @RequestMapping(value = "/releases/histories/by_release_id_and_operation", method = RequestMethod.GET) public PageDTO findReleaseHistoryByReleaseIdAndOperation( @RequestParam("releaseId") long releaseId, @RequestParam("operation") int operation, Pageable pageable) { Page result = releaseHistoryService.findByReleaseIdAndOperation(releaseId, operation, pageable); return transform2PageDTO(result, pageable); } @RequestMapping(value = "/releases/histories/by_previous_release_id_and_operation", method = RequestMethod.GET) public PageDTO findReleaseHistoryByPreviousReleaseIdAndOperation( @RequestParam("previousReleaseId") long previousReleaseId, @RequestParam("operation") int operation, Pageable pageable) { Page result = releaseHistoryService.findByPreviousReleaseIdAndOperation(previousReleaseId, operation, pageable); return transform2PageDTO(result, pageable); } private PageDTO transform2PageDTO(Page releaseHistoriesPage, Pageable pageable){ if (!releaseHistoriesPage.hasContent()) { return null; } List releaseHistories = releaseHistoriesPage.getContent(); List releaseHistoryDTOs = new ArrayList<>(releaseHistories.size()); for (ReleaseHistory releaseHistory : releaseHistories) { releaseHistoryDTOs.add(transformReleaseHistory2DTO(releaseHistory)); } return new PageDTO<>(releaseHistoryDTOs, pageable, releaseHistoriesPage.getTotalElements()); } private ReleaseHistoryDTO transformReleaseHistory2DTO(ReleaseHistory releaseHistory) { ReleaseHistoryDTO dto = new ReleaseHistoryDTO(); BeanUtils.copyProperties(releaseHistory, dto, "operationContext"); dto.setOperationContext(gson.fromJson(releaseHistory.getOperationContext(), configurationTypeReference)); return dto; } } ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/resources/META-INF/app.properties ================================================ app.id=100003172 jdkVersion=1.8 ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/resources/adminservice.properties ================================================ #Used for apollo-assembly spring.application.name= apollo-adminservice ctrip.appid= 100003172 server.port= 8090 #logging.file= /opt/logs/100003172/apollo-adminservice.log apollo_profile=github spring.datasource.url=jdbc:mysql://47.94.252.160:3306/ApolloConfigDB?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false spring.datasource.username=root spring.datasource.password=root #spring.jpa.properties.hibernate.show_sql=true spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/resources/application.yml ================================================ spring: application: name: apollo-adminservice profiles: active: ${apollo_profile} ctrip: appid: 100003172 server: port: 8090 logging: level: com.ctrip: INFO ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/resources/bootstrap.yml ================================================ eureka: instance: hostname: ${spring.cloud.client.ipAddress} preferIpAddress: true client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:8080/eureka/ healthcheck: enabled: true eurekaServiceUrlPollIntervalSeconds: 60 endpoints: health: sensitive: false management: security: enabled: false health: status: order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/resources/logback.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/scripts/shutdown.sh ================================================ #!/bin/bash SERVICE_NAME=apollo-adminservice if [[ -z "$JAVA_HOME" && -d /usr/java/latest/ ]]; then export JAVA_HOME=/usr/java/latest/ fi cd `dirname $0`/.. if [[ ! -f $SERVICE_NAME".jar" && -d current ]]; then cd current fi if [[ -f $SERVICE_NAME".jar" ]]; then chmod a+x $SERVICE_NAME".jar" ./$SERVICE_NAME".jar" stop fi ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/main/scripts/startup.sh ================================================ #!/bin/bash SERVICE_NAME=apollo-adminservice ## Adjust log dir if necessary LOG_DIR=/opt/logs/100003172 ## Adjust server port if necessary SERVER_PORT=8090 ## Adjust memory settings if necessary #export JAVA_OPTS="-Xms2560m -Xmx2560m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=1536m -XX:MaxNewSize=1536m -XX:SurvivorRatio=8" ## Only uncomment the following when you are using server jvm #export JAVA_OPTS="$JAVA_OPTS -server -XX:-ReduceInitialCardMarks" ########### The following is the same for configservice, adminservice, portal ########### export JAVA_OPTS="$JAVA_OPTS -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom" export JAVA_OPTS="$JAVA_OPTS -Dserver.port=$SERVER_PORT -Dlogging.file=$LOG_DIR/$SERVICE_NAME.log -Xloggc:$LOG_DIR/heap_trace.txt -XX:HeapDumpPath=$LOG_DIR/HeapDumpOnOutOfMemoryError/" PATH_TO_JAR=$SERVICE_NAME".jar" SERVER_URL="http://localhost:$SERVER_PORT" function checkPidAlive { for i in `ls -t $SERVICE_NAME*.pid 2>/dev/null` do read pid < $i result=$(ps -p "$pid") if [ "$?" -eq 0 ]; then return 0 else printf "\npid - $pid just quit unexpectedly, please check logs under $LOG_DIR and /tmp for more information!\n" exit 1; fi done printf "\nNo pid file found, startup may failed. Please check logs under $LOG_DIR and /tmp for more information!\n" exit 1; } if [ "$(uname)" == "Darwin" ]; then windows="0" elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then windows="0" elif [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then windows="1" else windows="0" fi # for Windows if [ "$windows" == "1" ] && [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then tmp_java_home=`cygpath -sw "$JAVA_HOME"` export JAVA_HOME=`cygpath -u $tmp_java_home` echo "Windows new JAVA_HOME is: $JAVA_HOME" fi cd `dirname $0`/.. for i in `ls $SERVICE_NAME-*.jar 2>/dev/null` do if [[ ! $i == *"-sources.jar" ]] then PATH_TO_JAR=$i break fi done if [[ ! -f PATH_TO_JAR && -d current ]]; then cd current for i in `ls $SERVICE_NAME-*.jar 2>/dev/null` do if [[ ! $i == *"-sources.jar" ]] then PATH_TO_JAR=$i break fi done fi if [[ -f $SERVICE_NAME".jar" ]]; then rm -rf $SERVICE_NAME".jar" fi printf "$(date) ==== Starting ==== \n" ln $PATH_TO_JAR $SERVICE_NAME".jar" chmod a+x $SERVICE_NAME".jar" ./$SERVICE_NAME".jar" start rc=$?; if [[ $rc != 0 ]]; then echo "$(date) Failed to start $SERVICE_NAME.jar, return code: $rc" exit $rc; fi declare -i counter=0 declare -i max_counter=48 # 48*5=240s declare -i total_time=0 printf "Waiting for server startup" until [[ (( counter -ge max_counter )) || "$(curl -X GET --silent --connect-timeout 1 --max-time 2 --head $SERVER_URL | grep "Coyote")" != "" ]]; do printf "." counter+=1 sleep 5 checkPidAlive done total_time=counter*5 if [[ (( counter -ge max_counter )) ]]; then printf "\n$(date) Server failed to start in $total_time seconds!\n" exit 1; fi printf "\n$(date) Server started in $total_time seconds!\n" exit 0; ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/application.properties ================================================ spring.datasource.url = jdbc:h2:mem:~/apolloconfigdb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy spring.jpa.properties.hibernate.show_sql=true spring.h2.console.enabled = true spring.h2.console.settings.web-allow-others=true ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/application.yml ================================================ spring: application: name: apollo-adminservice server: port: ${port:8090} logging: level: org.springframework.cloud: 'DEBUG' file: /opt/logs/${ctrip.appid}/apollo-adminservice.log ctrip: appid: 100003172 ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/bootstrap.yml ================================================ eureka: instance: hostname: ${hostname:localhost} client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:8090/eureka/ healthcheck: enabled: true endpoints: health: sensitive: false management: security: enabled: false health: status: order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/controller/cleanup.sql ================================================ DELETE FROM Item; DELETE FROM Namespace; DELETE FROM AppNamespace; DELETE FROM Cluster; DELETE FROM App; DELETE FROM NamespaceLock; DELETE FROM ServerConfig; ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/controller/test-itemset.sql ================================================ INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('someAppId','someAppName','someOwnerName','someOwnerName@ctrip.com'); INSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'default'); INSERT INTO AppNamespace (AppId, Name) VALUES ('someAppId', 'application'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'application'); ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/controller/test-release.sql ================================================ INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('someAppId','someAppName','someOwnerName','someOwnerName@ctrip.com'); INSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'default'); INSERT INTO AppNamespace (AppId, Name) VALUES ('someAppId', 'application'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (100, 'someAppId', 'default', 'application'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (100, 'k1', 'v1', 'comment1'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (100, 'k2', 'v2', 'comment1'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (100, 'k3', 'v3', 'comment1'); ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/data.sql ================================================ INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003171','apollo-config-service','刘一鸣','liuym@ctrip.com'); INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003172','apollo-admin-service','宋顺','song_s@ctrip.com'); INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003173','apollo-portal','张乐','zhanglea@ctrip.com'); INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('fxhermesproducer','fx-hermes-producer','梁锦华','jhliang@ctrip.com'); INSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'cluster1'); INSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'cluster2'); INSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'cluster3'); INSERT INTO Cluster (AppId, Name) VALUES ('fxhermesproducer', 'default'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'application'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'fx.apollo.config'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'application'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'fx.apollo.admin'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'application'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'fx.apollo.portal'); INSERT INTO AppNamespace (AppID, Name) VALUES ('fxhermesproducer', 'fx.hermes.producer'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (1, '100003171', 'default', 'application'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (5, '100003171', 'cluster1', 'application'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (2, 'fxhermesproducer', 'default', 'fx.hermes.producer'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (3, '100003172', 'default', 'application'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (4, '100003173', 'default', 'application'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k1', 'v1', 'comment1'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k2', 'v2', 'comment2'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (2, 'k3', 'v3', 'comment3'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment, LineNum) VALUES (5, 'k1', 'v4', 'comment4',1); INSERT INTO RELEASE (ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES ('TEST-RELEASE-KEY', 'REV1','First Release','100003171', 'default', 'application', '{"k1":"v1"}'); ================================================ FILE: open-config-center/apollo/apollo-adminservice/src/test/resources/logback-test.xml ================================================ utf-8 [%p] %c - %m%n ================================================ FILE: open-config-center/apollo/apollo-biz/pom.xml ================================================ com.ctrip.framework.apollo apollo 0.10.0-SNAPSHOT 4.0.0 apollo-biz Apollo Biz jar ${project.artifactId} com.ctrip.framework.apollo apollo-common org.springframework.cloud spring-cloud-starter-eureka com.h2database h2 test ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/ApolloBizConfig.java ================================================ package com.ctrip.framework.apollo.biz; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @EnableAutoConfiguration @Configuration @ComponentScan(basePackageClasses = ApolloBizConfig.class) public class ApolloBizConfig { } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/auth/WebSecurityConfig.java ================================================ package com.ctrip.framework.apollo.biz.auth; import com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @ConditionalOnMissingProfile("auth") @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic(); http.csrf().disable(); http.headers().frameOptions().sameOrigin(); } /** * Although the authentication below is useless, we may not remove them for backward compatibility. * Because if we remove them and the old clients(before 0.9.0) still send the authentication * information, the server will return 401, which should cause big problems. * * We may remove the following once we remove spring security from Apollo. */ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("").roles("USER").and() .withUser("apollo").password("").roles("USER", "ADMIN"); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/config/BizConfig.java ================================================ package com.ctrip.framework.apollo.biz.config; import com.google.common.base.Strings; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.ctrip.framework.apollo.biz.service.BizDBPropertySource; import com.ctrip.framework.apollo.common.config.RefreshableConfig; import com.ctrip.framework.apollo.common.config.RefreshablePropertySource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.lang.reflect.Type; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @Component public class BizConfig extends RefreshableConfig { private static final int DEFAULT_ITEM_KEY_LENGTH = 128; private static final int DEFAULT_ITEM_VALUE_LENGTH = 20000; private static final int DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL = 60; //60s private static final int DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL = 60; //60s private static final int DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL = 1; //1s private static final int DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL = 1; //1s private static final int DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS = 1000; //1000ms private static final int DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH = 100; private static final int DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI = 100;//100ms private Gson gson = new Gson(); private static final Type namespaceValueLengthOverrideTypeReference = new TypeToken>() { }.getType(); @Autowired private BizDBPropertySource propertySource; @Override protected List getRefreshablePropertySources() { return Collections.singletonList(propertySource); } public List eurekaServiceUrls() { String configuration = getValue("eureka.service.url", ""); if (Strings.isNullOrEmpty(configuration)) { return Collections.emptyList(); } return splitter.splitToList(configuration); } public int grayReleaseRuleScanInterval() { int interval = getIntProperty("apollo.gray-release-rule-scan.interval", DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL); return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_GRAY_RELEASE_RULE_SCAN_INTERVAL); } public int itemKeyLengthLimit() { int limit = getIntProperty("item.key.length.limit", DEFAULT_ITEM_KEY_LENGTH); return checkInt(limit, 5, Integer.MAX_VALUE, DEFAULT_ITEM_KEY_LENGTH); } public int itemValueLengthLimit() { int limit = getIntProperty("item.value.length.limit", DEFAULT_ITEM_VALUE_LENGTH); return checkInt(limit, 5, Integer.MAX_VALUE, DEFAULT_ITEM_VALUE_LENGTH); } public Map namespaceValueLengthLimitOverride() { String namespaceValueLengthOverrideString = getValue("namespace.value.length.limit.override"); Map namespaceValueLengthOverride = Maps.newHashMap(); if (!Strings.isNullOrEmpty(namespaceValueLengthOverrideString)) { namespaceValueLengthOverride = gson.fromJson(namespaceValueLengthOverrideString, namespaceValueLengthOverrideTypeReference); } return namespaceValueLengthOverride; } public boolean isNamespaceLockSwitchOff() { return !getBooleanProperty("namespace.lock.switch", false); } /** * ctrip config **/ public String cloggingUrl() { return getValue("clogging.server.url"); } public String cloggingPort() { return getValue("clogging.server.port"); } public int appNamespaceCacheScanInterval() { int interval = getIntProperty("apollo.app-namespace-cache-scan.interval", DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL); return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_APPNAMESPACE_CACHE_SCAN_INTERVAL); } public TimeUnit appNamespaceCacheScanIntervalTimeUnit() { return TimeUnit.SECONDS; } public int appNamespaceCacheRebuildInterval() { int interval = getIntProperty("apollo.app-namespace-cache-rebuild.interval", DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL); return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_APPNAMESPACE_CACHE_REBUILD_INTERVAL); } public TimeUnit appNamespaceCacheRebuildIntervalTimeUnit() { return TimeUnit.SECONDS; } public int releaseMessageCacheScanInterval() { int interval = getIntProperty("apollo.release-message-cache-scan.interval", DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL); return checkInt(interval, 1, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_CACHE_SCAN_INTERVAL); } public TimeUnit releaseMessageCacheScanIntervalTimeUnit() { return TimeUnit.SECONDS; } public int releaseMessageScanIntervalInMilli() { int interval = getIntProperty("apollo.message-scan.interval", DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS); return checkInt(interval, 100, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_SCAN_INTERVAL_IN_MS); } public int releaseMessageNotificationBatch() { int batch = getIntProperty("apollo.release-message.notification.batch", DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH); return checkInt(batch, 1, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH); } public int releaseMessageNotificationBatchIntervalInMilli() { int interval = getIntProperty("apollo.release-message.notification.batch.interval", DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI); return checkInt(interval, 10, Integer.MAX_VALUE, DEFAULT_RELEASE_MESSAGE_NOTIFICATION_BATCH_INTERVAL_IN_MILLI); } public boolean isConfigServiceCacheEnabled() { return getBooleanProperty("config-service.cache.enabled", false); } int checkInt(int value, int min, int max, int defaultValue) { if (value >= min && value <= max) { return value; } return defaultValue; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/customize/BizLoggingCustomizer.java ================================================ package com.ctrip.framework.apollo.biz.customize; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.common.customize.LoggingCustomizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @Component @Profile("ctrip") public class BizLoggingCustomizer extends LoggingCustomizer{ @Autowired private BizConfig bizConfig; @Override protected String cloggingUrl() { return bizConfig.cloggingUrl(); } @Override protected String cloggingPort() { return bizConfig.cloggingPort(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/customize/package-info.java ================================================ /** * 携程内部的日志系统,第三方公司可删除 */ package com.ctrip.framework.apollo.biz.customize; ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Audit.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "Audit") @SQLDelete(sql = "Update Audit set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Audit extends BaseEntity { public enum OP { INSERT, UPDATE, DELETE } @Column(name = "EntityName", nullable = false) private String entityName; @Column(name = "EntityId") private Long entityId; @Column(name = "OpName", nullable = false) private String opName; @Column(name = "Comment") private String comment; public String getComment() { return comment; } public Long getEntityId() { return entityId; } public String getEntityName() { return entityName; } public String getOpName() { return opName; } public void setComment(String comment) { this.comment = comment; } public void setEntityId(Long entityId) { this.entityId = entityId; } public void setEntityName(String entityName) { this.entityName = entityName; } public void setOpName(String opName) { this.opName = opName; } public String toString() { return toStringHelper().add("entityName", entityName).add("entityId", entityId) .add("opName", opName).add("comment", comment).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Cluster.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "Cluster") @SQLDelete(sql = "Update Cluster set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Cluster extends BaseEntity implements Comparable { @Column(name = "Name", nullable = false) private String name; @Column(name = "AppId", nullable = false) private String appId; @Column(name = "ParentClusterId", nullable = false) private long parentClusterId; public String getAppId() { return appId; } public String getName() { return name; } public void setAppId(String appId) { this.appId = appId; } public void setName(String name) { this.name = name; } public long getParentClusterId() { return parentClusterId; } public void setParentClusterId(long parentClusterId) { this.parentClusterId = parentClusterId; } public String toString() { return toStringHelper().add("name", name).add("appId", appId) .add("parentClusterId", parentClusterId).toString(); } @Override public int compareTo(Cluster o) { if (o == null || getId() > o.getId()) { return 1; } if (getId() == o.getId()) { return 0; } return -1; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Commit.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Lob; import javax.persistence.Table; @Entity @Table(name = "Commit") @SQLDelete(sql = "Update Commit set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Commit extends BaseEntity { @Lob @Column(name = "ChangeSets", nullable = false) private String changeSets; @Column(name = "AppId", nullable = false) private String appId; @Column(name = "ClusterName", nullable = false) private String clusterName; @Column(name = "NamespaceName", nullable = false) private String namespaceName; @Column(name = "Comment") private String comment; public String getChangeSets() { return changeSets; } public void setChangeSets(String changeSets) { this.changeSets = changeSets; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } @Override public String toString() { return toStringHelper().add("changeSets", changeSets).add("appId", appId).add("clusterName", clusterName) .add("namespaceName", namespaceName).add("comment", comment).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/GrayReleaseRule.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "GrayReleaseRule") @SQLDelete(sql = "Update GrayReleaseRule set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class GrayReleaseRule extends BaseEntity{ @Column(name = "appId", nullable = false) private String appId; @Column(name = "ClusterName", nullable = false) private String clusterName; @Column(name = "NamespaceName", nullable = false) private String namespaceName; @Column(name = "BranchName", nullable = false) private String branchName; @Column(name = "Rules") private String rules; @Column(name = "releaseId", nullable = false) private Long releaseId; @Column(name = "BranchStatus", nullable = false) private int branchStatus; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getBranchName() { return branchName; } public void setBranchName(String branchName) { this.branchName = branchName; } public String getRules() { return rules; } public void setRules(String rules) { this.rules = rules; } public Long getReleaseId() { return releaseId; } public void setReleaseId(Long releaseId) { this.releaseId = releaseId; } public int getBranchStatus() { return branchStatus; } public void setBranchStatus(int branchStatus) { this.branchStatus = branchStatus; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Instance.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.google.common.base.MoreObjects; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.PrePersist; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "Instance") public class Instance { @Id @GeneratedValue @Column(name = "Id") private long id; @Column(name = "AppId", nullable = false) private String appId; @Column(name = "ClusterName", nullable = false) private String clusterName; @Column(name = "DataCenter", nullable = false) private String dataCenter; @Column(name = "Ip", nullable = false) private String ip; @Column(name = "DataChange_CreatedTime", nullable = false) private Date dataChangeCreatedTime; @Column(name = "DataChange_LastTime") private Date dataChangeLastModifiedTime; @PrePersist protected void prePersist() { if (this.dataChangeCreatedTime == null) { dataChangeCreatedTime = new Date(); } if (this.dataChangeLastModifiedTime == null) { dataChangeLastModifiedTime = dataChangeCreatedTime; } } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getDataCenter() { return dataCenter; } public void setDataCenter(String dataCenter) { this.dataCenter = dataCenter; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Date getDataChangeCreatedTime() { return dataChangeCreatedTime; } public void setDataChangeCreatedTime(Date dataChangeCreatedTime) { this.dataChangeCreatedTime = dataChangeCreatedTime; } public Date getDataChangeLastModifiedTime() { return dataChangeLastModifiedTime; } public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) { this.dataChangeLastModifiedTime = dataChangeLastModifiedTime; } @Override public String toString() { return MoreObjects.toStringHelper(this) .omitNullValues() .add("id", id) .add("appId", appId) .add("clusterName", clusterName) .add("dataCenter", dataCenter) .add("ip", ip) .add("dataChangeCreatedTime", dataChangeCreatedTime) .add("dataChangeLastModifiedTime", dataChangeLastModifiedTime) .toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/InstanceConfig.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.google.common.base.MoreObjects; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "InstanceConfig") public class InstanceConfig { @Id @GeneratedValue @Column(name = "Id") private long id; @Column(name = "InstanceId") private long instanceId; @Column(name = "ConfigAppId", nullable = false) private String configAppId; @Column(name = "ConfigClusterName", nullable = false) private String configClusterName; @Column(name = "ConfigNamespaceName", nullable = false) private String configNamespaceName; @Column(name = "ReleaseKey", nullable = false) private String releaseKey; @Column(name = "ReleaseDeliveryTime", nullable = false) private Date releaseDeliveryTime; @Column(name = "DataChange_CreatedTime", nullable = false) private Date dataChangeCreatedTime; @Column(name = "DataChange_LastTime") private Date dataChangeLastModifiedTime; @PrePersist protected void prePersist() { if (this.dataChangeCreatedTime == null) { dataChangeCreatedTime = new Date(); } if (this.dataChangeLastModifiedTime == null) { dataChangeLastModifiedTime = dataChangeCreatedTime; } } @PreUpdate protected void preUpdate() { this.dataChangeLastModifiedTime = new Date(); } public long getId() { return id; } public void setId(long id) { this.id = id; } public long getInstanceId() { return instanceId; } public void setInstanceId(long instanceId) { this.instanceId = instanceId; } public String getConfigAppId() { return configAppId; } public void setConfigAppId(String configAppId) { this.configAppId = configAppId; } public String getConfigNamespaceName() { return configNamespaceName; } public void setConfigNamespaceName(String configNamespaceName) { this.configNamespaceName = configNamespaceName; } public String getReleaseKey() { return releaseKey; } public void setReleaseKey(String releaseKey) { this.releaseKey = releaseKey; } public Date getDataChangeCreatedTime() { return dataChangeCreatedTime; } public void setDataChangeCreatedTime(Date dataChangeCreatedTime) { this.dataChangeCreatedTime = dataChangeCreatedTime; } public Date getDataChangeLastModifiedTime() { return dataChangeLastModifiedTime; } public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) { this.dataChangeLastModifiedTime = dataChangeLastModifiedTime; } public String getConfigClusterName() { return configClusterName; } public void setConfigClusterName(String configClusterName) { this.configClusterName = configClusterName; } public Date getReleaseDeliveryTime() { return releaseDeliveryTime; } public void setReleaseDeliveryTime(Date releaseDeliveryTime) { this.releaseDeliveryTime = releaseDeliveryTime; } @Override public String toString() { return MoreObjects.toStringHelper(this) .omitNullValues() .add("id", id) .add("configAppId", configAppId) .add("configClusterName", configClusterName) .add("configNamespaceName", configNamespaceName) .add("releaseKey", releaseKey) .add("dataChangeCreatedTime", dataChangeCreatedTime) .add("dataChangeLastModifiedTime", dataChangeLastModifiedTime) .toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Item.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Lob; import javax.persistence.Table; @Entity @Table(name = "Item") @SQLDelete(sql = "Update Item set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Item extends BaseEntity { @Column(name = "NamespaceId", nullable = false) private long namespaceId; @Column(name = "key", nullable = false) private String key; @Column(name = "value") @Lob private String value; @Column(name = "comment") private String comment; @Column(name = "LineNum") private Integer lineNum; public String getComment() { return comment; } public String getKey() { return key; } public long getNamespaceId() { return namespaceId; } public String getValue() { return value; } public void setComment(String comment) { this.comment = comment; } public void setKey(String key) { this.key = key; } public void setNamespaceId(long namespaceId) { this.namespaceId = namespaceId; } public void setValue(String value) { this.value = value; } public Integer getLineNum() { return lineNum; } public void setLineNum(Integer lineNum) { this.lineNum = lineNum; } public String toString() { return toStringHelper().add("namespaceId", namespaceId).add("key", key).add("value", value) .add("lineNum", lineNum).add("comment", comment).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Namespace.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "Namespace") @SQLDelete(sql = "Update Namespace set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Namespace extends BaseEntity { @Column(name = "appId", nullable = false) private String appId; @Column(name = "ClusterName", nullable = false) private String clusterName; @Column(name = "NamespaceName", nullable = false) private String namespaceName; public Namespace(){ } public Namespace(String appId, String clusterName, String namespaceName) { this.appId = appId; this.clusterName = clusterName; this.namespaceName = namespaceName; } public String getAppId() { return appId; } public String getClusterName() { return clusterName; } public String getNamespaceName() { return namespaceName; } public void setAppId(String appId) { this.appId = appId; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String toString() { return toStringHelper().add("appId", appId).add("clusterName", clusterName) .add("namespaceName", namespaceName).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/NamespaceLock.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "NamespaceLock") @Where(clause = "isDeleted = 0") public class NamespaceLock extends BaseEntity{ @Column(name = "NamespaceId") private long namespaceId; public long getNamespaceId() { return namespaceId; } public void setNamespaceId(long namespaceId) { this.namespaceId = namespaceId; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Privilege.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "Privilege") @SQLDelete(sql = "Update Privilege set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Privilege extends BaseEntity { @Column(name = "Name", nullable = false) private String name; @Column(name = "PrivilType", nullable = false) private String privilType; @Column(name = "NamespaceId") private long namespaceId; public String getName() { return name; } public long getNamespaceId() { return namespaceId; } public String getPrivilType() { return privilType; } public void setName(String name) { this.name = name; } public void setNamespaceId(long namespaceId) { this.namespaceId = namespaceId; } public void setPrivilType(String privilType) { this.privilType = privilType; } public String toString() { return toStringHelper().add("namespaceId", namespaceId).add("privilType", privilType) .add("name", name).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Release.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Lob; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "Release") @SQLDelete(sql = "Update Release set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Release extends BaseEntity { @Column(name = "ReleaseKey", nullable = false) private String releaseKey; @Column(name = "Name", nullable = false) private String name; @Column(name = "AppId", nullable = false) private String appId; @Column(name = "ClusterName", nullable = false) private String clusterName; @Column(name = "NamespaceName", nullable = false) private String namespaceName; @Column(name = "Configurations", nullable = false) @Lob private String configurations; @Column(name = "Comment", nullable = false) private String comment; @Column(name = "IsAbandoned", columnDefinition = "Bit default '0'") private boolean isAbandoned; public String getReleaseKey() { return releaseKey; } public String getAppId() { return appId; } public String getClusterName() { return clusterName; } public String getComment() { return comment; } public String getConfigurations() { return configurations; } public String getNamespaceName() { return namespaceName; } public String getName() { return name; } public void setReleaseKey(String releaseKey) { this.releaseKey = releaseKey; } public void setAppId(String appId) { this.appId = appId; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public void setComment(String comment) { this.comment = comment; } public void setConfigurations(String configurations) { this.configurations = configurations; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public void setName(String name) { this.name = name; } public boolean isAbandoned() { return isAbandoned; } public void setAbandoned(boolean abandoned) { isAbandoned = abandoned; } public String toString() { return toStringHelper().add("name", name).add("appId", appId).add("clusterName", clusterName) .add("namespaceName", namespaceName).add("configurations", configurations) .add("comment", comment).add("isAbandoned", isAbandoned).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/ReleaseHistory.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "ReleaseHistory") @SQLDelete(sql = "Update ReleaseHistory set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class ReleaseHistory extends BaseEntity { @Column(name = "AppId", nullable = false) private String appId; @Column(name = "ClusterName", nullable = false) private String clusterName; @Column(name = "NamespaceName", nullable = false) private String namespaceName; @Column(name = "BranchName", nullable = false) private String branchName; @Column(name = "ReleaseId") private long releaseId; @Column(name = "PreviousReleaseId") private long previousReleaseId; @Column(name = "Operation") private int operation; @Column(name = "OperationContext", nullable = false) private String operationContext; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getBranchName() { return branchName; } public void setBranchName(String branchName) { this.branchName = branchName; } public long getReleaseId() { return releaseId; } public void setReleaseId(long releaseId) { this.releaseId = releaseId; } public long getPreviousReleaseId() { return previousReleaseId; } public void setPreviousReleaseId(long previousReleaseId) { this.previousReleaseId = previousReleaseId; } public int getOperation() { return operation; } public void setOperation(int operation) { this.operation = operation; } public String getOperationContext() { return operationContext; } public void setOperationContext(String operationContext) { this.operationContext = operationContext; } public String toString() { return toStringHelper().add("appId", appId).add("clusterName", clusterName) .add("namespaceName", namespaceName).add("branchName", branchName) .add("releaseId", releaseId).add("previousReleaseId", previousReleaseId) .add("operation", operation).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/ReleaseMessage.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.google.common.base.MoreObjects; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.PrePersist; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "ReleaseMessage") public class ReleaseMessage { @Id @GeneratedValue @Column(name = "Id") private long id; @Column(name = "Message", nullable = false) private String message; @Column(name = "DataChange_LastTime") private Date dataChangeLastModifiedTime; @PrePersist protected void prePersist() { if (this.dataChangeLastModifiedTime == null) { dataChangeLastModifiedTime = new Date(); } } public ReleaseMessage() { } public ReleaseMessage(String message) { this.message = message; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return MoreObjects.toStringHelper(this) .omitNullValues() .add("id", id) .add("message", message) .add("dataChangeLastModifiedTime", dataChangeLastModifiedTime) .toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/ServerConfig.java ================================================ package com.ctrip.framework.apollo.biz.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "ServerConfig") @SQLDelete(sql = "Update ServerConfig set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class ServerConfig extends BaseEntity { @Column(name = "Key", nullable = false) private String key; @Column(name = "Cluster", nullable = false) private String cluster; @Column(name = "Value", nullable = false) private String value; @Column(name = "Comment", nullable = false) private String comment; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public String getCluster() { return cluster; } public void setCluster(String cluster) { this.cluster = cluster; } public String toString() { return toStringHelper().add("key", key).add("value", value).add("comment", comment).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/eureka/ApolloEurekaClientConfig.java ================================================ package com.ctrip.framework.apollo.biz.eureka; import com.ctrip.framework.apollo.biz.config.BizConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; @Component @Primary public class ApolloEurekaClientConfig extends EurekaClientConfigBean { @Autowired private BizConfig bizConfig; /** * Assert only one zone: defaultZone, but multiple environments. */ public List getEurekaServerServiceUrls(String myZone) { List urls = bizConfig.eurekaServiceUrls(); return CollectionUtils.isEmpty(urls) ? super.getEurekaServerServiceUrls(myZone) : urls; } @Override public boolean equals(Object o) { return super.equals(o); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/grayReleaseRule/GrayReleaseRuleCache.java ================================================ package com.ctrip.framework.apollo.biz.grayReleaseRule; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ public class GrayReleaseRuleCache { private long ruleId; private String branchName; private String namespaceName; private long releaseId; private long loadVersion; private int branchStatus; private Set ruleItems; public GrayReleaseRuleCache(long ruleId, String branchName, String namespaceName, long releaseId, int branchStatus, long loadVersion, Set ruleItems) { this.ruleId = ruleId; this.branchName = branchName; this.namespaceName = namespaceName; this.releaseId = releaseId; this.branchStatus = branchStatus; this.loadVersion = loadVersion; this.ruleItems = ruleItems; } public long getRuleId() { return ruleId; } public Set getRuleItems() { return ruleItems; } public String getBranchName() { return branchName; } public int getBranchStatus() { return branchStatus; } public long getReleaseId() { return releaseId; } public long getLoadVersion() { return loadVersion; } public void setLoadVersion(long loadVersion) { this.loadVersion = loadVersion; } public String getNamespaceName() { return namespaceName; } public boolean matches(String clientAppId, String clientIp) { for (GrayReleaseRuleItemDTO ruleItem : ruleItems) { if (ruleItem.matches(clientAppId, clientIp)) { return true; } } return false; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/grayReleaseRule/GrayReleaseRulesHolder.java ================================================ package com.ctrip.framework.apollo.biz.grayReleaseRule; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.message.ReleaseMessageListener; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.repository.GrayReleaseRuleRepository; import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO; import com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; /** * @author Jason Song(song_s@ctrip.com) */ public class GrayReleaseRulesHolder implements ReleaseMessageListener, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(GrayReleaseRulesHolder.class); private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); private static final Splitter STRING_SPLITTER = Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings(); @Autowired private GrayReleaseRuleRepository grayReleaseRuleRepository; @Autowired private BizConfig bizConfig; private int databaseScanInterval; private ScheduledExecutorService executorService; //store configAppId+configCluster+configNamespace -> GrayReleaseRuleCache map private Multimap grayReleaseRuleCache; //store clientAppId+clientNamespace+ip -> ruleId map private Multimap reversedGrayReleaseRuleCache; //an auto increment version to indicate the age of rules private AtomicLong loadVersion; public GrayReleaseRulesHolder() { loadVersion = new AtomicLong(); grayReleaseRuleCache = Multimaps.synchronizedSetMultimap(HashMultimap.create()); reversedGrayReleaseRuleCache = Multimaps.synchronizedSetMultimap(HashMultimap.create()); executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory .create("GrayReleaseRulesHolder", true)); } @Override public void afterPropertiesSet() throws Exception { populateDataBaseInterval(); //force sync load for the first time periodicScanRules(); executorService.scheduleWithFixedDelay(this::periodicScanRules, getDatabaseScanIntervalSecond(), getDatabaseScanIntervalSecond(), getDatabaseScanTimeUnit() ); } @Override public void handleMessage(ReleaseMessage message, String channel) { logger.info("message received - channel: {}, message: {}", channel, message); String releaseMessage = message.getMessage(); if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(releaseMessage)) { return; } List keys = STRING_SPLITTER.splitToList(releaseMessage); //message should be appId+cluster+namespace if (keys.size() != 3) { logger.error("message format invalid - {}", releaseMessage); return; } String appId = keys.get(0); String cluster = keys.get(1); String namespace = keys.get(2); List rules = grayReleaseRuleRepository .findByAppIdAndClusterNameAndNamespaceName(appId, cluster, namespace); mergeGrayReleaseRules(rules); } private void periodicScanRules() { Transaction transaction = Tracer.newTransaction("Apollo.GrayReleaseRulesScanner", "scanGrayReleaseRules"); try { loadVersion.incrementAndGet(); scanGrayReleaseRules(); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); logger.error("Scan gray release rule failed", ex); } finally { transaction.complete(); } } public Long findReleaseIdFromGrayReleaseRule(String clientAppId, String clientIp, String configAppId, String configCluster, String configNamespaceName) { String key = assembleGrayReleaseRuleKey(configAppId, configCluster, configNamespaceName); if (!grayReleaseRuleCache.containsKey(key)) { return null; } //create a new list to avoid ConcurrentModificationException List rules = Lists.newArrayList(grayReleaseRuleCache.get(key)); for (GrayReleaseRuleCache rule : rules) { //check branch status if (rule.getBranchStatus() != NamespaceBranchStatus.ACTIVE) { continue; } if (rule.matches(clientAppId, clientIp)) { return rule.getReleaseId(); } } return null; } /** * Check whether there are gray release rules for the clientAppId, clientIp, namespace * combination. Please note that even there are gray release rules, it doesn't mean it will always * load gray releases. Because gray release rules actually apply to one more dimension - cluster. */ public boolean hasGrayReleaseRule(String clientAppId, String clientIp, String namespaceName) { return reversedGrayReleaseRuleCache.containsKey(assembleReversedGrayReleaseRuleKey(clientAppId, namespaceName, clientIp)) || reversedGrayReleaseRuleCache.containsKey (assembleReversedGrayReleaseRuleKey(clientAppId, namespaceName, GrayReleaseRuleItemDTO .ALL_IP)); } private void scanGrayReleaseRules() { long maxIdScanned = 0; boolean hasMore = true; while (hasMore && !Thread.currentThread().isInterrupted()) { List grayReleaseRules = grayReleaseRuleRepository .findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned); if (CollectionUtils.isEmpty(grayReleaseRules)) { break; } mergeGrayReleaseRules(grayReleaseRules); int rulesScanned = grayReleaseRules.size(); maxIdScanned = grayReleaseRules.get(rulesScanned - 1).getId(); //batch is 500 hasMore = rulesScanned == 500; } } private void mergeGrayReleaseRules(List grayReleaseRules) { if (CollectionUtils.isEmpty(grayReleaseRules)) { return; } for (GrayReleaseRule grayReleaseRule : grayReleaseRules) { if (grayReleaseRule.getReleaseId() == null || grayReleaseRule.getReleaseId() == 0) { //filter rules with no release id, i.e. never released continue; } String key = assembleGrayReleaseRuleKey(grayReleaseRule.getAppId(), grayReleaseRule .getClusterName(), grayReleaseRule.getNamespaceName()); //create a new list to avoid ConcurrentModificationException List rules = Lists.newArrayList(grayReleaseRuleCache.get(key)); GrayReleaseRuleCache oldRule = null; for (GrayReleaseRuleCache ruleCache : rules) { if (ruleCache.getBranchName().equals(grayReleaseRule.getBranchName())) { oldRule = ruleCache; break; } } //if old rule is null and new rule's branch status is not active, ignore if (oldRule == null && grayReleaseRule.getBranchStatus() != NamespaceBranchStatus.ACTIVE) { continue; } //use id comparison to avoid synchronization if (oldRule == null || grayReleaseRule.getId() > oldRule.getRuleId()) { addCache(key, transformRuleToRuleCache(grayReleaseRule)); if (oldRule != null) { removeCache(key, oldRule); } } else { if (oldRule.getBranchStatus() == NamespaceBranchStatus.ACTIVE) { //update load version oldRule.setLoadVersion(loadVersion.get()); } else if ((loadVersion.get() - oldRule.getLoadVersion()) > 1) { //remove outdated inactive branch rule after 2 update cycles removeCache(key, oldRule); } } } } private void addCache(String key, GrayReleaseRuleCache ruleCache) { if (ruleCache.getBranchStatus() == NamespaceBranchStatus.ACTIVE) { for (GrayReleaseRuleItemDTO ruleItemDTO : ruleCache.getRuleItems()) { for (String clientIp : ruleItemDTO.getClientIpList()) { reversedGrayReleaseRuleCache.put(assembleReversedGrayReleaseRuleKey(ruleItemDTO .getClientAppId(), ruleCache.getNamespaceName(), clientIp), ruleCache.getRuleId()); } } } grayReleaseRuleCache.put(key, ruleCache); } private void removeCache(String key, GrayReleaseRuleCache ruleCache) { grayReleaseRuleCache.remove(key, ruleCache); for (GrayReleaseRuleItemDTO ruleItemDTO : ruleCache.getRuleItems()) { for (String clientIp : ruleItemDTO.getClientIpList()) { reversedGrayReleaseRuleCache.remove(assembleReversedGrayReleaseRuleKey(ruleItemDTO .getClientAppId(), ruleCache.getNamespaceName(), clientIp), ruleCache.getRuleId()); } } } private GrayReleaseRuleCache transformRuleToRuleCache(GrayReleaseRule grayReleaseRule) { Set ruleItems; try { ruleItems = GrayReleaseRuleItemTransformer.batchTransformFromJSON(grayReleaseRule.getRules()); } catch (Throwable ex) { ruleItems = Sets.newHashSet(); Tracer.logError(ex); logger.error("parse rule for gray release rule {} failed", grayReleaseRule.getId(), ex); } GrayReleaseRuleCache ruleCache = new GrayReleaseRuleCache(grayReleaseRule.getId(), grayReleaseRule.getBranchName(), grayReleaseRule.getNamespaceName(), grayReleaseRule .getReleaseId(), grayReleaseRule.getBranchStatus(), loadVersion.get(), ruleItems); return ruleCache; } private void populateDataBaseInterval() { databaseScanInterval = bizConfig.grayReleaseRuleScanInterval(); } private int getDatabaseScanIntervalSecond() { return databaseScanInterval; } private TimeUnit getDatabaseScanTimeUnit() { return TimeUnit.SECONDS; } private String assembleGrayReleaseRuleKey(String configAppId, String configCluster, String configNamespaceName) { return STRING_JOINER.join(configAppId, configCluster, configNamespaceName); } private String assembleReversedGrayReleaseRuleKey(String clientAppId, String clientNamespaceName, String clientIp) { return STRING_JOINER.join(clientAppId, clientNamespaceName, clientIp); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/DatabaseMessageSender.java ================================================ package com.ctrip.framework.apollo.biz.message; import com.google.common.collect.Queues; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.PostConstruct; /** * @author Jason Song(song_s@ctrip.com) */ @Component public class DatabaseMessageSender implements MessageSender { private static final Logger logger = LoggerFactory.getLogger(DatabaseMessageSender.class); private static final int CLEAN_QUEUE_MAX_SIZE = 100; private BlockingQueue toClean = Queues.newLinkedBlockingQueue(CLEAN_QUEUE_MAX_SIZE); private final ExecutorService cleanExecutorService; private final AtomicBoolean cleanStopped; @Autowired private ReleaseMessageRepository releaseMessageRepository; public DatabaseMessageSender() { cleanExecutorService = Executors.newSingleThreadExecutor(ApolloThreadFactory.create("DatabaseMessageSender", true)); cleanStopped = new AtomicBoolean(false); } @Override @Transactional public void sendMessage(String message, String channel) { logger.info("Sending message {} to channel {}", message, channel); if (!Objects.equals(channel, Topics.APOLLO_RELEASE_TOPIC)) { logger.warn("Channel {} not supported by DatabaseMessageSender!"); return; } Tracer.logEvent("Apollo.AdminService.ReleaseMessage", message); Transaction transaction = Tracer.newTransaction("Apollo.AdminService", "sendMessage"); try { ReleaseMessage newMessage = releaseMessageRepository.save(new ReleaseMessage(message)); toClean.offer(newMessage.getId()); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { logger.error("Sending message to database failed", ex); transaction.setStatus(ex); throw ex; } finally { transaction.complete(); } } @PostConstruct private void initialize() { cleanExecutorService.submit(() -> { while (!cleanStopped.get() && !Thread.currentThread().isInterrupted()) { try { Long rm = toClean.poll(1, TimeUnit.SECONDS); if (rm != null) { cleanMessage(rm); } else { TimeUnit.SECONDS.sleep(5); } } catch (Throwable ex) { Tracer.logError(ex); } } }); } private void cleanMessage(Long id) { boolean hasMore = true; //double check in case the release message is rolled back ReleaseMessage releaseMessage = releaseMessageRepository.findOne(id); if (releaseMessage == null) { return; } while (hasMore && !Thread.currentThread().isInterrupted()) { List messages = releaseMessageRepository.findFirst100ByMessageAndIdLessThanOrderByIdAsc( releaseMessage.getMessage(), releaseMessage.getId()); releaseMessageRepository.delete(messages); hasMore = messages.size() == 100; messages.forEach(toRemove -> Tracer.logEvent( String.format("ReleaseMessage.Clean.%s", toRemove.getMessage()), String.valueOf(toRemove.getId()))); } } void stopClean() { cleanStopped.set(true); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/MessageSender.java ================================================ package com.ctrip.framework.apollo.biz.message; /** * @author Jason Song(song_s@ctrip.com) */ public interface MessageSender { void sendMessage(String message, String channel); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/ReleaseMessageListener.java ================================================ package com.ctrip.framework.apollo.biz.message; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; /** * @author Jason Song(song_s@ctrip.com) */ public interface ReleaseMessageListener { void handleMessage(ReleaseMessage message, String channel); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/ReleaseMessageScanner.java ================================================ package com.ctrip.framework.apollo.biz.message; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.google.common.collect.Lists; /** * @author Jason Song(song_s@ctrip.com) */ public class ReleaseMessageScanner implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(ReleaseMessageScanner.class); @Autowired private BizConfig bizConfig; @Autowired private ReleaseMessageRepository releaseMessageRepository; private int databaseScanInterval; private List listeners; private ScheduledExecutorService executorService; private long maxIdScanned; public ReleaseMessageScanner() { listeners = Lists.newCopyOnWriteArrayList(); executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory .create("ReleaseMessageScanner", true)); } @Override public void afterPropertiesSet() throws Exception { databaseScanInterval = bizConfig.releaseMessageScanIntervalInMilli(); maxIdScanned = loadLargestMessageId(); executorService.scheduleWithFixedDelay((Runnable) () -> { Transaction transaction = Tracer.newTransaction("Apollo.ReleaseMessageScanner", "scanMessage"); try { scanMessages(); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); logger.error("Scan and send message failed", ex); } finally { transaction.complete(); } }, databaseScanInterval, databaseScanInterval, TimeUnit.MILLISECONDS); } /** * add message listeners for release message * @param listener */ public void addMessageListener(ReleaseMessageListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } } /** * Scan messages, continue scanning until there is no more messages */ private void scanMessages() { boolean hasMoreMessages = true; while (hasMoreMessages && !Thread.currentThread().isInterrupted()) { hasMoreMessages = scanAndSendMessages(); } } /** * scan messages and send * * @return whether there are more messages */ private boolean scanAndSendMessages() { //current batch is 500 List releaseMessages = releaseMessageRepository.findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned); if (CollectionUtils.isEmpty(releaseMessages)) { return false; } fireMessageScanned(releaseMessages); int messageScanned = releaseMessages.size(); maxIdScanned = releaseMessages.get(messageScanned - 1).getId(); return messageScanned == 500; } /** * find largest message id as the current start point * @return current largest message id */ private long loadLargestMessageId() { ReleaseMessage releaseMessage = releaseMessageRepository.findTopByOrderByIdDesc(); return releaseMessage == null ? 0 : releaseMessage.getId(); } /** * Notify listeners with messages loaded * @param messages */ private void fireMessageScanned(List messages) { for (ReleaseMessage message : messages) { for (ReleaseMessageListener listener : listeners) { try { listener.handleMessage(message, Topics.APOLLO_RELEASE_TOPIC); } catch (Throwable ex) { Tracer.logError(ex); logger.error("Failed to invoke message listener {}", listener.getClass(), ex); } } } } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/message/Topics.java ================================================ package com.ctrip.framework.apollo.biz.message; /** * @author Jason Song(song_s@ctrip.com) */ public class Topics { public static final String APOLLO_RELEASE_TOPIC = "apollo-release"; } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.common.entity.AppNamespace; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; import java.util.Set; public interface AppNamespaceRepository extends PagingAndSortingRepository{ AppNamespace findByAppIdAndName(String appId, String namespaceName); List findByAppIdAndNameIn(String appId, Set namespaceNames); AppNamespace findByNameAndIsPublicTrue(String namespaceName); List findByNameInAndIsPublicTrue(Set namespaceNames); List findByAppIdAndIsPublic(String appId, boolean isPublic); List findByAppId(String appId); List findFirst500ByIdGreaterThanOrderByIdAsc(long id); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.common.entity.App; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import java.util.List; public interface AppRepository extends PagingAndSortingRepository { @Query("SELECT a from App a WHERE a.name LIKE %:name%") List findByName(@Param("name") String name); App findByAppId(String appId); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AuditRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Audit; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import java.util.List; public interface AuditRepository extends PagingAndSortingRepository { @Query("SELECT a from Audit a WHERE a.dataChangeCreatedBy = :owner") List findByOwner(@Param("owner") String owner); @Query("SELECT a from Audit a WHERE a.dataChangeCreatedBy = :owner AND a.entityName =:entity AND a.opName = :op") List findAudits(@Param("owner") String owner, @Param("entity") String entity, @Param("op") String op); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ClusterRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Cluster; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; public interface ClusterRepository extends PagingAndSortingRepository { List findByAppIdAndParentClusterId(String appId, Long parentClusterId); List findByAppId(String appId); Cluster findByAppIdAndName(String appId, String name); List findByParentClusterId(Long parentClusterId); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/CommitRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Commit; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; public interface CommitRepository extends PagingAndSortingRepository { List findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable pageable); @Modifying @Query("update Commit set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3") int batchDelete(String appId, String clusterName, String namespaceName, String operator); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/GrayReleaseRuleRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; public interface GrayReleaseRuleRepository extends PagingAndSortingRepository { GrayReleaseRule findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(String appId, String clusterName, String namespaceName, String branchName); List findByAppIdAndClusterNameAndNamespaceName(String appId, String clusterName, String namespaceName); List findFirst500ByIdGreaterThanOrderByIdAsc(Long id); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/InstanceConfigRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.InstanceConfig; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import java.util.Date; import java.util.List; import java.util.Set; public interface InstanceConfigRepository extends PagingAndSortingRepository { InstanceConfig findByInstanceIdAndConfigAppIdAndConfigNamespaceName(long instanceId, String configAppId, String configNamespaceName); Page findByReleaseKeyAndDataChangeLastModifiedTimeAfter(String releaseKey, Date validDate, Pageable pageable); Page findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfter( String appId, String clusterName, String namespaceName, Date validDate, Pageable pageable); List findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfterAndReleaseKeyNotIn( String appId, String clusterName, String namespaceName, Date validDate, Set releaseKey); @Modifying @Query("delete from InstanceConfig where ConfigAppId=?1 and ConfigClusterName=?2 and ConfigNamespaceName = ?3") int batchDelete(String appId, String clusterName, String namespaceName); @Query( value = "select b.Id from `InstanceConfig` a inner join `Instance` b on b.Id =" + " a.`InstanceId` where a.`ConfigAppId` = :configAppId and a.`ConfigClusterName` = " + ":clusterName and a.`ConfigNamespaceName` = :namespaceName and a.`DataChange_LastTime` " + "> :validDate and b.`AppId` = :instanceAppId and ?#{#pageable.pageSize} > 0", countQuery = "select count(1) from `InstanceConfig` a inner join `Instance` b on b.id =" + " a.`InstanceId` where a.`ConfigAppId` = :configAppId and a.`ConfigClusterName` = " + ":clusterName and a.`ConfigNamespaceName` = :namespaceName and a.`DataChange_LastTime` " + "> :validDate and b.`AppId` = :instanceAppId", nativeQuery = true) Page findInstanceIdsByNamespaceAndInstanceAppId( @Param("instanceAppId") String instanceAppId, @Param("configAppId") String configAppId, @Param("clusterName") String clusterName, @Param("namespaceName") String namespaceName, @Param("validDate") Date validDate, Pageable pageable); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/InstanceRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Instance; import org.springframework.data.repository.PagingAndSortingRepository; public interface InstanceRepository extends PagingAndSortingRepository { Instance findByAppIdAndClusterNameAndDataCenterAndIp(String appId, String clusterName, String dataCenter, String ip); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ItemRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Item; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.Date; import java.util.List; public interface ItemRepository extends PagingAndSortingRepository { Item findByNamespaceIdAndKey(Long namespaceId, String key); List findByNamespaceIdOrderByLineNumAsc(Long namespaceId); List findByNamespaceId(Long namespaceId); List findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(Long namespaceId, Date date); Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId); @Modifying @Query("update Item set isdeleted=1,DataChange_LastModifiedBy = ?2 where namespaceId = ?1") int deleteByNamespaceId(long namespaceId, String operator); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/NamespaceLockRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.NamespaceLock; import org.springframework.data.repository.PagingAndSortingRepository; public interface NamespaceLockRepository extends PagingAndSortingRepository { NamespaceLock findByNamespaceId(Long namespaceId); Long deleteByNamespaceId(Long namespaceId); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/NamespaceRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Namespace; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; public interface NamespaceRepository extends PagingAndSortingRepository { List findByAppIdAndClusterNameOrderByIdAsc(String appId, String clusterName); Namespace findByAppIdAndClusterNameAndNamespaceName(String appId, String clusterName, String namespaceName); @Modifying @Query("update Namespace set isdeleted=1,DataChange_LastModifiedBy = ?3 where appId=?1 and clusterName=?2") int batchDelete(String appId, String clusterName, String operator); List findByAppIdAndNamespaceName(String appId, String namespaceName); List findByNamespaceName(String namespaceName, Pageable page); int countByNamespaceNameAndAppIdNot(String namespaceName, String appId); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/PrivilegeRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Privilege; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; public interface PrivilegeRepository extends PagingAndSortingRepository { List findByNamespaceId(long namespaceId); List findByNamespaceIdAndPrivilType(long namespaceId, String privilType); Privilege findByNamespaceIdAndNameAndPrivilType(long namespaceId, String name, String privilType); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ReleaseHistoryRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.ReleaseHistory; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public interface ReleaseHistoryRepository extends PagingAndSortingRepository { Page findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable pageable); Page findByReleaseIdAndOperationOrderByIdDesc(long releaseId, int operation, Pageable pageable); Page findByPreviousReleaseIdAndOperationOrderByIdDesc(long previousReleaseId, int operation, Pageable pageable); @Modifying @Query("update ReleaseHistory set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3") int batchDelete(String appId, String clusterName, String namespaceName, String operator); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ReleaseMessageRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import java.util.Collection; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public interface ReleaseMessageRepository extends PagingAndSortingRepository { List findFirst500ByIdGreaterThanOrderByIdAsc(Long id); ReleaseMessage findTopByOrderByIdDesc(); ReleaseMessage findTopByMessageInOrderByIdDesc(Collection messages); List findFirst100ByMessageAndIdLessThanOrderByIdAsc(String message, Long id); @Query("select message, max(id) as id from ReleaseMessage where message in :messages group by message") List findLatestReleaseMessagesGroupByMessages(@Param("messages") Collection messages); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ReleaseRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.Release; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import java.util.List; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ public interface ReleaseRepository extends PagingAndSortingRepository { Release findFirstByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(@Param("appId") String appId, @Param("clusterName") String clusterName, @Param("namespaceName") String namespaceName); Release findByIdAndIsAbandonedFalse(long id); List findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable page); List findByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable page); List findByReleaseKeyIn(Set releaseKey); List findByIdIn(Set releaseIds); @Modifying @Query("update Release set isdeleted=1,DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3") int batchDelete(String appId, String clusterName, String namespaceName, String operator); // For release history conversion program, need to delete after conversion it done List findByAppIdAndClusterNameAndNamespaceNameOrderByIdAsc(String appId, String clusterName, String namespaceName); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ServerConfigRepository.java ================================================ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.ServerConfig; import org.springframework.data.repository.PagingAndSortingRepository; /** * @author Jason Song(song_s@ctrip.com) */ public interface ServerConfigRepository extends PagingAndSortingRepository { ServerConfig findTopByKeyAndCluster(String key, String cluster); } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.core.ConfigConsts; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class AdminService { @Autowired private AppService appService; @Autowired private AppNamespaceService appNamespaceService; @Autowired private ClusterService clusterService; @Autowired private NamespaceService namespaceService; @Transactional public App createNewApp(App app) { String createBy = app.getDataChangeCreatedBy(); App createdApp = appService.save(app); String appId = createdApp.getAppId(); appNamespaceService.createDefaultAppNamespace(appId, createBy); clusterService.createDefaultCluster(appId, createBy); namespaceService.instanceOfAppNamespaces(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, createBy); return app; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.Cluster; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @Service public class AppNamespaceService { @Autowired private AppNamespaceRepository appNamespaceRepository; @Autowired private NamespaceService namespaceService; @Autowired private ClusterService clusterService; @Autowired private AuditService auditService; public boolean isAppNamespaceNameUnique(String appId, String namespaceName) { Objects.requireNonNull(appId, "AppId must not be null"); Objects.requireNonNull(namespaceName, "Namespace must not be null"); return Objects.isNull(appNamespaceRepository.findByAppIdAndName(appId, namespaceName)); } public AppNamespace findPublicNamespaceByName(String namespaceName) { Preconditions.checkArgument(namespaceName != null, "Namespace must not be null"); return appNamespaceRepository.findByNameAndIsPublicTrue(namespaceName); } public List findByAppId(String appId) { return appNamespaceRepository.findByAppId(appId); } public List findPublicNamespacesByNames(Set namespaceNames) { if (namespaceNames == null || namespaceNames.isEmpty()) { return Collections.emptyList(); } return appNamespaceRepository.findByNameInAndIsPublicTrue(namespaceNames); } public List findPrivateAppNamespace(String appId) { return appNamespaceRepository.findByAppIdAndIsPublic(appId, false); } public AppNamespace findOne(String appId, String namespaceName) { Preconditions .checkArgument(!StringUtils.isContainEmpty(appId, namespaceName), "appId or Namespace must not be null"); return appNamespaceRepository.findByAppIdAndName(appId, namespaceName); } public List findByAppIdAndNamespaces(String appId, Set namespaceNames) { Preconditions.checkArgument(!Strings.isNullOrEmpty(appId), "appId must not be null"); if (namespaceNames == null || namespaceNames.isEmpty()) { return Collections.emptyList(); } return appNamespaceRepository.findByAppIdAndNameIn(appId, namespaceNames); } @Transactional public void createDefaultAppNamespace(String appId, String createBy) { if (!isAppNamespaceNameUnique(appId, ConfigConsts.NAMESPACE_APPLICATION)) { throw new ServiceException("appnamespace not unique"); } AppNamespace appNs = new AppNamespace(); appNs.setAppId(appId); appNs.setName(ConfigConsts.NAMESPACE_APPLICATION); appNs.setComment("default app namespace"); appNs.setFormat(ConfigFileFormat.Properties.getValue()); appNs.setDataChangeCreatedBy(createBy); appNs.setDataChangeLastModifiedBy(createBy); appNamespaceRepository.save(appNs); auditService.audit(AppNamespace.class.getSimpleName(), appNs.getId(), Audit.OP.INSERT, createBy); } @Transactional public AppNamespace createAppNamespace(AppNamespace appNamespace) { String createBy = appNamespace.getDataChangeCreatedBy(); if (!isAppNamespaceNameUnique(appNamespace.getAppId(), appNamespace.getName())) { throw new ServiceException("appnamespace not unique"); } appNamespace.setId(0);//protection appNamespace.setDataChangeCreatedBy(createBy); appNamespace.setDataChangeLastModifiedBy(createBy); appNamespace = appNamespaceRepository.save(appNamespace); instanceOfAppNamespaceInAllCluster(appNamespace.getAppId(), appNamespace.getName(), createBy); auditService.audit(AppNamespace.class.getSimpleName(), appNamespace.getId(), Audit.OP.INSERT, createBy); return appNamespace; } public AppNamespace update(AppNamespace appNamespace) { AppNamespace managedNs = appNamespaceRepository.findByAppIdAndName(appNamespace.getAppId(), appNamespace.getName()); BeanUtils.copyEntityProperties(appNamespace, managedNs); managedNs = appNamespaceRepository.save(managedNs); auditService.audit(AppNamespace.class.getSimpleName(), managedNs.getId(), Audit.OP.UPDATE, managedNs.getDataChangeLastModifiedBy()); return managedNs; } private void instanceOfAppNamespaceInAllCluster(String appId, String namespaceName, String createBy) { List clusters = clusterService.findParentClusters(appId); for (Cluster cluster : clusters) { Namespace namespace = new Namespace(); namespace.setClusterName(cluster.getName()); namespace.setAppId(appId); namespace.setNamespaceName(namespaceName); namespace.setDataChangeCreatedBy(createBy); namespace.setDataChangeLastModifiedBy(createBy); namespaceService.save(namespace); } } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.repository.AppRepository; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.ServiceException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Objects; @Service public class AppService { @Autowired private AppRepository appRepository; @Autowired private AuditService auditService; public boolean isAppIdUnique(String appId) { Objects.requireNonNull(appId, "AppId must not be null"); return Objects.isNull(appRepository.findByAppId(appId)); } @Transactional public void delete(long id, String operator) { App app = appRepository.findOne(id); if (app == null) { return; } app.setDeleted(true); app.setDataChangeLastModifiedBy(operator); appRepository.save(app); auditService.audit(App.class.getSimpleName(), id, Audit.OP.DELETE, operator); } public List findAll(Pageable pageable) { Page page = appRepository.findAll(pageable); return page.getContent(); } public List findByName(String name) { return appRepository.findByName(name); } public App findOne(String appId) { return appRepository.findByAppId(appId); } @Transactional public App save(App entity) { if (!isAppIdUnique(entity.getAppId())) { throw new ServiceException("appId not unique"); } entity.setId(0);//protection App app = appRepository.save(entity); auditService.audit(App.class.getSimpleName(), app.getId(), Audit.OP.INSERT, app.getDataChangeCreatedBy()); return app; } @Transactional public void update(App app) { String appId = app.getAppId(); App managedApp = appRepository.findByAppId(appId); if (managedApp == null) { throw new BadRequestException(String.format("App not exists. AppId = %s", appId)); } managedApp.setName(app.getName()); managedApp.setOrgId(app.getOrgId()); managedApp.setOrgName(app.getOrgName()); managedApp.setOwnerName(app.getOwnerName()); managedApp.setOwnerEmail(app.getOwnerEmail()); managedApp.setDataChangeLastModifiedBy(app.getDataChangeLastModifiedBy()); managedApp = appRepository.save(managedApp); auditService.audit(App.class.getSimpleName(), managedApp.getId(), Audit.OP.UPDATE, managedApp.getDataChangeLastModifiedBy()); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AuditService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.repository.AuditRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service public class AuditService { @Autowired private AuditRepository auditRepository; List findByOwner(String owner) { return auditRepository.findByOwner(owner); } List find(String owner, String entity, String op) { return auditRepository.findAudits(owner, entity, op); } @Transactional void audit(String entityName, Long entityId, Audit.OP op, String owner) { Audit audit = new Audit(); audit.setEntityName(entityName); audit.setEntityId(entityId); audit.setOpName(op.name()); audit.setDataChangeCreatedBy(owner); auditRepository.save(audit); } @Transactional void audit(Audit audit){ auditRepository.save(audit); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySource.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.base.Strings; import com.google.common.collect.Maps; import com.ctrip.framework.apollo.biz.entity.ServerConfig; import com.ctrip.framework.apollo.biz.repository.ServerConfigRepository; import com.ctrip.framework.apollo.common.config.RefreshablePropertySource; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.foundation.Foundation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Map; import java.util.Objects; /** * @author Jason Song(song_s@ctrip.com) */ @Component public class BizDBPropertySource extends RefreshablePropertySource { private static final Logger logger = LoggerFactory.getLogger(BizDBPropertySource.class); @Autowired private ServerConfigRepository serverConfigRepository; public BizDBPropertySource(String name, Map source) { super(name, source); } public BizDBPropertySource() { super("DBConfig", Maps.newConcurrentMap()); } String getCurrentDataCenter() { return Foundation.server().getDataCenter(); } @Override protected void refresh() { Iterable dbConfigs = serverConfigRepository.findAll(); Map newConfigs = Maps.newHashMap(); //default cluster's configs for (ServerConfig config : dbConfigs) { if (Objects.equals(ConfigConsts.CLUSTER_NAME_DEFAULT, config.getCluster())) { newConfigs.put(config.getKey(), config.getValue()); } } //data center's configs String dataCenter = getCurrentDataCenter(); for (ServerConfig config : dbConfigs) { if (Objects.equals(dataCenter, config.getCluster())) { newConfigs.put(config.getKey(), config.getValue()); } } //cluster's config if (!Strings.isNullOrEmpty(System.getProperty(ConfigConsts.APOLLO_CLUSTER_KEY))) { String cluster = System.getProperty(ConfigConsts.APOLLO_CLUSTER_KEY); for (ServerConfig config : dbConfigs) { if (Objects.equals(cluster, config.getCluster())) { newConfigs.put(config.getKey(), config.getValue()); } } } //put to environment for (Map.Entry config: newConfigs.entrySet()){ String key = config.getKey(); Object value = config.getValue(); if (this.source.get(key) == null) { logger.info("Load config from DB : {} = {}", key, value); } else if (!Objects.equals(this.source.get(key), value)) { logger.info("Load config from DB : {} = {}. Old value = {}", key, value, this.source.get(key)); } this.source.put(key, value); } } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.base.Strings; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.Cluster; import com.ctrip.framework.apollo.biz.repository.ClusterRepository; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.ConfigConsts; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; import java.util.Objects; @Service public class ClusterService { @Autowired private ClusterRepository clusterRepository; @Autowired private AuditService auditService; @Autowired private NamespaceService namespaceService; public boolean isClusterNameUnique(String appId, String clusterName) { Objects.requireNonNull(appId, "AppId must not be null"); Objects.requireNonNull(clusterName, "ClusterName must not be null"); return Objects.isNull(clusterRepository.findByAppIdAndName(appId, clusterName)); } public Cluster findOne(String appId, String name) { return clusterRepository.findByAppIdAndName(appId, name); } public Cluster findOne(long clusterId) { return clusterRepository.findOne(clusterId); } public List findParentClusters(String appId) { if (Strings.isNullOrEmpty(appId)) { return Collections.emptyList(); } List clusters = clusterRepository.findByAppIdAndParentClusterId(appId, 0L); if (clusters == null) { return Collections.emptyList(); } Collections.sort(clusters); return clusters; } @Transactional public Cluster saveWithInstanceOfAppNamespaces(Cluster entity) { Cluster savedCluster = saveWithoutInstanceOfAppNamespaces(entity); namespaceService.instanceOfAppNamespaces(savedCluster.getAppId(), savedCluster.getName(), savedCluster.getDataChangeCreatedBy()); return savedCluster; } @Transactional public Cluster saveWithoutInstanceOfAppNamespaces(Cluster entity) { if (!isClusterNameUnique(entity.getAppId(), entity.getName())) { throw new BadRequestException("cluster not unique"); } entity.setId(0);//protection Cluster cluster = clusterRepository.save(entity); auditService.audit(Cluster.class.getSimpleName(), cluster.getId(), Audit.OP.INSERT, cluster.getDataChangeCreatedBy()); return cluster; } @Transactional public void delete(long id, String operator) { Cluster cluster = clusterRepository.findOne(id); if (cluster == null) { throw new BadRequestException("cluster not exist"); } //delete linked namespaces namespaceService.deleteByAppIdAndClusterName(cluster.getAppId(), cluster.getName(), operator); cluster.setDeleted(true); cluster.setDataChangeLastModifiedBy(operator); clusterRepository.save(cluster); auditService.audit(Cluster.class.getSimpleName(), id, Audit.OP.DELETE, operator); } @Transactional public Cluster update(Cluster cluster) { Cluster managedCluster = clusterRepository.findByAppIdAndName(cluster.getAppId(), cluster.getName()); BeanUtils.copyEntityProperties(cluster, managedCluster); managedCluster = clusterRepository.save(managedCluster); auditService.audit(Cluster.class.getSimpleName(), managedCluster.getId(), Audit.OP.UPDATE, managedCluster.getDataChangeLastModifiedBy()); return managedCluster; } @Transactional public void createDefaultCluster(String appId, String createBy) { if (!isClusterNameUnique(appId, ConfigConsts.CLUSTER_NAME_DEFAULT)) { throw new ServiceException("cluster not unique"); } Cluster cluster = new Cluster(); cluster.setName(ConfigConsts.CLUSTER_NAME_DEFAULT); cluster.setAppId(appId); cluster.setDataChangeCreatedBy(createBy); cluster.setDataChangeLastModifiedBy(createBy); clusterRepository.save(cluster); auditService.audit(Cluster.class.getSimpleName(), cluster.getId(), Audit.OP.INSERT, createBy); } public List findChildClusters(String appId, String parentClusterName) { Cluster parentCluster = findOne(appId, parentClusterName); if (parentCluster == null) { throw new BadRequestException("parent cluster not exist"); } return clusterRepository.findByParentClusterId(parentCluster.getId()); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/CommitService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.biz.entity.Commit; import com.ctrip.framework.apollo.biz.repository.CommitRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service public class CommitService { @Autowired private CommitRepository commitRepository; @Transactional public Commit save(Commit commit){ commit.setId(0);//protection return commitRepository.save(commit); } public List find(String appId, String clusterName, String namespaceName, Pageable page){ return commitRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId, clusterName, namespaceName, page); } @Transactional public int batchDelete(String appId, String clusterName, String namespaceName, String operator){ return commitRepository.batchDelete(appId, clusterName, namespaceName, operator); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/InstanceService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.biz.entity.Instance; import com.ctrip.framework.apollo.biz.entity.InstanceConfig; import com.ctrip.framework.apollo.biz.repository.InstanceConfigRepository; import com.ctrip.framework.apollo.biz.repository.InstanceRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigInteger; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class InstanceService { @Autowired private InstanceRepository instanceRepository; @Autowired private InstanceConfigRepository instanceConfigRepository; public Instance findInstance(String appId, String clusterName, String dataCenter, String ip) { return instanceRepository.findByAppIdAndClusterNameAndDataCenterAndIp(appId, clusterName, dataCenter, ip); } public List findInstancesByIds(Set instanceIds) { Iterable instances = instanceRepository.findAll(instanceIds); if (instances == null) { return Collections.emptyList(); } return Lists.newArrayList(instances); } @Transactional public Instance createInstance(Instance instance) { instance.setId(0); //protection return instanceRepository.save(instance); } public InstanceConfig findInstanceConfig(long instanceId, String configAppId, String configNamespaceName) { return instanceConfigRepository .findByInstanceIdAndConfigAppIdAndConfigNamespaceName( instanceId, configAppId, configNamespaceName); } public Page findActiveInstanceConfigsByReleaseKey(String releaseKey, Pageable pageable) { Page instanceConfigs = instanceConfigRepository .findByReleaseKeyAndDataChangeLastModifiedTimeAfter(releaseKey, getValidInstanceConfigDate(), pageable); return instanceConfigs; } public Page findInstancesByNamespace(String appId, String clusterName, String namespaceName, Pageable pageable) { Page instanceConfigs = instanceConfigRepository. findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfter(appId, clusterName, namespaceName, getValidInstanceConfigDate(), pageable); List instances = Collections.emptyList(); if (instanceConfigs.hasContent()) { Set instanceIds = instanceConfigs.getContent().stream().map (InstanceConfig::getInstanceId).collect(Collectors.toSet()); instances = findInstancesByIds(instanceIds); } return new PageImpl<>(instances, pageable, instanceConfigs.getTotalElements()); } public Page findInstancesByNamespaceAndInstanceAppId(String instanceAppId, String appId, String clusterName, String namespaceName, Pageable pageable) { Page instanceIdResult = instanceConfigRepository .findInstanceIdsByNamespaceAndInstanceAppId(instanceAppId, appId, clusterName, namespaceName, getValidInstanceConfigDate(), pageable); List instances = Collections.emptyList(); if (instanceIdResult.hasContent()) { Set instanceIds = instanceIdResult.getContent().stream().map((Object o) -> { if (o == null) { return null; } if (o instanceof Integer) { return ((Integer)o).longValue(); } if (o instanceof Long) { return (Long) o; } //for h2 test if (o instanceof BigInteger) { return ((BigInteger) o).longValue(); } return null; }).filter((Long value) -> value != null).collect(Collectors.toSet()); instances = findInstancesByIds(instanceIds); } return new PageImpl<>(instances, pageable, instanceIdResult.getTotalElements()); } public List findInstanceConfigsByNamespaceWithReleaseKeysNotIn(String appId, String clusterName, String namespaceName, Set releaseKeysNotIn) { List instanceConfigs = instanceConfigRepository. findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfterAndReleaseKeyNotIn(appId, clusterName, namespaceName, getValidInstanceConfigDate(), releaseKeysNotIn); if (CollectionUtils.isEmpty(instanceConfigs)) { return Collections.emptyList(); } return instanceConfigs; } /** * Currently the instance config is expired by 1 day, add one more hour to avoid possible time * difference */ private Date getValidInstanceConfigDate() { Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); cal.add(Calendar.HOUR, -1); return cal.getTime(); } @Transactional public InstanceConfig createInstanceConfig(InstanceConfig instanceConfig) { instanceConfig.setId(0); //protection return instanceConfigRepository.save(instanceConfig); } @Transactional public InstanceConfig updateInstanceConfig(InstanceConfig instanceConfig) { InstanceConfig existedInstanceConfig = instanceConfigRepository.findOne(instanceConfig.getId()); Preconditions.checkArgument(existedInstanceConfig != null, String.format( "Instance config %d doesn't exist", instanceConfig.getId())); existedInstanceConfig.setConfigClusterName(instanceConfig.getConfigClusterName()); existedInstanceConfig.setReleaseKey(instanceConfig.getReleaseKey()); existedInstanceConfig.setReleaseDeliveryTime(instanceConfig.getReleaseDeliveryTime()); existedInstanceConfig.setDataChangeLastModifiedTime(instanceConfig .getDataChangeLastModifiedTime()); return instanceConfigRepository.save(existedInstanceConfig); } @Transactional public int batchDeleteInstanceConfig(String configAppId, String configClusterName, String configNamespaceName){ return instanceConfigRepository.batchDelete(configAppId, configClusterName, configNamespaceName); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.repository.ItemRepository; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @Service public class ItemService { @Autowired private ItemRepository itemRepository; @Autowired private NamespaceService namespaceService; @Autowired private AuditService auditService; @Autowired private BizConfig bizConfig; @Transactional public Item delete(long id, String operator) { Item item = itemRepository.findOne(id); if (item == null) { throw new IllegalArgumentException("item not exist. ID:" + id); } item.setDeleted(true); item.setDataChangeLastModifiedBy(operator); Item deletedItem = itemRepository.save(item); auditService.audit(Item.class.getSimpleName(), id, Audit.OP.DELETE, operator); return deletedItem; } @Transactional public int batchDelete(long namespaceId, String operator) { return itemRepository.deleteByNamespaceId(namespaceId, operator); } public Item findOne(String appId, String clusterName, String namespaceName, String key) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace == null) { throw new NotFoundException( String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName)); } Item item = itemRepository.findByNamespaceIdAndKey(namespace.getId(), key); return item; } public Item findLastOne(String appId, String clusterName, String namespaceName) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace == null) { throw new NotFoundException( String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName)); } return findLastOne(namespace.getId()); } public Item findLastOne(long namespaceId) { return itemRepository.findFirst1ByNamespaceIdOrderByLineNumDesc(namespaceId); } public Item findOne(long itemId) { Item item = itemRepository.findOne(itemId); return item; } public List findItemsWithoutOrdered(Long namespaceId) { List items = itemRepository.findByNamespaceId(namespaceId); if (items == null) { return Collections.emptyList(); } return items; } public List findItemsWithoutOrdered(String appId, String clusterName, String namespaceName) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace != null) { return findItemsWithoutOrdered(namespace.getId()); } else { return Collections.emptyList(); } } public List findItemsWithOrdered(Long namespaceId) { List items = itemRepository.findByNamespaceIdOrderByLineNumAsc(namespaceId); if (items == null) { return Collections.emptyList(); } return items; } public List findItemsWithOrdered(String appId, String clusterName, String namespaceName) { Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); if (namespace != null) { return findItemsWithOrdered(namespace.getId()); } else { return Collections.emptyList(); } } public List findItemsModifiedAfterDate(long namespaceId, Date date) { return itemRepository.findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(namespaceId, date); } @Transactional public Item save(Item entity) { checkItemKeyLength(entity.getKey()); checkItemValueLength(entity.getNamespaceId(), entity.getValue()); entity.setId(0);//protection if (entity.getLineNum() == 0) { Item lastItem = findLastOne(entity.getNamespaceId()); int lineNum = lastItem == null ? 1 : lastItem.getLineNum() + 1; entity.setLineNum(lineNum); } Item item = itemRepository.save(entity); auditService.audit(Item.class.getSimpleName(), item.getId(), Audit.OP.INSERT, item.getDataChangeCreatedBy()); return item; } @Transactional public Item update(Item item) { checkItemValueLength(item.getNamespaceId(), item.getValue()); Item managedItem = itemRepository.findOne(item.getId()); BeanUtils.copyEntityProperties(item, managedItem); managedItem = itemRepository.save(managedItem); auditService.audit(Item.class.getSimpleName(), managedItem.getId(), Audit.OP.UPDATE, managedItem.getDataChangeLastModifiedBy()); return managedItem; } private boolean checkItemValueLength(long namespaceId, String value) { int limit = getItemValueLengthLimit(namespaceId); if (!StringUtils.isEmpty(value) && value.length() > limit) { throw new BadRequestException("value too long. length limit:" + limit); } return true; } private boolean checkItemKeyLength(String key) { if (!StringUtils.isEmpty(key) && key.length() > bizConfig.itemKeyLengthLimit()) { throw new BadRequestException("key too long. length limit:" + bizConfig.itemKeyLengthLimit()); } return true; } private int getItemValueLengthLimit(long namespaceId) { Map namespaceValueLengthOverride = bizConfig.namespaceValueLengthLimitOverride(); if (namespaceValueLengthOverride != null && namespaceValueLengthOverride.containsKey(namespaceId)) { return namespaceValueLengthOverride.get(namespaceId); } return bizConfig.itemValueLengthLimit(); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemSetService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.Commit; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.utils.ConfigChangeContentBuilder; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @Service public class ItemSetService { @Autowired private AuditService auditService; @Autowired private CommitService commitService; @Autowired private ItemService itemService; @Transactional public ItemChangeSets updateSet(Namespace namespace, ItemChangeSets changeSets){ return updateSet(namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName(), changeSets); } @Transactional public ItemChangeSets updateSet(String appId, String clusterName, String namespaceName, ItemChangeSets changeSet) { String operator = changeSet.getDataChangeLastModifiedBy(); ConfigChangeContentBuilder configChangeContentBuilder = new ConfigChangeContentBuilder(); if (!CollectionUtils.isEmpty(changeSet.getCreateItems())) { for (ItemDTO item : changeSet.getCreateItems()) { Item entity = BeanUtils.transfrom(Item.class, item); entity.setDataChangeCreatedBy(operator); entity.setDataChangeLastModifiedBy(operator); Item createdItem = itemService.save(entity); configChangeContentBuilder.createItem(createdItem); } auditService.audit("ItemSet", null, Audit.OP.INSERT, operator); } if (!CollectionUtils.isEmpty(changeSet.getUpdateItems())) { for (ItemDTO item : changeSet.getUpdateItems()) { Item entity = BeanUtils.transfrom(Item.class, item); Item managedItem = itemService.findOne(entity.getId()); if (managedItem == null) { throw new NotFoundException(String.format("item not found.(key=%s)", entity.getKey())); } Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedItem); //protect. only value,comment,lastModifiedBy,lineNum can be modified managedItem.setValue(entity.getValue()); managedItem.setComment(entity.getComment()); managedItem.setLineNum(entity.getLineNum()); managedItem.setDataChangeLastModifiedBy(operator); Item updatedItem = itemService.update(managedItem); configChangeContentBuilder.updateItem(beforeUpdateItem, updatedItem); } auditService.audit("ItemSet", null, Audit.OP.UPDATE, operator); } if (!CollectionUtils.isEmpty(changeSet.getDeleteItems())) { for (ItemDTO item : changeSet.getDeleteItems()) { Item deletedItem = itemService.delete(item.getId(), operator); configChangeContentBuilder.deleteItem(deletedItem); } auditService.audit("ItemSet", null, Audit.OP.DELETE, operator); } if (configChangeContentBuilder.hasContent()){ createCommit(appId, clusterName, namespaceName, configChangeContentBuilder.build(), changeSet.getDataChangeLastModifiedBy()); } return changeSet; } private void createCommit(String appId, String clusterName, String namespaceName, String configChangeContent, String operator) { Commit commit = new Commit(); commit.setAppId(appId); commit.setClusterName(clusterName); commit.setNamespaceName(namespaceName); commit.setChangeSets(configChangeContent); commit.setDataChangeCreatedBy(operator); commit.setDataChangeLastModifiedBy(operator); commitService.save(commit); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceBranchService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.collect.Maps; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.Cluster; import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.repository.GrayReleaseRuleRepository; import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus; import com.ctrip.framework.apollo.common.constants.ReleaseOperation; import com.ctrip.framework.apollo.common.constants.ReleaseOperationContext; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer; import com.ctrip.framework.apollo.common.utils.UniqueKeyGenerator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Map; @Service public class NamespaceBranchService { @Autowired private AuditService auditService; @Autowired private GrayReleaseRuleRepository grayReleaseRuleRepository; @Autowired private ClusterService clusterService; @Autowired private ReleaseService releaseService; @Autowired private NamespaceService namespaceService; @Autowired private ReleaseHistoryService releaseHistoryService; @Transactional public Namespace createBranch(String appId, String parentClusterName, String namespaceName, String operator){ Namespace childNamespace = findBranch(appId, parentClusterName, namespaceName); if (childNamespace != null){ throw new BadRequestException("namespace already has branch"); } Cluster parentCluster = clusterService.findOne(appId, parentClusterName); if (parentCluster == null || parentCluster.getParentClusterId() != 0) { throw new BadRequestException("cluster not exist or illegal cluster"); } //create child cluster Cluster childCluster = createChildCluster(appId, parentCluster, namespaceName, operator); Cluster createdChildCluster = clusterService.saveWithoutInstanceOfAppNamespaces(childCluster); //create child namespace childNamespace = createNamespaceBranch(appId, createdChildCluster.getName(), namespaceName, operator); return namespaceService.save(childNamespace); } public Namespace findBranch(String appId, String parentClusterName, String namespaceName) { return namespaceService.findChildNamespace(appId, parentClusterName, namespaceName); } public GrayReleaseRule findBranchGrayRules(String appId, String clusterName, String namespaceName, String branchName) { return grayReleaseRuleRepository .findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(appId, clusterName, namespaceName, branchName); } @Transactional public void updateBranchGrayRules(String appId, String clusterName, String namespaceName, String branchName, GrayReleaseRule newRules) { doUpdateBranchGrayRules(appId, clusterName, namespaceName, branchName, newRules, true, ReleaseOperation.APPLY_GRAY_RULES); } private void doUpdateBranchGrayRules(String appId, String clusterName, String namespaceName, String branchName, GrayReleaseRule newRules, boolean recordReleaseHistory, int releaseOperation) { GrayReleaseRule oldRules = grayReleaseRuleRepository .findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(appId, clusterName, namespaceName, branchName); Release latestBranchRelease = releaseService.findLatestActiveRelease(appId, branchName, namespaceName); long latestBranchReleaseId = latestBranchRelease != null ? latestBranchRelease.getId() : 0; newRules.setReleaseId(latestBranchReleaseId); grayReleaseRuleRepository.save(newRules); //delete old rules if (oldRules != null) { grayReleaseRuleRepository.delete(oldRules); } if (recordReleaseHistory) { Map releaseOperationContext = Maps.newHashMap(); releaseOperationContext.put(ReleaseOperationContext.RULES, GrayReleaseRuleItemTransformer .batchTransformFromJSON(newRules.getRules())); if (oldRules != null) { releaseOperationContext.put(ReleaseOperationContext.OLD_RULES, GrayReleaseRuleItemTransformer.batchTransformFromJSON(oldRules.getRules())); } releaseHistoryService.createReleaseHistory(appId, clusterName, namespaceName, branchName, latestBranchReleaseId, latestBranchReleaseId, releaseOperation, releaseOperationContext, newRules.getDataChangeLastModifiedBy()); } } @Transactional public GrayReleaseRule updateRulesReleaseId(String appId, String clusterName, String namespaceName, String branchName, long latestReleaseId, String operator) { GrayReleaseRule oldRules = grayReleaseRuleRepository. findTopByAppIdAndClusterNameAndNamespaceNameAndBranchNameOrderByIdDesc(appId, clusterName, namespaceName, branchName); if (oldRules == null) { return null; } GrayReleaseRule newRules = new GrayReleaseRule(); newRules.setBranchStatus(NamespaceBranchStatus.ACTIVE); newRules.setReleaseId(latestReleaseId); newRules.setRules(oldRules.getRules()); newRules.setAppId(oldRules.getAppId()); newRules.setClusterName(oldRules.getClusterName()); newRules.setNamespaceName(oldRules.getNamespaceName()); newRules.setBranchName(oldRules.getBranchName()); newRules.setDataChangeCreatedBy(operator); newRules.setDataChangeLastModifiedBy(operator); grayReleaseRuleRepository.save(newRules); grayReleaseRuleRepository.delete(oldRules); return newRules; } @Transactional public void deleteBranch(String appId, String clusterName, String namespaceName, String branchName, int branchStatus, String operator) { Cluster toDeleteCluster = clusterService.findOne(appId, branchName); if (toDeleteCluster == null) { return; } Release latestBranchRelease = releaseService.findLatestActiveRelease(appId, branchName, namespaceName); long latestBranchReleaseId = latestBranchRelease != null ? latestBranchRelease.getId() : 0; //update branch rules GrayReleaseRule deleteRule = new GrayReleaseRule(); deleteRule.setRules("[]"); deleteRule.setAppId(appId); deleteRule.setClusterName(clusterName); deleteRule.setNamespaceName(namespaceName); deleteRule.setBranchName(branchName); deleteRule.setBranchStatus(branchStatus); deleteRule.setDataChangeLastModifiedBy(operator); deleteRule.setDataChangeCreatedBy(operator); doUpdateBranchGrayRules(appId, clusterName, namespaceName, branchName, deleteRule, false, -1); //delete branch cluster clusterService.delete(toDeleteCluster.getId(), operator); int releaseOperation = branchStatus == NamespaceBranchStatus.MERGED ? ReleaseOperation .GRAY_RELEASE_DELETED_AFTER_MERGE : ReleaseOperation.ABANDON_GRAY_RELEASE; releaseHistoryService.createReleaseHistory(appId, clusterName, namespaceName, branchName, latestBranchReleaseId, latestBranchReleaseId, releaseOperation, null, operator); auditService.audit("Branch", toDeleteCluster.getId(), Audit.OP.DELETE, operator); } private Cluster createChildCluster(String appId, Cluster parentCluster, String namespaceName, String operator) { Cluster childCluster = new Cluster(); childCluster.setAppId(appId); childCluster.setParentClusterId(parentCluster.getId()); childCluster.setName(UniqueKeyGenerator.generate(appId, parentCluster.getName(), namespaceName)); childCluster.setDataChangeCreatedBy(operator); childCluster.setDataChangeLastModifiedBy(operator); return childCluster; } private Namespace createNamespaceBranch(String appId, String clusterName, String namespaceName, String operator) { Namespace childNamespace = new Namespace(); childNamespace.setAppId(appId); childNamespace.setClusterName(clusterName); childNamespace.setNamespaceName(namespaceName); childNamespace.setDataChangeLastModifiedBy(operator); childNamespace.setDataChangeCreatedBy(operator); return childNamespace; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceLockService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.biz.entity.NamespaceLock; import com.ctrip.framework.apollo.biz.repository.NamespaceLockRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class NamespaceLockService { @Autowired private NamespaceLockRepository namespaceLockRepository; public NamespaceLock findLock(Long namespaceId){ return namespaceLockRepository.findByNamespaceId(namespaceId); } @Transactional public NamespaceLock tryLock(NamespaceLock lock){ return namespaceLockRepository.save(lock); } @Transactional public void unlock(Long namespaceId){ namespaceLockRepository.deleteByNamespaceId(namespaceId); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.Cluster; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.message.MessageSender; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.repository.NamespaceRepository; import com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator; import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.ConfigConsts; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @Service public class NamespaceService { private Gson gson = new Gson(); @Autowired private NamespaceRepository namespaceRepository; @Autowired private AuditService auditService; @Autowired private AppNamespaceService appNamespaceService; @Autowired private ItemService itemService; @Autowired private CommitService commitService; @Autowired private ReleaseService releaseService; @Autowired private ClusterService clusterService; @Autowired private NamespaceBranchService namespaceBranchService; @Autowired private ReleaseHistoryService releaseHistoryService; @Autowired private NamespaceLockService namespaceLockService; @Autowired private InstanceService instanceService; @Autowired private MessageSender messageSender; public Namespace findOne(Long namespaceId) { return namespaceRepository.findOne(namespaceId); } public Namespace findOne(String appId, String clusterName, String namespaceName) { return namespaceRepository.findByAppIdAndClusterNameAndNamespaceName(appId, clusterName, namespaceName); } public Namespace findPublicNamespaceForAssociatedNamespace(String clusterName, String namespaceName) { AppNamespace appNamespace = appNamespaceService.findPublicNamespaceByName(namespaceName); if (appNamespace == null) { throw new BadRequestException("namespace not exist"); } String appId = appNamespace.getAppId(); Namespace namespace = findOne(appId, clusterName, namespaceName); //default cluster's namespace if (Objects.equals(clusterName, ConfigConsts.CLUSTER_NAME_DEFAULT)) { return namespace; } //custom cluster's namespace not exist. //return default cluster's namespace if (namespace == null) { return findOne(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, namespaceName); } //custom cluster's namespace exist and has published. //return custom cluster's namespace Release latestActiveRelease = releaseService.findLatestActiveRelease(namespace); if (latestActiveRelease != null) { return namespace; } Namespace defaultNamespace = findOne(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, namespaceName); //custom cluster's namespace exist but never published. //and default cluster's namespace not exist. //return custom cluster's namespace if (defaultNamespace == null) { return namespace; } //custom cluster's namespace exist but never published. //and default cluster's namespace exist and has published. //return default cluster's namespace Release defaultNamespaceLatestActiveRelease = releaseService.findLatestActiveRelease(defaultNamespace); if (defaultNamespaceLatestActiveRelease != null) { return defaultNamespace; } //custom cluster's namespace exist but never published. //and default cluster's namespace exist but never published. //return custom cluster's namespace return namespace; } public List findPublicAppNamespaceAllNamespaces(String namespaceName, Pageable page) { AppNamespace publicAppNamespace = appNamespaceService.findPublicNamespaceByName(namespaceName); if (publicAppNamespace == null) { throw new BadRequestException( String.format("Public appNamespace not exists. NamespaceName = %s", namespaceName)); } List namespaces = namespaceRepository.findByNamespaceName(namespaceName, page); return filterChildNamespace(namespaces); } private List filterChildNamespace(List namespaces) { List result = new LinkedList<>(); if (CollectionUtils.isEmpty(namespaces)) { return result; } for (Namespace namespace : namespaces) { if (!isChildNamespace(namespace)) { result.add(namespace); } } return result; } public int countPublicAppNamespaceAssociatedNamespaces(String publicNamespaceName) { AppNamespace publicAppNamespace = appNamespaceService.findPublicNamespaceByName(publicNamespaceName); if (publicAppNamespace == null) { throw new BadRequestException( String.format("Public appNamespace not exists. NamespaceName = %s", publicNamespaceName)); } return namespaceRepository.countByNamespaceNameAndAppIdNot(publicNamespaceName, publicAppNamespace.getAppId()); } public List findNamespaces(String appId, String clusterName) { List namespaces = namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(appId, clusterName); if (namespaces == null) { return Collections.emptyList(); } return namespaces; } public List findByAppIdAndNamespaceName(String appId, String namespaceName) { return namespaceRepository.findByAppIdAndNamespaceName(appId, namespaceName); } public Namespace findChildNamespace(String appId, String parentClusterName, String namespaceName) { List namespaces = findByAppIdAndNamespaceName(appId, namespaceName); if (CollectionUtils.isEmpty(namespaces) || namespaces.size() == 1) { return null; } List childClusters = clusterService.findChildClusters(appId, parentClusterName); if (CollectionUtils.isEmpty(childClusters)) { return null; } Set childClusterNames = childClusters.stream().map(Cluster::getName).collect(Collectors.toSet()); //the child namespace is the intersection of the child clusters and child namespaces for (Namespace namespace : namespaces) { if (childClusterNames.contains(namespace.getClusterName())) { return namespace; } } return null; } public Namespace findChildNamespace(Namespace parentNamespace) { String appId = parentNamespace.getAppId(); String parentClusterName = parentNamespace.getClusterName(); String namespaceName = parentNamespace.getNamespaceName(); return findChildNamespace(appId, parentClusterName, namespaceName); } public Namespace findParentNamespace(String appId, String clusterName, String namespaceName) { return findParentNamespace(new Namespace(appId, clusterName, namespaceName)); } public Namespace findParentNamespace(Namespace namespace) { String appId = namespace.getAppId(); String namespaceName = namespace.getNamespaceName(); Cluster cluster = clusterService.findOne(appId, namespace.getClusterName()); if (cluster != null && cluster.getParentClusterId() > 0) { Cluster parentCluster = clusterService.findOne(cluster.getParentClusterId()); return findOne(appId, parentCluster.getName(), namespaceName); } return null; } public boolean isChildNamespace(String appId, String clusterName, String namespaceName) { return isChildNamespace(new Namespace(appId, clusterName, namespaceName)); } public boolean isChildNamespace(Namespace namespace) { return findParentNamespace(namespace) != null; } public boolean isNamespaceUnique(String appId, String cluster, String namespace) { Objects.requireNonNull(appId, "AppId must not be null"); Objects.requireNonNull(cluster, "Cluster must not be null"); Objects.requireNonNull(namespace, "Namespace must not be null"); return Objects.isNull( namespaceRepository.findByAppIdAndClusterNameAndNamespaceName(appId, cluster, namespace)); } @Transactional public void deleteByAppIdAndClusterName(String appId, String clusterName, String operator) { List toDeleteNamespaces = findNamespaces(appId, clusterName); for (Namespace namespace : toDeleteNamespaces) { deleteNamespace(namespace, operator); } } @Transactional public Namespace deleteNamespace(Namespace namespace, String operator) { String appId = namespace.getAppId(); String clusterName = namespace.getClusterName(); String namespaceName = namespace.getNamespaceName(); itemService.batchDelete(namespace.getId(), operator); commitService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator); if (!isChildNamespace(namespace)) { releaseService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator); } //delete child namespace Namespace childNamespace = findChildNamespace(namespace); if (childNamespace != null) { namespaceBranchService.deleteBranch(appId, clusterName, namespaceName, childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator); //delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, operator); } releaseHistoryService.batchDelete(appId, clusterName, namespaceName, operator); instanceService.batchDeleteInstanceConfig(appId, clusterName, namespaceName); namespaceLockService.unlock(namespace.getId()); namespace.setDeleted(true); namespace.setDataChangeLastModifiedBy(operator); auditService.audit(Namespace.class.getSimpleName(), namespace.getId(), Audit.OP.DELETE, operator); Namespace deleted = namespaceRepository.save(namespace); //Publish release message to do some clean up in config service, such as updating the cache messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName), Topics.APOLLO_RELEASE_TOPIC); return deleted; } @Transactional public Namespace save(Namespace entity) { if (!isNamespaceUnique(entity.getAppId(), entity.getClusterName(), entity.getNamespaceName())) { throw new ServiceException("namespace not unique"); } entity.setId(0);//protection Namespace namespace = namespaceRepository.save(entity); auditService.audit(Namespace.class.getSimpleName(), namespace.getId(), Audit.OP.INSERT, namespace.getDataChangeCreatedBy()); return namespace; } @Transactional public Namespace update(Namespace namespace) { Namespace managedNamespace = namespaceRepository.findByAppIdAndClusterNameAndNamespaceName( namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName()); BeanUtils.copyEntityProperties(namespace, managedNamespace); managedNamespace = namespaceRepository.save(managedNamespace); auditService.audit(Namespace.class.getSimpleName(), managedNamespace.getId(), Audit.OP.UPDATE, managedNamespace.getDataChangeLastModifiedBy()); return managedNamespace; } @Transactional public void instanceOfAppNamespaces(String appId, String clusterName, String createBy) { List appNamespaces = appNamespaceService.findByAppId(appId); for (AppNamespace appNamespace : appNamespaces) { Namespace ns = new Namespace(); ns.setAppId(appId); ns.setClusterName(clusterName); ns.setNamespaceName(appNamespace.getName()); ns.setDataChangeCreatedBy(createBy); ns.setDataChangeLastModifiedBy(createBy); namespaceRepository.save(ns); auditService.audit(Namespace.class.getSimpleName(), ns.getId(), Audit.OP.INSERT, createBy); } } public Map namespacePublishInfo(String appId) { List clusters = clusterService.findParentClusters(appId); if (CollectionUtils.isEmpty(clusters)) { throw new BadRequestException("app not exist"); } Map clusterHasNotPublishedItems = Maps.newHashMap(); for (Cluster cluster : clusters) { String clusterName = cluster.getName(); List namespaces = findNamespaces(appId, clusterName); for (Namespace namespace : namespaces) { boolean isNamespaceNotPublished = isNamespaceNotPublished(namespace); if (isNamespaceNotPublished) { clusterHasNotPublishedItems.put(clusterName, true); break; } } clusterHasNotPublishedItems.putIfAbsent(clusterName, false); } return clusterHasNotPublishedItems; } private boolean isNamespaceNotPublished(Namespace namespace) { Release latestRelease = releaseService.findLatestActiveRelease(namespace); long namespaceId = namespace.getId(); if (latestRelease == null) { Item lastItem = itemService.findLastOne(namespaceId); return lastItem != null; } Date lastPublishTime = latestRelease.getDataChangeLastModifiedTime(); List itemsModifiedAfterLastPublish = itemService.findItemsModifiedAfterDate(namespaceId, lastPublishTime); if (CollectionUtils.isEmpty(itemsModifiedAfterLastPublish)) { return false; } Map publishedConfiguration = gson.fromJson(latestRelease.getConfigurations(), GsonType.CONFIG); for (Item item : itemsModifiedAfterLastPublish) { if (!Objects.equals(item.getValue(), publishedConfiguration.get(item.getKey()))) { return true; } } return false; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseHistoryService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.gson.Gson; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.ReleaseHistory; import com.ctrip.framework.apollo.biz.repository.ReleaseHistoryRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; import java.util.Map; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ReleaseHistoryService { private Gson gson = new Gson(); @Autowired private ReleaseHistoryRepository releaseHistoryRepository; @Autowired private AuditService auditService; public Page findReleaseHistoriesByNamespace(String appId, String clusterName, String namespaceName, Pageable pageable) { return releaseHistoryRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId, clusterName, namespaceName, pageable); } public Page findByReleaseIdAndOperation(long releaseId, int operation, Pageable page) { return releaseHistoryRepository.findByReleaseIdAndOperationOrderByIdDesc(releaseId, operation, page); } public Page findByPreviousReleaseIdAndOperation(long previousReleaseId, int operation, Pageable page) { return releaseHistoryRepository.findByPreviousReleaseIdAndOperationOrderByIdDesc(previousReleaseId, operation, page); } @Transactional public ReleaseHistory createReleaseHistory(String appId, String clusterName, String namespaceName, String branchName, long releaseId, long previousReleaseId, int operation, Map operationContext, String operator) { ReleaseHistory releaseHistory = new ReleaseHistory(); releaseHistory.setAppId(appId); releaseHistory.setClusterName(clusterName); releaseHistory.setNamespaceName(namespaceName); releaseHistory.setBranchName(branchName); releaseHistory.setReleaseId(releaseId); releaseHistory.setPreviousReleaseId(previousReleaseId); releaseHistory.setOperation(operation); if (operationContext == null) { releaseHistory.setOperationContext("{}"); //default empty object } else { releaseHistory.setOperationContext(gson.toJson(operationContext)); } releaseHistory.setDataChangeCreatedTime(new Date()); releaseHistory.setDataChangeCreatedBy(operator); releaseHistory.setDataChangeLastModifiedBy(operator); releaseHistoryRepository.save(releaseHistory); auditService.audit(ReleaseHistory.class.getSimpleName(), releaseHistory.getId(), Audit.OP.INSERT, releaseHistory.getDataChangeCreatedBy()); return releaseHistory; } @Transactional public int batchDelete(String appId, String clusterName, String namespaceName, String operator) { return releaseHistoryRepository.batchDelete(appId, clusterName, namespaceName, operator); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseMessageService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.Collection; import java.util.Collections; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ReleaseMessageService { @Autowired private ReleaseMessageRepository releaseMessageRepository; public ReleaseMessage findLatestReleaseMessageForMessages(Collection messages) { if (CollectionUtils.isEmpty(messages)) { return null; } return releaseMessageRepository.findTopByMessageInOrderByIdDesc(messages); } public List findLatestReleaseMessagesGroupByMessages(Collection messages) { if (CollectionUtils.isEmpty(messages)) { return Collections.emptyList(); } List result = releaseMessageRepository.findLatestReleaseMessagesGroupByMessages(messages); List releaseMessages = Lists.newArrayList(); for (Object[] o : result) { try { ReleaseMessage releaseMessage = new ReleaseMessage((String) o[0]); releaseMessage.setId((Long) o[1]); releaseMessages.add(releaseMessage); } catch (Exception ex) { Tracer.logError("Parsing LatestReleaseMessagesGroupByMessages failed", ex); } } return releaseMessages; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ReleaseService.java ================================================ package com.ctrip.framework.apollo.biz.service; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.NamespaceLock; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.repository.ReleaseRepository; import com.ctrip.framework.apollo.biz.utils.ReleaseKeyGenerator; import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.constants.ReleaseOperation; import com.ctrip.framework.apollo.common.constants.ReleaseOperationContext; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.GrayReleaseRuleItemTransformer; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.apache.commons.lang.time.FastDateFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ReleaseService { private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss"); private Gson gson = new Gson(); @Autowired private ReleaseRepository releaseRepository; @Autowired private ItemService itemService; @Autowired private AuditService auditService; @Autowired private NamespaceLockService namespaceLockService; @Autowired private NamespaceService namespaceService; @Autowired private NamespaceBranchService namespaceBranchService; @Autowired private ReleaseHistoryService releaseHistoryService; @Autowired private ItemSetService itemSetService; public Release findOne(long releaseId) { return releaseRepository.findOne(releaseId); } public Release findActiveOne(long releaseId) { return releaseRepository.findByIdAndIsAbandonedFalse(releaseId); } public List findByReleaseIds(Set releaseIds) { Iterable releases = releaseRepository.findAll(releaseIds); if (releases == null) { return Collections.emptyList(); } return Lists.newArrayList(releases); } public List findByReleaseKeys(Set releaseKeys) { return releaseRepository.findByReleaseKeyIn(releaseKeys); } public Release findLatestActiveRelease(Namespace namespace) { return findLatestActiveRelease(namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName()); } public Release findLatestActiveRelease(String appId, String clusterName, String namespaceName) { return releaseRepository.findFirstByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(appId, clusterName, namespaceName); } public List findAllReleases(String appId, String clusterName, String namespaceName, Pageable page) { List releases = releaseRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId, clusterName, namespaceName, page); if (releases == null) { return Collections.emptyList(); } return releases; } public List findActiveReleases(String appId, String clusterName, String namespaceName, Pageable page) { List releases = releaseRepository.findByAppIdAndClusterNameAndNamespaceNameAndIsAbandonedFalseOrderByIdDesc(appId, clusterName, namespaceName, page); if (releases == null) { return Collections.emptyList(); } return releases; } @Transactional public Release mergeBranchChangeSetsAndRelease(Namespace namespace, String branchName, String releaseName, String releaseComment, boolean isEmergencyPublish, ItemChangeSets changeSets) { checkLock(namespace, isEmergencyPublish, changeSets.getDataChangeLastModifiedBy()); itemSetService.updateSet(namespace, changeSets); Release branchRelease = findLatestActiveRelease(namespace.getAppId(), branchName, namespace .getNamespaceName()); long branchReleaseId = branchRelease == null ? 0 : branchRelease.getId(); Map operateNamespaceItems = getNamespaceItems(namespace); Map operationContext = Maps.newHashMap(); operationContext.put(ReleaseOperationContext.SOURCE_BRANCH, branchName); operationContext.put(ReleaseOperationContext.BASE_RELEASE_ID, branchReleaseId); operationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish); return masterRelease(namespace, releaseName, releaseComment, operateNamespaceItems, changeSets.getDataChangeLastModifiedBy(), ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER, operationContext); } @Transactional public Release publish(Namespace namespace, String releaseName, String releaseComment, String operator, boolean isEmergencyPublish) { checkLock(namespace, isEmergencyPublish, operator); Map operateNamespaceItems = getNamespaceItems(namespace); Namespace parentNamespace = namespaceService.findParentNamespace(namespace); //branch release if (parentNamespace != null) { return publishBranchNamespace(parentNamespace, namespace, operateNamespaceItems, releaseName, releaseComment, operator, isEmergencyPublish); } Namespace childNamespace = namespaceService.findChildNamespace(namespace); Release previousRelease = null; if (childNamespace != null) { previousRelease = findLatestActiveRelease(namespace); } //master release Map operationContext = Maps.newHashMap(); operationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish); Release release = masterRelease(namespace, releaseName, releaseComment, operateNamespaceItems, operator, ReleaseOperation.NORMAL_RELEASE, operationContext); //merge to branch and auto release if (childNamespace != null) { mergeFromMasterAndPublishBranch(namespace, childNamespace, operateNamespaceItems, releaseName, releaseComment, operator, previousRelease, release, isEmergencyPublish); } return release; } private void checkLock(Namespace namespace, boolean isEmergencyPublish, String operator) { if (!isEmergencyPublish) { NamespaceLock lock = namespaceLockService.findLock(namespace.getId()); if (lock != null && lock.getDataChangeCreatedBy().equals(operator)) { throw new BadRequestException("Config can not be published by yourself."); } } } private void mergeFromMasterAndPublishBranch(Namespace parentNamespace, Namespace childNamespace, Map parentNamespaceItems, String releaseName, String releaseComment, String operator, Release masterPreviousRelease, Release parentRelease, boolean isEmergencyPublish) { //create release for child namespace Map childReleaseConfiguration = getNamespaceReleaseConfiguration(childNamespace); Map parentNamespaceOldConfiguration = masterPreviousRelease == null ? null : gson.fromJson(masterPreviousRelease.getConfigurations(), GsonType.CONFIG); Map childNamespaceToPublishConfigs = calculateChildNamespaceToPublishConfiguration(parentNamespaceOldConfiguration, parentNamespaceItems, childNamespace); //compare if (!childNamespaceToPublishConfigs.equals(childReleaseConfiguration)) { branchRelease(parentNamespace, childNamespace, releaseName, releaseComment, childNamespaceToPublishConfigs, parentRelease.getId(), operator, ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY, isEmergencyPublish); } } private Release publishBranchNamespace(Namespace parentNamespace, Namespace childNamespace, Map childNamespaceItems, String releaseName, String releaseComment, String operator, boolean isEmergencyPublish) { Release parentLatestRelease = findLatestActiveRelease(parentNamespace); Map parentConfigurations = parentLatestRelease != null ? gson.fromJson(parentLatestRelease.getConfigurations(), GsonType.CONFIG) : new HashMap<>(); long baseReleaseId = parentLatestRelease == null ? 0 : parentLatestRelease.getId(); Map childNamespaceToPublishConfigs = mergeConfiguration(parentConfigurations, childNamespaceItems); return branchRelease(parentNamespace, childNamespace, releaseName, releaseComment, childNamespaceToPublishConfigs, baseReleaseId, operator, ReleaseOperation.GRAY_RELEASE, isEmergencyPublish); } private Release masterRelease(Namespace namespace, String releaseName, String releaseComment, Map configurations, String operator, int releaseOperation, Map operationContext) { Release lastActiveRelease = findLatestActiveRelease(namespace); long previousReleaseId = lastActiveRelease == null ? 0 : lastActiveRelease.getId(); Release release = createRelease(namespace, releaseName, releaseComment, configurations, operator); releaseHistoryService.createReleaseHistory(namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName(), namespace.getClusterName(), release.getId(), previousReleaseId, releaseOperation, operationContext, operator); return release; } private Release branchRelease(Namespace parentNamespace, Namespace childNamespace, String releaseName, String releaseComment, Map configurations, long baseReleaseId, String operator, int releaseOperation, boolean isEmergencyPublish) { Release previousRelease = findLatestActiveRelease(childNamespace.getAppId(), childNamespace.getClusterName(), childNamespace.getNamespaceName()); long previousReleaseId = previousRelease == null ? 0 : previousRelease.getId(); Map releaseOperationContext = Maps.newHashMap(); releaseOperationContext.put(ReleaseOperationContext.BASE_RELEASE_ID, baseReleaseId); releaseOperationContext.put(ReleaseOperationContext.IS_EMERGENCY_PUBLISH, isEmergencyPublish); Release release = createRelease(childNamespace, releaseName, releaseComment, configurations, operator); //update gray release rules GrayReleaseRule grayReleaseRule = namespaceBranchService.updateRulesReleaseId(childNamespace.getAppId(), parentNamespace.getClusterName(), childNamespace.getNamespaceName(), childNamespace.getClusterName(), release.getId(), operator); if (grayReleaseRule != null) { releaseOperationContext.put(ReleaseOperationContext.RULES, GrayReleaseRuleItemTransformer .batchTransformFromJSON(grayReleaseRule.getRules())); } releaseHistoryService.createReleaseHistory(parentNamespace.getAppId(), parentNamespace.getClusterName(), parentNamespace.getNamespaceName(), childNamespace.getClusterName(), release.getId(), previousReleaseId, releaseOperation, releaseOperationContext, operator); return release; } private Map mergeConfiguration(Map baseConfigurations, Map coverConfigurations) { Map result = new HashMap<>(); //copy base configuration for (Map.Entry entry : baseConfigurations.entrySet()) { result.put(entry.getKey(), entry.getValue()); } //update and publish for (Map.Entry entry : coverConfigurations.entrySet()) { result.put(entry.getKey(), entry.getValue()); } return result; } private Map getNamespaceItems(Namespace namespace) { List items = itemService.findItemsWithoutOrdered(namespace.getId()); Map configurations = new HashMap(); for (Item item : items) { if (StringUtils.isEmpty(item.getKey())) { continue; } configurations.put(item.getKey(), item.getValue()); } return configurations; } private Map getNamespaceReleaseConfiguration(Namespace namespace) { Release release = findLatestActiveRelease(namespace); Map configuration = new HashMap<>(); if (release != null) { configuration = new Gson().fromJson(release.getConfigurations(), GsonType.CONFIG); } return configuration; } private Release createRelease(Namespace namespace, String name, String comment, Map configurations, String operator) { Release release = new Release(); release.setReleaseKey(ReleaseKeyGenerator.generateReleaseKey(namespace)); release.setDataChangeCreatedTime(new Date()); release.setDataChangeCreatedBy(operator); release.setDataChangeLastModifiedBy(operator); release.setName(name); release.setComment(comment); release.setAppId(namespace.getAppId()); release.setClusterName(namespace.getClusterName()); release.setNamespaceName(namespace.getNamespaceName()); release.setConfigurations(gson.toJson(configurations)); release = releaseRepository.save(release); namespaceLockService.unlock(namespace.getId()); auditService.audit(Release.class.getSimpleName(), release.getId(), Audit.OP.INSERT, release.getDataChangeCreatedBy()); return release; } @Transactional public Release rollback(long releaseId, String operator) { Release release = findOne(releaseId); if (release == null) { throw new NotFoundException("release not found"); } if (release.isAbandoned()) { throw new BadRequestException("release is not active"); } String appId = release.getAppId(); String clusterName = release.getClusterName(); String namespaceName = release.getNamespaceName(); PageRequest page = new PageRequest(0, 2); List twoLatestActiveReleases = findActiveReleases(appId, clusterName, namespaceName, page); if (twoLatestActiveReleases == null || twoLatestActiveReleases.size() < 2) { throw new BadRequestException(String.format( "Can't rollback namespace(appId=%s, clusterName=%s, namespaceName=%s) because there is only one active release", appId, clusterName, namespaceName)); } release.setAbandoned(true); release.setDataChangeLastModifiedBy(operator); releaseRepository.save(release); releaseHistoryService.createReleaseHistory(appId, clusterName, namespaceName, clusterName, twoLatestActiveReleases.get(1).getId(), release.getId(), ReleaseOperation.ROLLBACK, null, operator); //publish child namespace if namespace has child rollbackChildNamespace(appId, clusterName, namespaceName, twoLatestActiveReleases, operator); return release; } private void rollbackChildNamespace(String appId, String clusterName, String namespaceName, List parentNamespaceTwoLatestActiveRelease, String operator) { Namespace parentNamespace = namespaceService.findOne(appId, clusterName, namespaceName); Namespace childNamespace = namespaceService.findChildNamespace(appId, clusterName, namespaceName); if (parentNamespace == null || childNamespace == null) { return; } Release abandonedRelease = parentNamespaceTwoLatestActiveRelease.get(0); Release parentNamespaceNewLatestRelease = parentNamespaceTwoLatestActiveRelease.get(1); Map parentNamespaceAbandonedConfiguration = gson.fromJson(abandonedRelease.getConfigurations(), GsonType.CONFIG); Map parentNamespaceNewLatestConfiguration = gson.fromJson(parentNamespaceNewLatestRelease.getConfigurations(), GsonType.CONFIG); Map childNamespaceNewConfiguration = calculateChildNamespaceToPublishConfiguration(parentNamespaceAbandonedConfiguration, parentNamespaceNewLatestConfiguration, childNamespace); branchRelease(parentNamespace, childNamespace, TIMESTAMP_FORMAT.format(new Date()) + "-master-rollback-merge-to-gray", "", childNamespaceNewConfiguration, parentNamespaceNewLatestRelease.getId(), operator, ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY, false); } private Map calculateChildNamespaceToPublishConfiguration( Map parentNamespaceOldConfiguration, Map parentNamespaceNewConfiguration, Namespace childNamespace) { //first. calculate child namespace modified configs Release childNamespaceLatestActiveRelease = findLatestActiveRelease(childNamespace); Map childNamespaceLatestActiveConfiguration = childNamespaceLatestActiveRelease == null ? null : gson.fromJson(childNamespaceLatestActiveRelease .getConfigurations(), GsonType.CONFIG); Map childNamespaceModifiedConfiguration = calculateBranchModifiedItemsAccordingToRelease( parentNamespaceOldConfiguration, childNamespaceLatestActiveConfiguration); //second. append child namespace modified configs to parent namespace new latest configuration return mergeConfiguration(parentNamespaceNewConfiguration, childNamespaceModifiedConfiguration); } private Map calculateBranchModifiedItemsAccordingToRelease( Map masterReleaseConfigs, Map branchReleaseConfigs) { Map modifiedConfigs = new HashMap<>(); if (CollectionUtils.isEmpty(branchReleaseConfigs)) { return modifiedConfigs; } if (CollectionUtils.isEmpty(masterReleaseConfigs)) { return branchReleaseConfigs; } for (Map.Entry entry : branchReleaseConfigs.entrySet()) { if (!Objects.equals(entry.getValue(), masterReleaseConfigs.get(entry.getKey()))) { modifiedConfigs.put(entry.getKey(), entry.getValue()); } } return modifiedConfigs; } @Transactional public int batchDelete(String appId, String clusterName, String namespaceName, String operator) { return releaseRepository.batchDelete(appId, clusterName, namespaceName, operator); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/ConfigChangeContentBuilder.java ================================================ package com.ctrip.framework.apollo.biz.utils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.ctrip.framework.apollo.biz.entity.Item; import com.ctrip.framework.apollo.core.utils.StringUtils; import java.util.Date; import java.util.LinkedList; import java.util.List; import org.springframework.beans.BeanUtils; public class ConfigChangeContentBuilder { private static final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create(); private List createItems = new LinkedList<>(); private List updateItems = new LinkedList<>(); private List deleteItems = new LinkedList<>(); public ConfigChangeContentBuilder createItem(Item item) { if (!StringUtils.isEmpty(item.getKey())){ createItems.add(cloneItem(item)); } return this; } public ConfigChangeContentBuilder updateItem(Item oldItem, Item newItem) { if (!oldItem.getValue().equals(newItem.getValue())){ ItemPair itemPair = new ItemPair(cloneItem(oldItem), cloneItem(newItem)); updateItems.add(itemPair); } return this; } public ConfigChangeContentBuilder deleteItem(Item item) { if (!StringUtils.isEmpty(item.getKey())) { deleteItems.add(cloneItem(item)); } return this; } public boolean hasContent(){ return !createItems.isEmpty() || !updateItems.isEmpty() || !deleteItems.isEmpty(); } public String build() { //因为事务第一段提交并没有更新时间,所以build时统一更新 Date now = new Date(); for (Item item : createItems) { item.setDataChangeLastModifiedTime(now); } for (ItemPair item : updateItems) { item.newItem.setDataChangeLastModifiedTime(now); } for (Item item : deleteItems) { item.setDataChangeLastModifiedTime(now); } return gson.toJson(this); } static class ItemPair { Item oldItem; Item newItem; public ItemPair(Item oldItem, Item newItem) { this.oldItem = oldItem; this.newItem = newItem; } } Item cloneItem(Item source) { Item target = new Item(); BeanUtils.copyProperties(source, target); return target; } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/EntityManagerUtil.java ================================================ package com.ctrip.framework.apollo.biz.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.orm.jpa.EntityManagerFactoryAccessor; import org.springframework.orm.jpa.EntityManagerFactoryUtils; import org.springframework.orm.jpa.EntityManagerHolder; import org.springframework.stereotype.Component; import org.springframework.transaction.support.TransactionSynchronizationManager; /** * @author Jason Song(song_s@ctrip.com) */ @Component public class EntityManagerUtil extends EntityManagerFactoryAccessor { private static final Logger logger = LoggerFactory.getLogger(EntityManagerUtil.class); /** * close the entity manager. * Use it with caution! This is only intended for use with async request, which Spring won't * close the entity manager until the async request is finished. */ public void closeEntityManager() { EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getEntityManagerFactory()); if (emHolder == null) { return; } logger.debug("Closing JPA EntityManager in EntityManagerUtil"); EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager()); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/ReleaseKeyGenerator.java ================================================ package com.ctrip.framework.apollo.biz.utils; import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.common.utils.UniqueKeyGenerator; /** * @author Jason Song(song_s@ctrip.com) */ public class ReleaseKeyGenerator extends UniqueKeyGenerator { /** * Generate the release key in the format: timestamp+appId+cluster+namespace+hash(ipAsInt+counter) * * @param namespace the namespace of the release * @return the unique release key */ public static String generateReleaseKey(Namespace namespace) { return generate(namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName()); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/utils/ReleaseMessageKeyGenerator.java ================================================ package com.ctrip.framework.apollo.biz.utils; import com.google.common.base.Joiner; import com.ctrip.framework.apollo.core.ConfigConsts; public class ReleaseMessageKeyGenerator { private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); public static String generate(String appId, String cluster, String namespace) { return STRING_JOINER.join(appId, cluster, namespace); } } ================================================ FILE: open-config-center/apollo/apollo-biz/src/test/resources/application.properties ================================================ spring.datasource.url = jdbc:h2:mem:~/apolloconfigdb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy spring.jpa.properties.hibernate.show_sql=true spring.h2.console.enabled = true spring.h2.console.settings.web-allow-others=true ================================================ FILE: open-config-center/apollo/apollo-biz/src/test/resources/data.sql ================================================ INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003171', 'application', false); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003171', 'fx.apollo.config', true); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003172', 'application', false); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003172', 'fx.apollo.admin', true); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003173', 'application', false); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('100003173', 'fx.apollo.portal', true); INSERT INTO AppNamespace (AppID, Name, IsPublic) VALUES ('fxhermesproducer', 'fx.hermes.producer', true); ================================================ FILE: open-config-center/apollo/apollo-biz/src/test/resources/logback-test.xml ================================================ utf-8 [%p] %c - %m%n ================================================ FILE: open-config-center/apollo/apollo-biz/src/test/resources/sql/clean.sql ================================================ DELETE FROM App; DELETE FROM AppNamespace; DELETE FROM Cluster; DELETE FROM namespace; DELETE FROM grayreleaserule; DELETE FROM release; DELETE FROM item; DELETE FROM releasemessage; DELETE FROM releasehistory; DELETE FROM namespacelock; DELETE FROM `commit`; ================================================ FILE: open-config-center/apollo/apollo-biz/src/test/resources/sql/namespace-branch-test.sql ================================================ INSERT INTO `app` ( `AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'test0620-06', 'default', 'default', 'default', 'default', 0, 'default', 'default'); INSERT INTO `cluster` (`ID`, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (1, 'default', 'test', 0, 0, 'default', 'default'); INSERT INTO `cluster` (`Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('child-cluster', 'test', 1, 0, 'default', 'default'); INSERT INTO `namespace` (`AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'default', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (`AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'child-cluster', 'application', 0, 'apollo', 'apollo'); ================================================ FILE: open-config-center/apollo/apollo-biz/src/test/resources/sql/namespace-test.sql ================================================ INSERT INTO `app` ( `AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('testApp', 'test', 'default', 'default', 'default', 'default', 0, 'default', 'default'); INSERT INTO `cluster` (`ID`, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (1, 'default', 'testApp', 0, 0, 'default', 'default'); INSERT INTO `cluster` (`Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('child-cluster', 'testApp', 1, 0, 'default', 'default'); INSERT INTO `appnamespace` (`Name`, `AppId`, `Format`, `IsPublic`) VALUES ( 'application', 'testApp', 'properties', 0); INSERT INTO `namespace` (`ID`, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1,'testApp', 'default', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (`AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('testApp', 'child-cluster', 'application', 0, 'apollo', 'apollo'); INSERT INTO `commit` (`ChangeSets`, `AppId`, `ClusterName`, `NamespaceName`)VALUES('{}', 'testApp', 'default', 'application'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `LineNum`)VALUES(1, 'k1', 'v1', '', 1); INSERT INTO `namespacelock` (`NamespaceId`)VALUES(1); INSERT INTO `release` (`AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES('branch-test', 'default', 'application', '{}', 0); INSERT INTO `release` (`AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES('branch-test', 'child-cluster', 'application', '{}', 0); INSERT INTO `releasehistory` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `ReleaseId`, `PreviousReleaseId`, `Operation`, `OperationContext`)VALUES('branch-test', 'default', 'application', 'default', 0, 0, 7, '{}'); INSERT INTO `instanceconfig` (`ID`, `InstanceId`, `ConfigAppId`, `ConfigClusterName`, `ConfigNamespaceName`, `ReleaseKey`, `ReleaseDeliveryTime`, `DataChange_CreatedTime`, `DataChange_LastTime`) VALUES (1, 90, 'testApp', 'default', 'application', '20160829134524-dee271ddf9fced58', '2016-08-29 13:45:24', '2016-08-30 17:03:32', '2016-10-19 11:13:47'); ================================================ FILE: open-config-center/apollo/apollo-biz/src/test/resources/sql/release-creation-test.sql ================================================ INSERT INTO `app` ( `AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES('test', 'test0620-06', 'default', 'default', 'default', 'default', 0, 'default', 'default'); /* normal namespace*/ INSERT INTO `cluster` ( `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES ( 'only-master', 'test', 0, 0, 'default', 'default'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'test', 'only-master', 'application', 0, 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'k1', 'v1', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'k2', 'v2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(100, 'k3', 'v3', '', 'apollo', 'apollo'); /* namespace has branch. master has items but branch has not item*/ INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (101, 'default1', 'test', 0, 0, 'default', 'default'); INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(102, 'child-cluster1', 'test', 101, 0, 'default', 'default'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'test', 'default1', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(102, 'test', 'child-cluster1', 'application', 0, 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'k1', 'v1', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'k2', 'v2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(101, 'k3', 'v3', '', 'apollo', 'apollo'); INSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default1', 'application', 'child-cluster1', '[]', 1155, 1); /* namespace has branch. master has items and branch has item*/ INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (103, 'default2', 'test', 0, 0, 'default', 'default'); INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(104, 'child-cluster2', 'test', 103, 0, 'default', 'default'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'test', 'default2', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(104, 'test', 'child-cluster2', 'application', 0, 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'k1', 'v1', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'k2', 'v2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(103, 'k3', 'v3', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(104, 'k1', 'v1-1', '', 'apollo', 'apollo'); INSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default2', 'application', 'child-cluster2', '[]', 1155, 1); /* namespace has branch. master has items and branch has cover item */ INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (105, 'default3', 'test', 0, 0, 'default', 'default'); INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(106, 'child-cluster3', 'test', 105, 0, 'default', 'default'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(105, 'test', 'default3', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(106, 'test', 'child-cluster3', 'application', 0, 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(105, 'k1', 'v1', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(105, 'k2', 'v2-2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(106, 'k1', 'v1-2', '', 'apollo', 'apollo'); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(1, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default3', 'application', '{"k1":"v1","k2":"v2","k3":"v3"}', 0); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(2, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster3', 'application', '{"k1":"v1-1","k2":"v2","k3":"v3"}', 0); INSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default3', 'application', 'child-cluster3', '[]', 1155, 1); /*publish branch at first time */ INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (107, 'default4', 'test', 0, 0, 'default', 'default'); INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'child-cluster4', 'test', 107, 0, 'default', 'default'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(107, 'test', 'default4', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'test', 'child-cluster4', 'application', 0, 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(107, 'k1', 'v1', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(107, 'k2', 'v2-2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'k1', 'v1-2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(108, 'k4', 'v4', '', 'apollo', 'apollo'); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(3, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default4', 'application', '{"k1":"v1","k2":"v2","k3":"v3"}', 0); INSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default4', 'application', 'child-cluster4', '[]', 1155, 1); /*publish branch*/ INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (109, 'default5', 'test', 0, 0, 'default', 'default'); INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'child-cluster5', 'test', 109, 0, 'default', 'default'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(109, 'test', 'default5', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'test', 'child-cluster5', 'application', 0, 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(109, 'k1', 'v1', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(109, 'k2', 'v2-2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'k1', 'v1-2', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'k4', 'v4', '', 'apollo', 'apollo'); INSERT INTO `item` (`NamespaceId`, `Key`, `Value`, `Comment`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1010, 'k6', 'v6', '', 'apollo', 'apollo'); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(4, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default5', 'application', '{"k1":"v1","k2":"v2","k3":"v3"}', 0); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(5, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster5', 'application', '{"k1":"v1-1","k2":"v2","k3":"v3","k4":"v4","k5":"v5"}', 0); INSERT INTO `grayreleaserule` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`)VALUES ('test', 'default5', 'application', 'child-cluster5', '[]', 1155, 1); /* rollback */ INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (1011, 'default6', 'test', 0, 0, 'default', 'default'); INSERT INTO `cluster` (ID, `Name`, `AppId`, `ParentClusterId`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1012, 'child-cluster6', 'test', 1011, 0, 'default', 'default'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1011, 'test', 'default6', 'application', 0, 'apollo', 'apollo'); INSERT INTO `namespace` (ID, `AppId`, `ClusterName`, `NamespaceName`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)VALUES(1012, 'test', 'child-cluster6', 'application', 0, 'apollo', 'apollo'); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(6, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default6', 'application', '{"k1":"v1-1","k2":"v2-1","k3":"v3"}', 0); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(7, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'default6', 'application', '{"k1":"v1","k2":"v2"}', 0); INSERT INTO `release` (`Id`, `ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`, `IsAbandoned`)VALUES(8, '20160823102253-fc0071ddf9fd3260', '20160823101703-release', '', 'test', 'child-cluster6', 'application', '{"k1":"v1-2","k2":"v2-1","k3":"v3"}', 0); ================================================ FILE: open-config-center/apollo/apollo-client/README.md ================================================ ## I. Prerequisite ### I.I Requirements * Java: 1.7+ ### I.II Mandatory Setup Apollo client requires `AppId` and `Environment` information available to function properly, so please read the following and configure them properly: #### 1. AppId AppId is the identity for the application, which is a key information to retrieve the config from server. AppId information should be put in `classpath:/META-INF/app.properties` with its key as `app.id`. For example, you could place the file as the following screenshot: ![app.properties example](doc/pic/app-id-location.png) And config the file as: > app.id=YOUR-APP-ID #### 2. Environment Apollo supports config by multiple environments, so environment is another key information to retrieve the config from server. Environment could be configured in 3 ways: 1. As Java System Property * You could specify environment as java system property `env` * For example, when starting the java application, it can be configured via `-Denv=YOUR-ENVIRONMENT` * Please note the key should be lower case 2. As OS System Environment * You could also specify environment as system environment `ENV` * Please note the key should be UPPER CASE 3. As Property File * You could create a file `/opt/settings/server.properties` on the target machine * And specify the environment in the file as `env=YOUR-ENVIRONMENT` * Please note the key should be lower case Currently, `env` allows the following values (case-insensitive): * DEV * FWS * FAT * UAT * PRO ### I.III Optional Setup #### Cluster Apollo supports config separated by clusters, which means for one appId and one environment, you could have different configs. If you need this functionality, you could specify the cluster as follows: 1. As Java System Property * You could specify cluster as java system property `apollo.cluster` * For example, when starting the java application, it can be configured via `-Dapollo.cluster=xxx` * Please note the key should be lower case 2. As Property file * You could create a file `/opt/settings/server.properties` on the target machine * And specify the idc cluster in the file as `idc=xxx` * Please note the key should be lower case ##### Cluster Precedence 1. If both `apollo.cluster` and `idc` are specified: * We will first try to load config from cluster specified as `apollo.cluster` * If not found, we will fall back to cluster specified as `idc` * If still not found, we will fall back to the default cluster `default` 2. If only `apollo.cluster` is specified: * We will first try to load config from cluster specified as `apollo.cluster` * If not found, we will fall back to the default cluster `default` 3. If only `idc` is specified: * We will first try to load config from cluster specified as `idc` * If not found, we will fall back to the default cluster `default` 4. If neither `apollo.cluster` nor `idc` is specified: * We will load config from the default cluster `default` ## II. Maven Dependency com.ctrip.framework.apollo apollo-client 0.9.1 ## III. Client Usage ### 1. Load config from default namespace(application) ```java Config config = ConfigService.getAppConfig(); String someKey = "someKeyFromDefaultNamespace"; String someDefaultValue = "someDefaultValueForTheKey"; System.out.println(String.format("Value for key %s is %s", someKey, config.getProperty(someKey, someDefaultValue))); ``` ### 2. Register config change listener ```java Config config = ConfigService.getAppConfig(); config.addChangeListener(new ConfigChangeListener() { @Override public void onChange(ConfigChangeEvent changeEvent) { System.out.println("Changes for namespace " + changeEvent.getNamespace()); for (String key : changeEvent.changedKeys()) { ConfigChange change = changeEvent.getChange(key); System.out.println(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType())); } } }); ``` ### 3. Load config from public namespace ```java String somePublicNamespace = "CAT"; Config config = ConfigService.getConfig(somePublicNamespace); String someKey = "someKeyFromPublicNamespace"; String someDefaultValue = "someDefaultValueForTheKey"; System.out.println(String.format("Value for key %s is %s", someKey, config.getProperty(someKey, someDefaultValue))); ``` ================================================ FILE: open-config-center/apollo/apollo-client/pom.xml ================================================ com.ctrip.framework.apollo apollo 0.10.0-SNAPSHOT 4.0.0 apollo-client Apollo Client 1.7 ${project.artifactId} com.ctrip.framework.apollo apollo-core com.google.inject guice org.slf4j slf4j-api org.springframework spring-context true org.springframework.boot spring-boot-autoconfigure true org.eclipse.jetty jetty-server test org.slf4j jcl-over-slf4j test org.apache.logging.log4j log4j-slf4j-impl test org.apache.logging.log4j log4j-core test ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/Config.java ================================================ package com.ctrip.framework.apollo; import java.util.Date; import java.util.Locale; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ public interface Config { /** * Return the property value with the given key, or {@code defaultValue} if the key doesn't exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value */ public String getProperty(String key, String defaultValue); /** * Return the integer property value with the given key, or {@code defaultValue} if the key * doesn't exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value as integer */ public Integer getIntProperty(String key, Integer defaultValue); /** * Return the long property value with the given key, or {@code defaultValue} if the key doesn't * exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value as long */ public Long getLongProperty(String key, Long defaultValue); /** * Return the short property value with the given key, or {@code defaultValue} if the key doesn't * exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value as short */ public Short getShortProperty(String key, Short defaultValue); /** * Return the float property value with the given key, or {@code defaultValue} if the key doesn't * exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value as float */ public Float getFloatProperty(String key, Float defaultValue); /** * Return the double property value with the given key, or {@code defaultValue} if the key doesn't * exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value as double */ public Double getDoubleProperty(String key, Double defaultValue); /** * Return the byte property value with the given key, or {@code defaultValue} if the key doesn't * exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value as byte */ public Byte getByteProperty(String key, Byte defaultValue); /** * Return the boolean property value with the given key, or {@code defaultValue} if the key * doesn't exist. * * @param key the property name * @param defaultValue the default value when key is not found or any error occurred * @return the property value as boolean */ public Boolean getBooleanProperty(String key, Boolean defaultValue); /** * Return the array property value with the given key, or {@code defaultValue} if the key doesn't exist. * * @param key the property name * @param delimiter the delimiter regex * @param defaultValue the default value when key is not found or any error occurred */ public String[] getArrayProperty(String key, String delimiter, String[] defaultValue); /** * Return the Date property value with the given name, or {@code defaultValue} if the name doesn't exist. * Will try to parse the date with Locale.US and formats as follows: yyyy-MM-dd HH:mm:ss.SSS, * yyyy-MM-dd HH:mm:ss and yyyy-MM-dd * * @param key the property name * @param defaultValue the default value when name is not found or any error occurred * @return the property value */ public Date getDateProperty(String key, Date defaultValue); /** * Return the Date property value with the given name, or {@code defaultValue} if the name doesn't exist. * Will parse the date with the format specified and Locale.US * * @param key the property name * @param format the date format, see {@link java.text.SimpleDateFormat} for more * information * @param defaultValue the default value when name is not found or any error occurred * @return the property value */ public Date getDateProperty(String key, String format, Date defaultValue); /** * Return the Date property value with the given name, or {@code defaultValue} if the name doesn't exist. * * @param key the property name * @param format the date format, see {@link java.text.SimpleDateFormat} for more * information * @param locale the locale to use * @param defaultValue the default value when name is not found or any error occurred * @return the property value */ public Date getDateProperty(String key, String format, Locale locale, Date defaultValue); /** * Return the Enum property value with the given key, or {@code defaultValue} if the key doesn't exist. * * @param key the property name * @param enumType the enum class * @param defaultValue the default value when key is not found or any error occurred * @param the enum * @return the property value */ public > T getEnumProperty(String key, Class enumType, T defaultValue); /** * Return the duration property value(in milliseconds) with the given name, or {@code * defaultValue} if the name doesn't exist. Please note the format should comply with the follow * example (case insensitive). Examples: *
   *    "123MS"          -- parses as "123 milliseconds"
   *    "20S"            -- parses as "20 seconds"
   *    "15M"            -- parses as "15 minutes" (where a minute is 60 seconds)
   *    "10H"            -- parses as "10 hours" (where an hour is 3600 seconds)
   *    "2D"             -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
   *    "2D3H4M5S123MS"  -- parses as "2 days, 3 hours, 4 minutes, 5 seconds and 123 milliseconds"
   * 
* * @param key the property name * @param defaultValue the default value when name is not found or any error occurred * @return the parsed property value(in milliseconds) */ public long getDurationProperty(String key, long defaultValue); /** * Add change listener to this config instance. * * @param listener the config change listener */ public void addChangeListener(ConfigChangeListener listener); /** * Return a set of the property names * * @return the property names */ public Set getPropertyNames(); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigChangeListener.java ================================================ package com.ctrip.framework.apollo; import com.ctrip.framework.apollo.model.ConfigChangeEvent; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigChangeListener { /** * Invoked when there is any config change for the namespace. * @param changeEvent the event for this change */ public void onChange(ConfigChangeEvent changeEvent); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFile.java ================================================ package com.ctrip.framework.apollo; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigFile { /** * Get file content of the namespace * @return file content, {@code null} if there is no content */ String getContent(); /** * Whether the config file has any content * @return true if it has content, false otherwise. */ boolean hasContent(); /** * Get the namespace of this config file instance * @return the namespace */ String getNamespace(); /** * Get the file format of this config file instance * @return the config file format enum */ ConfigFileFormat getConfigFileFormat(); /** * Add change listener to this config file instance. * * @param listener the config file change listener */ void addChangeListener(ConfigFileChangeListener listener); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFileChangeListener.java ================================================ package com.ctrip.framework.apollo; import com.ctrip.framework.apollo.model.ConfigFileChangeEvent; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigFileChangeListener { /** * Invoked when there is any config change for the namespace. * @param changeEvent the event for this change */ void onChange(ConfigFileChangeEvent changeEvent); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigService.java ================================================ package com.ctrip.framework.apollo; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.internals.ConfigManager; import com.ctrip.framework.apollo.spi.ConfigFactory; import com.ctrip.framework.apollo.spi.ConfigRegistry; /** * Entry point for client config use * * @author Jason Song(song_s@ctrip.com) */ public class ConfigService { private static final ConfigService s_instance = new ConfigService(); private volatile ConfigManager m_configManager; private volatile ConfigRegistry m_configRegistry; private ConfigManager getManager() { if (m_configManager == null) { synchronized (this) { if (m_configManager == null) { m_configManager = ApolloInjector.getInstance(ConfigManager.class); } } } return m_configManager; } private ConfigRegistry getRegistry() { if (m_configRegistry == null) { synchronized (this) { if (m_configRegistry == null) { m_configRegistry = ApolloInjector.getInstance(ConfigRegistry.class); } } } return m_configRegistry; } /** * Get Application's config instance. * * @return config instance */ public static Config getAppConfig() { return getConfig(ConfigConsts.NAMESPACE_APPLICATION); } /** * Get the config instance for the namespace. * * @param namespace the namespace of the config * @return config instance */ public static Config getConfig(String namespace) { return s_instance.getManager().getConfig(namespace); } public static ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat) { return s_instance.getManager().getConfigFile(namespace, configFileFormat); } static void setConfig(Config config) { setConfig(ConfigConsts.NAMESPACE_APPLICATION, config); } /** * Manually set the config for the namespace specified, use with caution. * * @param namespace the namespace * @param config the config instance */ static void setConfig(String namespace, final Config config) { s_instance.getRegistry().register(namespace, new ConfigFactory() { @Override public Config create(String namespace) { return config; } @Override public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat) { return null; } }); } static void setConfigFactory(ConfigFactory factory) { setConfigFactory(ConfigConsts.NAMESPACE_APPLICATION, factory); } /** * Manually set the config factory for the namespace specified, use with caution. * * @param namespace the namespace * @param factory the factory instance */ static void setConfigFactory(String namespace, ConfigFactory factory) { s_instance.getRegistry().register(namespace, factory); } // for test only static void reset() { synchronized (s_instance) { s_instance.m_configManager = null; s_instance.m_configRegistry = null; } } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/build/ApolloInjector.java ================================================ package com.ctrip.framework.apollo.build; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.internals.Injector; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.foundation.internals.ServiceBootstrap; /** * @author Jason Song(song_s@ctrip.com) */ public class ApolloInjector { private static volatile Injector s_injector; private static Object lock = new Object(); private static Injector getInjector() { if (s_injector == null) { synchronized (lock) { if (s_injector == null) { try { s_injector = ServiceBootstrap.loadFirst(Injector.class); } catch (Throwable ex) { ApolloConfigException exception = new ApolloConfigException("Unable to initialize Apollo Injector!", ex); Tracer.logError(exception); throw exception; } } } } return s_injector; } public static T getInstance(Class clazz) { try { return getInjector().getInstance(clazz); } catch (Throwable ex) { Tracer.logError(ex); throw new ApolloConfigException(String.format("Unable to load instance for type %s!", clazz.getName()), ex); } } public static T getInstance(Class clazz, String name) { try { return getInjector().getInstance(clazz, name); } catch (Throwable ex) { Tracer.logError(ex); throw new ApolloConfigException( String.format("Unable to load instance for type %s and name %s !", clazz.getName(), name), ex); } } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/enums/PropertyChangeType.java ================================================ package com.ctrip.framework.apollo.enums; /** * @author Jason Song(song_s@ctrip.com) */ public enum PropertyChangeType { ADDED, MODIFIED, DELETED } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/exceptions/ApolloConfigException.java ================================================ package com.ctrip.framework.apollo.exceptions; /** * @author Jason Song(song_s@ctrip.com) */ public class ApolloConfigException extends RuntimeException { public ApolloConfigException(String message) { super(message); } public ApolloConfigException(String message, Throwable cause) { super(message, cause); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/exceptions/ApolloConfigStatusCodeException.java ================================================ package com.ctrip.framework.apollo.exceptions; /** * @author Jason Song(song_s@ctrip.com) */ public class ApolloConfigStatusCodeException extends RuntimeException{ private final int m_statusCode; public ApolloConfigStatusCodeException(int statusCode, String message) { super(String.format("[status code: %d] %s", statusCode, message)); this.m_statusCode = statusCode; } public int getStatusCode() { return m_statusCode; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfig.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigChangeListener; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.enums.PropertyChangeType; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.model.ConfigChange; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.apollo.util.ConfigUtil; import com.ctrip.framework.apollo.util.function.Functions; import com.ctrip.framework.apollo.util.parser.Parsers; import com.google.common.base.Function; import com.google.common.base.Objects; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; /** * @author Jason Song(song_s@ctrip.com) */ public abstract class AbstractConfig implements Config { private static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class); private static ExecutorService m_executorService; private List m_listeners = Lists.newCopyOnWriteArrayList(); private ConfigUtil m_configUtil; private volatile Cache m_integerCache; private volatile Cache m_longCache; private volatile Cache m_shortCache; private volatile Cache m_floatCache; private volatile Cache m_doubleCache; private volatile Cache m_byteCache; private volatile Cache m_booleanCache; private volatile Cache m_dateCache; private volatile Cache m_durationCache; private Map> m_arrayCache; private List allCaches; private AtomicLong m_configVersion; //indicate config version static { m_executorService = Executors.newCachedThreadPool(ApolloThreadFactory .create("Config", true)); } public AbstractConfig() { m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); m_configVersion = new AtomicLong(); m_arrayCache = Maps.newConcurrentMap(); allCaches = Lists.newArrayList(); } @Override public void addChangeListener(ConfigChangeListener listener) { if (!m_listeners.contains(listener)) { m_listeners.add(listener); } } @Override public Integer getIntProperty(String key, Integer defaultValue) { try { if (m_integerCache == null) { synchronized (this) { if (m_integerCache == null) { m_integerCache = newCache(); } } } return getValueFromCache(key, Functions.TO_INT_FUNCTION, m_integerCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getIntProperty for %s failed, return default value %d", key, defaultValue), ex)); } return defaultValue; } @Override public Long getLongProperty(String key, Long defaultValue) { try { if (m_longCache == null) { synchronized (this) { if (m_longCache == null) { m_longCache = newCache(); } } } return getValueFromCache(key, Functions.TO_LONG_FUNCTION, m_longCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getLongProperty for %s failed, return default value %d", key, defaultValue), ex)); } return defaultValue; } @Override public Short getShortProperty(String key, Short defaultValue) { try { if (m_shortCache == null) { synchronized (this) { if (m_shortCache == null) { m_shortCache = newCache(); } } } return getValueFromCache(key, Functions.TO_SHORT_FUNCTION, m_shortCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getShortProperty for %s failed, return default value %d", key, defaultValue), ex)); } return defaultValue; } @Override public Float getFloatProperty(String key, Float defaultValue) { try { if (m_floatCache == null) { synchronized (this) { if (m_floatCache == null) { m_floatCache = newCache(); } } } return getValueFromCache(key, Functions.TO_FLOAT_FUNCTION, m_floatCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getFloatProperty for %s failed, return default value %f", key, defaultValue), ex)); } return defaultValue; } @Override public Double getDoubleProperty(String key, Double defaultValue) { try { if (m_doubleCache == null) { synchronized (this) { if (m_doubleCache == null) { m_doubleCache = newCache(); } } } return getValueFromCache(key, Functions.TO_DOUBLE_FUNCTION, m_doubleCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getDoubleProperty for %s failed, return default value %f", key, defaultValue), ex)); } return defaultValue; } @Override public Byte getByteProperty(String key, Byte defaultValue) { try { if (m_byteCache == null) { synchronized (this) { if (m_byteCache == null) { m_byteCache = newCache(); } } } return getValueFromCache(key, Functions.TO_BYTE_FUNCTION, m_byteCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getByteProperty for %s failed, return default value %d", key, defaultValue), ex)); } return defaultValue; } @Override public Boolean getBooleanProperty(String key, Boolean defaultValue) { try { if (m_booleanCache == null) { synchronized (this) { if (m_booleanCache == null) { m_booleanCache = newCache(); } } } return getValueFromCache(key, Functions.TO_BOOLEAN_FUNCTION, m_booleanCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getBooleanProperty for %s failed, return default value %b", key, defaultValue), ex)); } return defaultValue; } @Override public String[] getArrayProperty(String key, final String delimiter, String[] defaultValue) { try { if (!m_arrayCache.containsKey(delimiter)) { synchronized (this) { if (!m_arrayCache.containsKey(delimiter)) { m_arrayCache.put(delimiter, this.newCache()); } } } Cache cache = m_arrayCache.get(delimiter); String[] result = cache.getIfPresent(key); if (result != null) { return result; } return getValueAndStoreToCache(key, new Function() { @Override public String[] apply(String input) { return input.split(delimiter); } }, cache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getArrayProperty for %s failed, return default value", key), ex)); } return defaultValue; } @Override public > T getEnumProperty(String key, Class enumType, T defaultValue) { try { String value = getProperty(key, null); if (value != null) { return Enum.valueOf(enumType, value); } } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getEnumProperty for %s failed, return default value %s", key, defaultValue), ex)); } return defaultValue; } @Override public Date getDateProperty(String key, Date defaultValue) { try { if (m_dateCache == null) { synchronized (this) { if (m_dateCache == null) { m_dateCache = newCache(); } } } return getValueFromCache(key, Functions.TO_DATE_FUNCTION, m_dateCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getDateProperty for %s failed, return default value %s", key, defaultValue), ex)); } return defaultValue; } @Override public Date getDateProperty(String key, String format, Date defaultValue) { try { String value = getProperty(key, null); if (value != null) { return Parsers.forDate().parse(value, format); } } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getDateProperty for %s failed, return default value %s", key, defaultValue), ex)); } return defaultValue; } @Override public Date getDateProperty(String key, String format, Locale locale, Date defaultValue) { try { String value = getProperty(key, null); if (value != null) { return Parsers.forDate().parse(value, format, locale); } } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getDateProperty for %s failed, return default value %s", key, defaultValue), ex)); } return defaultValue; } @Override public long getDurationProperty(String key, long defaultValue) { try { if (m_durationCache == null) { synchronized (this) { if (m_durationCache == null) { m_durationCache = newCache(); } } } return getValueFromCache(key, Functions.TO_DURATION_FUNCTION, m_durationCache, defaultValue); } catch (Throwable ex) { Tracer.logError(new ApolloConfigException( String.format("getDurationProperty for %s failed, return default value %d", key, defaultValue), ex)); } return defaultValue; } private T getValueFromCache(String key, Function parser, Cache cache, T defaultValue) { T result = cache.getIfPresent(key); if (result != null) { return result; } return getValueAndStoreToCache(key, parser, cache, defaultValue); } private T getValueAndStoreToCache(String key, Function parser, Cache cache, T defaultValue) { long currentConfigVersion = m_configVersion.get(); String value = getProperty(key, null); if (value != null) { T result = parser.apply(value); if (result != null) { synchronized (this) { if (m_configVersion.get() == currentConfigVersion) { cache.put(key, result); } } return result; } } return defaultValue; } private Cache newCache() { Cache cache = CacheBuilder.newBuilder() .maximumSize(m_configUtil.getMaxConfigCacheSize()) .expireAfterAccess(m_configUtil.getConfigCacheExpireTime(), m_configUtil.getConfigCacheExpireTimeUnit()) .build(); allCaches.add(cache); return cache; } /** * Clear config cache */ protected void clearConfigCache() { synchronized (this) { for (Cache c : allCaches) { if (c != null) { c.invalidateAll(); } } m_configVersion.incrementAndGet(); } } protected void fireConfigChange(final ConfigChangeEvent changeEvent) { for (final ConfigChangeListener listener : m_listeners) { m_executorService.submit(new Runnable() { @Override public void run() { String listenerName = listener.getClass().getName(); Transaction transaction = Tracer.newTransaction("Apollo.ConfigChangeListener", listenerName); try { listener.onChange(changeEvent); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); Tracer.logError(ex); logger.error("Failed to invoke config change listener {}", listenerName, ex); } finally { transaction.complete(); } } }); } } List calcPropertyChanges(String namespace, Properties previous, Properties current) { if (previous == null) { previous = new Properties(); } if (current == null) { current = new Properties(); } Set previousKeys = previous.stringPropertyNames(); Set currentKeys = current.stringPropertyNames(); Set commonKeys = Sets.intersection(previousKeys, currentKeys); Set newKeys = Sets.difference(currentKeys, commonKeys); Set removedKeys = Sets.difference(previousKeys, commonKeys); List changes = Lists.newArrayList(); for (String newKey : newKeys) { changes.add(new ConfigChange(namespace, newKey, null, current.getProperty(newKey), PropertyChangeType.ADDED)); } for (String removedKey : removedKeys) { changes.add(new ConfigChange(namespace, removedKey, previous.getProperty(removedKey), null, PropertyChangeType.DELETED)); } for (String commonKey : commonKeys) { String previousValue = previous.getProperty(commonKey); String currentValue = current.getProperty(commonKey); if (Objects.equal(previousValue, currentValue)) { continue; } changes.add(new ConfigChange(namespace, commonKey, previousValue, currentValue, PropertyChangeType.MODIFIED)); } return changes; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.List; import java.util.Objects; import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.ConfigFile; import com.ctrip.framework.apollo.ConfigFileChangeListener; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.enums.PropertyChangeType; import com.ctrip.framework.apollo.model.ConfigFileChangeEvent; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.google.common.collect.Lists; /** * @author Jason Song(song_s@ctrip.com) */ public abstract class AbstractConfigFile implements ConfigFile, RepositoryChangeListener { private static final Logger logger = LoggerFactory.getLogger(AbstractConfigFile.class); private static ExecutorService m_executorService; protected ConfigRepository m_configRepository; protected String m_namespace; protected AtomicReference m_configProperties; private List m_listeners = Lists.newCopyOnWriteArrayList(); static { m_executorService = Executors.newCachedThreadPool(ApolloThreadFactory .create("ConfigFile", true)); } public AbstractConfigFile(String namespace, ConfigRepository configRepository) { m_configRepository = configRepository; m_namespace = namespace; m_configProperties = new AtomicReference<>(); initialize(); } private void initialize() { try { m_configProperties.set(m_configRepository.getConfig()); } catch (Throwable ex) { Tracer.logError(ex); logger.warn("Init Apollo Config File failed - namespace: {}, reason: {}.", m_namespace, ExceptionUtil.getDetailMessage(ex)); } finally { //register the change listener no matter config repository is working or not //so that whenever config repository is recovered, config could get changed m_configRepository.addChangeListener(this); } } @Override public String getNamespace() { return m_namespace; } protected abstract void update(Properties newProperties); @Override public synchronized void onRepositoryChange(String namespace, Properties newProperties) { if (newProperties.equals(m_configProperties.get())) { return; } Properties newConfigProperties = new Properties(); newConfigProperties.putAll(newProperties); String oldValue = getContent(); update(newProperties); String newValue = getContent(); PropertyChangeType changeType = PropertyChangeType.MODIFIED; if (oldValue == null) { changeType = PropertyChangeType.ADDED; } else if (newValue == null) { changeType = PropertyChangeType.DELETED; } this.fireConfigChange(new ConfigFileChangeEvent(m_namespace, oldValue, newValue, changeType)); Tracer.logEvent("Apollo.Client.ConfigChanges", m_namespace); } @Override public void addChangeListener(ConfigFileChangeListener listener) { if (!m_listeners.contains(listener)) { m_listeners.add(listener); } } private void fireConfigChange(final ConfigFileChangeEvent changeEvent) { for (final ConfigFileChangeListener listener : m_listeners) { m_executorService.submit(new Runnable() { @Override public void run() { String listenerName = listener.getClass().getName(); Transaction transaction = Tracer.newTransaction("Apollo.ConfigFileChangeListener", listenerName); try { listener.onChange(changeEvent); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); Tracer.logError(ex); logger.error("Failed to invoke config file change listener {}", listenerName, ex); } finally { transaction.complete(); } } }); } } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigRepository.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.List; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.google.common.collect.Lists; /** * @author Jason Song(song_s@ctrip.com) */ public abstract class AbstractConfigRepository implements ConfigRepository { private static final Logger logger = LoggerFactory.getLogger(AbstractConfigRepository.class); private List m_listeners = Lists.newCopyOnWriteArrayList(); protected boolean trySync() { try { sync(); return true; } catch (Throwable ex) { Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex)); logger .warn("Sync config failed, will retry. Repository {}, reason: {}", this.getClass(), ExceptionUtil .getDetailMessage(ex)); } return false; } protected abstract void sync(); @Override public void addChangeListener(RepositoryChangeListener listener) { if (!m_listeners.contains(listener)) { m_listeners.add(listener); } } @Override public void removeChangeListener(RepositoryChangeListener listener) { m_listeners.remove(listener); } protected void fireRepositoryChange(String namespace, Properties newProperties) { for (RepositoryChangeListener listener : m_listeners) { try { listener.onRepositoryChange(namespace, newProperties); } catch (Throwable ex) { Tracer.logError(ex); logger.error("Failed to invoke repository change listener {}", listener.getClass(), ex); } } } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigManager.java ================================================ package com.ctrip.framework.apollo.internals; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigFile; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigManager { /** * Get the config instance for the namespace specified. * @param namespace the namespace * @return the config instance for the namespace */ public Config getConfig(String namespace); /** * Get the config file instance for the namespace specified. * @param namespace the namespace * @param configFileFormat the config file format * @return the config file instance for the namespace */ public ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigRepository.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.Properties; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigRepository { /** * Get the config from this repository. * @return config */ public Properties getConfig(); /** * Set the fallback repo for this repository. * @param upstreamConfigRepository the upstream repo */ public void setUpstreamRepository(ConfigRepository upstreamConfigRepository); /** * Add change listener. * @param listener the listener to observe the changes */ public void addChangeListener(RepositoryChangeListener listener); /** * Remove change listener. * @param listener the listener to remove */ public void removeChangeListener(RepositoryChangeListener listener); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigServiceLocator.java ================================================ package com.ctrip.framework.apollo.internals; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.dto.ServiceDTO; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.apollo.util.ConfigUtil; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.ctrip.framework.apollo.util.http.HttpRequest; import com.ctrip.framework.apollo.util.http.HttpResponse; import com.ctrip.framework.apollo.util.http.HttpUtil; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.escape.Escaper; import com.google.common.net.UrlEscapers; import com.google.gson.reflect.TypeToken; public class ConfigServiceLocator { private static final Logger logger = LoggerFactory.getLogger(ConfigServiceLocator.class); private HttpUtil m_httpUtil; private ConfigUtil m_configUtil; private AtomicReference> m_configServices; private Type m_responseType; private ScheduledExecutorService m_executorService; private static final Joiner.MapJoiner MAP_JOINER = Joiner.on("&").withKeyValueSeparator("="); private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper(); /** * Create a config service locator. */ public ConfigServiceLocator() { List initial = Lists.newArrayList(); m_configServices = new AtomicReference<>(initial); m_responseType = new TypeToken>() { }.getType(); m_httpUtil = ApolloInjector.getInstance(HttpUtil.class); m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); this.m_executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("ConfigServiceLocator", true)); this.tryUpdateConfigServices(); this.schedulePeriodicRefresh(); } /** * Get the config service info from remote meta server. * * @return the services dto */ public List getConfigServices() { if (m_configServices.get().isEmpty()) { updateConfigServices(); } return m_configServices.get(); } private boolean tryUpdateConfigServices() { try { updateConfigServices(); return true; } catch (Throwable ex) { //ignore } return false; } private void schedulePeriodicRefresh() { this.m_executorService.scheduleAtFixedRate( new Runnable() { @Override public void run() { logger.debug("refresh config services"); Tracer.logEvent("Apollo.MetaService", "periodicRefresh"); tryUpdateConfigServices(); } }, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit()); } private synchronized void updateConfigServices() { String url = assembleMetaServiceUrl(); HttpRequest request = new HttpRequest(url); int maxRetries = 2; Throwable exception = null; for (int i = 0; i < maxRetries; i++) { Transaction transaction = Tracer.newTransaction("Apollo.MetaService", "getConfigService"); transaction.addData("Url", url); try { HttpResponse> response = m_httpUtil.doGet(request, m_responseType); transaction.setStatus(Transaction.SUCCESS); List services = response.getBody(); if (services == null || services.isEmpty()) { logConfigService("Empty response!"); continue; } m_configServices.set(services); logConfigServices(services); return; } catch (Throwable ex) { Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex)); transaction.setStatus(ex); exception = ex; } finally { transaction.complete(); } try { m_configUtil.getOnErrorRetryIntervalTimeUnit().sleep(m_configUtil.getOnErrorRetryInterval()); } catch (InterruptedException ex) { //ignore } } throw new ApolloConfigException( String.format("Get config services failed from %s", url), exception); } private String assembleMetaServiceUrl() { String domainName = m_configUtil.getMetaServerDomainName(); String appId = m_configUtil.getAppId(); String localIp = m_configUtil.getLocalIp(); Map queryParams = Maps.newHashMap(); queryParams.put("appId", queryParamEscaper.escape(appId)); if (!Strings.isNullOrEmpty(localIp)) { queryParams.put("ip", queryParamEscaper.escape(localIp)); } return domainName + "/services/config?" + MAP_JOINER.join(queryParams); } private void logConfigServices(List serviceDtos) { for (ServiceDTO serviceDto : serviceDtos) { logConfigService(serviceDto.getHomepageUrl()); } } private void logConfigService(String serviceUrl) { Tracer.logEvent("Apollo.Config.Services", serviceUrl); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfig.java ================================================ package com.ctrip.framework.apollo.internals; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.core.utils.ClassLoaderUtil; import com.ctrip.framework.apollo.enums.PropertyChangeType; import com.ctrip.framework.apollo.model.ConfigChange; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.RateLimiter; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultConfig extends AbstractConfig implements RepositoryChangeListener { private static final Logger logger = LoggerFactory.getLogger(DefaultConfig.class); private final String m_namespace; private Properties m_resourceProperties; private AtomicReference m_configProperties; private ConfigRepository m_configRepository; private RateLimiter m_warnLogRateLimiter; /** * Constructor. * * @param namespace the namespace of this config instance * @param configRepository the config repository for this config instance */ public DefaultConfig(String namespace, ConfigRepository configRepository) { m_namespace = namespace; m_resourceProperties = loadFromResource(m_namespace); m_configRepository = configRepository; m_configProperties = new AtomicReference<>(); m_warnLogRateLimiter = RateLimiter.create(0.017); // 1 warning log output per minute initialize(); } private void initialize() { try { m_configProperties.set(m_configRepository.getConfig()); } catch (Throwable ex) { Tracer.logError(ex); logger.warn("Init Apollo Local Config failed - namespace: {}, reason: {}.", m_namespace, ExceptionUtil.getDetailMessage(ex)); } finally { //register the change listener no matter config repository is working or not //so that whenever config repository is recovered, config could get changed m_configRepository.addChangeListener(this); } } @Override public String getProperty(String key, String defaultValue) { // step 1: check system properties, i.e. -Dkey=value String value = System.getProperty(key); // step 2: check local cached properties file if (value == null && m_configProperties.get() != null) { value = m_configProperties.get().getProperty(key); } /** * step 3: check env variable, i.e. PATH=... * normally system environment variables are in UPPERCASE, however there might be exceptions. * so the caller should provide the key in the right case */ if (value == null) { value = System.getenv(key); } // step 4: check properties file from classpath if (value == null && m_resourceProperties != null) { value = (String) m_resourceProperties.get(key); } if (value == null && m_configProperties.get() == null && m_warnLogRateLimiter.tryAcquire()) { logger.warn("Could not load config for namespace {} from Apollo, please check whether the configs are released in Apollo! Return default value now!", m_namespace); } return value == null ? defaultValue : value; } @Override public Set getPropertyNames() { Properties properties = m_configProperties.get(); if (properties == null) { return Collections.emptySet(); } return properties.stringPropertyNames(); } @Override public synchronized void onRepositoryChange(String namespace, Properties newProperties) { if (newProperties.equals(m_configProperties.get())) { return; } Properties newConfigProperties = new Properties(); newConfigProperties.putAll(newProperties); Map actualChanges = updateAndCalcConfigChanges(newConfigProperties); //check double checked result if (actualChanges.isEmpty()) { return; } this.fireConfigChange(new ConfigChangeEvent(m_namespace, actualChanges)); Tracer.logEvent("Apollo.Client.ConfigChanges", m_namespace); } private Map updateAndCalcConfigChanges(Properties newConfigProperties) { List configChanges = calcPropertyChanges(m_namespace, m_configProperties.get(), newConfigProperties); ImmutableMap.Builder actualChanges = new ImmutableMap.Builder<>(); /** === Double check since DefaultConfig has multiple config sources ==== **/ //1. use getProperty to update configChanges's old value for (ConfigChange change : configChanges) { change.setOldValue(this.getProperty(change.getPropertyName(), change.getOldValue())); } //2. update m_configProperties m_configProperties.set(newConfigProperties); clearConfigCache(); //3. use getProperty to update configChange's new value and calc the final changes for (ConfigChange change : configChanges) { change.setNewValue(this.getProperty(change.getPropertyName(), change.getNewValue())); switch (change.getChangeType()) { case ADDED: if (Objects.equals(change.getOldValue(), change.getNewValue())) { break; } if (change.getOldValue() != null) { change.setChangeType(PropertyChangeType.MODIFIED); } actualChanges.put(change.getPropertyName(), change); break; case MODIFIED: if (!Objects.equals(change.getOldValue(), change.getNewValue())) { actualChanges.put(change.getPropertyName(), change); } break; case DELETED: if (Objects.equals(change.getOldValue(), change.getNewValue())) { break; } if (change.getNewValue() != null) { change.setChangeType(PropertyChangeType.MODIFIED); } actualChanges.put(change.getPropertyName(), change); break; default: //do nothing break; } } return actualChanges.build(); } private Properties loadFromResource(String namespace) { String name = String.format("META-INF/config/%s.properties", namespace); InputStream in = ClassLoaderUtil.getLoader().getResourceAsStream(name); Properties properties = null; if (in != null) { properties = new Properties(); try { properties.load(in); } catch (IOException ex) { Tracer.logError(ex); logger.error("Load resource config for namespace {} failed", namespace, ex); } finally { try { in.close(); } catch (IOException ex) { // ignore } } } return properties; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfigManager.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.Map; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigFile; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.spi.ConfigFactory; import com.ctrip.framework.apollo.spi.ConfigFactoryManager; import com.google.common.collect.Maps; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultConfigManager implements ConfigManager { private ConfigFactoryManager m_factoryManager; private Map m_configs = Maps.newConcurrentMap(); private Map m_configFiles = Maps.newConcurrentMap(); public DefaultConfigManager() { m_factoryManager = ApolloInjector.getInstance(ConfigFactoryManager.class); } @Override public Config getConfig(String namespace) { Config config = m_configs.get(namespace); if (config == null) { synchronized (this) { config = m_configs.get(namespace); if (config == null) { ConfigFactory factory = m_factoryManager.getFactory(namespace); config = factory.create(namespace); m_configs.put(namespace, config); } } } return config; } @Override public ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat) { String namespaceFileName = String.format("%s.%s", namespace, configFileFormat.getValue()); ConfigFile configFile = m_configFiles.get(namespaceFileName); if (configFile == null) { synchronized (this) { configFile = m_configFiles.get(namespaceFileName); if (configFile == null) { ConfigFactory factory = m_factoryManager.getFactory(namespaceFileName); configFile = factory.createConfigFile(namespaceFileName, configFileFormat); m_configFiles.put(namespaceFileName, configFile); } } } return configFile; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultInjector.java ================================================ package com.ctrip.framework.apollo.internals; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.spi.ConfigFactory; import com.ctrip.framework.apollo.spi.ConfigFactoryManager; import com.ctrip.framework.apollo.spi.ConfigRegistry; import com.ctrip.framework.apollo.spi.DefaultConfigFactory; import com.ctrip.framework.apollo.spi.DefaultConfigFactoryManager; import com.ctrip.framework.apollo.spi.DefaultConfigRegistry; import com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory; import com.ctrip.framework.apollo.spring.property.PlaceholderHelper; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.util.ConfigUtil; import com.ctrip.framework.apollo.util.http.HttpUtil; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Singleton; /** * Guice injector * @author Jason Song(song_s@ctrip.com) */ public class DefaultInjector implements Injector { private com.google.inject.Injector m_injector; public DefaultInjector() { try { m_injector = Guice.createInjector(new ApolloModule()); } catch (Throwable ex) { ApolloConfigException exception = new ApolloConfigException("Unable to initialize Guice Injector!", ex); Tracer.logError(exception); throw exception; } } @Override public T getInstance(Class clazz) { try { return m_injector.getInstance(clazz); } catch (Throwable ex) { Tracer.logError(ex); throw new ApolloConfigException( String.format("Unable to load instance for %s!", clazz.getName()), ex); } } @Override public T getInstance(Class clazz, String name) { //Guice does not support get instance by type and name return null; } private static class ApolloModule extends AbstractModule { @Override protected void configure() { bind(ConfigManager.class).to(DefaultConfigManager.class).in(Singleton.class); bind(ConfigFactoryManager.class).to(DefaultConfigFactoryManager.class).in(Singleton.class); bind(ConfigRegistry.class).to(DefaultConfigRegistry.class).in(Singleton.class); bind(ConfigFactory.class).to(DefaultConfigFactory.class).in(Singleton.class); bind(ConfigUtil.class).in(Singleton.class); bind(HttpUtil.class).in(Singleton.class); bind(ConfigServiceLocator.class).in(Singleton.class); bind(RemoteConfigLongPollService.class).in(Singleton.class); bind(PlaceholderHelper.class).in(Singleton.class); bind(ConfigPropertySourceFactory.class).in(Singleton.class); } } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/Injector.java ================================================ package com.ctrip.framework.apollo.internals; /** * @author Jason Song(song_s@ctrip.com) */ public interface Injector { /** * Returns the appropriate instance for the given injection type */ T getInstance(Class clazz); /** * Returns the appropriate instance for the given injection type and name */ T getInstance(Class clazz, String name); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/JsonConfigFile.java ================================================ package com.ctrip.framework.apollo.internals; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; /** * @author Jason Song(song_s@ctrip.com) */ public class JsonConfigFile extends PlainTextConfigFile { public JsonConfigFile(String namespace, ConfigRepository configRepository) { super(namespace, configRepository); } @Override public ConfigFileFormat getConfigFileFormat() { return ConfigFileFormat.JSON; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepository.java ================================================ package com.ctrip.framework.apollo.internals; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.utils.ClassLoaderUtil; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.apollo.util.ConfigUtil; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; /** * @author Jason Song(song_s@ctrip.com) */ public class LocalFileConfigRepository extends AbstractConfigRepository implements RepositoryChangeListener { private static final Logger logger = LoggerFactory.getLogger(LocalFileConfigRepository.class); private static final String CONFIG_DIR = "/config-cache"; private final String m_namespace; private File m_baseDir; private final ConfigUtil m_configUtil; private volatile Properties m_fileProperties; private volatile ConfigRepository m_upstream; /** * Constructor. * * @param namespace the namespace */ public LocalFileConfigRepository(String namespace) { this(namespace, null); } public LocalFileConfigRepository(String namespace, ConfigRepository upstream) { m_namespace = namespace; m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); this.setLocalCacheDir(findLocalCacheDir(), false); this.setUpstreamRepository(upstream); this.trySync(); } void setLocalCacheDir(File baseDir, boolean syncImmediately) { m_baseDir = baseDir; this.checkLocalConfigCacheDir(m_baseDir); if (syncImmediately) { this.trySync(); } } private File findLocalCacheDir() { try { String defaultCacheDir = m_configUtil.getDefaultLocalCacheDir(); Path path = Paths.get(defaultCacheDir); if (!Files.exists(path)) { Files.createDirectories(path); } if (Files.exists(path) && Files.isWritable(path)) { return new File(defaultCacheDir, CONFIG_DIR); } } catch (Throwable ex) { //ignore } return new File(ClassLoaderUtil.getClassPath(), CONFIG_DIR); } @Override public Properties getConfig() { if (m_fileProperties == null) { sync(); } Properties result = new Properties(); result.putAll(m_fileProperties); return result; } @Override public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) { if (upstreamConfigRepository == null) { return; } //clear previous listener if (m_upstream != null) { m_upstream.removeChangeListener(this); } m_upstream = upstreamConfigRepository; trySyncFromUpstream(); upstreamConfigRepository.addChangeListener(this); } @Override public void onRepositoryChange(String namespace, Properties newProperties) { if (newProperties.equals(m_fileProperties)) { return; } Properties newFileProperties = new Properties(); newFileProperties.putAll(newProperties); updateFileProperties(newFileProperties); this.fireRepositoryChange(namespace, newProperties); } @Override protected void sync() { //sync with upstream immediately boolean syncFromUpstreamResultSuccess = trySyncFromUpstream(); if (syncFromUpstreamResultSuccess) { return; } Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "syncLocalConfig"); Throwable exception = null; try { transaction.addData("Basedir", m_baseDir.getAbsolutePath()); m_fileProperties = this.loadFromLocalCacheFile(m_baseDir, m_namespace); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex)); transaction.setStatus(ex); exception = ex; //ignore } finally { transaction.complete(); } if (m_fileProperties == null) { throw new ApolloConfigException( "Load config from local config failed!", exception); } } private boolean trySyncFromUpstream() { if (m_upstream == null) { return false; } try { Properties properties = m_upstream.getConfig(); updateFileProperties(properties); return true; } catch (Throwable ex) { Tracer.logError(ex); logger .warn("Sync config from upstream repository {} failed, reason: {}", m_upstream.getClass(), ExceptionUtil.getDetailMessage(ex)); } return false; } private synchronized void updateFileProperties(Properties newProperties) { if (newProperties.equals(m_fileProperties)) { return; } this.m_fileProperties = newProperties; persistLocalCacheFile(m_baseDir, m_namespace); } private Properties loadFromLocalCacheFile(File baseDir, String namespace) throws IOException { Preconditions.checkNotNull(baseDir, "Basedir cannot be null"); File file = assembleLocalCacheFile(baseDir, namespace); Properties properties = null; if (file.isFile() && file.canRead()) { InputStream in = null; try { in = new FileInputStream(file); properties = new Properties(); properties.load(in); logger.debug("Loading local config file {} successfully!", file.getAbsolutePath()); } catch (IOException ex) { Tracer.logError(ex); throw new ApolloConfigException(String .format("Loading config from local cache file %s failed", file.getAbsolutePath()), ex); } finally { try { if (in != null) { in.close(); } } catch (IOException ex) { // ignore } } } else { throw new ApolloConfigException( String.format("Cannot read from local cache file %s", file.getAbsolutePath())); } return properties; } void persistLocalCacheFile(File baseDir, String namespace) { if (baseDir == null) { return; } File file = assembleLocalCacheFile(baseDir, namespace); OutputStream out = null; Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "persistLocalConfigFile"); transaction.addData("LocalConfigFile", file.getAbsolutePath()); try { out = new FileOutputStream(file); m_fileProperties.store(out, "Persisted by DefaultConfig"); transaction.setStatus(Transaction.SUCCESS); } catch (IOException ex) { ApolloConfigException exception = new ApolloConfigException( String.format("Persist local cache file %s failed", file.getAbsolutePath()), ex); Tracer.logError(exception); transaction.setStatus(exception); logger.warn("Persist local cache file {} failed, reason: {}.", file.getAbsolutePath(), ExceptionUtil.getDetailMessage(ex)); } finally { if (out != null) { try { out.close(); } catch (IOException ex) { //ignore } } transaction.complete(); } } private void checkLocalConfigCacheDir(File baseDir) { if (baseDir.exists()) { return; } Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "createLocalConfigDir"); transaction.addData("BaseDir", baseDir.getAbsolutePath()); try { Files.createDirectory(baseDir.toPath()); transaction.setStatus(Transaction.SUCCESS); } catch (IOException ex) { ApolloConfigException exception = new ApolloConfigException( String.format("Create local config directory %s failed", baseDir.getAbsolutePath()), ex); Tracer.logError(exception); transaction.setStatus(exception); logger.warn( "Unable to create local config cache directory {}, reason: {}. Will not able to cache config file.", baseDir.getAbsolutePath(), ExceptionUtil.getDetailMessage(ex)); } finally { transaction.complete(); } } File assembleLocalCacheFile(File baseDir, String namespace) { String fileName = String.format("%s.properties", Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR) .join(m_configUtil.getAppId(), m_configUtil.getCluster(), namespace)); return new File(baseDir, fileName); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PlainTextConfigFile.java ================================================ package com.ctrip.framework.apollo.internals; import com.ctrip.framework.apollo.core.ConfigConsts; import java.util.Properties; /** * @author Jason Song(song_s@ctrip.com) */ public abstract class PlainTextConfigFile extends AbstractConfigFile { public PlainTextConfigFile(String namespace, ConfigRepository configRepository) { super(namespace, configRepository); } @Override public String getContent() { if (!this.hasContent()) { return null; } return m_configProperties.get().getProperty(ConfigConsts.CONFIG_FILE_CONTENT_KEY); } @Override public boolean hasContent() { if (m_configProperties.get() == null) { return false; } return m_configProperties.get().containsKey(ConfigConsts.CONFIG_FILE_CONTENT_KEY); } @Override protected void update(Properties newProperties) { m_configProperties.set(newProperties); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PropertiesConfigFile.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.utils.PropertiesUtil; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.util.ExceptionUtil; /** * @author Jason Song(song_s@ctrip.com) */ public class PropertiesConfigFile extends AbstractConfigFile { private static final Logger logger = LoggerFactory.getLogger(PropertiesConfigFile.class); protected AtomicReference m_contentCache; public PropertiesConfigFile(String namespace, ConfigRepository configRepository) { super(namespace, configRepository); m_contentCache = new AtomicReference<>(); } @Override protected void update(Properties newProperties) { m_configProperties.set(newProperties); m_contentCache.set(null); } @Override public String getContent() { if (m_contentCache.get() == null) { m_contentCache.set(doGetContent()); } return m_contentCache.get(); } String doGetContent() { if (!this.hasContent()) { return null; } try { return PropertiesUtil.toString(m_configProperties.get()); } catch (Throwable ex) { ApolloConfigException exception = new ApolloConfigException(String .format("Parse properties file content failed for namespace: %s, cause: %s", m_namespace, ExceptionUtil.getDetailMessage(ex))); Tracer.logError(exception); throw exception; } } @Override public boolean hasContent() { return m_configProperties.get() != null && !m_configProperties.get().isEmpty(); } @Override public ConfigFileFormat getConfigFileFormat() { return ConfigFileFormat.Properties; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RemoteConfigLongPollService.java ================================================ package com.ctrip.framework.apollo.internals; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.common.escape.Escaper; import com.google.common.net.UrlEscapers; import com.google.common.reflect.TypeToken; import com.google.common.util.concurrent.RateLimiter; import com.google.gson.Gson; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; import com.ctrip.framework.apollo.core.dto.ServiceDTO; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.schedule.ExponentialSchedulePolicy; import com.ctrip.framework.apollo.core.schedule.SchedulePolicy; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.apollo.util.ConfigUtil; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.ctrip.framework.apollo.util.http.HttpRequest; import com.ctrip.framework.apollo.util.http.HttpResponse; import com.ctrip.framework.apollo.util.http.HttpUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * @author Jason Song(song_s@ctrip.com) */ public class RemoteConfigLongPollService { private static final Logger logger = LoggerFactory.getLogger(RemoteConfigLongPollService.class); private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); private static final Joiner.MapJoiner MAP_JOINER = Joiner.on("&").withKeyValueSeparator("="); private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper(); private static final long INIT_NOTIFICATION_ID = ConfigConsts.NOTIFICATION_ID_PLACEHOLDER; private final ExecutorService m_longPollingService; private final AtomicBoolean m_longPollingStopped; private SchedulePolicy m_longPollFailSchedulePolicyInSecond; private RateLimiter m_longPollRateLimiter; private final AtomicBoolean m_longPollStarted; private final Multimap m_longPollNamespaces; private final ConcurrentMap m_notifications; private final Map m_remoteNotificationMessages;//namespaceName -> watchedKey -> notificationId private Type m_responseType; private Gson gson; private ConfigUtil m_configUtil; private HttpUtil m_httpUtil; private ConfigServiceLocator m_serviceLocator; /** * Constructor. */ public RemoteConfigLongPollService() { m_longPollFailSchedulePolicyInSecond = new ExponentialSchedulePolicy(1, 120); //in second m_longPollingStopped = new AtomicBoolean(false); m_longPollingService = Executors.newSingleThreadExecutor( ApolloThreadFactory.create("RemoteConfigLongPollService", true)); m_longPollStarted = new AtomicBoolean(false); m_longPollNamespaces = Multimaps.synchronizedSetMultimap(HashMultimap.create()); m_notifications = Maps.newConcurrentMap(); m_remoteNotificationMessages = Maps.newConcurrentMap(); m_responseType = new TypeToken>() { }.getType(); gson = new Gson(); m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); m_httpUtil = ApolloInjector.getInstance(HttpUtil.class); m_serviceLocator = ApolloInjector.getInstance(ConfigServiceLocator.class); m_longPollRateLimiter = RateLimiter.create(m_configUtil.getLongPollQPS()); } public boolean submit(String namespace, RemoteConfigRepository remoteConfigRepository) { boolean added = m_longPollNamespaces.put(namespace, remoteConfigRepository); m_notifications.putIfAbsent(namespace, INIT_NOTIFICATION_ID); if (!m_longPollStarted.get()) { startLongPolling(); } return added; } private void startLongPolling() { if (!m_longPollStarted.compareAndSet(false, true)) { //already started return; } try { final String appId = m_configUtil.getAppId(); final String cluster = m_configUtil.getCluster(); final String dataCenter = m_configUtil.getDataCenter(); final long longPollingInitialDelayInMills = m_configUtil.getLongPollingInitialDelayInMills(); m_longPollingService.submit(new Runnable() { @Override public void run() { if (longPollingInitialDelayInMills > 0) { try { logger.debug("Long polling will start in {} ms.", longPollingInitialDelayInMills); TimeUnit.MILLISECONDS.sleep(longPollingInitialDelayInMills); } catch (InterruptedException e) { //ignore } } doLongPollingRefresh(appId, cluster, dataCenter); } }); } catch (Throwable ex) { m_longPollStarted.set(false); ApolloConfigException exception = new ApolloConfigException("Schedule long polling refresh failed", ex); Tracer.logError(exception); logger.warn(ExceptionUtil.getDetailMessage(exception)); } } void stopLongPollingRefresh() { this.m_longPollingStopped.compareAndSet(false, true); } private void doLongPollingRefresh(String appId, String cluster, String dataCenter) { final Random random = new Random(); ServiceDTO lastServiceDto = null; while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted()) { if (!m_longPollRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) { //wait at most 5 seconds try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { } } Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "pollNotification"); String url = null; try { if (lastServiceDto == null) { List configServices = getConfigServices(); lastServiceDto = configServices.get(random.nextInt(configServices.size())); } url = assembleLongPollRefreshUrl(lastServiceDto.getHomepageUrl(), appId, cluster, dataCenter, m_notifications); logger.debug("Long polling from {}", url); HttpRequest request = new HttpRequest(url); //longer timeout for read - 10 minutes request.setReadTimeout(600000); transaction.addData("Url", url); final HttpResponse> response = m_httpUtil.doGet(request, m_responseType); logger.debug("Long polling response: {}, url: {}", response.getStatusCode(), url); if (response.getStatusCode() == 200 && response.getBody() != null) { updateNotifications(response.getBody()); updateRemoteNotifications(response.getBody()); transaction.addData("Result", response.getBody().toString()); notify(lastServiceDto, response.getBody()); } //try to load balance if (response.getStatusCode() == 304 && random.nextBoolean()) { lastServiceDto = null; } m_longPollFailSchedulePolicyInSecond.success(); transaction.addData("StatusCode", response.getStatusCode()); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { lastServiceDto = null; Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex)); transaction.setStatus(ex); long sleepTimeInSecond = m_longPollFailSchedulePolicyInSecond.fail(); logger.warn( "Long polling failed, will retry in {} seconds. appId: {}, cluster: {}, namespaces: {}, long polling url: {}, reason: {}", sleepTimeInSecond, appId, cluster, assembleNamespaces(), url, ExceptionUtil.getDetailMessage(ex)); try { TimeUnit.SECONDS.sleep(sleepTimeInSecond); } catch (InterruptedException ie) { //ignore } } finally { transaction.complete(); } } } private void notify(ServiceDTO lastServiceDto, List notifications) { if (notifications == null || notifications.isEmpty()) { return; } for (ApolloConfigNotification notification : notifications) { String namespaceName = notification.getNamespaceName(); //create a new list to avoid ConcurrentModificationException List toBeNotified = Lists.newArrayList(m_longPollNamespaces.get(namespaceName)); ApolloNotificationMessages originalMessages = m_remoteNotificationMessages.get(namespaceName); ApolloNotificationMessages remoteMessages = originalMessages == null ? null : originalMessages.clone(); //since .properties are filtered out by default, so we need to check if there is any listener for it toBeNotified.addAll(m_longPollNamespaces .get(String.format("%s.%s", namespaceName, ConfigFileFormat.Properties.getValue()))); for (RemoteConfigRepository remoteConfigRepository : toBeNotified) { try { remoteConfigRepository.onLongPollNotified(lastServiceDto, remoteMessages); } catch (Throwable ex) { Tracer.logError(ex); } } } } private void updateNotifications(List deltaNotifications) { for (ApolloConfigNotification notification : deltaNotifications) { if (Strings.isNullOrEmpty(notification.getNamespaceName())) { continue; } String namespaceName = notification.getNamespaceName(); if (m_notifications.containsKey(namespaceName)) { m_notifications.put(namespaceName, notification.getNotificationId()); } //since .properties are filtered out by default, so we need to check if there is notification with .properties suffix String namespaceNameWithPropertiesSuffix = String.format("%s.%s", namespaceName, ConfigFileFormat.Properties.getValue()); if (m_notifications.containsKey(namespaceNameWithPropertiesSuffix)) { m_notifications.put(namespaceNameWithPropertiesSuffix, notification.getNotificationId()); } } } private void updateRemoteNotifications(List deltaNotifications) { for (ApolloConfigNotification notification : deltaNotifications) { if (Strings.isNullOrEmpty(notification.getNamespaceName())) { continue; } if (notification.getMessages() == null || notification.getMessages().isEmpty()) { continue; } ApolloNotificationMessages localRemoteMessages = m_remoteNotificationMessages.get(notification.getNamespaceName()); if (localRemoteMessages == null) { localRemoteMessages = new ApolloNotificationMessages(); m_remoteNotificationMessages.put(notification.getNamespaceName(), localRemoteMessages); } localRemoteMessages.mergeFrom(notification.getMessages()); } } private String assembleNamespaces() { return STRING_JOINER.join(m_longPollNamespaces.keySet()); } String assembleLongPollRefreshUrl(String uri, String appId, String cluster, String dataCenter, Map notificationsMap) { Map queryParams = Maps.newHashMap(); queryParams.put("appId", queryParamEscaper.escape(appId)); queryParams.put("cluster", queryParamEscaper.escape(cluster)); queryParams .put("notifications", queryParamEscaper.escape(assembleNotifications(notificationsMap))); if (!Strings.isNullOrEmpty(dataCenter)) { queryParams.put("dataCenter", queryParamEscaper.escape(dataCenter)); } String localIp = m_configUtil.getLocalIp(); if (!Strings.isNullOrEmpty(localIp)) { queryParams.put("ip", queryParamEscaper.escape(localIp)); } String params = MAP_JOINER.join(queryParams); if (!uri.endsWith("/")) { uri += "/"; } return uri + "notifications/v2?" + params; } String assembleNotifications(Map notificationsMap) { List notifications = Lists.newArrayList(); for (Map.Entry entry : notificationsMap.entrySet()) { ApolloConfigNotification notification = new ApolloConfigNotification(entry.getKey(), entry.getValue()); notifications.add(notification); } return gson.toJson(notifications); } private List getConfigServices() { List services = m_serviceLocator.getConfigServices(); if (services.size() == 0) { throw new ApolloConfigException("No available config service"); } return services; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RemoteConfigRepository.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.Apollo; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloConfig; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; import com.ctrip.framework.apollo.core.dto.ServiceDTO; import com.ctrip.framework.apollo.core.schedule.ExponentialSchedulePolicy; import com.ctrip.framework.apollo.core.schedule.SchedulePolicy; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.exceptions.ApolloConfigStatusCodeException; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.apollo.util.ConfigUtil; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.ctrip.framework.apollo.util.http.HttpRequest; import com.ctrip.framework.apollo.util.http.HttpResponse; import com.ctrip.framework.apollo.util.http.HttpUtil; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.escape.Escaper; import com.google.common.net.UrlEscapers; import com.google.common.util.concurrent.RateLimiter; import com.google.gson.Gson; /** * @author Jason Song(song_s@ctrip.com) */ public class RemoteConfigRepository extends AbstractConfigRepository { private static final Logger logger = LoggerFactory.getLogger(RemoteConfigRepository.class); private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); private static final Joiner.MapJoiner MAP_JOINER = Joiner.on("&").withKeyValueSeparator("="); private ConfigServiceLocator m_serviceLocator; private HttpUtil m_httpUtil; private ConfigUtil m_configUtil; private RemoteConfigLongPollService remoteConfigLongPollService; private volatile AtomicReference m_configCache; private final String m_namespace; private final static ScheduledExecutorService m_executorService; private AtomicReference m_longPollServiceDto; private AtomicReference m_remoteMessages; private RateLimiter m_loadConfigRateLimiter; private AtomicBoolean m_configNeedForceRefresh; private SchedulePolicy m_loadConfigFailSchedulePolicy; private Gson gson; private static final Escaper pathEscaper = UrlEscapers.urlPathSegmentEscaper(); private static final Escaper queryParamEscaper = UrlEscapers.urlFormParameterEscaper(); static { m_executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("RemoteConfigRepository", true)); } /** * Constructor. * * @param namespace the namespace */ public RemoteConfigRepository(String namespace) { m_namespace = namespace; m_configCache = new AtomicReference<>(); m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); m_httpUtil = ApolloInjector.getInstance(HttpUtil.class); m_serviceLocator = ApolloInjector.getInstance(ConfigServiceLocator.class); remoteConfigLongPollService = ApolloInjector.getInstance(RemoteConfigLongPollService.class); m_longPollServiceDto = new AtomicReference<>(); m_remoteMessages = new AtomicReference<>(); m_loadConfigRateLimiter = RateLimiter.create(m_configUtil.getLoadConfigQPS()); m_configNeedForceRefresh = new AtomicBoolean(true); m_loadConfigFailSchedulePolicy = new ExponentialSchedulePolicy(m_configUtil.getOnErrorRetryInterval(), m_configUtil.getOnErrorRetryInterval() * 8); gson = new Gson(); this.trySync(); this.schedulePeriodicRefresh(); this.scheduleLongPollingRefresh(); } @Override public Properties getConfig() { if (m_configCache.get() == null) { this.sync(); } return transformApolloConfigToProperties(m_configCache.get()); } @Override public void setUpstreamRepository(ConfigRepository upstreamConfigRepository) { //remote config doesn't need upstream } private void schedulePeriodicRefresh() { logger.debug("Schedule periodic refresh with interval: {} {}", m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit()); m_executorService.scheduleAtFixedRate( new Runnable() { @Override public void run() { Tracer.logEvent("Apollo.ConfigService", String.format("periodicRefresh: %s", m_namespace)); logger.debug("refresh config for namespace: {}", m_namespace); trySync(); Tracer.logEvent("Apollo.Client.Version", Apollo.VERSION); } }, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(), m_configUtil.getRefreshIntervalTimeUnit()); } @Override protected synchronized void sync() { Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "syncRemoteConfig"); try { ApolloConfig previous = m_configCache.get(); ApolloConfig current = loadApolloConfig(); //reference equals means HTTP 304 if (previous != current) { logger.debug("Remote Config refreshed!"); m_configCache.set(current); this.fireRepositoryChange(m_namespace, this.getConfig()); } if (current != null) { Tracer.logEvent(String.format("Apollo.Client.Configs.%s", current.getNamespaceName()), current.getReleaseKey()); } transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); throw ex; } finally { transaction.complete(); } } private Properties transformApolloConfigToProperties(ApolloConfig apolloConfig) { Properties result = new Properties(); result.putAll(apolloConfig.getConfigurations()); return result; } private ApolloConfig loadApolloConfig() { if (!m_loadConfigRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) { //wait at most 5 seconds try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { } } String appId = m_configUtil.getAppId(); String cluster = m_configUtil.getCluster(); String dataCenter = m_configUtil.getDataCenter(); Tracer.logEvent("Apollo.Client.ConfigMeta", STRING_JOINER.join(appId, cluster, m_namespace)); int maxRetries = m_configNeedForceRefresh.get() ? 2 : 1; long onErrorSleepTime = 0; // 0 means no sleep Throwable exception = null; List configServices = getConfigServices(); String url = null; for (int i = 0; i < maxRetries; i++) { List randomConfigServices = Lists.newLinkedList(configServices); Collections.shuffle(randomConfigServices); //Access the server which notifies the client first if (m_longPollServiceDto.get() != null) { randomConfigServices.add(0, m_longPollServiceDto.getAndSet(null)); } for (ServiceDTO configService : randomConfigServices) { if (onErrorSleepTime > 0) { logger.warn( "Load config failed, will retry in {} {}. appId: {}, cluster: {}, namespaces: {}", onErrorSleepTime, m_configUtil.getOnErrorRetryIntervalTimeUnit(), appId, cluster, m_namespace); try { m_configUtil.getOnErrorRetryIntervalTimeUnit().sleep(onErrorSleepTime); } catch (InterruptedException e) { //ignore } } url = assembleQueryConfigUrl(configService.getHomepageUrl(), appId, cluster, m_namespace, dataCenter, m_remoteMessages.get(), m_configCache.get()); logger.debug("Loading config from {}", url); HttpRequest request = new HttpRequest(url); Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "queryConfig"); transaction.addData("Url", url); try { HttpResponse response = m_httpUtil.doGet(request, ApolloConfig.class); m_configNeedForceRefresh.set(false); m_loadConfigFailSchedulePolicy.success(); transaction.addData("StatusCode", response.getStatusCode()); transaction.setStatus(Transaction.SUCCESS); if (response.getStatusCode() == 304) { logger.debug("Config server responds with 304 HTTP status code."); return m_configCache.get(); } ApolloConfig result = response.getBody(); logger.debug("Loaded config for {}: {}", m_namespace, result); return result; } catch (ApolloConfigStatusCodeException ex) { ApolloConfigStatusCodeException statusCodeException = ex; //config not found if (ex.getStatusCode() == 404) { String message = String.format( "Could not find config for namespace - appId: %s, cluster: %s, namespace: %s, " + "please check whether the configs are released in Apollo!", appId, cluster, m_namespace); statusCodeException = new ApolloConfigStatusCodeException(ex.getStatusCode(), message); } Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(statusCodeException)); transaction.setStatus(statusCodeException); exception = statusCodeException; } catch (Throwable ex) { Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex)); transaction.setStatus(ex); exception = ex; } finally { transaction.complete(); } // if force refresh, do normal sleep, if normal config load, do exponential sleep onErrorSleepTime = m_configNeedForceRefresh.get() ? m_configUtil.getOnErrorRetryInterval() : m_loadConfigFailSchedulePolicy.fail(); } } String message = String.format( "Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s, url: %s", appId, cluster, m_namespace, url); throw new ApolloConfigException(message, exception); } String assembleQueryConfigUrl(String uri, String appId, String cluster, String namespace, String dataCenter, ApolloNotificationMessages remoteMessages, ApolloConfig previousConfig) { String path = "configs/%s/%s/%s"; List pathParams = Lists.newArrayList(pathEscaper.escape(appId), pathEscaper.escape(cluster), pathEscaper.escape(namespace)); Map queryParams = Maps.newHashMap(); if (previousConfig != null) { queryParams.put("releaseKey", queryParamEscaper.escape(previousConfig.getReleaseKey())); } if (!Strings.isNullOrEmpty(dataCenter)) { queryParams.put("dataCenter", queryParamEscaper.escape(dataCenter)); } String localIp = m_configUtil.getLocalIp(); if (!Strings.isNullOrEmpty(localIp)) { queryParams.put("ip", queryParamEscaper.escape(localIp)); } if (remoteMessages != null) { queryParams.put("messages", queryParamEscaper.escape(gson.toJson(remoteMessages))); } String pathExpanded = String.format(path, pathParams.toArray()); if (!queryParams.isEmpty()) { pathExpanded += "?" + MAP_JOINER.join(queryParams); } if (!uri.endsWith("/")) { uri += "/"; } return uri + pathExpanded; } private void scheduleLongPollingRefresh() { remoteConfigLongPollService.submit(m_namespace, this); } public void onLongPollNotified(ServiceDTO longPollNotifiedServiceDto, ApolloNotificationMessages remoteMessages) { m_longPollServiceDto.set(longPollNotifiedServiceDto); m_remoteMessages.set(remoteMessages); m_executorService.submit(new Runnable() { @Override public void run() { m_configNeedForceRefresh.set(true); trySync(); } }); } private List getConfigServices() { List services = m_serviceLocator.getConfigServices(); if (services.size() == 0) { throw new ApolloConfigException("No available config service"); } return services; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/RepositoryChangeListener.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.Properties; /** * @author Jason Song(song_s@ctrip.com) */ public interface RepositoryChangeListener { /** * Invoked when config repository changes. * @param namespace the namespace of this repository change * @param newProperties the properties after change */ public void onRepositoryChange(String namespace, Properties newProperties); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/SimpleConfig.java ================================================ package com.ctrip.framework.apollo.internals; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.model.ConfigChange; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.util.ExceptionUtil; import com.google.common.base.Function; import com.google.common.collect.Maps; /** * @author Jason Song(song_s@ctrip.com) */ public class SimpleConfig extends AbstractConfig implements RepositoryChangeListener { private static final Logger logger = LoggerFactory.getLogger(SimpleConfig.class); private final String m_namespace; private final ConfigRepository m_configRepository; private volatile Properties m_configProperties; /** * Constructor. * * @param namespace the namespace for this config instance * @param configRepository the config repository for this config instance */ public SimpleConfig(String namespace, ConfigRepository configRepository) { m_namespace = namespace; m_configRepository = configRepository; this.initialize(); } private void initialize() { try { m_configProperties = m_configRepository.getConfig(); } catch (Throwable ex) { Tracer.logError(ex); logger.warn("Init Apollo Simple Config failed - namespace: {}, reason: {}", m_namespace, ExceptionUtil.getDetailMessage(ex)); } finally { //register the change listener no matter config repository is working or not //so that whenever config repository is recovered, config could get changed m_configRepository.addChangeListener(this); } } @Override public String getProperty(String key, String defaultValue) { if (m_configProperties == null) { logger.warn("Could not load config from Apollo, always return default value!"); return defaultValue; } return this.m_configProperties.getProperty(key, defaultValue); } @Override public Set getPropertyNames() { if (m_configProperties == null) { return Collections.emptySet(); } return m_configProperties.stringPropertyNames(); } @Override public synchronized void onRepositoryChange(String namespace, Properties newProperties) { if (newProperties.equals(m_configProperties)) { return; } Properties newConfigProperties = new Properties(); newConfigProperties.putAll(newProperties); List changes = calcPropertyChanges(namespace, m_configProperties, newConfigProperties); Map changeMap = Maps.uniqueIndex(changes, new Function() { @Override public String apply(ConfigChange input) { return input.getPropertyName(); } }); m_configProperties = newConfigProperties; clearConfigCache(); this.fireConfigChange(new ConfigChangeEvent(m_namespace, changeMap)); Tracer.logEvent("Apollo.Client.ConfigChanges", m_namespace); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/XmlConfigFile.java ================================================ package com.ctrip.framework.apollo.internals; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; /** * @author Jason Song(song_s@ctrip.com) */ public class XmlConfigFile extends PlainTextConfigFile { public XmlConfigFile(String namespace, ConfigRepository configRepository) { super(namespace, configRepository); } @Override public ConfigFileFormat getConfigFileFormat() { return ConfigFileFormat.XML; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/YamlConfigFile.java ================================================ package com.ctrip.framework.apollo.internals; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; /** * @author Jason Song(song_s@ctrip.com) */ public class YamlConfigFile extends PlainTextConfigFile { public YamlConfigFile(String namespace, ConfigRepository configRepository) { super(namespace, configRepository); } @Override public ConfigFileFormat getConfigFileFormat() { return ConfigFileFormat.YAML; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/internals/YmlConfigFile.java ================================================ package com.ctrip.framework.apollo.internals; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; /** * @author Jason Song(song_s@ctrip.com) */ public class YmlConfigFile extends PlainTextConfigFile { public YmlConfigFile(String namespace, ConfigRepository configRepository) { super(namespace, configRepository); } @Override public ConfigFileFormat getConfigFileFormat() { return ConfigFileFormat.YML; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/model/ConfigChange.java ================================================ package com.ctrip.framework.apollo.model; import com.ctrip.framework.apollo.enums.PropertyChangeType; /** * Holds the information for a config change. * @author Jason Song(song_s@ctrip.com) */ public class ConfigChange { private final String namespace; private final String propertyName; private String oldValue; private String newValue; private PropertyChangeType changeType; /** * Constructor. * @param namespace the namespace of the key * @param propertyName the key whose value is changed * @param oldValue the value before change * @param newValue the value after change * @param changeType the change type */ public ConfigChange(String namespace, String propertyName, String oldValue, String newValue, PropertyChangeType changeType) { this.namespace = namespace; this.propertyName = propertyName; this.oldValue = oldValue; this.newValue = newValue; this.changeType = changeType; } public String getPropertyName() { return propertyName; } public String getOldValue() { return oldValue; } public String getNewValue() { return newValue; } public PropertyChangeType getChangeType() { return changeType; } public void setOldValue(String oldValue) { this.oldValue = oldValue; } public void setNewValue(String newValue) { this.newValue = newValue; } public void setChangeType(PropertyChangeType changeType) { this.changeType = changeType; } public String getNamespace() { return namespace; } @Override public String toString() { final StringBuilder sb = new StringBuilder("ConfigChange{"); sb.append("namespace='").append(namespace).append('\''); sb.append(", propertyName='").append(propertyName).append('\''); sb.append(", oldValue='").append(oldValue).append('\''); sb.append(", newValue='").append(newValue).append('\''); sb.append(", changeType=").append(changeType); sb.append('}'); return sb.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/model/ConfigChangeEvent.java ================================================ package com.ctrip.framework.apollo.model; import java.util.Map; import java.util.Set; /** * A change event when a namespace's config is changed. * @author Jason Song(song_s@ctrip.com) */ public class ConfigChangeEvent { private final String m_namespace; private final Map m_changes; /** * Constructor. * @param namespace the namespace of this change * @param changes the actual changes */ public ConfigChangeEvent(String namespace, Map changes) { m_namespace = namespace; m_changes = changes; } /** * Get the keys changed. * @return the list of the keys */ public Set changedKeys() { return m_changes.keySet(); } /** * Get a specific change instance for the key specified. * @param key the changed key * @return the change instance */ public ConfigChange getChange(String key) { return m_changes.get(key); } /** * Check whether the specified key is changed * @param key the key * @return true if the key is changed, false otherwise. */ public boolean isChanged(String key) { return m_changes.containsKey(key); } /** * Get the namespace of this change event. * @return the namespace */ public String getNamespace() { return m_namespace; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/model/ConfigFileChangeEvent.java ================================================ package com.ctrip.framework.apollo.model; import com.ctrip.framework.apollo.enums.PropertyChangeType; /** * @author Jason Song(song_s@ctrip.com) */ public class ConfigFileChangeEvent { private final String namespace; private final String oldValue; private final String newValue; private final PropertyChangeType changeType; /** * Constructor. * * @param namespace the namespace of the config file change event * @param oldValue the value before change * @param newValue the value after change * @param changeType the change type */ public ConfigFileChangeEvent(String namespace, String oldValue, String newValue, PropertyChangeType changeType) { this.namespace = namespace; this.oldValue = oldValue; this.newValue = newValue; this.changeType = changeType; } public String getNamespace() { return namespace; } public String getOldValue() { return oldValue; } public String getNewValue() { return newValue; } public PropertyChangeType getChangeType() { return changeType; } @Override public String toString() { final StringBuilder sb = new StringBuilder("ConfigFileChangeEvent{"); sb.append("namespace='").append(namespace).append('\''); sb.append(", oldValue='").append(oldValue).append('\''); sb.append(", newValue='").append(newValue).append('\''); sb.append(", changeType=").append(changeType); sb.append('}'); return sb.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigFactory.java ================================================ package com.ctrip.framework.apollo.spi; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigFile; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigFactory { /** * Create the config instance for the namespace. * * @param namespace the namespace * @return the newly created config instance */ public Config create(String namespace); /** * Create the config file instance for the namespace * @param namespace the namespace * @return the newly created config file instance */ public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigFactoryManager.java ================================================ package com.ctrip.framework.apollo.spi; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigFactoryManager { /** * Get the config factory for the namespace. * * @param namespace the namespace * @return the config factory for this namespace */ public ConfigFactory getFactory(String namespace); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigRegistry.java ================================================ package com.ctrip.framework.apollo.spi; /** * The manually config registry, use with caution! * * @author Jason Song(song_s@ctrip.com) */ public interface ConfigRegistry { /** * Register the config factory for the namespace specified. * * @param namespace the namespace * @param factory the factory for this namespace */ public void register(String namespace, ConfigFactory factory); /** * Get the registered config factory for the namespace. * * @param namespace the namespace * @return the factory registered for this namespace */ public ConfigFactory getFactory(String namespace); } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigFactory.java ================================================ package com.ctrip.framework.apollo.spi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigFile; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.internals.ConfigRepository; import com.ctrip.framework.apollo.internals.DefaultConfig; import com.ctrip.framework.apollo.internals.JsonConfigFile; import com.ctrip.framework.apollo.internals.LocalFileConfigRepository; import com.ctrip.framework.apollo.internals.PropertiesConfigFile; import com.ctrip.framework.apollo.internals.RemoteConfigRepository; import com.ctrip.framework.apollo.internals.XmlConfigFile; import com.ctrip.framework.apollo.internals.YamlConfigFile; import com.ctrip.framework.apollo.internals.YmlConfigFile; import com.ctrip.framework.apollo.util.ConfigUtil; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultConfigFactory implements ConfigFactory { private static final Logger logger = LoggerFactory.getLogger(DefaultConfigFactory.class); private ConfigUtil m_configUtil; public DefaultConfigFactory() { m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); } @Override public Config create(String namespace) { DefaultConfig defaultConfig = new DefaultConfig(namespace, createLocalConfigRepository(namespace)); return defaultConfig; } @Override public ConfigFile createConfigFile(String namespace, ConfigFileFormat configFileFormat) { ConfigRepository configRepository = createLocalConfigRepository(namespace); switch (configFileFormat) { case Properties: return new PropertiesConfigFile(namespace, configRepository); case XML: return new XmlConfigFile(namespace, configRepository); case JSON: return new JsonConfigFile(namespace, configRepository); case YAML: return new YamlConfigFile(namespace, configRepository); case YML: return new YmlConfigFile(namespace, configRepository); } return null; } LocalFileConfigRepository createLocalConfigRepository(String namespace) { if (m_configUtil.isInLocalMode()) { logger.warn( "==== Apollo is in local mode! Won't pull configs from remote server for namespace {} ! ====", namespace); return new LocalFileConfigRepository(namespace); } return new LocalFileConfigRepository(namespace, createRemoteConfigRepository(namespace)); } RemoteConfigRepository createRemoteConfigRepository(String namespace) { return new RemoteConfigRepository(namespace); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigFactoryManager.java ================================================ package com.ctrip.framework.apollo.spi; import java.util.Map; import com.ctrip.framework.apollo.build.ApolloInjector; import com.google.common.collect.Maps; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultConfigFactoryManager implements ConfigFactoryManager { private ConfigRegistry m_registry; private Map m_factories = Maps.newConcurrentMap(); public DefaultConfigFactoryManager() { m_registry = ApolloInjector.getInstance(ConfigRegistry.class); } @Override public ConfigFactory getFactory(String namespace) { // step 1: check hacked factory ConfigFactory factory = m_registry.getFactory(namespace); if (factory != null) { return factory; } // step 2: check cache factory = m_factories.get(namespace); if (factory != null) { return factory; } // step 3: check declared config factory factory = ApolloInjector.getInstance(ConfigFactory.class, namespace); if (factory != null) { return factory; } // step 4: check default config factory factory = ApolloInjector.getInstance(ConfigFactory.class); m_factories.put(namespace, factory); // factory should not be null return factory; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigRegistry.java ================================================ package com.ctrip.framework.apollo.spi; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Maps; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultConfigRegistry implements ConfigRegistry { private static final Logger s_logger = LoggerFactory.getLogger(DefaultConfigRegistry.class); private Map m_instances = Maps.newConcurrentMap(); @Override public void register(String namespace, ConfigFactory factory) { if (m_instances.containsKey(namespace)) { s_logger.warn("ConfigFactory({}) is overridden by {}!", namespace, factory.getClass()); } m_instances.put(namespace, factory); } @Override public ConfigFactory getFactory(String namespace) { ConfigFactory config = m_instances.get(namespace); return config; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloAnnotationProcessor.java ================================================ package com.ctrip.framework.apollo.spring.annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.ReflectionUtils; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigChangeListener; import com.ctrip.framework.apollo.ConfigService; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.google.common.base.Preconditions; /** * Apollo Annotation Processor for Spring Application * * @author Jason Song(song_s@ctrip.com) */ public class ApolloAnnotationProcessor implements BeanPostProcessor, PriorityOrdered { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Class clazz = bean.getClass(); processFields(bean, clazz.getDeclaredFields()); processMethods(bean, clazz.getDeclaredMethods()); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } private void processFields(Object bean, Field[] declaredFields) { for (Field field : declaredFields) { ApolloConfig annotation = AnnotationUtils.getAnnotation(field, ApolloConfig.class); if (annotation == null) { continue; } Preconditions.checkArgument(Config.class.isAssignableFrom(field.getType()), "Invalid type: %s for field: %s, should be Config", field.getType(), field); String namespace = annotation.value(); Config config = ConfigService.getConfig(namespace); ReflectionUtils.makeAccessible(field); ReflectionUtils.setField(field, bean, config); } } private void processMethods(final Object bean, Method[] declaredMethods) { for (final Method method : declaredMethods) { ApolloConfigChangeListener annotation = AnnotationUtils.findAnnotation(method, ApolloConfigChangeListener.class); if (annotation == null) { continue; } Class[] parameterTypes = method.getParameterTypes(); Preconditions.checkArgument(parameterTypes.length == 1, "Invalid number of parameters: %s for method: %s, should be 1", parameterTypes.length, method); Preconditions.checkArgument(ConfigChangeEvent.class.isAssignableFrom(parameterTypes[0]), "Invalid parameter type: %s for method: %s, should be ConfigChangeEvent", parameterTypes[0], method); ReflectionUtils.makeAccessible(method); String[] namespaces = annotation.value(); for (String namespace : namespaces) { Config config = ConfigService.getConfig(namespace); config.addChangeListener(new ConfigChangeListener() { @Override public void onChange(ConfigChangeEvent changeEvent) { ReflectionUtils.invokeMethod(method, bean, changeEvent); } }); } } } @Override public int getOrder() { //make it as late as possible return Ordered.LOWEST_PRECEDENCE; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfig.java ================================================ package com.ctrip.framework.apollo.spring.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.ctrip.framework.apollo.core.ConfigConsts; /** * Use this annotation to inject Apollo Config Instance. * *

Usage example:

*
 * //Inject the config for "someNamespace"
 * @ApolloConfig("someNamespace")
 * private Config config;
 * 
* * @author Jason Song(song_s@ctrip.com) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Documented public @interface ApolloConfig { /** * Apollo namespace for the config, if not specified then default to application */ String value() default ConfigConsts.NAMESPACE_APPLICATION; } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigChangeListener.java ================================================ package com.ctrip.framework.apollo.spring.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.ctrip.framework.apollo.core.ConfigConsts; /** * Use this annotation to register Apollo ConfigChangeListener. * *

Usage example:

*
 * //Listener on namespaces of "someNamespace" and "anotherNamespace"
 * @ApolloConfigChangeListener({"someNamespace","anotherNamespace"})
 * private void onChange(ConfigChangeEvent changeEvent) {
 *     //handle change event
 * }
 * 
* * @author Jason Song(song_s@ctrip.com) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface ApolloConfigChangeListener { /** * Apollo namespace for the config, if not specified then default to application */ String[] value() default {ConfigConsts.NAMESPACE_APPLICATION}; } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java ================================================ package com.ctrip.framework.apollo.spring.annotation; import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; import com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor; import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; import com.google.common.collect.Lists; /** * @author Jason Song(song_s@ctrip.com) */ public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata .getAnnotationAttributes(EnableApolloConfig.class.getName())); String[] namespaces = attributes.getStringArray("value"); int order = attributes.getNumber("order"); PropertySourcesProcessor.addNamespaces(Lists.newArrayList(namespaces), order); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), PropertySourcesPlaceholderConfigurer.class); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class.getName(), PropertySourcesProcessor.class); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), ApolloAnnotationProcessor.class); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueDefinitionProcessor.class.getName(), SpringValueDefinitionProcessor.class); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/EnableApolloConfig.java ================================================ package com.ctrip.framework.apollo.spring.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; import org.springframework.core.Ordered; import com.ctrip.framework.apollo.core.ConfigConsts; /** * Use this annotation to register Apollo property sources when using Java Config. * *

Configuration example:

*
 * @Configuration
 * @EnableApolloConfig({"someNamespace","anotherNamespace"})
 * public class AppConfig {
 *
 * }
 * 
* * @author Jason Song(song_s@ctrip.com) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(ApolloConfigRegistrar.class) public @interface EnableApolloConfig { /** * Apollo namespaces to inject configuration into Spring Property Sources. */ String[] value() default {ConfigConsts.NAMESPACE_APPLICATION}; /** * The order of the apollo config, default is {@link Ordered#LOWEST_PRECEDENCE}, which is Integer.MAX_VALUE. * If there are properties with the same name in different apollo configs, the apollo config with smaller order wins. * @return */ int order() default Ordered.LOWEST_PRECEDENCE; } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/SpringValueProcessor.java ================================================ package com.ctrip.framework.apollo.spring.annotation; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.TypeConverter; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.Scope; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.Bean; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import org.springframework.core.env.Environment; import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; import com.ctrip.framework.apollo.ConfigChangeListener; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.model.ConfigChange; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.spring.config.ConfigPropertySource; import com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory; import com.ctrip.framework.apollo.spring.property.PlaceholderHelper; import com.ctrip.framework.apollo.spring.property.SpringValue; import com.ctrip.framework.apollo.spring.property.SpringValueDefinition; import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor; import com.ctrip.framework.apollo.util.ConfigUtil; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; /** * Spring value processor of field or method which has @Value and xml config placeholders. * * @author github.com/zhegexiaohuozi seimimaster@gmail.com * @since 2017/12/20. */ public class SpringValueProcessor implements BeanPostProcessor, PriorityOrdered, EnvironmentAware, BeanFactoryAware, BeanFactoryPostProcessor { private static final Logger logger = LoggerFactory.getLogger(SpringValueProcessor.class); private final Multimap monitor = LinkedListMultimap.create(); private final ConfigUtil configUtil; private final PlaceholderHelper placeholderHelper; private final ConfigPropertySourceFactory configPropertySourceFactory; private final boolean typeConverterHasConvertIfNecessaryWithFieldParameter; private Environment environment; private ConfigurableBeanFactory beanFactory; private TypeConverter typeConverter; private static Multimap beanName2SpringValueDefinitions = LinkedListMultimap.create(); public SpringValueProcessor() { configUtil = ApolloInjector.getInstance(ConfigUtil.class); placeholderHelper = ApolloInjector.getInstance(PlaceholderHelper.class); configPropertySourceFactory = ApolloInjector.getInstance(ConfigPropertySourceFactory.class); typeConverterHasConvertIfNecessaryWithFieldParameter = testTypeConverterHasConvertIfNecessaryWithFieldParameter(); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ConfigurableBeanFactory) beanFactory; this.typeConverter = this.beanFactory.getTypeConverter(); } @Override public void setEnvironment(Environment env) { this.environment = env; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) { beanName2SpringValueDefinitions = SpringValueDefinitionProcessor.getBeanName2SpringValueDefinitions(); registerConfigChangeListener(); } } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) { Class clazz = bean.getClass(); processFields(bean, beanName, findAllField(clazz)); processMethods(bean, beanName, findAllMethod(clazz)); processBeanPropertyValues(bean, beanName); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } private void processFields(Object bean, String beanName, List declaredFields) { for (Field field : declaredFields) { // register @Value on field Value value = field.getAnnotation(Value.class); if (value == null) { continue; } Set keys = placeholderHelper.extractPlaceholderKeys(value.value()); if (keys.isEmpty()) { continue; } for (String key : keys) { SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field); monitor.put(key, springValue); logger.debug("Monitoring {}", springValue); } } } private void processMethods(final Object bean, String beanName, List declaredMethods) { for (final Method method : declaredMethods) { //register @Value on method Value value = method.getAnnotation(Value.class); if (value == null) { continue; } //skip Configuration bean methods if (method.getAnnotation(Bean.class) != null) { continue; } if (method.getParameterTypes().length != 1) { logger.error("Ignore @Value setter {}.{}, expecting 1 parameter, actual {} parameters", bean.getClass().getName(), method.getName(), method.getParameterTypes().length); continue; } Set keys = placeholderHelper.extractPlaceholderKeys(value.value()); if (keys.isEmpty()) { continue; } for (String key : keys) { SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, method); monitor.put(key, springValue); logger.debug("Monitoring {}", springValue); } } } private void processBeanPropertyValues(Object bean, String beanName) { Collection propertySpringValues = beanName2SpringValueDefinitions .get(beanName); if (propertySpringValues == null || propertySpringValues.isEmpty()) { return; } for (SpringValueDefinition definition : propertySpringValues) { try { PropertyDescriptor pd = BeanUtils .getPropertyDescriptor(bean.getClass(), definition.getPropertyName()); Method method = pd.getWriteMethod(); if (method == null) { continue; } SpringValue springValue = new SpringValue(definition.getKey(), definition.getPlaceholder(), bean, beanName, method); monitor.put(definition.getKey(), springValue); logger.debug("Monitoring {}", springValue); } catch (Throwable ex) { logger.error("Failed to enable auto update feature for {}.{}", bean.getClass(), definition.getPropertyName()); } } // clear beanName2SpringValueDefinitions.removeAll(beanName); } private List findAllField(Class clazz) { final List res = new LinkedList<>(); ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { res.add(field); } }); return res; } private List findAllMethod(Class clazz) { final List res = new LinkedList<>(); ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { res.add(method); } }); return res; } private void registerConfigChangeListener() { ConfigChangeListener changeListener = new ConfigChangeListener() { @Override public void onChange(ConfigChangeEvent changeEvent) { Set keys = changeEvent.changedKeys(); if (CollectionUtils.isEmpty(keys)) { return; } for (String key : keys) { // 1. check whether the changed key is relevant Collection targetValues = monitor.get(key); if (targetValues == null || targetValues.isEmpty()) { continue; } // 2. check whether the value is really changed or not (since spring property sources have hierarchies) ConfigChange configChange = changeEvent.getChange(key); if (!Objects.equals(environment.getProperty(key), configChange.getNewValue())) { continue; } // 3. update the value for (SpringValue val : targetValues) { updateSpringValue(val); } } } }; List configPropertySources = configPropertySourceFactory.getAllConfigPropertySources(); for (ConfigPropertySource configPropertySource : configPropertySources) { configPropertySource.addChangeListener(changeListener); } } private void updateSpringValue(SpringValue springValue) { try { Object value = resolvePropertyValue(springValue); springValue.update(value); logger.debug("Auto update apollo changed value successfully, new value: {}, {}", value, springValue.toString()); } catch (Throwable ex) { logger.error("Auto update apollo changed value failed, {}", springValue.toString(), ex); } } /** * Logic transplanted from DefaultListableBeanFactory * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set, org.springframework.beans.TypeConverter) */ private Object resolvePropertyValue(SpringValue springValue) { String strVal = beanFactory.resolveEmbeddedValue(springValue.getPlaceholder()); Object value; BeanDefinition bd = (beanFactory.containsBean(springValue.getBeanName()) ? beanFactory .getMergedBeanDefinition(springValue.getBeanName()) : null); value = evaluateBeanDefinitionString(strVal, bd); if (springValue.isField()) { // org.springframework.beans.TypeConverter#convertIfNecessary(java.lang.Object, java.lang.Class, java.lang.reflect.Field) is available from Spring 3.2.0+ if (typeConverterHasConvertIfNecessaryWithFieldParameter) { value = this.typeConverter .convertIfNecessary(value, springValue.getTargetType(), springValue.getField()); } else { value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType()); } } else { value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType(), springValue.getMethodParameter()); } return value; } private Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) { if (beanFactory.getBeanExpressionResolver() == null) { return value; } Scope scope = (beanDefinition != null ? beanFactory.getRegisteredScope(beanDefinition.getScope()) : null); return beanFactory.getBeanExpressionResolver().evaluate(value, new BeanExpressionContext(beanFactory, scope)); } private boolean testTypeConverterHasConvertIfNecessaryWithFieldParameter() { try { TypeConverter.class.getMethod("convertIfNecessary", Object.class, Class.class, Field.class); } catch (Throwable ex) { return false; } return true; } @Override public int getOrder() { //make it as late as possible return Ordered.LOWEST_PRECEDENCE; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java ================================================ package com.ctrip.framework.apollo.spring.boot; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigService; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory; import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants; import com.google.common.base.Splitter; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; /** * Inject the Apollo config in Spring Boot bootstrap phase * *

Configuration example:

*
 *   # will inject 'application' namespace in bootstrap phase
 *   apollo.bootstrap.enabled = true
 * 
* * or * *
 *   apollo.bootstrap.enabled = true
 *   # will inject 'application' and 'FX.apollo' namespaces in bootstrap phase
 *   apollo.bootstrap.namespaces = application,FX.apollo
 * 
*/ public class ApolloApplicationContextInitializer implements ApplicationContextInitializer { private static final Logger logger = LoggerFactory.getLogger(ApolloApplicationContextInitializer.class); private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults(); private final ConfigPropertySourceFactory configPropertySourceFactory = ApolloInjector .getInstance(ConfigPropertySourceFactory.class); @Override public void initialize(ConfigurableApplicationContext context) { ConfigurableEnvironment environment = context.getEnvironment(); String enabled = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, "false"); if (!Boolean.valueOf(enabled)) { logger.debug("Apollo bootstrap config is not enabled for context {}, see property: ${{}}", context, PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED); return; } logger.debug("Apollo bootstrap config is enabled for context {}", context); if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) { //already initialized return; } String namespaces = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES, ConfigConsts.NAMESPACE_APPLICATION); logger.debug("Apollo bootstrap namespaces: {}", namespaces); List namespaceList = NAMESPACE_SPLITTER.splitToList(namespaces); CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); for (String namespace : namespaceList) { Config config = ConfigService.getConfig(namespace); composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config)); } environment.getPropertySources().addFirst(composite); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloAutoConfiguration.java ================================================ package com.ctrip.framework.apollo.spring.boot; import com.ctrip.framework.apollo.spring.config.ConfigPropertySourcesProcessor; import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants; import com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @ConditionalOnProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED) @ConditionalOnMissingBean(PropertySourcesProcessor.class) public class ApolloAutoConfiguration { @Bean public ConfigPropertySourcesProcessor configPropertySourcesProcessor() { return new ConfigPropertySourcesProcessor(); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java ================================================ package com.ctrip.framework.apollo.spring.config; import com.ctrip.framework.apollo.ConfigChangeListener; import java.util.Set; import org.springframework.core.env.EnumerablePropertySource; import com.ctrip.framework.apollo.Config; /** * Property source wrapper for Config * * @author Jason Song(song_s@ctrip.com) */ public class ConfigPropertySource extends EnumerablePropertySource { private static final String[] EMPTY_ARRAY = new String[0]; ConfigPropertySource(String name, Config source) { super(name, source); } @Override public String[] getPropertyNames() { Set propertyNames = this.source.getPropertyNames(); if (propertyNames.isEmpty()) { return EMPTY_ARRAY; } return propertyNames.toArray(new String[propertyNames.size()]); } @Override public Object getProperty(String name) { return this.source.getProperty(name, null); } public void addChangeListener(ConfigChangeListener listener) { this.source.addChangeListener(listener); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourceFactory.java ================================================ package com.ctrip.framework.apollo.spring.config; import java.util.List; import com.ctrip.framework.apollo.Config; import com.google.common.collect.Lists; public class ConfigPropertySourceFactory { private final List configPropertySources = Lists.newLinkedList(); public ConfigPropertySource getConfigPropertySource(String name, Config source) { ConfigPropertySource configPropertySource = new ConfigPropertySource(name, source); configPropertySources.add(configPropertySource); return configPropertySource; } public List getAllConfigPropertySources() { return Lists.newLinkedList(configPropertySources); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java ================================================ package com.ctrip.framework.apollo.spring.config; import com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor; import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import com.ctrip.framework.apollo.spring.annotation.ApolloAnnotationProcessor; import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; /** * Apollo Property Sources processor for Spring XML Based Application * * @author Jason Song(song_s@ctrip.com) */ public class ConfigPropertySourcesProcessor extends PropertySourcesProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), PropertySourcesPlaceholderConfigurer.class); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), ApolloAnnotationProcessor.class); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class); processSpringValueDefinition(registry); } /** * For Spring 3.x versions, the BeanDefinitionRegistryPostProcessor would not be * instantiated if it is added in postProcessBeanDefinitionRegistry phase, so we have to manually * call the postProcessBeanDefinitionRegistry method of SpringValueDefinitionProcessor here... */ private void processSpringValueDefinition(BeanDefinitionRegistry registry) { SpringValueDefinitionProcessor springValueDefinitionProcessor = new SpringValueDefinitionProcessor(); springValueDefinitionProcessor.postProcessBeanDefinitionRegistry(registry); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/NamespaceHandler.java ================================================ package com.ctrip.framework.apollo.spring.config; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; import org.springframework.core.Ordered; import org.w3c.dom.Element; import com.ctrip.framework.apollo.core.ConfigConsts; import com.google.common.base.Splitter; import com.google.common.base.Strings; /** * @author Jason Song(song_s@ctrip.com) */ public class NamespaceHandler extends NamespaceHandlerSupport { private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults(); @Override public void init() { registerBeanDefinitionParser("config", new BeanParser()); } static class BeanParser extends AbstractSingleBeanDefinitionParser { @Override protected Class getBeanClass(Element element) { return ConfigPropertySourcesProcessor.class; } @Override protected boolean shouldGenerateId() { return true; } @Override protected void doParse(Element element, BeanDefinitionBuilder builder) { String namespaces = element.getAttribute("namespaces"); //default to application if (Strings.isNullOrEmpty(namespaces)) { namespaces = ConfigConsts.NAMESPACE_APPLICATION; } int order = Ordered.LOWEST_PRECEDENCE; String orderAttribute = element.getAttribute("order"); if (!Strings.isNullOrEmpty(orderAttribute)) { try { order = Integer.parseInt(orderAttribute); } catch (Throwable ex) { throw new IllegalArgumentException( String.format("Invalid order: %s for namespaces: %s", orderAttribute, namespaces)); } } PropertySourcesProcessor.addNamespaces(NAMESPACE_SPLITTER.splitToList(namespaces), order); } } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesConstants.java ================================================ package com.ctrip.framework.apollo.spring.config; public interface PropertySourcesConstants { String APOLLO_PROPERTY_SOURCE_NAME = "ApolloPropertySources"; String APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME = "ApolloBootstrapPropertySources"; String APOLLO_BOOTSTRAP_ENABLED = "apollo.bootstrap.enabled"; String APOLLO_BOOTSTRAP_NAMESPACES = "apollo.bootstrap.namespaces"; } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java ================================================ package com.ctrip.framework.apollo.spring.config; import com.ctrip.framework.apollo.build.ApolloInjector; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigService; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.EnvironmentAware; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import java.util.Collection; import java.util.Iterator; /** * Apollo Property Sources processor for Spring Annotation Based Application.

* * The reason why PropertySourcesProcessor implements {@link BeanFactoryPostProcessor} instead of * {@link org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor} is that lower versions of * Spring (e.g. 3.1.1) doesn't support registering BeanDefinitionRegistryPostProcessor in ImportBeanDefinitionRegistrar * - {@link com.ctrip.framework.apollo.spring.annotation.ApolloConfigRegistrar} * * @author Jason Song(song_s@ctrip.com) */ public class PropertySourcesProcessor implements BeanFactoryPostProcessor, EnvironmentAware, PriorityOrdered { private static final Multimap NAMESPACE_NAMES = LinkedHashMultimap.create(); private final ConfigPropertySourceFactory configPropertySourceFactory = ApolloInjector .getInstance(ConfigPropertySourceFactory.class); private ConfigurableEnvironment environment; public static boolean addNamespaces(Collection namespaces, int order) { return NAMESPACE_NAMES.putAll(order, namespaces); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { initializePropertySources(); } protected void initializePropertySources() { if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME)) { //already initialized return; } CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME); //sort by order asc ImmutableSortedSet orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet()); Iterator iterator = orders.iterator(); while (iterator.hasNext()) { int order = iterator.next(); for (String namespace : NAMESPACE_NAMES.get(order)) { Config config = ConfigService.getConfig(namespace); composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config)); } } // add after the bootstrap property source or to the first if (environment.getPropertySources() .contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) { environment.getPropertySources() .addAfter(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME, composite); } else { environment.getPropertySources().addFirst(composite); } } @Override public void setEnvironment(Environment environment) { //it is safe enough to cast as all known environment is derived from ConfigurableEnvironment this.environment = (ConfigurableEnvironment) environment; } //only for test private static void reset() { NAMESPACE_NAMES.clear(); } @Override public int getOrder() { //make it as early as possible return Ordered.HIGHEST_PRECEDENCE; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/package-info.java ================================================ /** * This package contains Apollo Spring integration codes and enables the following features:
*

1. Support Spring XML based configuration

*
    *
  • <apollo:config namespaces="someNamespace"/> to inject configurations from Apollo into Spring Property * Sources so that placeholders like ${someProperty} and @Value("someProperty") are supported.
  • *
*

2. Support Spring Java based configuration

*
    *
  • @EnableApolloConfig(namespaces={"someNamespace"}) to inject configurations from Apollo into Spring Property * Sources so that placeholders like ${someProperty} and @Value("someProperty") are supported.
  • *
* * With the above configuration, annotations like @ApolloConfig("someNamespace") * and @ApolloConfigChangeListener("someNamespace) are also supported.
*
* Requires Spring 3.1.1+ */ package com.ctrip.framework.apollo.spring; ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/PlaceholderHelper.java ================================================ package com.ctrip.framework.apollo.spring.property; import com.google.common.base.Strings; import com.google.common.collect.Sets; import java.util.Set; import java.util.Stack; import org.springframework.util.StringUtils; /** * Extract keys from placeholder, e.g. *
    *
  • ${some.key} => "some.key"
  • *
  • ${some.key:${some.other.key:100}} => "some.key", "some.other.key"
  • *
  • ${${some.key}} => "some.key"
  • *
  • ${${some.key:other.key}} => "some.key"
  • *
  • ${${some.key}:${another.key}} => "some.key", "another.key"
  • *
  • #{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')} => "some.key", "another.key"
  • *
*/ public class PlaceholderHelper { private static final String PLACEHOLDER_PREFIX = "${"; private static final String PLACEHOLDER_SUFFIX = "}"; private static final String VALUE_SEPARATOR = ":"; private static final String SIMPLE_PLACEHOLDER_PREFIX = "{"; private static final String EXPRESSION_PREFIX = "#{"; private static final String EXPRESSION_SUFFIX = "}"; public Set extractPlaceholderKeys(String propertyString) { Set placeholderKeys = Sets.newHashSet(); if (!isNormalizedPlaceholder(propertyString) && !isExpressionWithPlaceholder(propertyString)) { return placeholderKeys; } Stack stack = new Stack<>(); stack.push(propertyString); while (!stack.isEmpty()) { String strVal = stack.pop(); int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); if (startIndex == -1) { placeholderKeys.add(strVal); continue; } int endIndex = findPlaceholderEndIndex(strVal, startIndex); if (endIndex == -1) { // invalid placeholder? continue; } String placeholderCandidate = strVal.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); // ${some.key:other.key} if (placeholderCandidate.startsWith(PLACEHOLDER_PREFIX)) { stack.push(placeholderCandidate); } else { // some.key:${some.other.key:100} int separatorIndex = placeholderCandidate.indexOf(VALUE_SEPARATOR); if (separatorIndex == -1) { stack.push(placeholderCandidate); } else { stack.push(placeholderCandidate.substring(0, separatorIndex)); String defaultValuePart = normalizeToPlaceholder(placeholderCandidate.substring(separatorIndex + VALUE_SEPARATOR.length())); if (!Strings.isNullOrEmpty(defaultValuePart)) { stack.push(defaultValuePart); } } } // has remaining part, e.g. ${a}.${b} if (endIndex + PLACEHOLDER_SUFFIX.length() < strVal.length() - 1) { String remainingPart = normalizeToPlaceholder(strVal.substring(endIndex + PLACEHOLDER_SUFFIX.length())); if (!Strings.isNullOrEmpty(remainingPart)) { stack.push(remainingPart); } } } return placeholderKeys; } private boolean isNormalizedPlaceholder(String propertyString) { return propertyString.startsWith(PLACEHOLDER_PREFIX) && propertyString.endsWith(PLACEHOLDER_SUFFIX); } private boolean isExpressionWithPlaceholder(String propertyString) { return propertyString.startsWith(EXPRESSION_PREFIX) && propertyString.endsWith(EXPRESSION_SUFFIX) && propertyString.contains(PLACEHOLDER_PREFIX); } private String normalizeToPlaceholder(String strVal) { int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); if (startIndex == -1) { return null; } int endIndex = strVal.lastIndexOf(PLACEHOLDER_SUFFIX); if (endIndex == -1) { return null; } return strVal.substring(startIndex, endIndex + PLACEHOLDER_SUFFIX.length()); } private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { int index = startIndex + PLACEHOLDER_PREFIX.length(); int withinNestedPlaceholder = 0; while (index < buf.length()) { if (StringUtils.substringMatch(buf, index, PLACEHOLDER_SUFFIX)) { if (withinNestedPlaceholder > 0) { withinNestedPlaceholder--; index = index + PLACEHOLDER_SUFFIX.length(); } else { return index; } } else if (StringUtils.substringMatch(buf, index, SIMPLE_PLACEHOLDER_PREFIX)) { withinNestedPlaceholder++; index = index + SIMPLE_PLACEHOLDER_PREFIX.length(); } else { index++; } } return -1; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValue.java ================================================ package com.ctrip.framework.apollo.spring.property; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.springframework.core.MethodParameter; /** * Spring @Value method info * * @author github.com/zhegexiaohuozi seimimaster@gmail.com * @since 2018/2/6. */ public class SpringValue { private MethodParameter methodParameter; private Field field; private Object bean; private String beanName; private String key; private String placeholder; private Class targetType; public SpringValue(String key, String placeholder, Object bean, String beanName, Field field) { this.bean = bean; this.beanName = beanName; this.field = field; this.key = key; this.placeholder = placeholder; this.targetType = field.getType(); } public SpringValue(String key, String placeholder, Object bean, String beanName, Method method) { this.bean = bean; this.beanName = beanName; this.methodParameter = new MethodParameter(method, 0); this.key = key; this.placeholder = placeholder; Class[] paramTps = method.getParameterTypes(); this.targetType = paramTps[0]; } public void update(Object newVal) throws IllegalAccessException, InvocationTargetException { if (isField()) { injectField(newVal); } else { injectMethod(newVal); } } private void injectField(Object newVal) throws IllegalAccessException { boolean accessible = field.isAccessible(); field.setAccessible(true); field.set(bean, newVal); field.setAccessible(accessible); } private void injectMethod(Object newVal) throws InvocationTargetException, IllegalAccessException { methodParameter.getMethod().invoke(bean, newVal); } public String getBeanName() { return beanName; } public Class getTargetType() { return targetType; } public String getPlaceholder() { return this.placeholder; } public MethodParameter getMethodParameter() { return methodParameter; } public boolean isField() { return this.field != null; } public Field getField() { return field; } @Override public String toString() { if (isField()) { return String .format("key: %s, beanName: %s, field: %s.%s", key, beanName, bean.getClass().getName(), field.getName()); } return String.format("key: %s, beanName: %s, method: %s.%s", key, beanName, bean.getClass().getName(), methodParameter.getMethod().getName()); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinition.java ================================================ package com.ctrip.framework.apollo.spring.property; public class SpringValueDefinition { private final String key; private final String placeholder; private final String propertyName; public SpringValueDefinition(String key, String placeholder, String propertyName) { this.key = key; this.placeholder = placeholder; this.propertyName = propertyName; } public String getKey() { return key; } public String getPlaceholder() { return placeholder; } public String getPropertyName() { return propertyName; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinitionProcessor.java ================================================ package com.ctrip.framework.apollo.spring.property; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.util.ConfigUtil; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; /** * To process xml config placeholders, e.g. * *
 *  <bean class="com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.bean.XmlBean">
 *    <property name="timeout" value="${timeout:200}"/>
 *    <property name="batch" value="${batch:100}"/>
 *  </bean>
 * 
*/ public class SpringValueDefinitionProcessor implements BeanDefinitionRegistryPostProcessor { private static final Multimap beanName2SpringValueDefinitions = LinkedListMultimap.create(); private static final AtomicBoolean initialized = new AtomicBoolean(false); private final ConfigUtil configUtil; private final PlaceholderHelper placeholderHelper; public SpringValueDefinitionProcessor() { configUtil = ApolloInjector.getInstance(ConfigUtil.class); placeholderHelper = ApolloInjector.getInstance(PlaceholderHelper.class); } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) { processPropertyValues(registry); } } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } public static Multimap getBeanName2SpringValueDefinitions() { return beanName2SpringValueDefinitions; } private void processPropertyValues(BeanDefinitionRegistry beanRegistry) { if (!initialized.compareAndSet(false, true)) { // already initialized return; } String[] beanNames = beanRegistry.getBeanDefinitionNames(); for (String beanName : beanNames) { BeanDefinition beanDefinition = beanRegistry.getBeanDefinition(beanName); MutablePropertyValues mutablePropertyValues = beanDefinition.getPropertyValues(); List propertyValues = mutablePropertyValues.getPropertyValueList(); for (PropertyValue propertyValue : propertyValues) { Object value = propertyValue.getValue(); if (!(value instanceof TypedStringValue)) { continue; } String placeholder = ((TypedStringValue) value).getValue(); Set keys = placeholderHelper.extractPlaceholderKeys(placeholder); if (keys.isEmpty()) { continue; } for (String key : keys) { beanName2SpringValueDefinitions.put(beanName, new SpringValueDefinition(key, placeholder, propertyValue.getName())); } } } } //only for test private static void reset() { initialized.set(false); beanName2SpringValueDefinitions.clear(); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/util/BeanRegistrationUtil.java ================================================ package com.ctrip.framework.apollo.spring.util; import java.util.Objects; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; /** * @author Jason Song(song_s@ctrip.com) */ public class BeanRegistrationUtil { public static boolean registerBeanDefinitionIfNotExists(BeanDefinitionRegistry registry, String beanName, Class beanClass) { if (registry.containsBeanDefinition(beanName)) { return false; } String[] candidates = registry.getBeanDefinitionNames(); for (String candidate : candidates) { BeanDefinition beanDefinition = registry.getBeanDefinition(candidate); if (Objects.equals(beanDefinition.getBeanClassName(), beanClass.getName())) { return false; } } BeanDefinition annotationProcessor = BeanDefinitionBuilder.genericBeanDefinition(beanClass).getBeanDefinition(); registry.registerBeanDefinition(beanName, annotationProcessor); return true; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java ================================================ package com.ctrip.framework.apollo.util; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.MetaDomainConsts; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.enums.EnvUtils; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.foundation.Foundation; import com.google.common.base.Strings; /** * @author Jason Song(song_s@ctrip.com) */ public class ConfigUtil { private static final Logger logger = LoggerFactory.getLogger(ConfigUtil.class); private int refreshInterval = 5; private TimeUnit refreshIntervalTimeUnit = TimeUnit.MINUTES; private int connectTimeout = 1000; //1 second private int readTimeout = 5000; //5 seconds private String cluster; private int loadConfigQPS = 2; //2 times per second private int longPollQPS = 2; //2 times per second //for on error retry private long onErrorRetryInterval = 1;//1 second private TimeUnit onErrorRetryIntervalTimeUnit = TimeUnit.SECONDS;//1 second //for typed config cache of parser result, e.g. integer, double, long, etc. private long maxConfigCacheSize = 500;//500 cache key private long configCacheExpireTime = 1;//1 minute private TimeUnit configCacheExpireTimeUnit = TimeUnit.MINUTES;//1 minute private long longPollingInitialDelayInMills = 2000;//2 seconds private boolean autoUpdateInjectedSpringProperties = true; public ConfigUtil() { initRefreshInterval(); initConnectTimeout(); initReadTimeout(); initCluster(); initQPS(); initMaxConfigCacheSize(); initLongPollingInitialDelayInMills(); initAutoUpdateInjectedSpringProperties(); } /** * Get the app id for the current application. * * @return the app id or ConfigConsts.NO_APPID_PLACEHOLDER if app id is not available */ public String getAppId() { String appId = Foundation.app().getAppId(); if (Strings.isNullOrEmpty(appId)) { appId = ConfigConsts.NO_APPID_PLACEHOLDER; logger.warn("app.id is not set, please make sure it is set in classpath:/META-INF/app.properties, now apollo " + "will only load public namespace configurations!"); } return appId; } /** * Get the data center info for the current application. * * @return the current data center, null if there is no such info. */ public String getDataCenter() { return Foundation.server().getDataCenter(); } private void initCluster() { //Load data center from system property cluster = System.getProperty(ConfigConsts.APOLLO_CLUSTER_KEY); //Use data center as cluster if (Strings.isNullOrEmpty(cluster)) { cluster = getDataCenter(); } //Use default cluster if (Strings.isNullOrEmpty(cluster)) { cluster = ConfigConsts.CLUSTER_NAME_DEFAULT; } } /** * Get the cluster name for the current application. * * @return the cluster name, or "default" if not specified */ public String getCluster() { return cluster; } /** * Get the current environment. * * @return the env * @throws ApolloConfigException if env is set */ public Env getApolloEnv() { Env env = EnvUtils.transformEnv(Foundation.server().getEnvType()); if (env == null) { String path = isOSWindows() ? "C:\\opt\\settings\\server.properties" : "/opt/settings/server.properties"; String message = String.format("env is not set, please make sure it is set in %s!", path); logger.error(message); throw new ApolloConfigException(message); } return env; } public String getLocalIp() { return Foundation.net().getHostAddress(); } public String getMetaServerDomainName() { return MetaDomainConsts.getDomain(getApolloEnv()); } private void initConnectTimeout() { String customizedConnectTimeout = System.getProperty("apollo.connectTimeout"); if (!Strings.isNullOrEmpty(customizedConnectTimeout)) { try { connectTimeout = Integer.parseInt(customizedConnectTimeout); } catch (Throwable ex) { logger.error("Config for apollo.connectTimeout is invalid: {}", customizedConnectTimeout); } } } public int getConnectTimeout() { return connectTimeout; } private void initReadTimeout() { String customizedReadTimeout = System.getProperty("apollo.readTimeout"); if (!Strings.isNullOrEmpty(customizedReadTimeout)) { try { readTimeout = Integer.parseInt(customizedReadTimeout); } catch (Throwable ex) { logger.error("Config for apollo.readTimeout is invalid: {}", customizedReadTimeout); } } } public int getReadTimeout() { return readTimeout; } private void initRefreshInterval() { String customizedRefreshInterval = System.getProperty("apollo.refreshInterval"); if (!Strings.isNullOrEmpty(customizedRefreshInterval)) { try { refreshInterval = Integer.parseInt(customizedRefreshInterval); } catch (Throwable ex) { logger.error("Config for apollo.refreshInterval is invalid: {}", customizedRefreshInterval); } } } public int getRefreshInterval() { return refreshInterval; } public TimeUnit getRefreshIntervalTimeUnit() { return refreshIntervalTimeUnit; } private void initQPS() { String customizedLoadConfigQPS = System.getProperty("apollo.loadConfigQPS"); if (!Strings.isNullOrEmpty(customizedLoadConfigQPS)) { try { loadConfigQPS = Integer.parseInt(customizedLoadConfigQPS); } catch (Throwable ex) { logger.error("Config for apollo.loadConfigQPS is invalid: {}", customizedLoadConfigQPS); } } String customizedLongPollQPS = System.getProperty("apollo.longPollQPS"); if (!Strings.isNullOrEmpty(customizedLongPollQPS)) { try { longPollQPS = Integer.parseInt(customizedLongPollQPS); } catch (Throwable ex) { logger.error("Config for apollo.longPollQPS is invalid: {}", customizedLongPollQPS); } } } public int getLoadConfigQPS() { return loadConfigQPS; } public int getLongPollQPS() { return longPollQPS; } public long getOnErrorRetryInterval() { return onErrorRetryInterval; } public TimeUnit getOnErrorRetryIntervalTimeUnit() { return onErrorRetryIntervalTimeUnit; } public String getDefaultLocalCacheDir() { String cacheRoot = isOSWindows() ? "C:\\opt\\data\\%s" : "/opt/data/%s"; return String.format(cacheRoot, getAppId()); } public boolean isInLocalMode() { try { Env env = getApolloEnv(); return env == Env.LOCAL; } catch (Throwable ex) { //ignore } return false; } public boolean isOSWindows() { String osName = System.getProperty("os.name"); if (Strings.isNullOrEmpty(osName)) { return false; } return osName.startsWith("Windows"); } private void initMaxConfigCacheSize() { String customizedConfigCacheSize = System.getProperty("apollo.configCacheSize"); if (!Strings.isNullOrEmpty(customizedConfigCacheSize)) { try { maxConfigCacheSize = Long.valueOf(customizedConfigCacheSize); } catch (Throwable ex) { logger.error("Config for apollo.configCacheSize is invalid: {}", customizedConfigCacheSize); } } } public long getMaxConfigCacheSize() { return maxConfigCacheSize; } public long getConfigCacheExpireTime() { return configCacheExpireTime; } public TimeUnit getConfigCacheExpireTimeUnit() { return configCacheExpireTimeUnit; } private void initLongPollingInitialDelayInMills() { String customizedLongPollingInitialDelay = System.getProperty("apollo.longPollingInitialDelayInMills"); if (!Strings.isNullOrEmpty(customizedLongPollingInitialDelay)) { try { longPollingInitialDelayInMills = Long.valueOf(customizedLongPollingInitialDelay); } catch (Throwable ex) { logger.error("Config for apollo.longPollingInitialDelayInMills is invalid: {}", customizedLongPollingInitialDelay); } } } public long getLongPollingInitialDelayInMills() { return longPollingInitialDelayInMills; } private void initAutoUpdateInjectedSpringProperties() { // 1. Get from System Property String enableAutoUpdate = System.getProperty("apollo.autoUpdateInjectedSpringProperties"); if (Strings.isNullOrEmpty(enableAutoUpdate)) { // 2. Get from app.properties enableAutoUpdate = Foundation.app().getProperty("apollo.autoUpdateInjectedSpringProperties", null); } if (!Strings.isNullOrEmpty(enableAutoUpdate)) { autoUpdateInjectedSpringProperties = Boolean.parseBoolean(enableAutoUpdate.trim()); } } public boolean isAutoUpdateInjectedSpringPropertiesEnabled() { return autoUpdateInjectedSpringProperties; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/ExceptionUtil.java ================================================ package com.ctrip.framework.apollo.util; import java.util.List; import com.google.common.base.Strings; import com.google.common.collect.Lists; /** * @author Jason Song(song_s@ctrip.com) */ public class ExceptionUtil { /** * Assemble the detail message for the throwable with all of its cause included (at most 10 causes). * @param ex the exception * @return the message along with its causes */ public static String getDetailMessage(Throwable ex) { if (ex == null || Strings.isNullOrEmpty(ex.getMessage())) { return ""; } StringBuilder builder = new StringBuilder(ex.getMessage()); List causes = Lists.newLinkedList(); int counter = 0; Throwable current = ex; //retrieve up to 10 causes while (current.getCause() != null && counter < 10) { Throwable next = current.getCause(); causes.add(next); current = next; counter++; } for (Throwable cause : causes) { if (Strings.isNullOrEmpty(cause.getMessage())) { counter--; continue; } builder.append(" [Cause: ").append(cause.getMessage()); } builder.append(Strings.repeat("]", counter)); return builder.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/function/Functions.java ================================================ package com.ctrip.framework.apollo.util.function; import java.util.Date; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.util.parser.ParserException; import com.ctrip.framework.apollo.util.parser.Parsers; import com.google.common.base.Function; /** * @author Jason Song(song_s@ctrip.com) */ public interface Functions { Function TO_INT_FUNCTION = new Function() { @Override public Integer apply(String input) { return Integer.parseInt(input); } }; Function TO_LONG_FUNCTION = new Function() { @Override public Long apply(String input) { return Long.parseLong(input); } }; Function TO_SHORT_FUNCTION = new Function() { @Override public Short apply(String input) { return Short.parseShort(input); } }; Function TO_FLOAT_FUNCTION = new Function() { @Override public Float apply(String input) { return Float.parseFloat(input); } }; Function TO_DOUBLE_FUNCTION = new Function() { @Override public Double apply(String input) { return Double.parseDouble(input); } }; Function TO_BYTE_FUNCTION = new Function() { @Override public Byte apply(String input) { return Byte.parseByte(input); } }; Function TO_BOOLEAN_FUNCTION = new Function() { @Override public Boolean apply(String input) { return Boolean.parseBoolean(input); } }; Function TO_DATE_FUNCTION = new Function() { @Override public Date apply(String input) { try { return Parsers.forDate().parse(input); } catch (ParserException ex) { throw new ApolloConfigException("Parse date failed", ex); } } }; Function TO_DURATION_FUNCTION = new Function() { @Override public Long apply(String input) { try { return Parsers.forDuration().parseToMillis(input); } catch (ParserException ex) { throw new ApolloConfigException("Parse duration failed", ex); } } }; } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/http/HttpRequest.java ================================================ package com.ctrip.framework.apollo.util.http; /** * @author Jason Song(song_s@ctrip.com) */ public class HttpRequest { private String m_url; private int m_connectTimeout; private int m_readTimeout; /** * Create the request for the url. * @param url the url */ public HttpRequest(String url) { this.m_url = url; m_connectTimeout = -1; m_readTimeout = -1; } public String getUrl() { return m_url; } public int getConnectTimeout() { return m_connectTimeout; } public void setConnectTimeout(int connectTimeout) { this.m_connectTimeout = connectTimeout; } public int getReadTimeout() { return m_readTimeout; } public void setReadTimeout(int readTimeout) { this.m_readTimeout = readTimeout; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/http/HttpResponse.java ================================================ package com.ctrip.framework.apollo.util.http; /** * @author Jason Song(song_s@ctrip.com) */ public class HttpResponse { private final int m_statusCode; private final T m_body; public HttpResponse(int statusCode, T body) { this.m_statusCode = statusCode; this.m_body = body; } public int getStatusCode() { return m_statusCode; } public T getBody() { return m_body; } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/http/HttpUtil.java ================================================ package com.ctrip.framework.apollo.util.http; import com.ctrip.framework.apollo.build.ApolloInjector; import com.ctrip.framework.apollo.exceptions.ApolloConfigException; import com.ctrip.framework.apollo.exceptions.ApolloConfigStatusCodeException; import com.ctrip.framework.apollo.util.ConfigUtil; import com.google.common.base.Function; import com.google.common.io.CharStreams; import com.google.gson.Gson; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; /** * @author Jason Song(song_s@ctrip.com) */ public class HttpUtil { private ConfigUtil m_configUtil; private Gson gson; /** * Constructor. */ public HttpUtil() { m_configUtil = ApolloInjector.getInstance(ConfigUtil.class); gson = new Gson(); } /** * Do get operation for the http request. * * @param httpRequest the request * @param responseType the response type * @return the response * @throws ApolloConfigException if any error happened or response code is neither 200 nor 304 */ public HttpResponse doGet(HttpRequest httpRequest, final Class responseType) { Function convertResponse = new Function() { @Override public T apply(String input) { return gson.fromJson(input, responseType); } }; return doGetWithSerializeFunction(httpRequest, convertResponse); } /** * Do get operation for the http request. * * @param httpRequest the request * @param responseType the response type * @return the response * @throws ApolloConfigException if any error happened or response code is neither 200 nor 304 */ public HttpResponse doGet(HttpRequest httpRequest, final Type responseType) { Function convertResponse = new Function() { @Override public T apply(String input) { return gson.fromJson(input, responseType); } }; return doGetWithSerializeFunction(httpRequest, convertResponse); } private HttpResponse doGetWithSerializeFunction(HttpRequest httpRequest, Function serializeFunction) { InputStreamReader isr = null; InputStreamReader esr = null; int statusCode; try { HttpURLConnection conn = (HttpURLConnection) new URL(httpRequest.getUrl()).openConnection(); conn.setRequestMethod("GET"); int connectTimeout = httpRequest.getConnectTimeout(); if (connectTimeout < 0) { connectTimeout = m_configUtil.getConnectTimeout(); } int readTimeout = httpRequest.getReadTimeout(); if (readTimeout < 0) { readTimeout = m_configUtil.getReadTimeout(); } conn.setConnectTimeout(connectTimeout); conn.setReadTimeout(readTimeout); conn.connect(); statusCode = conn.getResponseCode(); String response; try { isr = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8); response = CharStreams.toString(isr); } catch (IOException ex) { /** * according to https://docs.oracle.com/javase/7/docs/technotes/guides/net/http-keepalive.html, * we should clean up the connection by reading the response body so that the connection * could be reused. */ InputStream errorStream = conn.getErrorStream(); if (errorStream != null) { esr = new InputStreamReader(errorStream, StandardCharsets.UTF_8); try { CharStreams.toString(esr); } catch (IOException ioe) { //ignore } } throw ex; } if (statusCode == 200) { return new HttpResponse<>(statusCode, serializeFunction.apply(response)); } if (statusCode == 304) { return new HttpResponse<>(statusCode, null); } } catch (Throwable ex) { throw new ApolloConfigException("Could not complete get operation", ex); } finally { if (isr != null) { try { isr.close(); } catch (IOException ex) { // ignore } } if (esr != null) { try { esr.close(); } catch (IOException ex) { // ignore } } } throw new ApolloConfigStatusCodeException(statusCode, String.format("Get operation failed for %s", httpRequest.getUrl())); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/parser/ParserException.java ================================================ package com.ctrip.framework.apollo.util.parser; public class ParserException extends Exception { public ParserException(String message) { super(message); } public ParserException(String message, Throwable cause) { super(message, cause); } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/java/com/ctrip/framework/apollo/util/parser/Parsers.java ================================================ package com.ctrip.framework.apollo.util.parser; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Parsers { public static DateParser forDate() { return DateParser.INSTANCE; } public static DurationParser forDuration() { return DurationParser.INSTANCE; } public enum DateParser { INSTANCE; private static final String LONG_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; private static final String MEDIUM_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static final String SHORT_DATE_FORMAT = "yyyy-MM-dd"; /** * Will try to parse the date with Locale.US and formats as follows: * yyyy-MM-dd HH:mm:ss.SSS, yyyy-MM-dd HH:mm:ss and yyyy-MM-dd * * @param text the text to parse * @return the parsed date * @throws ParserException if the text cannot be parsed */ public Date parse(String text) throws ParserException { text = text.trim(); int length = text.length(); if (length == LONG_DATE_FORMAT.length()) { return parse(text, LONG_DATE_FORMAT); } if (length == MEDIUM_DATE_FORMAT.length()) { return parse(text, MEDIUM_DATE_FORMAT); } return parse(text, SHORT_DATE_FORMAT); } /** * Parse the text with the format specified and Locale.US * * @param text the text to parse * @param format the date format, see {@link java.text.SimpleDateFormat} for more information * @return the parsed date * @throws ParserException if the text cannot be parsed */ public Date parse(String text, String format) throws ParserException { return parse(text, format, Locale.US); } /** * Parse the text with the format and locale specified * * @param text the text to parse * @param format the date format, see {@link java.text.SimpleDateFormat} for more information * @param locale the locale * @return the parsed date * @throws ParserException if the text cannot be parsed */ public Date parse(String text, String format, Locale locale) throws ParserException { SimpleDateFormat dateFormat = getDateFormat(format, locale); try { return dateFormat.parse(text.trim()); } catch (ParseException e) { throw new ParserException("Error when parsing date(" + dateFormat.toPattern() + ") from " + text, e); } } private SimpleDateFormat getDateFormat(String format, Locale locale) { return new SimpleDateFormat(format, locale); } } public enum DurationParser { INSTANCE; private static final Pattern PATTERN = Pattern.compile("(?:([0-9]+)D)?(?:([0-9]+)H)?(?:([0-9]+)M)?(?:([0-9]+)S)?(?:([0-9]+)(?:MS)?)?", Pattern.CASE_INSENSITIVE); private static final int HOURS_PER_DAY = 24; private static final int MINUTES_PER_HOUR = 60; private static final int SECONDS_PER_MINUTE = 60; private static final int MILLIS_PER_SECOND = 1000; private static final int MILLIS_PER_MINUTE = MILLIS_PER_SECOND * SECONDS_PER_MINUTE; private static final int MILLIS_PER_HOUR = MILLIS_PER_MINUTE * MINUTES_PER_HOUR; private static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * HOURS_PER_DAY; public long parseToMillis(String text) throws ParserException { Matcher matcher = PATTERN.matcher(text); if (matcher.matches()) { String dayMatch = matcher.group(1); String hourMatch = matcher.group(2); String minuteMatch = matcher.group(3); String secondMatch = matcher.group(4); String fractionMatch = matcher.group(5); if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null || fractionMatch != null) { int daysAsMilliSecs = parseNumber(dayMatch, MILLIS_PER_DAY); int hoursAsMilliSecs = parseNumber(hourMatch, MILLIS_PER_HOUR); int minutesAsMilliSecs = parseNumber(minuteMatch, MILLIS_PER_MINUTE); int secondsAsMilliSecs = parseNumber(secondMatch, MILLIS_PER_SECOND); int milliseconds = parseNumber(fractionMatch, 1); return daysAsMilliSecs + hoursAsMilliSecs + minutesAsMilliSecs + secondsAsMilliSecs + milliseconds; } } throw new ParserException(String.format("Text %s cannot be parsed to duration)", text)); } private static int parseNumber(String parsed, int multiplier) { // regex limits to [0-9]+ if (parsed == null || parsed.trim().isEmpty()) { return 0; } return Integer.parseInt(parsed) * multiplier; } } } ================================================ FILE: open-config-center/apollo/apollo-client/src/main/resources/META-INF/apollo-1.0.0.xsd ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.internals.Injector ================================================ com.ctrip.framework.apollo.internals.DefaultInjector ================================================ FILE: open-config-center/apollo/apollo-client/src/main/resources/META-INF/spring.factories ================================================ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration org.springframework.context.ApplicationContextInitializer=\ com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer ================================================ FILE: open-config-center/apollo/apollo-client/src/main/resources/META-INF/spring.handlers ================================================ http\://www.ctrip.com/schema/apollo=com.ctrip.framework.apollo.spring.config.NamespaceHandler ================================================ FILE: open-config-center/apollo/apollo-client/src/main/resources/META-INF/spring.schemas ================================================ http\://www.ctrip.com/schema/apollo-1.0.0.xsd=/META-INF/apollo-1.0.0.xsd http\://www.ctrip.com/schema/apollo.xsd=/META-INF/apollo-1.0.0.xsd ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.internals.Injector ================================================ com.ctrip.framework.apollo.build.MockInjector ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/log4j2.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest1.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest2.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest3.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest4.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigAnnotationTest5.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest1.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest10.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest2.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest3.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest4.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest5.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest6.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest7.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest8.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest9.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-common/pom.xml ================================================ com.ctrip.framework.apollo apollo 0.10.0-SNAPSHOT 4.0.0 apollo-common Apollo Common ${project.artifactId} com.ctrip.framework.apollo apollo-core org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security org.springframework.cloud spring-cloud-starter-spectator org.springframework.security spring-security-crypto org.springframework.boot spring-boot-starter-data-jpa org.springframework.data spring-data-commons org.apache.httpcomponents httpclient commons-logging commons-logging ch.qos.logback logback-classic commons-lang commons-lang ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/ApolloCommonConfig.java ================================================ package com.ctrip.framework.apollo.common; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @EnableAutoConfiguration @Configuration @ComponentScan(basePackageClasses = ApolloCommonConfig.class) public class ApolloCommonConfig { } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/aop/RepositoryAspect.java ================================================ package com.ctrip.framework.apollo.common.aop; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class RepositoryAspect { @Pointcut("execution(public * org.springframework.data.repository.Repository+.*(..))") public void anyRepositoryMethod() { } @Around("anyRepositoryMethod()") public Object invokeWithCatTransaction(ProceedingJoinPoint joinPoint) throws Throwable { String name = joinPoint.getSignature().getDeclaringType().getSimpleName() + "." + joinPoint.getSignature() .getName(); Transaction catTransaction = Tracer.newTransaction("SQL", name); try { Object result = joinPoint.proceed(); catTransaction.setStatus(Transaction.SUCCESS); return result; } catch (Throwable ex) { catTransaction.setStatus(ex); throw ex; } finally { catTransaction.complete(); } } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/condition/ConditionalOnMissingProfile.java ================================================ package com.ctrip.framework.apollo.common.condition; import org.springframework.context.annotation.Conditional; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * {@link Conditional} that only matches when the specified profiles are inactive. * * @author Jason Song(song_s@ctrip.com) */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnProfileCondition.class) public @interface ConditionalOnMissingProfile { /** * The profiles that should be inactive * @return */ String[] value() default {}; } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/condition/ConditionalOnProfile.java ================================================ package com.ctrip.framework.apollo.common.condition; import org.springframework.context.annotation.Conditional; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * {@link Conditional} that only matches when the specified profiles are active. * * @author Jason Song(song_s@ctrip.com) */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnProfileCondition.class) public @interface ConditionalOnProfile { /** * The profiles that should be active * @return */ String[] value() default {}; } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/condition/OnProfileCondition.java ================================================ package com.ctrip.framework.apollo.common.condition; import com.google.common.collect.Sets; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.util.MultiValueMap; import java.util.Collections; import java.util.List; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ public class OnProfileCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Set activeProfiles = Sets.newHashSet(context.getEnvironment().getActiveProfiles()); Set requiredActiveProfiles = retrieveAnnotatedProfiles(metadata, ConditionalOnProfile.class.getName()); Set requiredInactiveProfiles = retrieveAnnotatedProfiles(metadata, ConditionalOnMissingProfile.class .getName()); return Sets.difference(requiredActiveProfiles, activeProfiles).isEmpty() && Sets.intersection(requiredInactiveProfiles, activeProfiles).isEmpty(); } private Set retrieveAnnotatedProfiles(AnnotatedTypeMetadata metadata, String annotationType) { if (!metadata.isAnnotated(annotationType)) { return Collections.emptySet(); } MultiValueMap attributes = metadata.getAllAnnotationAttributes(annotationType); if (attributes == null) { return Collections.emptySet(); } Set profiles = Sets.newHashSet(); List values = attributes.get("value"); if (values != null) { for (Object value : values) { if (value instanceof String[]) { Collections.addAll(profiles, (String[]) value); } else { profiles.add((String) value); } } } return profiles; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/config/RefreshableConfig.java ================================================ package com.ctrip.framework.apollo.common.config; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; public abstract class RefreshableConfig { private static final Logger logger = LoggerFactory.getLogger(RefreshableConfig.class); private static final String LIST_SEPARATOR = ","; //TimeUnit: second private static final int CONFIG_REFRESH_INTERVAL = 60; protected Splitter splitter = Splitter.on(LIST_SEPARATOR).omitEmptyStrings().trimResults(); @Autowired private ConfigurableEnvironment environment; private List propertySources; /** * register refreshable property source. * Notice: The front property source has higher priority. */ protected abstract List getRefreshablePropertySources(); @PostConstruct public void setup() { propertySources = getRefreshablePropertySources(); if (CollectionUtils.isEmpty(propertySources)) { throw new IllegalStateException("Property sources can not be empty."); } //add property source to environment for (RefreshablePropertySource propertySource : propertySources) { propertySource.refresh(); environment.getPropertySources().addLast(propertySource); } //task to update configs ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("ConfigRefresher", true)); executorService .scheduleWithFixedDelay(() -> { try { propertySources.forEach(RefreshablePropertySource::refresh); } catch (Throwable t) { logger.error("Refresh configs failed.", t); Tracer.logError("Refresh configs failed.", t); } }, CONFIG_REFRESH_INTERVAL, CONFIG_REFRESH_INTERVAL, TimeUnit.SECONDS); } public int getIntProperty(String key, int defaultValue) { try { String value = getValue(key); return value == null ? defaultValue : Integer.parseInt(value); } catch (Throwable e) { Tracer.logError("Get int property failed.", e); return defaultValue; } } public boolean getBooleanProperty(String key, boolean defaultValue) { try { String value = getValue(key); return value == null ? defaultValue : "true".equals(value); } catch (Throwable e) { Tracer.logError("Get boolean property failed.", e); return defaultValue; } } public String[] getArrayProperty(String key, String[] defaultValue) { try { String value = getValue(key); return Strings.isNullOrEmpty(value) ? defaultValue : value.split(LIST_SEPARATOR); } catch (Throwable e) { Tracer.logError("Get array property failed.", e); return defaultValue; } } public String getValue(String key, String defaultValue) { try { return environment.getProperty(key, defaultValue); } catch (Throwable e) { Tracer.logError("Get value failed.", e); return defaultValue; } } public String getValue(String key) { return environment.getProperty(key); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/config/RefreshablePropertySource.java ================================================ package com.ctrip.framework.apollo.common.config; import org.springframework.core.env.MapPropertySource; import java.util.Map; public abstract class RefreshablePropertySource extends MapPropertySource { public RefreshablePropertySource(String name, Map source) { super(name, source); } @Override public Object getProperty(String name) { return this.source.get(name); } /** * refresh property */ protected abstract void refresh(); } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/GsonType.java ================================================ package com.ctrip.framework.apollo.common.constants; import com.google.gson.reflect.TypeToken; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO; import java.lang.reflect.Type; import java.util.List; import java.util.Map; public interface GsonType { Type CONFIG = new TypeToken>() {}.getType(); Type RULE_ITEMS = new TypeToken>() {}.getType(); } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/NamespaceBranchStatus.java ================================================ package com.ctrip.framework.apollo.common.constants; public interface NamespaceBranchStatus { int DELETED = 0; int ACTIVE = 1; int MERGED = 2; } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/ReleaseOperation.java ================================================ package com.ctrip.framework.apollo.common.constants; /** * @author Jason Song(song_s@ctrip.com) */ public interface ReleaseOperation { int NORMAL_RELEASE = 0; int ROLLBACK = 1; int GRAY_RELEASE = 2; int APPLY_GRAY_RULES = 3; int GRAY_RELEASE_MERGE_TO_MASTER = 4; int MASTER_NORMAL_RELEASE_MERGE_TO_GRAY = 5; int MATER_ROLLBACK_MERGE_TO_GRAY = 6; int ABANDON_GRAY_RELEASE = 7; int GRAY_RELEASE_DELETED_AFTER_MERGE = 8; } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/constants/ReleaseOperationContext.java ================================================ package com.ctrip.framework.apollo.common.constants; /** * @author Jason Song(song_s@ctrip.com) */ public interface ReleaseOperationContext { String SOURCE_BRANCH = "sourceBranch"; String RULES = "rules"; String OLD_RULES = "oldRules"; String BASE_RELEASE_ID = "baseReleaseId"; String IS_EMERGENCY_PUBLISH = "isEmergencyPublish"; } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/ApolloInfoController.java ================================================ package com.ctrip.framework.apollo.common.controller; import com.ctrip.framework.apollo.Apollo; import com.ctrip.framework.foundation.Foundation; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(path = "/apollo") public class ApolloInfoController { @RequestMapping("app") public String getApp() { return Foundation.app().toString(); } @RequestMapping("net") public String getNet() { return Foundation.net().toString(); } @RequestMapping("server") public String getServer() { return Foundation.server().toString(); } @RequestMapping("version") public String getVersion() { return Apollo.VERSION; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/CharacterEncodingFilterConfiguration.java ================================================ package com.ctrip.framework.apollo.common.controller; import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.CharacterEncodingFilter; import javax.servlet.DispatcherType; @Configuration public class CharacterEncodingFilterConfiguration { @Bean public FilterRegistrationBean encodingFilter() { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new CharacterEncodingFilter()); bean.addInitParameter("encoding", "UTF-8"); //FIXME: https://github.com/Netflix/eureka/issues/702 // bean.addInitParameter("forceEncoding", "true"); bean.setName("encodingFilter"); bean.addUrlPatterns("/*"); bean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD); return bean; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/GlobalDefaultExceptionHandler.java ================================================ package com.ctrip.framework.apollo.common.controller; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.ctrip.framework.apollo.common.exception.AbstractApolloHttpException; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; import org.springframework.web.HttpMediaTypeException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.client.HttpStatusCodeException; import java.lang.reflect.Type; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.FORBIDDEN; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.MediaType.APPLICATION_JSON; @ControllerAdvice public class GlobalDefaultExceptionHandler { private Gson gson = new Gson(); private static Type mapType = new TypeToken>() { }.getType(); private static final Logger logger = LoggerFactory.getLogger(GlobalDefaultExceptionHandler.class); //处理系统内置的Exception @ExceptionHandler(Throwable.class) public ResponseEntity> exception(HttpServletRequest request, Throwable ex) { return handleError(request, INTERNAL_SERVER_ERROR, ex); } @ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class}) public ResponseEntity> badRequest(HttpServletRequest request, ServletException ex) { return handleError(request, BAD_REQUEST, ex); } @ExceptionHandler(HttpStatusCodeException.class) public ResponseEntity> restTemplateException(HttpServletRequest request, HttpStatusCodeException ex) { return handleError(request, ex.getStatusCode(), ex); } @ExceptionHandler(AccessDeniedException.class) public ResponseEntity> accessDeny(HttpServletRequest request, AccessDeniedException ex) { return handleError(request, FORBIDDEN, ex); } //处理自定义Exception @ExceptionHandler({AbstractApolloHttpException.class}) public ResponseEntity> badRequest(HttpServletRequest request, AbstractApolloHttpException ex) { return handleError(request, ex); } private ResponseEntity> handleError(HttpServletRequest request, AbstractApolloHttpException ex) { return handleError(request, ex.getHttpStatus(), ex); } private ResponseEntity> handleError(HttpServletRequest request, HttpStatus status, Throwable ex) { String message = ex.getMessage(); logger.error(message, ex); Tracer.logError(ex); Map errorAttributes = new HashMap<>(); boolean errorHandled = false; if (ex instanceof HttpStatusCodeException) { try { //try to extract the original error info if it is thrown from apollo programs, e.g. admin service errorAttributes = gson.fromJson(((HttpStatusCodeException) ex).getResponseBodyAsString(), mapType); status = ((HttpStatusCodeException) ex).getStatusCode(); errorHandled = true; } catch (Throwable th) { //ignore } } if (!errorHandled) { errorAttributes.put("status", status.value()); errorAttributes.put("message", message); errorAttributes.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); errorAttributes.put("exception", ex.getClass().getName()); } HttpHeaders headers = new HttpHeaders(); headers.setContentType(APPLICATION_JSON); return new ResponseEntity<>(errorAttributes, headers, status); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/HttpMessageConverterConfiguration.java ================================================ package com.ctrip.framework.apollo.common.controller; import com.google.common.collect.Lists; import com.google.gson.GsonBuilder; import org.springframework.boot.autoconfigure.web.HttpMessageConverters; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; import java.util.List; /** * Created by Jason on 5/11/16. */ @Configuration public class HttpMessageConverterConfiguration { @Bean public HttpMessageConverters messageConverters() { GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter(); gsonHttpMessageConverter.setGson( new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create()); final List> converters = Lists.newArrayList( new ByteArrayHttpMessageConverter(), new StringHttpMessageConverter(), new AllEncompassingFormHttpMessageConverter(), gsonHttpMessageConverter); return new HttpMessageConverters() { @Override public List> getConverters() { return converters; } }; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/controller/WebMvcConfig.java ================================================ package com.ctrip.framework.apollo.common.controller; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.context.embedded.MimeMappings; import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.PageRequest; import org.springframework.data.web.PageableHandlerMethodArgumentResolver; import org.springframework.http.MediaType; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import java.util.List; @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer { @Override public void addArgumentResolvers(List argumentResolvers) { PageableHandlerMethodArgumentResolver pageResolver = new PageableHandlerMethodArgumentResolver(); pageResolver.setFallbackPageable(new PageRequest(0, 10)); argumentResolvers.add(pageResolver); } @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); configurer.ignoreAcceptHeader(true).defaultContentType(MediaType.APPLICATION_JSON); } @Override public void customize(ConfigurableEmbeddedServletContainer container) { MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT); mappings.add("html", "text/html;charset=utf-8"); container.setMimeMappings(mappings ); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/customize/LoggingCustomizer.java ================================================ package com.ctrip.framework.apollo.common.customize; import com.google.common.base.Strings; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.foundation.Foundation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.core.Appender; /** * clogging config.only used in ctrip * @author Jason Song(song_s@ctrip.com) */ public abstract class LoggingCustomizer implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(LoggingCustomizer.class); private static final String cLoggingAppenderClass = "com.ctrip.framework.clogging.agent.appender.CLoggingAppender"; private static boolean cLoggingAppenderPresent = ClassUtils.isPresent(cLoggingAppenderClass, LoggingCustomizer.class.getClassLoader()); @Override public void afterPropertiesSet() { if (!cLoggingAppenderPresent) { return; } try { tryConfigCLogging(); } catch (Throwable ex) { logger.error("Config CLogging failed", ex); Tracer.logError(ex); } } private void tryConfigCLogging() throws Exception { String appId = Foundation.app().getAppId(); if (Strings.isNullOrEmpty(appId)) { logger.warn("App id is null or empty!"); return; } LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); Class clazz = Class.forName(cLoggingAppenderClass); Appender cLoggingAppender = (Appender) clazz.newInstance(); ReflectionUtils.findMethod(clazz, "setAppId", String.class).invoke(cLoggingAppender, appId); ReflectionUtils.findMethod(clazz, "setServerIp", String.class) .invoke(cLoggingAppender, cloggingUrl()); ReflectionUtils.findMethod(clazz, "setServerPort", int.class) .invoke(cLoggingAppender, Integer.parseInt(cloggingPort())); cLoggingAppender.setName("CentralLogging"); cLoggingAppender.setContext(loggerContext); cLoggingAppender.start(); ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("root"); logger.addAppender(cLoggingAppender); } /** * clogging server url * @return */ protected abstract String cloggingUrl(); /** * clogging server port * @return */ protected abstract String cloggingPort(); } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/customize/TomcatContainerCustomizer.java ================================================ package com.ctrip.framework.apollo.common.customize; import org.apache.catalina.connector.Connector; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.http11.Http11NioProtocol; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; /** * @author Jason Song(song_s@ctrip.com) */ @Component public class TomcatContainerCustomizer implements EmbeddedServletContainerCustomizer { private static final Logger logger = LoggerFactory.getLogger(TomcatContainerCustomizer.class); private static final String TOMCAT_ACCEPTOR_COUNT = "server.tomcat.accept-count"; @Autowired private Environment environment; @Override public void customize(ConfigurableEmbeddedServletContainer container) { if (!(container instanceof TomcatEmbeddedServletContainerFactory)) { return; } if (!environment.containsProperty(TOMCAT_ACCEPTOR_COUNT)) { return; } TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container; tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override public void customize(Connector connector) { ProtocolHandler handler = connector.getProtocolHandler(); if (handler instanceof Http11NioProtocol) { Http11NioProtocol http = (Http11NioProtocol) handler; int acceptCount = Integer.parseInt(environment.getProperty(TOMCAT_ACCEPTOR_COUNT)); http.setBacklog(acceptCount); logger.info("Setting tomcat accept count to {}", acceptCount); } } }); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/customize/package-info.java ================================================ /** * 携程内部的日志系统,第三方公司可删除 */ package com.ctrip.framework.apollo.common.customize; ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/TitanCondition.java ================================================ package com.ctrip.framework.apollo.common.datasource; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class TitanCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { if (!StringUtils.isEmpty(context.getEnvironment().getProperty("fat.titan.url"))) { return true; } else if (!StringUtils.isEmpty(context.getEnvironment().getProperty("uat.titan.url"))) { return true; } else if (!StringUtils.isEmpty(context.getEnvironment().getProperty("pro.titan.url"))) { return true; } return false; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/TitanEntityManager.java ================================================ package com.ctrip.framework.apollo.common.datasource; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import javax.sql.DataSource; @Component @Conditional(TitanCondition.class) public class TitanEntityManager { @Autowired private TitanSettings settings; @SuppressWarnings({"rawtypes", "unchecked"}) @Bean public DataSource datasource() throws Exception { Class clazz = Class.forName("com.ctrip.datasource.configure.DalDataSourceFactory"); Object obj = clazz.newInstance(); Method method = clazz.getMethod("createDataSource", new Class[] {String.class, String.class}); DataSource ds = ((DataSource) method.invoke(obj, new Object[] {settings.getTitanDbname(), settings.getTitanUrl()})); Tracer.logEvent("Apollo.Datasource.Titan", settings.getTitanDbname()); return ds; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/TitanSettings.java ================================================ package com.ctrip.framework.apollo.common.datasource; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.enums.EnvUtils; import com.ctrip.framework.foundation.Foundation; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class TitanSettings { @Value("${fat.titan.url:}") private String fatTitanUrl; @Value("${uat.titan.url:}") private String uatTitanUrl; @Value("${pro.titan.url:}") private String proTitanUrl; @Value("${fat.titan.dbname:}") private String fatTitanDbname; @Value("${uat.titan.dbname:}") private String uatTitanDbname; @Value("${pro.titan.dbname:}") private String proTitanDbname; public String getTitanUrl() { Env env = EnvUtils.transformEnv(Foundation.server().getEnvType()); if (env == null) { return ""; } switch (env) { case FAT: case FWS: return fatTitanUrl; case UAT: return uatTitanUrl; case TOOLS: case PRO: return proTitanUrl; default: return ""; } } public String getTitanDbname() { Env env = EnvUtils.transformEnv(Foundation.server().getEnvType()); if (env == null) { return ""; } switch (env) { case FAT: case FWS: return fatTitanDbname; case UAT: return uatTitanDbname; case TOOLS: case PRO: return proTitanDbname; default: return ""; } } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/datasource/package-info.java ================================================ /** * 携程内部的dal,第三方公司可替换实现 */ package com.ctrip.framework.apollo.common.datasource; ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/AppDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class AppDTO extends BaseDTO{ private long id; private String name; private String appId; private String orgId; private String orgName; private String ownerName; private String ownerEmail; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAppId() { return appId; } public String getName() { return name; } public String getOrgId() { return orgId; } public String getOrgName() { return orgName; } public String getOwnerEmail() { return ownerEmail; } public String getOwnerName() { return ownerName; } public void setAppId(String appId) { this.appId = appId; } public void setName(String name) { this.name = name; } public void setOrgId(String orgId) { this.orgId = orgId; } public void setOrgName(String orgName) { this.orgName = orgName; } public void setOwnerEmail(String ownerEmail) { this.ownerEmail = ownerEmail; } public void setOwnerName(String ownerName) { this.ownerName = ownerName; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/AppNamespaceDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class AppNamespaceDTO extends BaseDTO{ private long id; private String name; private String appId; private String comment; private String format; private boolean isPublic = false; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public boolean isPublic() { return isPublic; } public void setPublic(boolean aPublic) { isPublic = aPublic; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/BaseDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; import java.util.Date; public class BaseDTO { protected String dataChangeCreatedBy; protected String dataChangeLastModifiedBy; protected Date dataChangeCreatedTime; protected Date dataChangeLastModifiedTime; public String getDataChangeCreatedBy() { return dataChangeCreatedBy; } public void setDataChangeCreatedBy(String dataChangeCreatedBy) { this.dataChangeCreatedBy = dataChangeCreatedBy; } public String getDataChangeLastModifiedBy() { return dataChangeLastModifiedBy; } public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) { this.dataChangeLastModifiedBy = dataChangeLastModifiedBy; } public Date getDataChangeCreatedTime() { return dataChangeCreatedTime; } public void setDataChangeCreatedTime(Date dataChangeCreatedTime) { this.dataChangeCreatedTime = dataChangeCreatedTime; } public Date getDataChangeLastModifiedTime() { return dataChangeLastModifiedTime; } public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) { this.dataChangeLastModifiedTime = dataChangeLastModifiedTime; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ClusterDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class ClusterDTO extends BaseDTO{ private long id; private String name; private String appId; private long parentClusterId; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public long getParentClusterId() { return parentClusterId; } public void setParentClusterId(long parentClusterId) { this.parentClusterId = parentClusterId; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/CommitDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class CommitDTO extends BaseDTO{ private String changeSets; private String appId; private String clusterName; private String namespaceName; private String comment; public String getChangeSets() { return changeSets; } public void setChangeSets(String changeSets) { this.changeSets = changeSets; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/GrayReleaseRuleDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; import com.google.common.collect.Sets; import java.util.Set; public class GrayReleaseRuleDTO extends BaseDTO { private String appId; private String clusterName; private String namespaceName; private String branchName; private Set ruleItems; private Long releaseId; public GrayReleaseRuleDTO(String appId, String clusterName, String namespaceName, String branchName) { this.appId = appId; this.clusterName = clusterName; this.namespaceName = namespaceName; this.branchName = branchName; this.ruleItems = Sets.newHashSet(); } public String getAppId() { return appId; } public String getClusterName() { return clusterName; } public String getNamespaceName() { return namespaceName; } public String getBranchName() { return branchName; } public Set getRuleItems() { return ruleItems; } public void setRuleItems(Set ruleItems) { this.ruleItems = ruleItems; } public void addRuleItem(GrayReleaseRuleItemDTO ruleItem) { this.ruleItems.add(ruleItem); } public Long getReleaseId() { return releaseId; } public void setReleaseId(Long releaseId) { this.releaseId = releaseId; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/GrayReleaseRuleItemDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; import com.google.common.collect.Sets; import java.util.Set; import static com.google.common.base.MoreObjects.toStringHelper; /** * @author Jason Song(song_s@ctrip.com) */ public class GrayReleaseRuleItemDTO { public static final String ALL_IP = "*"; private String clientAppId; private Set clientIpList; public GrayReleaseRuleItemDTO(String clientAppId) { this(clientAppId, Sets.newHashSet()); } public GrayReleaseRuleItemDTO(String clientAppId, Set clientIpList) { this.clientAppId = clientAppId; this.clientIpList = clientIpList; } public String getClientAppId() { return clientAppId; } public Set getClientIpList() { return clientIpList; } public boolean matches(String clientAppId, String clientIp) { return appIdMatches(clientAppId) && ipMatches(clientIp); } private boolean appIdMatches(String clientAppId) { return this.clientAppId.equals(clientAppId); } private boolean ipMatches(String clientIp) { return this.clientIpList.contains(ALL_IP) || clientIpList.contains(clientIp); } @Override public String toString() { return toStringHelper(this).add("clientAppId", clientAppId) .add("clientIpList", clientIpList).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/InstanceConfigDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; import java.util.Date; /** * @author Jason Song(song_s@ctrip.com) */ public class InstanceConfigDTO { private ReleaseDTO release; private Date releaseDeliveryTime; private Date dataChangeLastModifiedTime; public ReleaseDTO getRelease() { return release; } public void setRelease(ReleaseDTO release) { this.release = release; } public Date getDataChangeLastModifiedTime() { return dataChangeLastModifiedTime; } public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) { this.dataChangeLastModifiedTime = dataChangeLastModifiedTime; } public Date getReleaseDeliveryTime() { return releaseDeliveryTime; } public void setReleaseDeliveryTime(Date releaseDeliveryTime) { this.releaseDeliveryTime = releaseDeliveryTime; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/InstanceDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; import java.util.Date; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public class InstanceDTO { private long id; private String appId; private String clusterName; private String dataCenter; private String ip; private List configs; private Date dataChangeCreatedTime; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getDataCenter() { return dataCenter; } public void setDataCenter(String dataCenter) { this.dataCenter = dataCenter; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public List getConfigs() { return configs; } public void setConfigs(List configs) { this.configs = configs; } public Date getDataChangeCreatedTime() { return dataChangeCreatedTime; } public void setDataChangeCreatedTime(Date dataChangeCreatedTime) { this.dataChangeCreatedTime = dataChangeCreatedTime; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ItemChangeSets.java ================================================ package com.ctrip.framework.apollo.common.dto; import java.util.LinkedList; import java.util.List; /** * storage cud result */ public class ItemChangeSets extends BaseDTO{ private List createItems = new LinkedList<>(); private List updateItems = new LinkedList<>(); private List deleteItems = new LinkedList<>(); public void addCreateItem(ItemDTO item) { createItems.add(item); } public void addUpdateItem(ItemDTO item) { updateItems.add(item); } public void addDeleteItem(ItemDTO item) { deleteItems.add(item); } public boolean isEmpty(){ return createItems.isEmpty() && updateItems.isEmpty() && deleteItems.isEmpty(); } public List getCreateItems() { return createItems; } public List getUpdateItems() { return updateItems; } public List getDeleteItems() { return deleteItems; } public void setCreateItems(List createItems) { this.createItems = createItems; } public void setUpdateItems(List updateItems) { this.updateItems = updateItems; } public void setDeleteItems(List deleteItems) { this.deleteItems = deleteItems; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ItemDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class ItemDTO extends BaseDTO{ private long id; private long namespaceId; private String key; private String value; private String comment; private int lineNum; public ItemDTO() { } public ItemDTO(String key, String value, String comment, int lineNum) { this.key = key; this.value = value; this.comment = comment; this.lineNum = lineNum; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getComment() { return comment; } public String getKey() { return key; } public long getNamespaceId() { return namespaceId; } public String getValue() { return value; } public void setComment(String comment) { this.comment = comment; } public void setKey(String key) { this.key = key; } public void setNamespaceId(long namespaceId) { this.namespaceId = namespaceId; } public void setValue(String value) { this.value = value; } public int getLineNum() { return lineNum; } public void setLineNum(int lineNum) { this.lineNum = lineNum; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/NamespaceDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class NamespaceDTO extends BaseDTO{ private long id; private String appId; private String clusterName; private String namespaceName; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAppId() { return appId; } public String getClusterName() { return clusterName; } public String getNamespaceName() { return namespaceName; } public void setAppId(String appId) { this.appId = appId; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/NamespaceLockDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class NamespaceLockDTO extends BaseDTO{ private long namespaceId; public long getNamespaceId() { return namespaceId; } public void setNamespaceId(long namespaceId) { this.namespaceId = namespaceId; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/PageDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; import org.springframework.data.domain.Pageable; import java.util.Collections; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public class PageDTO { private final long total; private final List content; private final int page; private final int size; public PageDTO(List content, Pageable pageable, long total) { this.total = total; this.content = content; this.page = pageable.getPageNumber(); this.size = pageable.getPageSize(); } public long getTotal() { return total; } public List getContent() { return Collections.unmodifiableList(content); } public int getPage() { return page; } public int getSize() { return size; } public boolean hasContent(){ return content != null && content.size() > 0; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ReleaseDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; public class ReleaseDTO extends BaseDTO{ private long id; private String releaseKey; private String name; private String appId; private String clusterName; private String namespaceName; private String configurations; private String comment; private boolean isAbandoned; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getReleaseKey() { return releaseKey; } public void setReleaseKey(String releaseKey) { this.releaseKey = releaseKey; } public String getAppId() { return appId; } public String getClusterName() { return clusterName; } public String getComment() { return comment; } public String getConfigurations() { return configurations; } public String getName() { return name; } public String getNamespaceName() { return namespaceName; } public void setAppId(String appId) { this.appId = appId; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public void setComment(String comment) { this.comment = comment; } public void setConfigurations(String configurations) { this.configurations = configurations; } public void setName(String name) { this.name = name; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public boolean isAbandoned() { return isAbandoned; } public void setAbandoned(boolean abandoned) { isAbandoned = abandoned; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/ReleaseHistoryDTO.java ================================================ package com.ctrip.framework.apollo.common.dto; import java.util.Map; public class ReleaseHistoryDTO extends BaseDTO{ private long id; private String appId; private String clusterName; private String namespaceName; private String branchName; private long releaseId; private long previousReleaseId; private int operation; private Map operationContext; public ReleaseHistoryDTO(){} public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getBranchName() { return branchName; } public void setBranchName(String branchName) { this.branchName = branchName; } public long getReleaseId() { return releaseId; } public void setReleaseId(long releaseId) { this.releaseId = releaseId; } public long getPreviousReleaseId() { return previousReleaseId; } public void setPreviousReleaseId(long previousReleaseId) { this.previousReleaseId = previousReleaseId; } public int getOperation() { return operation; } public void setOperation(int operation) { this.operation = operation; } public Map getOperationContext() { return operationContext; } public void setOperationContext(Map operationContext) { this.operationContext = operationContext; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/App.java ================================================ package com.ctrip.framework.apollo.common.entity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "App") @SQLDelete(sql = "Update App set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class App extends BaseEntity { @Column(name = "Name", nullable = false) private String name; @Column(name = "AppId", nullable = false) private String appId; @Column(name = "OrgId", nullable = false) private String orgId; @Column(name = "OrgName", nullable = false) private String orgName; @Column(name = "OwnerName", nullable = false) private String ownerName; @Column(name = "OwnerEmail", nullable = false) private String ownerEmail; public String getAppId() { return appId; } public String getName() { return name; } public String getOrgId() { return orgId; } public String getOrgName() { return orgName; } public String getOwnerEmail() { return ownerEmail; } public String getOwnerName() { return ownerName; } public void setAppId(String appId) { this.appId = appId; } public void setName(String name) { this.name = name; } public void setOrgId(String orgId) { this.orgId = orgId; } public void setOrgName(String orgName) { this.orgName = orgName; } public void setOwnerEmail(String ownerEmail) { this.ownerEmail = ownerEmail; } public void setOwnerName(String ownerName) { this.ownerName = ownerName; } public String toString() { return toStringHelper().add("name", name).add("appId", appId) .add("orgId", orgId) .add("orgName", orgName) .add("ownerName", ownerName) .add("ownerEmail", ownerEmail).toString(); } public static class Builder { public Builder() { } private App app = new App(); public Builder name(String name) { app.setName(name); return this; } public Builder appId(String appId) { app.setAppId(appId); return this; } public Builder orgId(String orgId) { app.setOrgId(orgId); return this; } public Builder orgName(String orgName) { app.setOrgName(orgName); return this; } public Builder ownerName(String ownerName) { app.setOwnerName(ownerName); return this; } public Builder ownerEmail(String ownerEmail) { app.setOwnerEmail(ownerEmail); return this; } public App build() { return app; } } public static Builder builder() { return new Builder(); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/AppNamespace.java ================================================ package com.ctrip.framework.apollo.common.entity; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "AppNamespace") @SQLDelete(sql = "Update AppNamespace set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class AppNamespace extends BaseEntity { @Column(name = "Name", nullable = false) private String name; @Column(name = "AppId", nullable = false) private String appId; @Column(name = "Format", nullable = false) private String format; @Column(name = "IsPublic", columnDefinition = "Bit default '0'") private boolean isPublic = false; @Column(name = "Comment") private String comment; public String getAppId() { return appId; } public String getComment() { return comment; } public String getName() { return name; } public void setAppId(String appId) { this.appId = appId; } public void setComment(String comment) { this.comment = comment; } public void setName(String name) { this.name = name; } public boolean isPublic() { return isPublic; } public void setPublic(boolean aPublic) { isPublic = aPublic; } public ConfigFileFormat formatAsEnum() { return ConfigFileFormat.fromString(this.format); } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public String toString() { return toStringHelper().add("name", name).add("appId", appId).add("comment", comment) .add("format", format).add("isPublic", isPublic).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/BaseEntity.java ================================================ package com.ctrip.framework.apollo.common.entity; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; import java.util.Date; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.MappedSuperclass; import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; @MappedSuperclass @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class BaseEntity { @Id @GeneratedValue @Column(name = "Id") private long id; @Column(name = "IsDeleted", columnDefinition = "Bit default '0'") protected boolean isDeleted = false; @Column(name = "DataChange_CreatedBy", nullable = false) private String dataChangeCreatedBy; @Column(name = "DataChange_CreatedTime", nullable = false) private Date dataChangeCreatedTime; @Column(name = "DataChange_LastModifiedBy") private String dataChangeLastModifiedBy; @Column(name = "DataChange_LastTime") private Date dataChangeLastModifiedTime; public String getDataChangeCreatedBy() { return dataChangeCreatedBy; } public Date getDataChangeCreatedTime() { return dataChangeCreatedTime; } public String getDataChangeLastModifiedBy() { return dataChangeLastModifiedBy; } public Date getDataChangeLastModifiedTime() { return dataChangeLastModifiedTime; } public long getId() { return id; } public boolean isDeleted() { return isDeleted; } public void setDataChangeCreatedBy(String dataChangeCreatedBy) { this.dataChangeCreatedBy = dataChangeCreatedBy; } public void setDataChangeCreatedTime(Date dataChangeCreatedTime) { this.dataChangeCreatedTime = dataChangeCreatedTime; } public void setDataChangeLastModifiedBy(String dataChangeLastModifiedBy) { this.dataChangeLastModifiedBy = dataChangeLastModifiedBy; } public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) { this.dataChangeLastModifiedTime = dataChangeLastModifiedTime; } public void setDeleted(boolean deleted) { isDeleted = deleted; } public void setId(long id) { this.id = id; } @PrePersist protected void prePersist() { if (this.dataChangeCreatedTime == null) dataChangeCreatedTime = new Date(); if (this.dataChangeLastModifiedTime == null) dataChangeLastModifiedTime = new Date(); } @PreUpdate protected void preUpdate() { this.dataChangeLastModifiedTime = new Date(); } @PreRemove protected void preRemove() { this.dataChangeLastModifiedTime = new Date(); } protected ToStringHelper toStringHelper() { return MoreObjects.toStringHelper(this).omitNullValues().add("id", id) .add("dataChangeCreatedBy", dataChangeCreatedBy) .add("dataChangeCreatedTime", dataChangeCreatedTime) .add("dataChangeLastModifiedBy", dataChangeLastModifiedBy) .add("dataChangeLastModifiedTime", dataChangeLastModifiedTime); } public String toString(){ return toStringHelper().toString(); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/EntityPair.java ================================================ package com.ctrip.framework.apollo.common.entity; public class EntityPair { private E firstEntity; private E secondEntity; public EntityPair(E firstEntity, E secondEntity){ this.firstEntity = firstEntity; this.secondEntity = secondEntity; } public E getFirstEntity() { return firstEntity; } public void setFirstEntity(E firstEntity) { this.firstEntity = firstEntity; } public E getSecondEntity() { return secondEntity; } public void setSecondEntity(E secondEntity) { this.secondEntity = secondEntity; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/AbstractApolloHttpException.java ================================================ package com.ctrip.framework.apollo.common.exception; import org.springframework.http.HttpStatus; public abstract class AbstractApolloHttpException extends RuntimeException{ private static final long serialVersionUID = -1713129594004951820L; protected HttpStatus httpStatus; public AbstractApolloHttpException(String msg){ super(msg); } public AbstractApolloHttpException(String msg, Exception e){ super(msg,e); } protected void setHttpStatus(HttpStatus httpStatus){ this.httpStatus = httpStatus; } public HttpStatus getHttpStatus() { return httpStatus; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/BadRequestException.java ================================================ package com.ctrip.framework.apollo.common.exception; import org.springframework.http.HttpStatus; public class BadRequestException extends AbstractApolloHttpException { public BadRequestException(String str) { super(str); setHttpStatus(HttpStatus.BAD_REQUEST); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/BeanUtilsException.java ================================================ package com.ctrip.framework.apollo.common.exception; public class BeanUtilsException extends RuntimeException{ public BeanUtilsException(Throwable e){ super(e); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/NotFoundException.java ================================================ package com.ctrip.framework.apollo.common.exception; import org.springframework.http.HttpStatus; public class NotFoundException extends AbstractApolloHttpException { public NotFoundException(String str) { super(str); setHttpStatus(HttpStatus.NOT_FOUND); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/exception/ServiceException.java ================================================ package com.ctrip.framework.apollo.common.exception; import org.springframework.http.HttpStatus; public class ServiceException extends AbstractApolloHttpException { public ServiceException(String str) { super(str); setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR); } public ServiceException(String str, Exception e) { super(str, e); setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/http/MultiResponseEntity.java ================================================ package com.ctrip.framework.apollo.common.http; import org.springframework.http.HttpStatus; import java.util.LinkedList; import java.util.List; /** * 一个Response中包含多个ResponseEntity */ public class MultiResponseEntity { private int code; private List> entities = new LinkedList<>(); private MultiResponseEntity(HttpStatus httpCode) { this.code = httpCode.value(); } public static MultiResponseEntity instance(HttpStatus statusCode) { return new MultiResponseEntity<>(statusCode); } public static MultiResponseEntity ok() { return new MultiResponseEntity<>(HttpStatus.OK); } public void addResponseEntity(RichResponseEntity responseEntity) { if (responseEntity == null){ throw new IllegalArgumentException("sub response entity can not be null"); } entities.add(responseEntity); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/http/RichResponseEntity.java ================================================ package com.ctrip.framework.apollo.common.http; import org.springframework.http.HttpStatus; public class RichResponseEntity{ private int code; private Object message; private T body; public static RichResponseEntity ok(T body){ RichResponseEntity richResponseEntity = new RichResponseEntity<>(); richResponseEntity.message = HttpStatus.OK.getReasonPhrase(); richResponseEntity.code = HttpStatus.OK.value(); richResponseEntity.body = body; return richResponseEntity; } public static RichResponseEntity error(HttpStatus httpCode, Object message){ RichResponseEntity richResponseEntity = new RichResponseEntity<>(); richResponseEntity.message = message; richResponseEntity.code = httpCode.value(); return richResponseEntity; } public int getCode() { return code; } public Object getMessage() { return message; } public T getBody() { return body; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/BeanUtils.java ================================================ package com.ctrip.framework.apollo.common.utils; import com.ctrip.framework.apollo.common.exception.BeanUtilsException; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.util.CollectionUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class BeanUtils { /** *
   *     List userBeans = userDao.queryUsers();
   *     List userDTOs = BeanUtil.batchTransform(UserDTO.class, userBeans);
   * 
*/ public static List batchTransform(final Class clazz, List srcList) { if (CollectionUtils.isEmpty(srcList)) { return Collections.emptyList(); } List result = new ArrayList<>(srcList.size()); for (Object srcObject : srcList) { result.add(transfrom(clazz, srcObject)); } return result; } /** * 封装{@link org.springframework.beans.BeanUtils#copyProperties},惯用与直接将转换结果返回 * *
   *      UserBean userBean = new UserBean("username");
   *      return BeanUtil.transform(UserDTO.class, userBean);
   * 
*/ public static T transfrom(Class clazz, Object src) { if (src == null) { return null; } T instance = null; try { instance = clazz.newInstance(); } catch (Exception e) { throw new BeanUtilsException(e); } org.springframework.beans.BeanUtils.copyProperties(src, instance, getNullPropertyNames(src)); return instance; } private static String[] getNullPropertyNames(Object source) { final BeanWrapper src = new BeanWrapperImpl(source); PropertyDescriptor[] pds = src.getPropertyDescriptors(); Set emptyNames = new HashSet(); for (PropertyDescriptor pd : pds) { Object srcValue = src.getPropertyValue(pd.getName()); if (srcValue == null) emptyNames.add(pd.getName()); } String[] result = new String[emptyNames.size()]; return emptyNames.toArray(result); } /** * 用于将一个列表转换为列表中的对象的某个属性映射到列表中的对象 * *
   *      List userList = userService.queryUsers();
   *      Map userIdToUser = BeanUtil.mapByKey("userId", userList);
   * 
* * @param key 属性名 */ @SuppressWarnings("unchecked") public static Map mapByKey(String key, List list) { Map map = new HashMap(); if (CollectionUtils.isEmpty(list)) { return map; } try { Class clazz = list.get(0).getClass(); Field field = deepFindField(clazz, key); if (field == null) throw new IllegalArgumentException("Could not find the key"); field.setAccessible(true); for (Object o : list) { map.put((K) field.get(o), (V) o); } } catch (Exception e) { throw new BeanUtilsException(e); } return map; } /** * 根据列表里面的属性聚合 * *
   *       List shopList = shopService.queryShops();
   *       Map> city2Shops = BeanUtil.aggByKeyToList("cityId", shopList);
   * 
*/ @SuppressWarnings("unchecked") public static Map> aggByKeyToList(String key, List list) { Map> map = new HashMap>(); if (CollectionUtils.isEmpty(list)) {// 防止外面传入空list return map; } try { Class clazz = list.get(0).getClass(); Field field = deepFindField(clazz, key); if (field == null) throw new IllegalArgumentException("Could not find the key"); field.setAccessible(true); for (Object o : list) { K k = (K) field.get(o); if (map.get(k) == null) { map.put(k, new ArrayList()); } map.get(k).add((V) o); } } catch (Exception e) { throw new BeanUtilsException(e); } return map; } /** * 用于将一个对象的列表转换为列表中对象的属性集合 * *
   *     List userList = userService.queryUsers();
   *     Set userIds = BeanUtil.toPropertySet("userId", userList);
   * 
*/ @SuppressWarnings("unchecked") public static Set toPropertySet(String key, List list) { Set set = new HashSet(); if (CollectionUtils.isEmpty(list)) {// 防止外面传入空list return set; } try { Class clazz = list.get(0).getClass(); Field field = deepFindField(clazz, key); if (field == null) throw new IllegalArgumentException("Could not find the key"); field.setAccessible(true); for (Object o : list) { set.add((K)field.get(o)); } } catch (Exception e) { throw new BeanUtilsException(e); } return set; } private static Field deepFindField(Class clazz, String key) { Field field = null; while (!clazz.getName().equals(Object.class.getName())) { try { field = clazz.getDeclaredField(key); if (field != null) { break; } } catch (Exception e) { clazz = clazz.getSuperclass(); } } return field; } /** * 获取某个对象的某个属性 */ public static Object getProperty(Object obj, String fieldName) { try { Field field = deepFindField(obj.getClass(), fieldName); if (field != null) { field.setAccessible(true); return field.get(obj); } } catch (Exception e) { throw new BeanUtilsException(e); } return null; } /** * 设置某个对象的某个属性 */ public static void setProperty(Object obj, String fieldName, Object value) { try { Field field = deepFindField(obj.getClass(), fieldName); if (field != null) { field.setAccessible(true); field.set(obj, value); } } catch (Exception e) { throw new BeanUtilsException(e); } } /** * * @param source * @param target */ public static void copyProperties(Object source, Object target, String... ignoreProperties) { org.springframework.beans.BeanUtils.copyProperties(source, target, ignoreProperties); } /** * The copy will ignore BaseEntity field * * @param source * @param target */ public static void copyEntityProperties(Object source, Object target) { org.springframework.beans.BeanUtils.copyProperties(source, target, COPY_IGNORED_PROPERTIES); } private static final String[] COPY_IGNORED_PROPERTIES = {"id", "dataChangeCreatedBy", "dataChangeCreatedTime", "dataChangeLastModifiedTime"}; } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/ExceptionUtils.java ================================================ package com.ctrip.framework.apollo.common.utils; import com.google.common.base.MoreObjects; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.springframework.web.client.HttpStatusCodeException; import java.lang.reflect.Type; import java.util.Map; public final class ExceptionUtils { private static Gson gson = new Gson(); private static Type mapType = new TypeToken>() {}.getType(); public static String toString(HttpStatusCodeException e) { Map errorAttributes = gson.fromJson(e.getResponseBodyAsString(), mapType); if (errorAttributes != null) { return MoreObjects.toStringHelper(HttpStatusCodeException.class).omitNullValues() .add("status", errorAttributes.get("status")) .add("message", errorAttributes.get("message")) .add("timestamp", errorAttributes.get("timestamp")) .add("exception", errorAttributes.get("exception")) .add("errorCode", errorAttributes.get("errorCode")) .add("stackTrace", errorAttributes.get("stackTrace")).toString(); } return ""; } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/GrayReleaseRuleItemTransformer.java ================================================ package com.ctrip.framework.apollo.common.utils; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO; import java.lang.reflect.Type; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ public class GrayReleaseRuleItemTransformer { private static final Gson gson = new Gson(); private static final Type grayReleaseRuleItemsType = new TypeToken>() { }.getType(); public static Set batchTransformFromJSON(String content) { return gson.fromJson(content, grayReleaseRuleItemsType); } public static String batchTransformToJSON(Set ruleItems) { return gson.toJson(ruleItems); } } ================================================ FILE: open-config-center/apollo/apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/InputValidator.java ================================================ package com.ctrip.framework.apollo.common.utils; import com.ctrip.framework.apollo.core.utils.StringUtils; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Jason Song(song_s@ctrip.com) */ public class InputValidator { public static final String INVALID_CLUSTER_NAMESPACE_MESSAGE = "只允许输入数字,字母和符号 - _ ."; public static final String INVALID_NAMESPACE_NAMESPACE_MESSAGE = "不允许以.json, .yml, .yaml, .xml, .properties结尾"; public static final String CLUSTER_NAMESPACE_VALIDATOR = "[0-9a-zA-Z_.-]+"; public static final String APP_NAMESPACE_VALIDATOR = "[a-zA-Z0-9._-]+(? ================================================ FILE: open-config-center/apollo/apollo-common/src/test/java/com/ctrip/framework/apollo/common/AllTests.java ================================================ package com.ctrip.framework.apollo.common; import com.ctrip.framework.apollo.common.conditional.ConditionalOnProfileTest; import com.ctrip.framework.apollo.common.utils.InputValidatorTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ InputValidatorTest.class, ConditionalOnProfileTest.class }) public class AllTests { } ================================================ FILE: open-config-center/apollo/apollo-common/src/test/java/com/ctrip/framework/apollo/common/conditional/ConditionalOnProfileTest.java ================================================ package com.ctrip.framework.apollo.common.conditional; import com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile; import com.ctrip.framework.apollo.common.condition.ConditionalOnProfile; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static com.ctrip.framework.apollo.common.conditional.ConditionalOnProfileTest.ANOTHER_PROFILE; import static com.ctrip.framework.apollo.common.conditional.ConditionalOnProfileTest.SOME_PROFILE; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * @author Jason Song(song_s@ctrip.com) */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = ConditionalOnProfileTest.TestConfiguration.class) @ActiveProfiles({SOME_PROFILE, ANOTHER_PROFILE}) public class ConditionalOnProfileTest { static final String SOME_PROFILE = "someProfile"; static final String ANOTHER_PROFILE = "anotherProfile"; static final String YET_ANOTHER_PROFILE = "yetAnotherProfile"; static boolean someConfigurationEnabled = false; static boolean anotherConfigurationEnabled = false; static boolean yetAnotherConfigurationEnabled = false; static boolean combinedConfigurationEnabled = false; static boolean anotherCombinedConfigurationEnabled = false; @Test public void test() throws Exception { assertTrue(someConfigurationEnabled); assertFalse(anotherConfigurationEnabled); assertTrue(yetAnotherConfigurationEnabled); assertTrue(combinedConfigurationEnabled); assertFalse(anotherCombinedConfigurationEnabled); } @Configuration static class TestConfiguration { @Configuration @ConditionalOnProfile(SOME_PROFILE) static class SomeConfiguration { { someConfigurationEnabled = true; } } @Configuration @ConditionalOnMissingProfile(ANOTHER_PROFILE) static class AnotherConfiguration { { anotherConfigurationEnabled = true; } } @Configuration @ConditionalOnMissingProfile(YET_ANOTHER_PROFILE) static class YetAnotherConfiguration { { yetAnotherConfigurationEnabled = true; } } @Configuration @ConditionalOnProfile({SOME_PROFILE, ANOTHER_PROFILE}) @ConditionalOnMissingProfile(YET_ANOTHER_PROFILE) static class CombinedConfiguration { { combinedConfigurationEnabled = true; } } @Configuration @ConditionalOnProfile(SOME_PROFILE) @ConditionalOnMissingProfile({YET_ANOTHER_PROFILE, ANOTHER_PROFILE}) static class AnotherCombinedConfiguration { { anotherCombinedConfigurationEnabled = true; } } } } ================================================ FILE: open-config-center/apollo/apollo-common/src/test/java/com/ctrip/framework/apollo/common/utils/InputValidatorTest.java ================================================ package com.ctrip.framework.apollo.common.utils; import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * @author Jason Song(song_s@ctrip.com) */ public class InputValidatorTest { @Test public void testIsValidClusterNamespaceWithCorrectInput() throws Exception { String someValidInput = "a1-b2_c3.d4"; assertTrue(InputValidator.isValidClusterNamespace(someValidInput)); } @Test public void testIsValidClusterNamespaceWithInCorrectInput() throws Exception { String someInvalidInput = "中文123"; assertFalse(InputValidator.isValidClusterNamespace(someInvalidInput)); String anotherInvalidInput = "123@#{}"; assertFalse(InputValidator.isValidClusterNamespace(anotherInvalidInput)); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/pom.xml ================================================ com.ctrip.framework.apollo apollo 0.10.0-SNAPSHOT 4.0.0 apollo-configservice Apollo ConfigService ${project.artifactId} com.ctrip.framework.apollo apollo-biz org.springframework.cloud spring-cloud-starter-eureka-server spring-cloud-starter-archaius org.springframework.cloud spring-cloud-starter-ribbon org.springframework.cloud ribbon-eureka com.netflix.ribbon aws-java-sdk-core com.amazonaws aws-java-sdk-ec2 com.amazonaws aws-java-sdk-autoscaling com.amazonaws aws-java-sdk-sts com.amazonaws aws-java-sdk-route53 com.amazonaws org.springframework.security spring-security-crypto com.h2database h2 test org.springframework.boot spring-boot-starter-jdbc mysql mysql-connector-java org.springframework.boot spring-boot-maven-plugin repackage apollo-configservice ================================================ FILE: open-config-center/apollo/apollo-configservice/src/assembly/assembly-descriptor.xml ================================================ apollo-assembly zip false src/main/scripts scripts *.sh 0755 unix src/main/config config apollo-configservice.conf unix src/main/config / apollo-configservice.conf unix target / ${project.artifactId}-*.jar 0755 ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/config/apollo-configservice.conf ================================================ MODE=service PID_FOLDER=. LOG_FOLDER=/opt/logs/100003171/ ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/config/app.properties ================================================ appId=100003171 jdkVersion=1.8 ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/docker/Dockerfile ================================================ # Dockerfile for apollo-configservice # Build with: # docker build -t apollo-configservice . # Run with: # docker run -p 8080:8080 -d -v /tmp/logs:/opt/logs --name apollo-configservice apollo-configservice FROM openjdk:8-jre-alpine MAINTAINER ameizi ENV VERSION 0.9.0 RUN echo "http://mirrors.aliyun.com/alpine/v3.6/main" > /etc/apk/repositories \ && echo "http://mirrors.aliyun.com/alpine/v3.6/community" >> /etc/apk/repositories \ && apk update upgrade \ && apk add --no-cache procps unzip curl bash tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone ADD apollo-configservice-${VERSION}-github.zip /apollo-configservice/apollo-configservice-${VERSION}-github.zip RUN unzip /apollo-configservice/apollo-configservice-${VERSION}-github.zip -d /apollo-configservice \ && rm -rf /apollo-configservice/apollo-configservice-${VERSION}-github.zip \ && sed -i '$d' /apollo-configservice/scripts/startup.sh \ && echo "tail -f /dev/null" >> /apollo-configservice/scripts/startup.sh EXPOSE 8080 CMD ["/apollo-configservice/scripts/startup.sh"] ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceApplication.java ================================================ package com.ctrip.framework.apollo.configservice; import com.ctrip.framework.apollo.biz.ApolloBizConfig; import com.ctrip.framework.apollo.common.ApolloCommonConfig; import com.ctrip.framework.apollo.metaservice.ApolloMetaServiceConfig; import org.springframework.boot.actuate.system.ApplicationPidFileWriter; import org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Spring boot application entry point * * @author Jason Song(song_s@ctrip.com) */ @EnableEurekaClient @EnableAspectJAutoProxy @EnableAutoConfiguration // (exclude = EurekaClientConfigBean.class) @Configuration @EnableTransactionManagement @PropertySource(value = {"classpath:configservice.properties"}) @ComponentScan(basePackageClasses = {ApolloCommonConfig.class, ApolloBizConfig.class, ConfigServiceApplication.class, ApolloMetaServiceConfig.class}) public class ConfigServiceApplication { public static void main(String[] args) throws Exception { ConfigurableApplicationContext context = new SpringApplicationBuilder(ConfigServiceApplication.class).run(args); context.addApplicationListener(new ApplicationPidFileWriter()); context.addApplicationListener(new EmbeddedServerPortFileWriter()); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java ================================================ package com.ctrip.framework.apollo.configservice; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder; import com.ctrip.framework.apollo.biz.message.ReleaseMessageScanner; import com.ctrip.framework.apollo.configservice.controller.ConfigFileController; import com.ctrip.framework.apollo.configservice.controller.NotificationController; import com.ctrip.framework.apollo.configservice.controller.NotificationControllerV2; import com.ctrip.framework.apollo.configservice.service.ReleaseMessageServiceWithCache; import com.ctrip.framework.apollo.configservice.service.config.ConfigService; import com.ctrip.framework.apollo.configservice.service.config.ConfigServiceWithCache; import com.ctrip.framework.apollo.configservice.service.config.DefaultConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author Jason Song(song_s@ctrip.com) */ @Configuration public class ConfigServiceAutoConfiguration { @Autowired private BizConfig bizConfig; @Bean public GrayReleaseRulesHolder grayReleaseRulesHolder() { return new GrayReleaseRulesHolder(); } @Bean public ConfigService configService() { if (bizConfig.isConfigServiceCacheEnabled()) { return new ConfigServiceWithCache(); } return new DefaultConfigService(); } @Configuration static class MessageScannerConfiguration { @Autowired private NotificationController notificationController; @Autowired private ConfigFileController configFileController; @Autowired private NotificationControllerV2 notificationControllerV2; @Autowired private GrayReleaseRulesHolder grayReleaseRulesHolder; @Autowired private ReleaseMessageServiceWithCache releaseMessageServiceWithCache; @Autowired private ConfigService configService; @Bean public ReleaseMessageScanner releaseMessageScanner() { ReleaseMessageScanner releaseMessageScanner = new ReleaseMessageScanner(); //0. handle release message cache releaseMessageScanner.addMessageListener(releaseMessageServiceWithCache); //1. handle gray release rule releaseMessageScanner.addMessageListener(grayReleaseRulesHolder); //2. handle server cache releaseMessageScanner.addMessageListener(configService); releaseMessageScanner.addMessageListener(configFileController); //3. notify clients releaseMessageScanner.addMessageListener(notificationControllerV2); releaseMessageScanner.addMessageListener(notificationController); return releaseMessageScanner; } } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceHealthIndicator.java ================================================ package com.ctrip.framework.apollo.configservice; import com.ctrip.framework.apollo.biz.service.AppService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Component; @Component public class ConfigServiceHealthIndicator implements HealthIndicator { @Autowired private AppService appService; @Override public Health health() { int errorCode = check(); if (errorCode != 0) { return Health.down().withDetail("Error Code", errorCode).build(); } return Health.up().build(); } private int check() { PageRequest pageable = new PageRequest(0, 1); appService.findAll(pageable); return 0; } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ServletInitializer.java ================================================ package com.ctrip.framework.apollo.configservice; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.web.SpringBootServletInitializer; /** * Entry point for traditional web app * * @author Jason Song(song_s@ctrip.com) */ public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(ConfigServiceApplication.class); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigController.java ================================================ package com.ctrip.framework.apollo.configservice.controller; import java.io.IOException; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.configservice.service.AppNamespaceServiceWithCache; import com.ctrip.framework.apollo.configservice.service.config.ConfigService; import com.ctrip.framework.apollo.configservice.util.InstanceConfigAuditUtil; import com.ctrip.framework.apollo.configservice.util.NamespaceUtil; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloConfig; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; import com.ctrip.framework.apollo.tracer.Tracer; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; /** * @author Jason Song(song_s@ctrip.com) */ @RestController @RequestMapping("/configs") public class ConfigController { private static final Splitter X_FORWARDED_FOR_SPLITTER = Splitter.on(",").omitEmptyStrings() .trimResults(); @Autowired private ConfigService configService; @Autowired private AppNamespaceServiceWithCache appNamespaceService; @Autowired private NamespaceUtil namespaceUtil; @Autowired private InstanceConfigAuditUtil instanceConfigAuditUtil; @Autowired private Gson gson; private static final Type configurationTypeReference = new TypeToken>() { }.getType(); @RequestMapping(value = "/{appId}/{clusterName}/{namespace:.+}", method = RequestMethod.GET) public ApolloConfig queryConfig(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespace, @RequestParam(value = "dataCenter", required = false) String dataCenter, @RequestParam(value = "releaseKey", defaultValue = "-1") String clientSideReleaseKey, @RequestParam(value = "ip", required = false) String clientIp, @RequestParam(value = "messages", required = false) String messagesAsString, HttpServletRequest request, HttpServletResponse response) throws IOException { String originalNamespace = namespace; //strip out .properties suffix namespace = namespaceUtil.filterNamespaceName(namespace); //fix the character case issue, such as FX.apollo <-> fx.apollo namespace = namespaceUtil.normalizeNamespace(appId, namespace); if (Strings.isNullOrEmpty(clientIp)) { clientIp = tryToGetClientIp(request); } ApolloNotificationMessages clientMessages = transformMessages(messagesAsString); List releases = Lists.newLinkedList(); String appClusterNameLoaded = clusterName; if (!ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) { Release currentAppRelease = configService.loadConfig(appId, clientIp, appId, clusterName, namespace, dataCenter, clientMessages); if (currentAppRelease != null) { releases.add(currentAppRelease); //we have cluster search process, so the cluster name might be overridden appClusterNameLoaded = currentAppRelease.getClusterName(); } } //if namespace does not belong to this appId, should check if there is a public configuration if (!namespaceBelongsToAppId(appId, namespace)) { Release publicRelease = this.findPublicConfig(appId, clientIp, clusterName, namespace, dataCenter, clientMessages); if (!Objects.isNull(publicRelease)) { releases.add(publicRelease); } } if (releases.isEmpty()) { response.sendError(HttpServletResponse.SC_NOT_FOUND, String.format( "Could not load configurations with appId: %s, clusterName: %s, namespace: %s", appId, clusterName, originalNamespace)); Tracer.logEvent("Apollo.Config.NotFound", assembleKey(appId, clusterName, originalNamespace, dataCenter)); return null; } auditReleases(appId, clusterName, dataCenter, clientIp, releases); String mergedReleaseKey = releases.stream().map(Release::getReleaseKey) .collect(Collectors.joining(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR)); if (mergedReleaseKey.equals(clientSideReleaseKey)) { // Client side configuration is the same with server side, return 304 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); Tracer.logEvent("Apollo.Config.NotModified", assembleKey(appId, appClusterNameLoaded, originalNamespace, dataCenter)); return null; } ApolloConfig apolloConfig = new ApolloConfig(appId, appClusterNameLoaded, originalNamespace, mergedReleaseKey); apolloConfig.setConfigurations(mergeReleaseConfigurations(releases)); Tracer.logEvent("Apollo.Config.Found", assembleKey(appId, appClusterNameLoaded, originalNamespace, dataCenter)); return apolloConfig; } private boolean namespaceBelongsToAppId(String appId, String namespaceName) { //Every app has an 'application' namespace if (Objects.equals(ConfigConsts.NAMESPACE_APPLICATION, namespaceName)) { return true; } //if no appId is present, then no other namespace belongs to it if (ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) { return false; } AppNamespace appNamespace = appNamespaceService.findByAppIdAndNamespace(appId, namespaceName); return appNamespace != null; } /** * @param clientAppId the application which uses public config * @param namespace the namespace * @param dataCenter the datacenter */ private Release findPublicConfig(String clientAppId, String clientIp, String clusterName, String namespace, String dataCenter, ApolloNotificationMessages clientMessages) { AppNamespace appNamespace = appNamespaceService.findPublicNamespaceByName(namespace); //check whether the namespace's appId equals to current one if (Objects.isNull(appNamespace) || Objects.equals(clientAppId, appNamespace.getAppId())) { return null; } String publicConfigAppId = appNamespace.getAppId(); return configService.loadConfig(clientAppId, clientIp, publicConfigAppId, clusterName, namespace, dataCenter, clientMessages); } /** * Merge configurations of releases. * Release in lower index override those in higher index */ Map mergeReleaseConfigurations(List releases) { Map result = Maps.newHashMap(); for (Release release : Lists.reverse(releases)) { result.putAll(gson.fromJson(release.getConfigurations(), configurationTypeReference)); } return result; } private String assembleKey(String appId, String cluster, String namespace, String dataCenter) { List keyParts = Lists.newArrayList(appId, cluster, namespace); if (!Strings.isNullOrEmpty(dataCenter)) { keyParts.add(dataCenter); } return keyParts.stream().collect(Collectors.joining(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR)); } private void auditReleases(String appId, String cluster, String dataCenter, String clientIp, List releases) { if (Strings.isNullOrEmpty(clientIp)) { //no need to audit instance config when there is no ip return; } for (Release release : releases) { instanceConfigAuditUtil.audit(appId, cluster, dataCenter, clientIp, release.getAppId(), release.getClusterName(), release.getNamespaceName(), release.getReleaseKey()); } } private String tryToGetClientIp(HttpServletRequest request) { String forwardedFor = request.getHeader("X-FORWARDED-FOR"); if (!Strings.isNullOrEmpty(forwardedFor)) { return X_FORWARDED_FOR_SPLITTER.splitToList(forwardedFor).get(0); } return request.getRemoteAddr(); } ApolloNotificationMessages transformMessages(String messagesAsString) { ApolloNotificationMessages notificationMessages = null; if (!Strings.isNullOrEmpty(messagesAsString)) { try { notificationMessages = gson.fromJson(messagesAsString, ApolloNotificationMessages.class); } catch (Throwable ex) { Tracer.logError(ex); } } return notificationMessages; } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileController.java ================================================ package com.ctrip.framework.apollo.configservice.controller; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; import com.google.common.cache.Weigher; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.gson.Gson; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder; import com.ctrip.framework.apollo.biz.message.ReleaseMessageListener; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.configservice.util.NamespaceUtil; import com.ctrip.framework.apollo.configservice.util.WatchKeysUtil; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloConfig; import com.ctrip.framework.apollo.core.utils.PropertiesUtil; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Jason Song(song_s@ctrip.com) */ @RestController @RequestMapping("/configfiles") public class ConfigFileController implements ReleaseMessageListener { private static final Logger logger = LoggerFactory.getLogger(ConfigFileController.class); private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); private static final Splitter X_FORWARDED_FOR_SPLITTER = Splitter.on(",").omitEmptyStrings() .trimResults(); private static final long MAX_CACHE_SIZE = 50 * 1024 * 1024; // 50MB private static final long EXPIRE_AFTER_WRITE = 30; private final HttpHeaders propertiesResponseHeaders; private final HttpHeaders jsonResponseHeaders; private final ResponseEntity NOT_FOUND_RESPONSE; private Cache localCache; private final Multimap watchedKeys2CacheKey = Multimaps.synchronizedSetMultimap(HashMultimap.create()); private final Multimap cacheKey2WatchedKeys = Multimaps.synchronizedSetMultimap(HashMultimap.create()); private static final Gson gson = new Gson(); @Autowired private ConfigController configController; @Autowired private NamespaceUtil namespaceUtil; @Autowired private WatchKeysUtil watchKeysUtil; @Autowired private GrayReleaseRulesHolder grayReleaseRulesHolder; public ConfigFileController() { localCache = CacheBuilder.newBuilder() .expireAfterWrite(EXPIRE_AFTER_WRITE, TimeUnit.MINUTES) .weigher(new Weigher() { @Override public int weigh(String key, String value) { return value == null ? 0 : value.length(); } }) .maximumWeight(MAX_CACHE_SIZE) .removalListener(new RemovalListener() { @Override public void onRemoval(RemovalNotification notification) { String cacheKey = notification.getKey(); logger.debug("removing cache key: {}", cacheKey); if (!cacheKey2WatchedKeys.containsKey(cacheKey)) { return; } //create a new list to avoid ConcurrentModificationException List watchedKeys = new ArrayList<>(cacheKey2WatchedKeys.get(cacheKey)); for (String watchedKey : watchedKeys) { watchedKeys2CacheKey.remove(watchedKey, cacheKey); } cacheKey2WatchedKeys.removeAll(cacheKey); logger.debug("removed cache key: {}", cacheKey); } }) .build(); propertiesResponseHeaders = new HttpHeaders(); propertiesResponseHeaders.add("Content-Type", "text/plain;charset=UTF-8"); jsonResponseHeaders = new HttpHeaders(); jsonResponseHeaders.add("Content-Type", "application/json;charset=UTF-8"); NOT_FOUND_RESPONSE = new ResponseEntity<>(HttpStatus.NOT_FOUND); } @RequestMapping(value = "/{appId}/{clusterName}/{namespace:.+}", method = RequestMethod.GET) public ResponseEntity queryConfigAsProperties(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespace, @RequestParam(value = "dataCenter", required = false) String dataCenter, @RequestParam(value = "ip", required = false) String clientIp, HttpServletRequest request, HttpServletResponse response) throws IOException { String result = queryConfig(ConfigFileOutputFormat.PROPERTIES, appId, clusterName, namespace, dataCenter, clientIp, request, response); if (result == null) { return NOT_FOUND_RESPONSE; } return new ResponseEntity<>(result, propertiesResponseHeaders, HttpStatus.OK); } @RequestMapping(value = "/json/{appId}/{clusterName}/{namespace:.+}", method = RequestMethod.GET) public ResponseEntity queryConfigAsJson(@PathVariable String appId, @PathVariable String clusterName, @PathVariable String namespace, @RequestParam(value = "dataCenter", required = false) String dataCenter, @RequestParam(value = "ip", required = false) String clientIp, HttpServletRequest request, HttpServletResponse response) throws IOException { String result = queryConfig(ConfigFileOutputFormat.JSON, appId, clusterName, namespace, dataCenter, clientIp, request, response); if (result == null) { return NOT_FOUND_RESPONSE; } return new ResponseEntity<>(result, jsonResponseHeaders, HttpStatus.OK); } String queryConfig(ConfigFileOutputFormat outputFormat, String appId, String clusterName, String namespace, String dataCenter, String clientIp, HttpServletRequest request, HttpServletResponse response) throws IOException { //strip out .properties suffix namespace = namespaceUtil.filterNamespaceName(namespace); //fix the character case issue, such as FX.apollo <-> fx.apollo namespace = namespaceUtil.normalizeNamespace(appId, namespace); if (Strings.isNullOrEmpty(clientIp)) { clientIp = tryToGetClientIp(request); } //1. check whether this client has gray release rules boolean hasGrayReleaseRule = grayReleaseRulesHolder.hasGrayReleaseRule(appId, clientIp, namespace); String cacheKey = assembleCacheKey(outputFormat, appId, clusterName, namespace, dataCenter); //2. try to load gray release and return if (hasGrayReleaseRule) { Tracer.logEvent("ConfigFile.Cache.GrayRelease", cacheKey); return loadConfig(outputFormat, appId, clusterName, namespace, dataCenter, clientIp, request, response); } //3. if not gray release, check weather cache exists, if exists, return String result = localCache.getIfPresent(cacheKey); //4. if not exists, load from ConfigController if (Strings.isNullOrEmpty(result)) { Tracer.logEvent("ConfigFile.Cache.Miss", cacheKey); result = loadConfig(outputFormat, appId, clusterName, namespace, dataCenter, clientIp, request, response); if (result == null) { return null; } //5. Double check if this client needs to load gray release, if yes, load from db again //This step is mainly to avoid cache pollution if (grayReleaseRulesHolder.hasGrayReleaseRule(appId, clientIp, namespace)) { Tracer.logEvent("ConfigFile.Cache.GrayReleaseConflict", cacheKey); return loadConfig(outputFormat, appId, clusterName, namespace, dataCenter, clientIp, request, response); } localCache.put(cacheKey, result); logger.debug("adding cache for key: {}", cacheKey); Set watchedKeys = watchKeysUtil.assembleAllWatchKeys(appId, clusterName, namespace, dataCenter); for (String watchedKey : watchedKeys) { watchedKeys2CacheKey.put(watchedKey, cacheKey); } cacheKey2WatchedKeys.putAll(cacheKey, watchedKeys); logger.debug("added cache for key: {}", cacheKey); } else { Tracer.logEvent("ConfigFile.Cache.Hit", cacheKey); } return result; } private String loadConfig(ConfigFileOutputFormat outputFormat, String appId, String clusterName, String namespace, String dataCenter, String clientIp, HttpServletRequest request, HttpServletResponse response) throws IOException { ApolloConfig apolloConfig = configController.queryConfig(appId, clusterName, namespace, dataCenter, "-1", clientIp, null, request, response); if (apolloConfig == null || apolloConfig.getConfigurations() == null) { return null; } String result = null; switch (outputFormat) { case PROPERTIES: Properties properties = new Properties(); properties.putAll(apolloConfig.getConfigurations()); result = PropertiesUtil.toString(properties); break; case JSON: result = gson.toJson(apolloConfig.getConfigurations()); break; } return result; } String assembleCacheKey(ConfigFileOutputFormat outputFormat, String appId, String clusterName, String namespace, String dataCenter) { List keyParts = Lists.newArrayList(outputFormat.getValue(), appId, clusterName, namespace); if (!Strings.isNullOrEmpty(dataCenter)) { keyParts.add(dataCenter); } return STRING_JOINER.join(keyParts); } @Override public void handleMessage(ReleaseMessage message, String channel) { logger.info("message received - channel: {}, message: {}", channel, message); String content = message.getMessage(); if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) { return; } if (!watchedKeys2CacheKey.containsKey(content)) { return; } //create a new list to avoid ConcurrentModificationException List cacheKeys = new ArrayList<>(watchedKeys2CacheKey.get(content)); for (String cacheKey : cacheKeys) { logger.debug("invalidate cache key: {}", cacheKey); localCache.invalidate(cacheKey); } } enum ConfigFileOutputFormat { PROPERTIES("properties"), JSON("json"); private String value; ConfigFileOutputFormat(String value) { this.value = value; } public String getValue() { return value; } } private String tryToGetClientIp(HttpServletRequest request) { String forwardedFor = request.getHeader("X-FORWARDED-FOR"); if (!Strings.isNullOrEmpty(forwardedFor)) { return X_FORWARDED_FOR_SPLITTER.splitToList(forwardedFor).get(0); } return request.getRemoteAddr(); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationController.java ================================================ package com.ctrip.framework.apollo.configservice.controller; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.message.ReleaseMessageListener; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.utils.EntityManagerUtil; import com.ctrip.framework.apollo.configservice.service.ReleaseMessageServiceWithCache; import com.ctrip.framework.apollo.configservice.util.NamespaceUtil; import com.ctrip.framework.apollo.configservice.util.WatchKeysUtil; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; import java.util.List; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ @Deprecated @RestController @RequestMapping("/notifications") public class NotificationController implements ReleaseMessageListener { private static final Logger logger = LoggerFactory.getLogger(NotificationController.class); private static final long TIMEOUT = 30 * 1000;//30 seconds private final Multimap>> deferredResults = Multimaps.synchronizedSetMultimap(HashMultimap.create()); private static final ResponseEntity NOT_MODIFIED_RESPONSE = new ResponseEntity<>(HttpStatus.NOT_MODIFIED); private static final Splitter STRING_SPLITTER = Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings(); @Autowired private WatchKeysUtil watchKeysUtil; @Autowired private ReleaseMessageServiceWithCache releaseMessageService; @Autowired private EntityManagerUtil entityManagerUtil; @Autowired private NamespaceUtil namespaceUtil; /** * For single namespace notification, reserved for older version of apollo clients * * @param appId the appId * @param cluster the cluster * @param namespace the namespace name * @param dataCenter the datacenter * @param notificationId the notification id for the namespace * @param clientIp the client side ip * @return a deferred result */ @RequestMapping(method = RequestMethod.GET) public DeferredResult> pollNotification( @RequestParam(value = "appId") String appId, @RequestParam(value = "cluster") String cluster, @RequestParam(value = "namespace", defaultValue = ConfigConsts.NAMESPACE_APPLICATION) String namespace, @RequestParam(value = "dataCenter", required = false) String dataCenter, @RequestParam(value = "notificationId", defaultValue = "-1") long notificationId, @RequestParam(value = "ip", required = false) String clientIp) { //strip out .properties suffix namespace = namespaceUtil.filterNamespaceName(namespace); Set watchedKeys = watchKeysUtil.assembleAllWatchKeys(appId, cluster, namespace, dataCenter); DeferredResult> deferredResult = new DeferredResult<>(TIMEOUT, NOT_MODIFIED_RESPONSE); //check whether client is out-dated ReleaseMessage latest = releaseMessageService.findLatestReleaseMessageForMessages(watchedKeys); /** * Manually close the entity manager. * Since for async request, Spring won't do so until the request is finished, * which is unacceptable since we are doing long polling - means the db connection would be hold * for a very long time */ entityManagerUtil.closeEntityManager(); if (latest != null && latest.getId() != notificationId) { deferredResult.setResult(new ResponseEntity<>( new ApolloConfigNotification(namespace, latest.getId()), HttpStatus.OK)); } else { //register all keys for (String key : watchedKeys) { this.deferredResults.put(key, deferredResult); } deferredResult .onTimeout(() -> logWatchedKeys(watchedKeys, "Apollo.LongPoll.TimeOutKeys")); deferredResult.onCompletion(() -> { //unregister all keys for (String key : watchedKeys) { deferredResults.remove(key, deferredResult); } logWatchedKeys(watchedKeys, "Apollo.LongPoll.CompletedKeys"); }); logWatchedKeys(watchedKeys, "Apollo.LongPoll.RegisteredKeys"); logger.debug("Listening {} from appId: {}, cluster: {}, namespace: {}, datacenter: {}", watchedKeys, appId, cluster, namespace, dataCenter); } return deferredResult; } @Override public void handleMessage(ReleaseMessage message, String channel) { logger.info("message received - channel: {}, message: {}", channel, message); String content = message.getMessage(); Tracer.logEvent("Apollo.LongPoll.Messages", content); if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) { return; } List keys = STRING_SPLITTER.splitToList(content); //message should be appId+cluster+namespace if (keys.size() != 3) { logger.error("message format invalid - {}", content); return; } ResponseEntity notification = new ResponseEntity<>( new ApolloConfigNotification(keys.get(2), message.getId()), HttpStatus.OK); if (!deferredResults.containsKey(content)) { return; } //create a new list to avoid ConcurrentModificationException List>> results = Lists.newArrayList(deferredResults.get(content)); logger.debug("Notify {} clients for key {}", results.size(), content); for (DeferredResult> result : results) { result.setResult(notification); } logger.debug("Notification completed"); } private void logWatchedKeys(Set watchedKeys, String eventName) { for (String watchedKey : watchedKeys) { Tracer.logEvent(eventName, watchedKey); } } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationControllerV2.java ================================================ package com.ctrip.framework.apollo.configservice.controller; import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.message.ReleaseMessageListener; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.utils.EntityManagerUtil; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.configservice.service.ReleaseMessageServiceWithCache; import com.ctrip.framework.apollo.configservice.util.NamespaceUtil; import com.ctrip.framework.apollo.configservice.util.WatchKeysUtil; import com.ctrip.framework.apollo.configservice.wrapper.DeferredResultWrapper; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; import java.lang.reflect.Type; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author Jason Song(song_s@ctrip.com) */ @RestController @RequestMapping("/notifications/v2") public class NotificationControllerV2 implements ReleaseMessageListener { private static final Logger logger = LoggerFactory.getLogger(NotificationControllerV2.class); private final Multimap deferredResults = Multimaps.synchronizedSetMultimap(HashMultimap.create()); private static final Splitter STRING_SPLITTER = Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings(); private static final Type notificationsTypeReference = new TypeToken>() { }.getType(); private final ExecutorService largeNotificationBatchExecutorService; @Autowired private WatchKeysUtil watchKeysUtil; @Autowired private ReleaseMessageServiceWithCache releaseMessageService; @Autowired private EntityManagerUtil entityManagerUtil; @Autowired private NamespaceUtil namespaceUtil; @Autowired private Gson gson; @Autowired private BizConfig bizConfig; public NotificationControllerV2() { largeNotificationBatchExecutorService = Executors.newSingleThreadExecutor(ApolloThreadFactory.create ("NotificationControllerV2", true)); } @RequestMapping(method = RequestMethod.GET) public DeferredResult>> pollNotification( @RequestParam(value = "appId") String appId, @RequestParam(value = "cluster") String cluster, @RequestParam(value = "notifications") String notificationsAsString, @RequestParam(value = "dataCenter", required = false) String dataCenter, @RequestParam(value = "ip", required = false) String clientIp) { List notifications = null; try { notifications = gson.fromJson(notificationsAsString, notificationsTypeReference); } catch (Throwable ex) { Tracer.logError(ex); } if (CollectionUtils.isEmpty(notifications)) { throw new BadRequestException("Invalid format of notifications: " + notificationsAsString); } DeferredResultWrapper deferredResultWrapper = new DeferredResultWrapper(); Set namespaces = Sets.newHashSet(); Map clientSideNotifications = Maps.newHashMap(); Map filteredNotifications = filterNotifications(appId, notifications); for (Map.Entry notificationEntry : filteredNotifications.entrySet()) { String normalizedNamespace = notificationEntry.getKey(); ApolloConfigNotification notification = notificationEntry.getValue(); namespaces.add(normalizedNamespace); clientSideNotifications.put(normalizedNamespace, notification.getNotificationId()); if (!Objects.equals(notification.getNamespaceName(), normalizedNamespace)) { deferredResultWrapper.recordNamespaceNameNormalizedResult(notification.getNamespaceName(), normalizedNamespace); } } if (CollectionUtils.isEmpty(namespaces)) { throw new BadRequestException("Invalid format of notifications: " + notificationsAsString); } Multimap watchedKeysMap = watchKeysUtil.assembleAllWatchKeys(appId, cluster, namespaces, dataCenter); Set watchedKeys = Sets.newHashSet(watchedKeysMap.values()); List latestReleaseMessages = releaseMessageService.findLatestReleaseMessagesGroupByMessages(watchedKeys); /** * Manually close the entity manager. * Since for async request, Spring won't do so until the request is finished, * which is unacceptable since we are doing long polling - means the db connection would be hold * for a very long time */ entityManagerUtil.closeEntityManager(); List newNotifications = getApolloConfigNotifications(namespaces, clientSideNotifications, watchedKeysMap, latestReleaseMessages); if (!CollectionUtils.isEmpty(newNotifications)) { deferredResultWrapper.setResult(newNotifications); } else { deferredResultWrapper .onTimeout(() -> logWatchedKeys(watchedKeys, "Apollo.LongPoll.TimeOutKeys")); deferredResultWrapper.onCompletion(() -> { //unregister all keys for (String key : watchedKeys) { deferredResults.remove(key, deferredResultWrapper); } logWatchedKeys(watchedKeys, "Apollo.LongPoll.CompletedKeys"); }); //register all keys for (String key : watchedKeys) { this.deferredResults.put(key, deferredResultWrapper); } logWatchedKeys(watchedKeys, "Apollo.LongPoll.RegisteredKeys"); logger.debug("Listening {} from appId: {}, cluster: {}, namespace: {}, datacenter: {}", watchedKeys, appId, cluster, namespaces, dataCenter); } return deferredResultWrapper.getResult(); } private Map filterNotifications(String appId, List notifications) { Map filteredNotifications = Maps.newHashMap(); for (ApolloConfigNotification notification : notifications) { if (Strings.isNullOrEmpty(notification.getNamespaceName())) { continue; } //strip out .properties suffix String originalNamespace = namespaceUtil.filterNamespaceName(notification.getNamespaceName()); notification.setNamespaceName(originalNamespace); //fix the character case issue, such as FX.apollo <-> fx.apollo String normalizedNamespace = namespaceUtil.normalizeNamespace(appId, originalNamespace); // in case client side namespace name has character case issue and has difference notification ids // such as FX.apollo = 1 but fx.apollo = 2, we should let FX.apollo have the chance to update its notification id // which means we should record FX.apollo = 1 here and ignore fx.apollo = 2 if (filteredNotifications.containsKey(normalizedNamespace) && filteredNotifications.get(normalizedNamespace).getNotificationId() < notification.getNotificationId()) { continue; } filteredNotifications.put(normalizedNamespace, notification); } return filteredNotifications; } private List getApolloConfigNotifications(Set namespaces, Map clientSideNotifications, Multimap watchedKeysMap, List latestReleaseMessages) { List newNotifications = Lists.newArrayList(); if (!CollectionUtils.isEmpty(latestReleaseMessages)) { Map latestNotifications = Maps.newHashMap(); for (ReleaseMessage releaseMessage : latestReleaseMessages) { latestNotifications.put(releaseMessage.getMessage(), releaseMessage.getId()); } for (String namespace : namespaces) { long clientSideId = clientSideNotifications.get(namespace); long latestId = ConfigConsts.NOTIFICATION_ID_PLACEHOLDER; Collection namespaceWatchedKeys = watchedKeysMap.get(namespace); for (String namespaceWatchedKey : namespaceWatchedKeys) { long namespaceNotificationId = latestNotifications.getOrDefault(namespaceWatchedKey, ConfigConsts.NOTIFICATION_ID_PLACEHOLDER); if (namespaceNotificationId > latestId) { latestId = namespaceNotificationId; } } if (latestId > clientSideId) { ApolloConfigNotification notification = new ApolloConfigNotification(namespace, latestId); namespaceWatchedKeys.stream().filter(latestNotifications::containsKey).forEach(namespaceWatchedKey -> notification.addMessage(namespaceWatchedKey, latestNotifications.get(namespaceWatchedKey))); newNotifications.add(notification); } } } return newNotifications; } @Override public void handleMessage(ReleaseMessage message, String channel) { logger.info("message received - channel: {}, message: {}", channel, message); String content = message.getMessage(); Tracer.logEvent("Apollo.LongPoll.Messages", content); if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) { return; } String changedNamespace = retrieveNamespaceFromReleaseMessage.apply(content); if (Strings.isNullOrEmpty(changedNamespace)) { logger.error("message format invalid - {}", content); return; } if (!deferredResults.containsKey(content)) { return; } //create a new list to avoid ConcurrentModificationException List results = Lists.newArrayList(deferredResults.get(content)); ApolloConfigNotification configNotification = new ApolloConfigNotification(changedNamespace, message.getId()); configNotification.addMessage(content, message.getId()); //do async notification if too many clients if (results.size() > bizConfig.releaseMessageNotificationBatch()) { largeNotificationBatchExecutorService.submit(() -> { logger.debug("Async notify {} clients for key {} with batch {}", results.size(), content, bizConfig.releaseMessageNotificationBatch()); for (int i = 0; i < results.size(); i++) { if (i > 0 && i % bizConfig.releaseMessageNotificationBatch() == 0) { try { TimeUnit.MILLISECONDS.sleep(bizConfig.releaseMessageNotificationBatchIntervalInMilli()); } catch (InterruptedException e) { //ignore } } logger.debug("Async notify {}", results.get(i)); results.get(i).setResult(configNotification); } }); return; } logger.debug("Notify {} clients for key {}", results.size(), content); for (DeferredResultWrapper result : results) { result.setResult(configNotification); } logger.debug("Notification completed"); } private static final Function retrieveNamespaceFromReleaseMessage = releaseMessage -> { if (Strings.isNullOrEmpty(releaseMessage)) { return null; } List keys = STRING_SPLITTER.splitToList(releaseMessage); //message should be appId+cluster+namespace if (keys.size() != 3) { logger.error("message format invalid - {}", releaseMessage); return null; } return keys.get(2); }; private void logWatchedKeys(Set watchedKeys, String eventName) { for (String watchedKey : watchedKeys) { Tracer.logEvent(eventName, watchedKey); } } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/AppNamespaceServiceWithCache.java ================================================ package com.ctrip.framework.apollo.configservice.service; import com.ctrip.framework.apollo.configservice.wrapper.CaseInsensitiveMapWrapper; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class AppNamespaceServiceWithCache implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(AppNamespaceServiceWithCache.class); private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR) .skipNulls(); @Autowired private AppNamespaceRepository appNamespaceRepository; @Autowired private BizConfig bizConfig; private int scanInterval; private TimeUnit scanIntervalTimeUnit; private int rebuildInterval; private TimeUnit rebuildIntervalTimeUnit; private ScheduledExecutorService scheduledExecutorService; private long maxIdScanned; //store namespaceName -> AppNamespace private CaseInsensitiveMapWrapper publicAppNamespaceCache; //store appId+namespaceName -> AppNamespace private CaseInsensitiveMapWrapper appNamespaceCache; //store id -> AppNamespace private Map appNamespaceIdCache; public AppNamespaceServiceWithCache() { initialize(); } private void initialize() { maxIdScanned = 0; publicAppNamespaceCache = new CaseInsensitiveMapWrapper<>(Maps.newConcurrentMap()); appNamespaceCache = new CaseInsensitiveMapWrapper<>(Maps.newConcurrentMap()); appNamespaceIdCache = Maps.newConcurrentMap(); scheduledExecutorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory .create("AppNamespaceServiceWithCache", true)); } public AppNamespace findByAppIdAndNamespace(String appId, String namespaceName) { Preconditions.checkArgument(!StringUtils.isContainEmpty(appId, namespaceName), "appId and namespaceName must not be empty"); return appNamespaceCache.get(STRING_JOINER.join(appId, namespaceName)); } public List findByAppIdAndNamespaces(String appId, Set namespaceNames) { Preconditions.checkArgument(!Strings.isNullOrEmpty(appId), "appId must not be null"); if (namespaceNames == null || namespaceNames.isEmpty()) { return Collections.emptyList(); } List result = Lists.newArrayList(); for (String namespaceName : namespaceNames) { AppNamespace appNamespace = appNamespaceCache.get(STRING_JOINER.join(appId, namespaceName)); if (appNamespace != null) { result.add(appNamespace); } } return result; } public AppNamespace findPublicNamespaceByName(String namespaceName) { Preconditions.checkArgument(!Strings.isNullOrEmpty(namespaceName), "namespaceName must not be empty"); return publicAppNamespaceCache.get(namespaceName); } public List findPublicNamespacesByNames(Set namespaceNames) { if (namespaceNames == null || namespaceNames.isEmpty()) { return Collections.emptyList(); } List result = Lists.newArrayList(); for (String namespaceName : namespaceNames) { AppNamespace appNamespace = publicAppNamespaceCache.get(namespaceName); if (appNamespace != null) { result.add(appNamespace); } } return result; } @Override public void afterPropertiesSet() throws Exception { populateDataBaseInterval(); scanNewAppNamespaces(); //block the startup process until load finished scheduledExecutorService.scheduleAtFixedRate(() -> { Transaction transaction = Tracer.newTransaction("Apollo.AppNamespaceServiceWithCache", "rebuildCache"); try { this.updateAndDeleteCache(); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); logger.error("Rebuild cache failed", ex); } finally { transaction.complete(); } }, rebuildInterval, rebuildInterval, rebuildIntervalTimeUnit); scheduledExecutorService.scheduleWithFixedDelay(this::scanNewAppNamespaces, scanInterval, scanInterval, scanIntervalTimeUnit); } private void scanNewAppNamespaces() { Transaction transaction = Tracer.newTransaction("Apollo.AppNamespaceServiceWithCache", "scanNewAppNamespaces"); try { this.loadNewAppNamespaces(); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); logger.error("Load new app namespaces failed", ex); } finally { transaction.complete(); } } //for those new app namespaces private void loadNewAppNamespaces() { boolean hasMore = true; while (hasMore && !Thread.currentThread().isInterrupted()) { //current batch is 500 List appNamespaces = appNamespaceRepository .findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned); if (CollectionUtils.isEmpty(appNamespaces)) { break; } mergeAppNamespaces(appNamespaces); int scanned = appNamespaces.size(); maxIdScanned = appNamespaces.get(scanned - 1).getId(); hasMore = scanned == 500; logger.info("Loaded {} new app namespaces with startId {}", scanned, maxIdScanned); } } private void mergeAppNamespaces(List appNamespaces) { for (AppNamespace appNamespace : appNamespaces) { appNamespaceCache.put(assembleAppNamespaceKey(appNamespace), appNamespace); appNamespaceIdCache.put(appNamespace.getId(), appNamespace); if (appNamespace.isPublic()) { publicAppNamespaceCache.put(appNamespace.getName(), appNamespace); } } } //for those updated or deleted app namespaces private void updateAndDeleteCache() { List ids = Lists.newArrayList(appNamespaceIdCache.keySet()); if (CollectionUtils.isEmpty(ids)) { return; } List> partitionIds = Lists.partition(ids, 500); for (List toRebuild : partitionIds) { Iterable appNamespaces = appNamespaceRepository.findAll(toRebuild); if (appNamespaces == null) { continue; } //handle updated Set foundIds = handleUpdatedAppNamespaces(appNamespaces); //handle deleted handleDeletedAppNamespaces(Sets.difference(Sets.newHashSet(toRebuild), foundIds)); } } //for those updated app namespaces private Set handleUpdatedAppNamespaces(Iterable appNamespaces) { Set foundIds = Sets.newHashSet(); for (AppNamespace appNamespace : appNamespaces) { foundIds.add(appNamespace.getId()); AppNamespace thatInCache = appNamespaceIdCache.get(appNamespace.getId()); if (thatInCache != null && appNamespace.getDataChangeLastModifiedTime().after(thatInCache .getDataChangeLastModifiedTime())) { appNamespaceIdCache.put(appNamespace.getId(), appNamespace); String oldKey = assembleAppNamespaceKey(thatInCache); String newKey = assembleAppNamespaceKey(appNamespace); appNamespaceCache.put(newKey, appNamespace); //in case appId or namespaceName changes if (!newKey.equals(oldKey)) { appNamespaceCache.remove(oldKey); } if (appNamespace.isPublic()) { publicAppNamespaceCache.put(appNamespace.getName(), appNamespace); //in case namespaceName changes if (!appNamespace.getName().equals(thatInCache.getName()) && thatInCache.isPublic()) { publicAppNamespaceCache.remove(thatInCache.getName()); } } else if (thatInCache.isPublic()) { //just in case isPublic changes publicAppNamespaceCache.remove(thatInCache.getName()); } logger.info("Found AppNamespace changes, old: {}, new: {}", thatInCache, appNamespace); } } return foundIds; } //for those deleted app namespaces private void handleDeletedAppNamespaces(Set deletedIds) { if (CollectionUtils.isEmpty(deletedIds)) { return; } for (Long deletedId : deletedIds) { AppNamespace deleted = appNamespaceIdCache.remove(deletedId); if (deleted == null) { continue; } appNamespaceCache.remove(assembleAppNamespaceKey(deleted)); if (deleted.isPublic()) { publicAppNamespaceCache.remove(deleted.getName()); } logger.info("Found AppNamespace deleted, {}", deleted); } } private String assembleAppNamespaceKey(AppNamespace appNamespace) { return STRING_JOINER.join(appNamespace.getAppId(), appNamespace.getName()); } private void populateDataBaseInterval() { scanInterval = bizConfig.appNamespaceCacheScanInterval(); scanIntervalTimeUnit = bizConfig.appNamespaceCacheScanIntervalTimeUnit(); rebuildInterval = bizConfig.appNamespaceCacheRebuildInterval(); rebuildIntervalTimeUnit = bizConfig.appNamespaceCacheRebuildIntervalTimeUnit(); } //only for test use private void reset() throws Exception { scheduledExecutorService.shutdownNow(); initialize(); afterPropertiesSet(); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/ReleaseMessageServiceWithCache.java ================================================ package com.ctrip.framework.apollo.configservice.service; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.ctrip.framework.apollo.biz.config.BizConfig; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.message.ReleaseMessageListener; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ReleaseMessageServiceWithCache implements ReleaseMessageListener, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(ReleaseMessageServiceWithCache .class); @Autowired private ReleaseMessageRepository releaseMessageRepository; @Autowired private BizConfig bizConfig; private int scanInterval; private TimeUnit scanIntervalTimeUnit; private volatile long maxIdScanned; private ConcurrentMap releaseMessageCache; private AtomicBoolean doScan; private ExecutorService executorService; public ReleaseMessageServiceWithCache() { initialize(); } private void initialize() { releaseMessageCache = Maps.newConcurrentMap(); doScan = new AtomicBoolean(true); executorService = Executors.newSingleThreadExecutor(ApolloThreadFactory .create("ReleaseMessageServiceWithCache", true)); } public ReleaseMessage findLatestReleaseMessageForMessages(Set messages) { if (CollectionUtils.isEmpty(messages)) { return null; } long maxReleaseMessageId = 0; ReleaseMessage result = null; for (String message : messages) { ReleaseMessage releaseMessage = releaseMessageCache.get(message); if (releaseMessage != null && releaseMessage.getId() > maxReleaseMessageId) { maxReleaseMessageId = releaseMessage.getId(); result = releaseMessage; } } return result; } public List findLatestReleaseMessagesGroupByMessages(Set messages) { if (CollectionUtils.isEmpty(messages)) { return Collections.emptyList(); } List releaseMessages = Lists.newArrayList(); for (String message : messages) { ReleaseMessage releaseMessage = releaseMessageCache.get(message); if (releaseMessage != null) { releaseMessages.add(releaseMessage); } } return releaseMessages; } @Override public void handleMessage(ReleaseMessage message, String channel) { //Could stop once the ReleaseMessageScanner starts to work doScan.set(false); logger.info("message received - channel: {}, message: {}", channel, message); String content = message.getMessage(); Tracer.logEvent("Apollo.ReleaseMessageService.UpdateCache", String.valueOf(message.getId())); if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) { return; } long gap = message.getId() - maxIdScanned; if (gap == 1) { mergeReleaseMessage(message); } else if (gap > 1) { //gap found! loadReleaseMessages(maxIdScanned); } } @Override public void afterPropertiesSet() throws Exception { populateDataBaseInterval(); //block the startup process until load finished //this should happen before ReleaseMessageScanner due to autowire loadReleaseMessages(0); executorService.submit(() -> { while (doScan.get() && !Thread.currentThread().isInterrupted()) { Transaction transaction = Tracer.newTransaction("Apollo.ReleaseMessageServiceWithCache", "scanNewReleaseMessages"); try { loadReleaseMessages(maxIdScanned); transaction.setStatus(Transaction.SUCCESS); } catch (Throwable ex) { transaction.setStatus(ex); logger.error("Scan new release messages failed", ex); } finally { transaction.complete(); } try { scanIntervalTimeUnit.sleep(scanInterval); } catch (InterruptedException e) { //ignore } } }); } private synchronized void mergeReleaseMessage(ReleaseMessage releaseMessage) { ReleaseMessage old = releaseMessageCache.get(releaseMessage.getMessage()); if (old == null || releaseMessage.getId() > old.getId()) { releaseMessageCache.put(releaseMessage.getMessage(), releaseMessage); maxIdScanned = releaseMessage.getId(); } } private void loadReleaseMessages(long startId) { boolean hasMore = true; while (hasMore && !Thread.currentThread().isInterrupted()) { //current batch is 500 List releaseMessages = releaseMessageRepository .findFirst500ByIdGreaterThanOrderByIdAsc(startId); if (CollectionUtils.isEmpty(releaseMessages)) { break; } releaseMessages.forEach(this::mergeReleaseMessage); int scanned = releaseMessages.size(); startId = releaseMessages.get(scanned - 1).getId(); hasMore = scanned == 500; logger.info("Loaded {} release messages with startId {}", scanned, startId); } } private void populateDataBaseInterval() { scanInterval = bizConfig.releaseMessageCacheScanInterval(); scanIntervalTimeUnit = bizConfig.releaseMessageCacheScanIntervalTimeUnit(); } //only for test use private void reset() throws Exception { executorService.shutdownNow(); initialize(); afterPropertiesSet(); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/AbstractConfigService.java ================================================ package com.ctrip.framework.apollo.configservice.service.config; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; import com.google.common.base.Strings; import java.util.Map; import java.util.Objects; import org.springframework.beans.factory.annotation.Autowired; /** * @author Jason Song(song_s@ctrip.com) */ public abstract class AbstractConfigService implements ConfigService { @Autowired private GrayReleaseRulesHolder grayReleaseRulesHolder; @Override public Release loadConfig(String clientAppId, String clientIp, String configAppId, String configClusterName, String configNamespace, String dataCenter, ApolloNotificationMessages clientMessages) { // load from specified cluster fist if (!Objects.equals(ConfigConsts.CLUSTER_NAME_DEFAULT, configClusterName)) { Release clusterRelease = findRelease(clientAppId, clientIp, configAppId, configClusterName, configNamespace, clientMessages); if (!Objects.isNull(clusterRelease)) { return clusterRelease; } } // try to load via data center if (!Strings.isNullOrEmpty(dataCenter) && !Objects.equals(dataCenter, configClusterName)) { Release dataCenterRelease = findRelease(clientAppId, clientIp, configAppId, dataCenter, configNamespace, clientMessages); if (!Objects.isNull(dataCenterRelease)) { return dataCenterRelease; } } // fallback to default release return findRelease(clientAppId, clientIp, configAppId, ConfigConsts.CLUSTER_NAME_DEFAULT, configNamespace, clientMessages); } /** * Find release * * @param clientAppId the client's app id * @param clientIp the client ip * @param configAppId the requested config's app id * @param configClusterName the requested config's cluster name * @param configNamespace the requested config's namespace name * @param clientMessages the messages received in client side * @return the release */ private Release findRelease(String clientAppId, String clientIp, String configAppId, String configClusterName, String configNamespace, ApolloNotificationMessages clientMessages) { Long grayReleaseId = grayReleaseRulesHolder.findReleaseIdFromGrayReleaseRule(clientAppId, clientIp, configAppId, configClusterName, configNamespace); Release release = null; if (grayReleaseId != null) { release = findActiveOne(grayReleaseId, clientMessages); } if (release == null) { release = findLatestActiveRelease(configAppId, configClusterName, configNamespace, clientMessages); } return release; } /** * Find active release by id */ protected abstract Release findActiveOne(long id, ApolloNotificationMessages clientMessages); /** * Find active release by app id, cluster name and namespace name */ protected abstract Release findLatestActiveRelease(String configAppId, String configClusterName, String configNamespaceName, ApolloNotificationMessages clientMessages); } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigService.java ================================================ package com.ctrip.framework.apollo.configservice.service.config; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.message.ReleaseMessageListener; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConfigService extends ReleaseMessageListener { /** * Load config * * @param clientAppId the client's app id * @param clientIp the client ip * @param configAppId the requested config's app id * @param configClusterName the requested config's cluster name * @param configNamespace the requested config's namespace name * @param dataCenter the client data center * @param clientMessages the messages received in client side * @return the Release */ Release loadConfig(String clientAppId, String clientIp, String configAppId, String configClusterName, String configNamespace, String dataCenter, ApolloNotificationMessages clientMessages); } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/ConfigServiceWithCache.java ================================================ package com.ctrip.framework.apollo.configservice.service.config; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.biz.service.ReleaseMessageService; import com.ctrip.framework.apollo.biz.service.ReleaseService; import com.ctrip.framework.apollo.biz.utils.ReleaseMessageKeyGenerator; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; /** * config service with guava cache * * @author Jason Song(song_s@ctrip.com) */ public class ConfigServiceWithCache extends AbstractConfigService { private static final Logger logger = LoggerFactory.getLogger(ConfigServiceWithCache.class); private static final long DEFAULT_EXPIRED_AFTER_ACCESS_IN_MINUTES = 60;//1 hour private static final String TRACER_EVENT_CACHE_INVALIDATE = "ConfigCache.Invalidate"; private static final String TRACER_EVENT_CACHE_LOAD = "ConfigCache.LoadFromDB"; private static final String TRACER_EVENT_CACHE_LOAD_ID = "ConfigCache.LoadFromDBById"; private static final String TRACER_EVENT_CACHE_GET = "ConfigCache.Get"; private static final String TRACER_EVENT_CACHE_GET_ID = "ConfigCache.GetById"; private static final Splitter STRING_SPLITTER = Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings(); @Autowired private ReleaseService releaseService; @Autowired private ReleaseMessageService releaseMessageService; private LoadingCache configCache; private LoadingCache> configIdCache; private ConfigCacheEntry nullConfigCacheEntry; public ConfigServiceWithCache() { nullConfigCacheEntry = new ConfigCacheEntry(ConfigConsts.NOTIFICATION_ID_PLACEHOLDER, null); } @PostConstruct void initialize() { configCache = CacheBuilder.newBuilder() .expireAfterAccess(DEFAULT_EXPIRED_AFTER_ACCESS_IN_MINUTES, TimeUnit.MINUTES) .build(new CacheLoader() { @Override public ConfigCacheEntry load(String key) throws Exception { List namespaceInfo = STRING_SPLITTER.splitToList(key); if (namespaceInfo.size() != 3) { Tracer.logError( new IllegalArgumentException(String.format("Invalid cache load key %s", key))); return nullConfigCacheEntry; } Transaction transaction = Tracer.newTransaction(TRACER_EVENT_CACHE_LOAD, key); try { ReleaseMessage latestReleaseMessage = releaseMessageService.findLatestReleaseMessageForMessages(Lists .newArrayList(key)); Release latestRelease = releaseService.findLatestActiveRelease(namespaceInfo.get(0), namespaceInfo.get(1), namespaceInfo.get(2)); transaction.setStatus(Transaction.SUCCESS); long notificationId = latestReleaseMessage == null ? ConfigConsts.NOTIFICATION_ID_PLACEHOLDER : latestReleaseMessage .getId(); if (notificationId == ConfigConsts.NOTIFICATION_ID_PLACEHOLDER && latestRelease == null) { return nullConfigCacheEntry; } return new ConfigCacheEntry(notificationId, latestRelease); } catch (Throwable ex) { transaction.setStatus(ex); throw ex; } finally { transaction.complete(); } } }); configIdCache = CacheBuilder.newBuilder() .expireAfterAccess(DEFAULT_EXPIRED_AFTER_ACCESS_IN_MINUTES, TimeUnit.MINUTES) .build(new CacheLoader>() { @Override public Optional load(Long key) throws Exception { Transaction transaction = Tracer.newTransaction(TRACER_EVENT_CACHE_LOAD_ID, String.valueOf(key)); try { Release release = releaseService.findActiveOne(key); transaction.setStatus(Transaction.SUCCESS); return Optional.ofNullable(release); } catch (Throwable ex) { transaction.setStatus(ex); throw ex; } finally { transaction.complete(); } } }); } @Override protected Release findActiveOne(long id, ApolloNotificationMessages clientMessages) { Tracer.logEvent(TRACER_EVENT_CACHE_GET_ID, String.valueOf(id)); return configIdCache.getUnchecked(id).orElse(null); } @Override protected Release findLatestActiveRelease(String appId, String clusterName, String namespaceName, ApolloNotificationMessages clientMessages) { String key = ReleaseMessageKeyGenerator.generate(appId, clusterName, namespaceName); Tracer.logEvent(TRACER_EVENT_CACHE_GET, key); ConfigCacheEntry cacheEntry = configCache.getUnchecked(key); //cache is out-dated if (clientMessages != null && clientMessages.has(key) && clientMessages.get(key) > cacheEntry.getNotificationId()) { //invalidate the cache and try to load from db again invalidate(key); cacheEntry = configCache.getUnchecked(key); } return cacheEntry.getRelease(); } private void invalidate(String key) { configCache.invalidate(key); Tracer.logEvent(TRACER_EVENT_CACHE_INVALIDATE, key); } @Override public void handleMessage(ReleaseMessage message, String channel) { logger.info("message received - channel: {}, message: {}", channel, message); if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(message.getMessage())) { return; } try { invalidate(message.getMessage()); //warm up the cache configCache.getUnchecked(message.getMessage()); } catch (Throwable ex) { //ignore } } private static class ConfigCacheEntry { private final long notificationId; private final Release release; public ConfigCacheEntry(long notificationId, Release release) { this.notificationId = notificationId; this.release = release; } public long getNotificationId() { return notificationId; } public Release getRelease() { return release; } } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/config/DefaultConfigService.java ================================================ package com.ctrip.framework.apollo.configservice.service.config; import com.ctrip.framework.apollo.biz.entity.Release; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.service.ReleaseService; import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages; import org.springframework.beans.factory.annotation.Autowired; /** * config service with no cache * * @author Jason Song(song_s@ctrip.com) */ public class DefaultConfigService extends AbstractConfigService { @Autowired private ReleaseService releaseService; @Override protected Release findActiveOne(long id, ApolloNotificationMessages clientMessages) { return releaseService.findActiveOne(id); } @Override protected Release findLatestActiveRelease(String configAppId, String configClusterName, String configNamespace, ApolloNotificationMessages clientMessages) { return releaseService.findLatestActiveRelease(configAppId, configClusterName, configNamespace); } @Override public void handleMessage(ReleaseMessage message, String channel) { // since there is no cache, so do nothing } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/InstanceConfigAuditUtil.java ================================================ package com.ctrip.framework.apollo.configservice.util; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Lists; import com.google.common.collect.Queues; import com.ctrip.framework.apollo.biz.entity.Instance; import com.ctrip.framework.apollo.biz.entity.InstanceConfig; import com.ctrip.framework.apollo.biz.service.InstanceService; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class InstanceConfigAuditUtil implements InitializingBean { private static final int INSTANCE_CONFIG_AUDIT_MAX_SIZE = 10000; private static final int INSTANCE_CACHE_MAX_SIZE = 50000; private static final int INSTANCE_CONFIG_CACHE_MAX_SIZE = 50000; private static final long OFFER_TIME_LAST_MODIFIED_TIME_THRESHOLD_IN_MILLI = TimeUnit.MINUTES.toMillis(10);//10 minutes private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); private final ExecutorService auditExecutorService; private final AtomicBoolean auditStopped; private BlockingQueue audits = Queues.newLinkedBlockingQueue (INSTANCE_CONFIG_AUDIT_MAX_SIZE); private Cache instanceCache; private Cache instanceConfigReleaseKeyCache; @Autowired private InstanceService instanceService; public InstanceConfigAuditUtil() { auditExecutorService = Executors.newSingleThreadExecutor( ApolloThreadFactory.create("InstanceConfigAuditUtil", true)); auditStopped = new AtomicBoolean(false); instanceCache = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.HOURS) .maximumSize(INSTANCE_CACHE_MAX_SIZE).build(); instanceConfigReleaseKeyCache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.DAYS) .maximumSize(INSTANCE_CONFIG_CACHE_MAX_SIZE).build(); } public boolean audit(String appId, String clusterName, String dataCenter, String ip, String configAppId, String configClusterName, String configNamespace, String releaseKey) { return this.audits.offer(new InstanceConfigAuditModel(appId, clusterName, dataCenter, ip, configAppId, configClusterName, configNamespace, releaseKey)); } void doAudit(InstanceConfigAuditModel auditModel) { String instanceCacheKey = assembleInstanceKey(auditModel.getAppId(), auditModel .getClusterName(), auditModel.getIp(), auditModel.getDataCenter()); Long instanceId = instanceCache.getIfPresent(instanceCacheKey); if (instanceId == null) { instanceId = prepareInstanceId(auditModel); instanceCache.put(instanceCacheKey, instanceId); } //load instance config release key from cache, and check if release key is the same String instanceConfigCacheKey = assembleInstanceConfigKey(instanceId, auditModel .getConfigAppId(), auditModel.getConfigNamespace()); String cacheReleaseKey = instanceConfigReleaseKeyCache.getIfPresent(instanceConfigCacheKey); //if release key is the same, then skip audit if (cacheReleaseKey != null && Objects.equals(cacheReleaseKey, auditModel.getReleaseKey())) { return; } instanceConfigReleaseKeyCache.put(instanceConfigCacheKey, auditModel.getReleaseKey()); //if release key is not the same or cannot find in cache, then do audit InstanceConfig instanceConfig = instanceService.findInstanceConfig(instanceId, auditModel .getConfigAppId(), auditModel.getConfigNamespace()); if (instanceConfig != null) { if (!Objects.equals(instanceConfig.getReleaseKey(), auditModel.getReleaseKey())) { instanceConfig.setConfigClusterName(auditModel.getConfigClusterName()); instanceConfig.setReleaseKey(auditModel.getReleaseKey()); instanceConfig.setReleaseDeliveryTime(auditModel.getOfferTime()); } else if (offerTimeAndLastModifiedTimeCloseEnough(auditModel.getOfferTime(), instanceConfig.getDataChangeLastModifiedTime())) { //when releaseKey is the same, optimize to reduce writes if the record was updated not long ago return; } //we need to update no matter the release key is the same or not, to ensure the //last modified time is updated each day instanceConfig.setDataChangeLastModifiedTime(auditModel.getOfferTime()); instanceService.updateInstanceConfig(instanceConfig); return; } instanceConfig = new InstanceConfig(); instanceConfig.setInstanceId(instanceId); instanceConfig.setConfigAppId(auditModel.getConfigAppId()); instanceConfig.setConfigClusterName(auditModel.getConfigClusterName()); instanceConfig.setConfigNamespaceName(auditModel.getConfigNamespace()); instanceConfig.setReleaseKey(auditModel.getReleaseKey()); instanceConfig.setReleaseDeliveryTime(auditModel.getOfferTime()); instanceConfig.setDataChangeCreatedTime(auditModel.getOfferTime()); try { instanceService.createInstanceConfig(instanceConfig); } catch (DataIntegrityViolationException ex) { //concurrent insertion, safe to ignore } } private boolean offerTimeAndLastModifiedTimeCloseEnough(Date offerTime, Date lastModifiedTime) { return (offerTime.getTime() - lastModifiedTime.getTime()) < OFFER_TIME_LAST_MODIFIED_TIME_THRESHOLD_IN_MILLI; } private long prepareInstanceId(InstanceConfigAuditModel auditModel) { Instance instance = instanceService.findInstance(auditModel.getAppId(), auditModel .getClusterName(), auditModel.getDataCenter(), auditModel.getIp()); if (instance != null) { return instance.getId(); } instance = new Instance(); instance.setAppId(auditModel.getAppId()); instance.setClusterName(auditModel.getClusterName()); instance.setDataCenter(auditModel.getDataCenter()); instance.setIp(auditModel.getIp()); try { return instanceService.createInstance(instance).getId(); } catch (DataIntegrityViolationException ex) { //return the one exists return instanceService.findInstance(instance.getAppId(), instance.getClusterName(), instance.getDataCenter(), instance.getIp()).getId(); } } @Override public void afterPropertiesSet() throws Exception { auditExecutorService.submit(() -> { while (!auditStopped.get() && !Thread.currentThread().isInterrupted()) { try { InstanceConfigAuditModel model = audits.poll(); if (model == null) { TimeUnit.SECONDS.sleep(1); continue; } doAudit(model); } catch (Throwable ex) { Tracer.logError(ex); } } }); } private String assembleInstanceKey(String appId, String cluster, String ip, String datacenter) { List keyParts = Lists.newArrayList(appId, cluster, ip); if (!Strings.isNullOrEmpty(datacenter)) { keyParts.add(datacenter); } return STRING_JOINER.join(keyParts); } private String assembleInstanceConfigKey(long instanceId, String configAppId, String configNamespace) { return STRING_JOINER.join(instanceId, configAppId, configNamespace); } public static class InstanceConfigAuditModel { private String appId; private String clusterName; private String dataCenter; private String ip; private String configAppId; private String configClusterName; private String configNamespace; private String releaseKey; private Date offerTime; public InstanceConfigAuditModel(String appId, String clusterName, String dataCenter, String clientIp, String configAppId, String configClusterName, String configNamespace, String releaseKey) { this.offerTime = new Date(); this.appId = appId; this.clusterName = clusterName; this.dataCenter = Strings.isNullOrEmpty(dataCenter) ? "" : dataCenter; this.ip = clientIp; this.configAppId = configAppId; this.configClusterName = configClusterName; this.configNamespace = configNamespace; this.releaseKey = releaseKey; } public String getAppId() { return appId; } public String getClusterName() { return clusterName; } public String getDataCenter() { return dataCenter; } public String getIp() { return ip; } public String getConfigAppId() { return configAppId; } public String getConfigNamespace() { return configNamespace; } public String getReleaseKey() { return releaseKey; } public String getConfigClusterName() { return configClusterName; } public Date getOfferTime() { return offerTime; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; InstanceConfigAuditModel model = (InstanceConfigAuditModel) o; return Objects.equals(appId, model.appId) && Objects.equals(clusterName, model.clusterName) && Objects.equals(dataCenter, model.dataCenter) && Objects.equals(ip, model.ip) && Objects.equals(configAppId, model.configAppId) && Objects.equals(configClusterName, model.configClusterName) && Objects.equals(configNamespace, model.configNamespace) && Objects.equals(releaseKey, model.releaseKey); } @Override public int hashCode() { return Objects.hash(appId, clusterName, dataCenter, ip, configAppId, configClusterName, configNamespace, releaseKey); } } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/NamespaceUtil.java ================================================ package com.ctrip.framework.apollo.configservice.util; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.configservice.service.AppNamespaceServiceWithCache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * @author Jason Song(song_s@ctrip.com) */ @Component public class NamespaceUtil { @Autowired private AppNamespaceServiceWithCache appNamespaceServiceWithCache; public String filterNamespaceName(String namespaceName) { if (namespaceName.toLowerCase().endsWith(".properties")) { int dotIndex = namespaceName.lastIndexOf("."); return namespaceName.substring(0, dotIndex); } return namespaceName; } public String normalizeNamespace(String appId, String namespaceName) { AppNamespace appNamespace = appNamespaceServiceWithCache.findByAppIdAndNamespace(appId, namespaceName); if (appNamespace != null) { return appNamespace.getName(); } appNamespace = appNamespaceServiceWithCache.findPublicNamespaceByName(namespaceName); if (appNamespace != null) { return appNamespace.getName(); } return namespaceName; } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/WatchKeysUtil.java ================================================ package com.ctrip.framework.apollo.configservice.util; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.FluentIterable; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.configservice.service.AppNamespaceServiceWithCache; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.core.ConfigConsts; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ @Component public class WatchKeysUtil { private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); @Autowired private AppNamespaceServiceWithCache appNamespaceService; /** * Assemble watch keys for the given appId, cluster, namespace, dataCenter combination */ public Set assembleAllWatchKeys(String appId, String clusterName, String namespace, String dataCenter) { Multimap watchedKeysMap = assembleAllWatchKeys(appId, clusterName, Sets.newHashSet(namespace), dataCenter); return Sets.newHashSet(watchedKeysMap.get(namespace)); } /** * Assemble watch keys for the given appId, cluster, namespaces, dataCenter combination * * @return a multimap with namespace as the key and watch keys as the value */ public Multimap assembleAllWatchKeys(String appId, String clusterName, Set namespaces, String dataCenter) { Multimap watchedKeysMap = assembleWatchKeys(appId, clusterName, namespaces, dataCenter); //Every app has an 'application' namespace if (!(namespaces.size() == 1 && namespaces.contains(ConfigConsts.NAMESPACE_APPLICATION))) { Set namespacesBelongToAppId = namespacesBelongToAppId(appId, namespaces); Set publicNamespaces = Sets.difference(namespaces, namespacesBelongToAppId); //Listen on more namespaces if it's a public namespace if (!publicNamespaces.isEmpty()) { watchedKeysMap .putAll(findPublicConfigWatchKeys(appId, clusterName, publicNamespaces, dataCenter)); } } return watchedKeysMap; } private Multimap findPublicConfigWatchKeys(String applicationId, String clusterName, Set namespaces, String dataCenter) { Multimap watchedKeysMap = HashMultimap.create(); List appNamespaces = appNamespaceService.findPublicNamespacesByNames(namespaces); for (AppNamespace appNamespace : appNamespaces) { //check whether the namespace's appId equals to current one if (Objects.equals(applicationId, appNamespace.getAppId())) { continue; } String publicConfigAppId = appNamespace.getAppId(); watchedKeysMap.putAll(appNamespace.getName(), assembleWatchKeys(publicConfigAppId, clusterName, appNamespace.getName(), dataCenter)); } return watchedKeysMap; } private String assembleKey(String appId, String cluster, String namespace) { return STRING_JOINER.join(appId, cluster, namespace); } private Set assembleWatchKeys(String appId, String clusterName, String namespace, String dataCenter) { if (ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) { return Collections.emptySet(); } Set watchedKeys = Sets.newHashSet(); //watch specified cluster config change if (!Objects.equals(ConfigConsts.CLUSTER_NAME_DEFAULT, clusterName)) { watchedKeys.add(assembleKey(appId, clusterName, namespace)); } //watch data center config change if (!Strings.isNullOrEmpty(dataCenter) && !Objects.equals(dataCenter, clusterName)) { watchedKeys.add(assembleKey(appId, dataCenter, namespace)); } //watch default cluster config change watchedKeys.add(assembleKey(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, namespace)); return watchedKeys; } private Multimap assembleWatchKeys(String appId, String clusterName, Set namespaces, String dataCenter) { Multimap watchedKeysMap = HashMultimap.create(); for (String namespace : namespaces) { watchedKeysMap .putAll(namespace, assembleWatchKeys(appId, clusterName, namespace, dataCenter)); } return watchedKeysMap; } private Set namespacesBelongToAppId(String appId, Set namespaces) { if (ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) { return Collections.emptySet(); } List appNamespaces = appNamespaceService.findByAppIdAndNamespaces(appId, namespaces); if (appNamespaces == null || appNamespaces.isEmpty()) { return Collections.emptySet(); } return FluentIterable.from(appNamespaces).transform(AppNamespace::getName).toSet(); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/wrapper/CaseInsensitiveMapWrapper.java ================================================ package com.ctrip.framework.apollo.configservice.wrapper; import java.util.Map; /** * @author Jason Song(song_s@ctrip.com) */ public class CaseInsensitiveMapWrapper { private final Map delegate; public CaseInsensitiveMapWrapper(Map delegate) { this.delegate = delegate; } public T get(String key) { return delegate.get(key.toLowerCase()); } public T put(String key, T value) { return delegate.put(key.toLowerCase(), value); } public T remove(String key) { return delegate.remove(key.toLowerCase()); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/wrapper/DeferredResultWrapper.java ================================================ package com.ctrip.framework.apollo.configservice.wrapper; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.ctrip.framework.apollo.core.dto.ApolloConfig; import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.context.request.async.DeferredResult; import java.util.List; import java.util.Map; /** * @author Jason Song(song_s@ctrip.com) */ public class DeferredResultWrapper { private static final long TIMEOUT = 30 * 1000;//30 seconds private static final ResponseEntity> NOT_MODIFIED_RESPONSE_LIST = new ResponseEntity<>(HttpStatus.NOT_MODIFIED); private Map normalizedNamespaceNameToOriginalNamespaceName; private DeferredResult>> result; public DeferredResultWrapper() { result = new DeferredResult<>(TIMEOUT, NOT_MODIFIED_RESPONSE_LIST); } public void recordNamespaceNameNormalizedResult(String originalNamespaceName, String normalizedNamespaceName) { if (normalizedNamespaceNameToOriginalNamespaceName == null) { normalizedNamespaceNameToOriginalNamespaceName = Maps.newHashMap(); } normalizedNamespaceNameToOriginalNamespaceName.put(normalizedNamespaceName, originalNamespaceName); } public void onTimeout(Runnable timeoutCallback) { result.onTimeout(timeoutCallback); } public void onCompletion(Runnable completionCallback) { result.onCompletion(completionCallback); } public void setResult(ApolloConfigNotification notification) { setResult(Lists.newArrayList(notification)); } /** * The namespace name is used as a key in client side, so we have to return the original one instead of the correct one */ public void setResult(List notifications) { if (normalizedNamespaceNameToOriginalNamespaceName != null) { notifications.stream().filter(notification -> normalizedNamespaceNameToOriginalNamespaceName.containsKey (notification.getNamespaceName())).forEach(notification -> notification.setNamespaceName( normalizedNamespaceNameToOriginalNamespaceName.get(notification.getNamespaceName()))); } result.setResult(new ResponseEntity<>(notifications, HttpStatus.OK)); } public DeferredResult>> getResult() { return result; } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/metaservice/ApolloMetaServiceConfig.java ================================================ package com.ctrip.framework.apollo.metaservice; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @EnableAutoConfiguration @Configuration @ComponentScan(basePackageClasses = ApolloMetaServiceConfig.class) public class ApolloMetaServiceConfig { } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/metaservice/controller/ServiceController.java ================================================ package com.ctrip.framework.apollo.metaservice.controller; import com.ctrip.framework.apollo.core.dto.ServiceDTO; import com.ctrip.framework.apollo.metaservice.service.DiscoveryService; import com.netflix.appinfo.InstanceInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; @RestController @RequestMapping("/services") public class ServiceController { @Autowired private DiscoveryService discoveryService; @RequestMapping("/meta") public List getMetaService() { List instances = discoveryService.getMetaServiceInstances(); List result = instances.stream().map(new Function() { @Override public ServiceDTO apply(InstanceInfo instance) { ServiceDTO service = new ServiceDTO(); service.setAppName(instance.getAppName()); service.setInstanceId(instance.getInstanceId()); service.setHomepageUrl(instance.getHomePageUrl()); return service; } }).collect(Collectors.toList()); return result; } @RequestMapping("/config") public List getConfigService( @RequestParam(value = "appId", defaultValue = "") String appId, @RequestParam(value = "ip", required = false) String clientIp) { List instances = discoveryService.getConfigServiceInstances(); List result = instances.stream().map(new Function() { @Override public ServiceDTO apply(InstanceInfo instance) { ServiceDTO service = new ServiceDTO(); service.setAppName(instance.getAppName()); service.setInstanceId(instance.getInstanceId()); service.setHomepageUrl(instance.getHomePageUrl()); return service; } }).collect(Collectors.toList()); return result; } @RequestMapping("/admin") public List getAdminService() { List instances = discoveryService.getAdminServiceInstances(); List result = instances.stream().map(new Function() { @Override public ServiceDTO apply(InstanceInfo instance) { ServiceDTO service = new ServiceDTO(); service.setAppName(instance.getAppName()); service.setInstanceId(instance.getInstanceId()); service.setHomepageUrl(instance.getHomePageUrl()); return service; } }).collect(Collectors.toList()); return result; } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/java/com/ctrip/framework/apollo/metaservice/service/DiscoveryService.java ================================================ package com.ctrip.framework.apollo.metaservice.service; import com.ctrip.framework.apollo.core.ServiceNameConsts; import com.ctrip.framework.apollo.tracer.Tracer; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; import com.netflix.discovery.shared.Application; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; @Service public class DiscoveryService { @Autowired private EurekaClient eurekaClient; public List getConfigServiceInstances() { Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_CONFIGSERVICE); if (application == null) { Tracer.logEvent("Apollo.EurekaDiscovery.NotFound", ServiceNameConsts.APOLLO_CONFIGSERVICE); } return application != null ? application.getInstances() : Collections.emptyList(); } public List getMetaServiceInstances() { Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_METASERVICE); if (application == null) { Tracer.logEvent("Apollo.EurekaDiscovery.NotFound", ServiceNameConsts.APOLLO_METASERVICE); } return application != null ? application.getInstances() : Collections.emptyList(); } public List getAdminServiceInstances() { Application application = eurekaClient.getApplication(ServiceNameConsts.APOLLO_ADMINSERVICE); if (application == null) { Tracer.logEvent("Apollo.EurekaDiscovery.NotFound", ServiceNameConsts.APOLLO_ADMINSERVICE); } return application != null ? application.getInstances() : Collections.emptyList(); } } ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/resources/META-INF/app.properties ================================================ app.id=100003171 jdkVersion=1.8 ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/resources/application.yml ================================================ spring: application: name: apollo-configservice profiles: active: ${apollo_profile} ctrip: appid: 100003171 server: port: 8080 logging: level: com.ctrip: INFO ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/resources/bootstrap.yml ================================================ eureka: instance: hostname: ${spring.cloud.client.ipAddress} instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} prefer-ip-address: true server: peerEurekaNodesUpdateIntervalMs: 60000 enableSelfPreservation: false client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:8080/eureka/ healthcheck: enabled: true eurekaServiceUrlPollIntervalSeconds: 60 endpoints: health: sensitive: false management: security: enabled: false health: status: order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/resources/configservice.properties ================================================ #Used for apollo-assembly spring.application.name= apollo-configservice ctrip.appid= 100003171 server.port= 8080 #logging.file= /opt/logs/100003171/apollo-configservice.log apollo_profile=github #192.168.3.150 spring.datasource.url=jdbc:mysql://47.94.252.160:3306/ApolloConfigDB?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false spring.datasource.username=root spring.datasource.password=root #spring.jpa.properties.hibernate.show_sql=true spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/resources/logback.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/scripts/shutdown.sh ================================================ #!/bin/bash SERVICE_NAME=apollo-configservice if [[ -z "$JAVA_HOME" && -d /usr/java/latest/ ]]; then export JAVA_HOME=/usr/java/latest/ fi cd `dirname $0`/.. if [[ ! -f $SERVICE_NAME".jar" && -d current ]]; then cd current fi if [[ -f $SERVICE_NAME".jar" ]]; then chmod a+x $SERVICE_NAME".jar" ./$SERVICE_NAME".jar" stop fi ================================================ FILE: open-config-center/apollo/apollo-configservice/src/main/scripts/startup.sh ================================================ #!/bin/bash SERVICE_NAME=apollo-configservice ## Adjust log dir if necessary LOG_DIR=/opt/logs/100003171 ## Adjust server port if necessary SERVER_PORT=8080 ## Adjust memory settings if necessary #export JAVA_OPTS="-Xms6144m -Xmx6144m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=4096m -XX:MaxNewSize=4096m -XX:SurvivorRatio=8" ## Only uncomment the following when you are using server jvm #export JAVA_OPTS="$JAVA_OPTS -server -XX:-ReduceInitialCardMarks" ########### The following is the same for configservice, adminservice, portal ########### export JAVA_OPTS="$JAVA_OPTS -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom" export JAVA_OPTS="$JAVA_OPTS -Dserver.port=$SERVER_PORT -Dlogging.file=$LOG_DIR/$SERVICE_NAME.log -Xloggc:$LOG_DIR/heap_trace.txt -XX:HeapDumpPath=$LOG_DIR/HeapDumpOnOutOfMemoryError/" PATH_TO_JAR=$SERVICE_NAME".jar" SERVER_URL="http://localhost:$SERVER_PORT" function checkPidAlive { for i in `ls -t $SERVICE_NAME*.pid 2>/dev/null` do read pid < $i result=$(ps -p "$pid") if [ "$?" -eq 0 ]; then return 0 else printf "\npid - $pid just quit unexpectedly, please check logs under $LOG_DIR and /tmp for more information!\n" exit 1; fi done printf "\nNo pid file found, startup may failed. Please check logs under $LOG_DIR and /tmp for more information!\n" exit 1; } if [ "$(uname)" == "Darwin" ]; then windows="0" elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then windows="0" elif [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then windows="1" else windows="0" fi # for Windows if [ "$windows" == "1" ] && [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then tmp_java_home=`cygpath -sw "$JAVA_HOME"` export JAVA_HOME=`cygpath -u $tmp_java_home` echo "Windows new JAVA_HOME is: $JAVA_HOME" fi cd `dirname $0`/.. for i in `ls $SERVICE_NAME-*.jar 2>/dev/null` do if [[ ! $i == *"-sources.jar" ]] then PATH_TO_JAR=$i break fi done if [[ ! -f PATH_TO_JAR && -d current ]]; then cd current for i in `ls $SERVICE_NAME-*.jar 2>/dev/null` do if [[ ! $i == *"-sources.jar" ]] then PATH_TO_JAR=$i break fi done fi if [[ -f $SERVICE_NAME".jar" ]]; then rm -rf $SERVICE_NAME".jar" fi printf "$(date) ==== Starting ==== \n" ln $PATH_TO_JAR $SERVICE_NAME".jar" chmod a+x $SERVICE_NAME".jar" ./$SERVICE_NAME".jar" start rc=$?; if [[ $rc != 0 ]]; then echo "$(date) Failed to start $SERVICE_NAME.jar, return code: $rc" exit $rc; fi declare -i counter=0 declare -i max_counter=48 # 48*5=240s declare -i total_time=0 printf "Waiting for server startup" until [[ (( counter -ge max_counter )) || "$(curl -X GET --silent --connect-timeout 1 --max-time 2 --head $SERVER_URL | grep "Coyote")" != "" ]]; do printf "." counter+=1 sleep 5 checkPidAlive done total_time=counter*5 if [[ (( counter -ge max_counter )) ]]; then printf "\n$(date) Server failed to start in $total_time seconds!\n" exit 1; fi printf "\n$(date) Server started in $total_time seconds!\n" exit 0; ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/application.properties ================================================ spring.datasource.url = jdbc:h2:mem:~/apolloconfigdb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy spring.h2.console.enabled = true spring.h2.console.settings.web-allow-others=true spring.jpa.properties.hibernate.show_sql=true # for ReleaseMessageScanner test apollo.message-scan.interval=100 ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/application.yml ================================================ spring: application: name: apollo-configservice server: port: ${port:8080} logging: level: org.springframework.cloud: 'DEBUG' file: /opt/logs/${ctrip.appid}/apollo-configservice.log ctrip: appid: 100003171 ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/bootstrap.yml ================================================ eureka: instance: hostname: ${hostname:localhost} preferIpAddress: true client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:8080/eureka/ healthcheck: enabled: true endpoints: health: sensitive: false management: security: enabled: false health: status: order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/data.sql ================================================ INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003171','apollo-config-service','刘一鸣','liuym@ctrip.com'); INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003172','apollo-admin-service','宋顺','song_s@ctrip.com'); INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('100003173','apollo-portal','张乐','zhanglea@ctrip.com'); INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('fxhermesproducer','fx-hermes-producer','梁锦华','jhliang@ctrip.com'); INSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('100003171', 'cluster1'); INSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('100003172', 'cluster2'); INSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('100003173', 'cluster3'); INSERT INTO Cluster (AppId, Name) VALUES ('fxhermesproducer', 'default'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'application'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003171', 'fx.apollo.config'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'application'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003172', 'fx.apollo.admin'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'application'); INSERT INTO AppNamespace (AppId, Name) VALUES ('100003173', 'fx.apollo.portal'); INSERT INTO AppNamespace (AppID, Name) VALUES ('fxhermesproducer', 'fx.hermes.producer'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (1, '100003171', 'default', 'application'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (2, 'fxhermesproducer', 'default', 'fx.hermes.producer'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (3, '100003172', 'default', 'application'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (4, '100003173', 'default', 'application'); INSERT INTO Namespace (Id, AppId, ClusterName, NamespaceName) VALUES (5, '100003171', 'default', 'application'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k1', 'v1', 'comment1'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (1, 'k2', 'v2', 'comment2'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (2, 'k3', 'v3', 'comment3'); INSERT INTO Item (NamespaceId, `Key`, Value, Comment) VALUES (5, 'k3', 'v4', 'comment4'); INSERT INTO RELEASE (ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES ('TEST-RELEASE-KEY', 'REV1','First Release','100003171', 'default', 'application', '{"k1":"v1"}'); ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/cleanup.sql ================================================ DELETE FROM Release; DELETE FROM Namespace; DELETE FROM AppNamespace; DELETE FROM Cluster; DELETE FROM App; DELETE FROM ReleaseMessage; DELETE FROM GrayReleaseRule; ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-gray-release.sql ================================================ INSERT INTO GrayReleaseRule (`Id`, `AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`) VALUES (1, 'someAppId', 'default', 'application', 'gray-branch-1', '[{"clientAppId":"someAppId","clientIpList":["1.1.1.1"]}]', 986, 1); INSERT INTO GrayReleaseRule (`Id`, `AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `Rules`, `ReleaseId`, `BranchStatus`) VALUES (2, 'somePublicAppId', 'default', 'somePublicNamespace', 'gray-branch-2', '[{"clientAppId":"someAppId","clientIpList":["1.1.1.1"]}]', 985, 1); ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release-message.sql ================================================ INSERT INTO `releasemessage` (`Id`, `Message`) VALUES (10, 'someAppId+default+application'); INSERT INTO `releasemessage` (`Id`, `Message`) VALUES (20, 'somePublicAppId+default+somePublicNamespace'); ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release-public-dc-override.sql ================================================ INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (995, 'TEST-RELEASE-KEY6', 'INTEGRATION-TEST-DEFAULT-OVERRIDE-PUBLIC-DC','First Release','someAppId', 'someDC', 'somePublicNamespace', '{"k1":"override-someDC-v1"}'); ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release-public-default-override.sql ================================================ INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (994, 'TEST-RELEASE-KEY5', 'INTEGRATION-TEST-DEFAULT-OVERRIDE-PUBLIC','First Release','someAppId', 'default', 'somePublicNamespace', '{"k1":"override-v1"}'); ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/integration-test/test-release.sql ================================================ INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('someAppId','someAppName','someOwnerName','someOwnerName@ctrip.com'); INSERT INTO App (AppId, Name, OwnerName, OwnerEmail) VALUES ('somePublicAppId','somePublicAppName','someOwnerName','someOwnerName@ctrip.com'); INSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'someCluster'); INSERT INTO Cluster (AppId, Name) VALUES ('somePublicAppId', 'default'); INSERT INTO Cluster (AppId, Name) VALUES ('somePublicAppId', 'someDC'); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'application', false); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'someNamespace', true); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'someNamespace.xml', false); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('someAppId', 'anotherNamespace', false); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('somePublicAppId', 'application', false); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('somePublicAppId', 'somePublicNamespace', true); INSERT INTO AppNamespace (AppId, Name, IsPublic) VALUES ('somePublicAppId', 'anotherNamespace', true); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'application'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'someNamespace.xml'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'anotherNamespace'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'someCluster', 'someNamespace'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('somePublicAppId', 'default', 'application'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('somePublicAppId', 'someDC', 'somePublicNamespace'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('someAppId', 'default', 'somePublicNamespace'); INSERT INTO Namespace (AppId, ClusterName, NamespaceName) VALUES ('somePublicAppId', 'default', 'anotherNamespace'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (990, 'TEST-RELEASE-KEY1', 'INTEGRATION-TEST-DEFAULT','First Release','someAppId', 'default', 'application', '{"k1":"v1"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (991, 'TEST-RELEASE-KEY2', 'INTEGRATION-TEST-NAMESPACE','First Release','someAppId', 'someCluster', 'someNamespace', '{"k2":"v2"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (992, 'TEST-RELEASE-KEY3', 'INTEGRATION-TEST-PUBLIC-DEFAULT','First Release','somePublicAppId', 'default', 'somePublicNamespace', '{"k1":"default-v1", "k2":"default-v2"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (993, 'TEST-RELEASE-KEY4', 'INTEGRATION-TEST-PUBLIC-NAMESPACE','First Release','somePublicAppId', 'someDC', 'somePublicNamespace', '{"k1":"someDC-v1", "k2":"someDC-v2"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (989, 'TEST-RELEASE-KEY5', 'INTEGRATION-TEST-PRIVATE-CONFIG-FILE','First Release','someAppId', 'default', 'someNamespace.xml', '{"k1":"v1-file", "k2":"v2-file"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (988, 'TEST-RELEASE-KEY6', 'INTEGRATION-TEST-PRIVATE-CONFIG-FILE','First Release','someAppId', 'default', 'anotherNamespace', '{"k1":"v1-file"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (987, 'TEST-RELEASE-KEY7', 'INTEGRATION-TEST-PUBLIC-CONFIG-FILE','First Release','somePublicAppId', 'default', 'anotherNamespace', '{"k2":"v2-file"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (986, 'TEST-GRAY-RELEASE-KEY1', 'INTEGRATION-TEST-DEFAULT','Gray Release','someAppId', 'gray-branch-1', 'application', '{"k1":"v1-gray"}'); INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, NamespaceName, Configurations) VALUES (985, 'TEST-GRAY-RELEASE-KEY2', 'INTEGRATION-TEST-NAMESPACE','Gray Release','somePublicAppId', 'gray-branch-2', 'somePublicNamespace', '{"k1":"gray-v1", "k2":"gray-v2"}'); ================================================ FILE: open-config-center/apollo/apollo-configservice/src/test/resources/logback-test.xml ================================================ utf-8 [%p] %c - %m%n ================================================ FILE: open-config-center/apollo/apollo-core/pom.xml ================================================ com.ctrip.framework.apollo apollo 0.10.0-SNAPSHOT 4.0.0 apollo-core Apollo Core jar 1.7 ${project.artifactId} com.google.code.gson gson com.google.guava guava org.slf4j slf4j-api org.apache.logging.log4j log4j-slf4j-impl test org.apache.logging.log4j log4j-core test ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/Apollo.java ================================================ package com.ctrip.framework.apollo; /** * @author Jason Song(song_s@ctrip.com) */ public class Apollo { public final static String VERSION = "java-" + Apollo.class.getPackage().getImplementationVersion(); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ConfigConsts.java ================================================ package com.ctrip.framework.apollo.core; public interface ConfigConsts { String NAMESPACE_APPLICATION = "application"; String CLUSTER_NAME_DEFAULT = "default"; String CLUSTER_NAMESPACE_SEPARATOR = "+"; String APOLLO_CLUSTER_KEY = "apollo.cluster"; String CONFIG_FILE_CONTENT_KEY = "content"; String NO_APPID_PLACEHOLDER = "ApolloNoAppIdPlaceHolder"; long NOTIFICATION_ID_PLACEHOLDER = -1; } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/MetaDomainConsts.java ================================================ package com.ctrip.framework.apollo.core; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.ResourceUtils; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * The meta domain will load the meta server from System environment first, if not exist, will load * from apollo-env.properties. If neither exists, will load the default meta url. * * Currently, apollo supports local/dev/fat/uat/lpt/pro environments. */ public class MetaDomainConsts { private static Map domains = new HashMap<>(); public static final String DEFAULT_META_URL = "http://config.local"; static { Properties prop = new Properties(); prop = ResourceUtils.readConfigFile("apollo-env.properties", prop); Properties env = System.getProperties(); domains.put(Env.LOCAL, env.getProperty("local_meta", prop.getProperty("local.meta", DEFAULT_META_URL))); domains.put(Env.DEV, env.getProperty("dev_meta", prop.getProperty("dev.meta", DEFAULT_META_URL))); domains.put(Env.FAT, env.getProperty("fat_meta", prop.getProperty("fat.meta", DEFAULT_META_URL))); domains.put(Env.UAT, env.getProperty("uat_meta", prop.getProperty("uat.meta", DEFAULT_META_URL))); domains.put(Env.LPT, env.getProperty("lpt_meta", prop.getProperty("lpt.meta", DEFAULT_META_URL))); domains.put(Env.PRO, env.getProperty("pro_meta", prop.getProperty("pro.meta", DEFAULT_META_URL))); } public static String getDomain(Env env) { return String.valueOf(domains.get(env)); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/ServiceNameConsts.java ================================================ package com.ctrip.framework.apollo.core; public interface ServiceNameConsts { String APOLLO_METASERVICE = "apollo-metaservice"; String APOLLO_CONFIGSERVICE = "apollo-configservice"; String APOLLO_ADMINSERVICE = "apollo-adminservice"; String APOLLO_PORTAL = "apollo-portal"; } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ApolloConfig.java ================================================ package com.ctrip.framework.apollo.core.dto; import java.util.Map; /** * @author Jason Song(song_s@ctrip.com) */ public class ApolloConfig { private String appId; private String cluster; private String namespaceName; private Map configurations; private String releaseKey; public ApolloConfig() { } public ApolloConfig(String appId, String cluster, String namespaceName, String releaseKey) { this.appId = appId; this.cluster = cluster; this.namespaceName = namespaceName; this.releaseKey = releaseKey; } public String getAppId() { return appId; } public String getCluster() { return cluster; } public String getNamespaceName() { return namespaceName; } public String getReleaseKey() { return releaseKey; } public Map getConfigurations() { return configurations; } public void setAppId(String appId) { this.appId = appId; } public void setCluster(String cluster) { this.cluster = cluster; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public void setReleaseKey(String releaseKey) { this.releaseKey = releaseKey; } public void setConfigurations(Map configurations) { this.configurations = configurations; } @Override public String toString() { final StringBuilder sb = new StringBuilder("ApolloConfig{"); sb.append("appId='").append(appId).append('\''); sb.append(", cluster='").append(cluster).append('\''); sb.append(", namespaceName='").append(namespaceName).append('\''); sb.append(", configurations=").append(configurations); sb.append(", releaseKey='").append(releaseKey).append('\''); sb.append('}'); return sb.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ApolloConfigNotification.java ================================================ package com.ctrip.framework.apollo.core.dto; /** * @author Jason Song(song_s@ctrip.com) */ public class ApolloConfigNotification { private String namespaceName; private long notificationId; private volatile ApolloNotificationMessages messages; //for json converter public ApolloConfigNotification() { } public ApolloConfigNotification(String namespaceName, long notificationId) { this.namespaceName = namespaceName; this.notificationId = notificationId; } public String getNamespaceName() { return namespaceName; } public long getNotificationId() { return notificationId; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public ApolloNotificationMessages getMessages() { return messages; } public void setMessages(ApolloNotificationMessages messages) { this.messages = messages; } public void addMessage(String key, long notificationId) { if (this.messages == null) { synchronized (this) { if (this.messages == null) { this.messages = new ApolloNotificationMessages(); } } } this.messages.put(key, notificationId); } @Override public String toString() { return "ApolloConfigNotification{" + "namespaceName='" + namespaceName + '\'' + ", notificationId=" + notificationId + '}'; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ApolloNotificationMessages.java ================================================ package com.ctrip.framework.apollo.core.dto; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import java.util.Map; /** * @author Jason Song(song_s@ctrip.com) */ public class ApolloNotificationMessages { private Map details; public ApolloNotificationMessages() { this(Maps.newHashMap()); } private ApolloNotificationMessages(Map details) { this.details = details; } public void put(String key, long notificationId) { details.put(key, notificationId); } public Long get(String key) { return this.details.get(key); } public boolean has(String key) { return this.details.containsKey(key); } public boolean isEmpty() { return this.details.isEmpty(); } public Map getDetails() { return details; } public void setDetails(Map details) { this.details = details; } public void mergeFrom(ApolloNotificationMessages source) { if (source == null) { return; } for (Map.Entry entry : source.getDetails().entrySet()) { //to make sure the notification id always grows bigger if (this.has(entry.getKey()) && this.get(entry.getKey()) >= entry.getValue()) { continue; } this.put(entry.getKey(), entry.getValue()); } } public ApolloNotificationMessages clone() { return new ApolloNotificationMessages(ImmutableMap.copyOf(this.details)); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/ServiceDTO.java ================================================ package com.ctrip.framework.apollo.core.dto; public class ServiceDTO { private String appName; private String instanceId; private String homepageUrl; public String getAppName() { return appName; } public String getHomepageUrl() { return homepageUrl; } public String getInstanceId() { return instanceId; } public void setAppName(String appName) { this.appName = appName; } public void setHomepageUrl(String homepageUrl) { this.homepageUrl = homepageUrl; } public void setInstanceId(String instanceId) { this.instanceId = instanceId; } @Override public String toString() { final StringBuilder sb = new StringBuilder("ServiceDTO{"); sb.append("appName='").append(appName).append('\''); sb.append(", instanceId='").append(instanceId).append('\''); sb.append(", homepageUrl='").append(homepageUrl).append('\''); sb.append('}'); return sb.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/ConfigFileFormat.java ================================================ package com.ctrip.framework.apollo.core.enums; import com.ctrip.framework.apollo.core.utils.StringUtils; /** * @author Jason Song(song_s@ctrip.com) */ public enum ConfigFileFormat { Properties("properties"), XML("xml"), JSON("json"), YML("yml"), YAML("yaml"); private String value; ConfigFileFormat(String value) { this.value = value; } public String getValue() { return value; } public static ConfigFileFormat fromString(String value) { if (StringUtils.isEmpty(value)) { throw new IllegalArgumentException("value can not be empty"); } switch (value) { case "properties": return Properties; case "xml": return XML; case "json": return JSON; case "yml": return YML; case "yaml": return YAML; } throw new IllegalArgumentException(value + " can not map enum"); } public static boolean isValidFormat(String value) { try { fromString(value); return true; } catch (IllegalArgumentException e) { return false; } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/Env.java ================================================ package com.ctrip.framework.apollo.core.enums; import com.google.common.base.Preconditions; /** * @author Jason Song(song_s@ctrip.com) */ public enum Env{ LOCAL, DEV, FWS, FAT, UAT, LPT, PRO, TOOLS; public static Env fromString(String env) { Env environment = EnvUtils.transformEnv(env); Preconditions.checkArgument(environment != null, String.format("Env %s is invalid", env)); return environment; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/EnvUtils.java ================================================ package com.ctrip.framework.apollo.core.enums; import com.ctrip.framework.apollo.core.utils.StringUtils; public final class EnvUtils { public static Env transformEnv(String envName) { if (StringUtils.isBlank(envName)) { return null; } switch (envName.trim().toUpperCase()) { case "LPT": return Env.LPT; case "FAT": case "FWS": return Env.FAT; case "UAT": return Env.UAT; case "PRO": case "PROD": //just in case return Env.PRO; case "DEV": return Env.DEV; case "LOCAL": return Env.LOCAL; case "TOOLS": return Env.TOOLS; default: return null; } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/schedule/ExponentialSchedulePolicy.java ================================================ package com.ctrip.framework.apollo.core.schedule; /** * @author Jason Song(song_s@ctrip.com) */ public class ExponentialSchedulePolicy implements SchedulePolicy { private final long delayTimeLowerBound; private final long delayTimeUpperBound; private long lastDelayTime; public ExponentialSchedulePolicy(long delayTimeLowerBound, long delayTimeUpperBound) { this.delayTimeLowerBound = delayTimeLowerBound; this.delayTimeUpperBound = delayTimeUpperBound; } @Override public long fail() { long delayTime = lastDelayTime; if (delayTime == 0) { delayTime = delayTimeLowerBound; } else { delayTime = Math.min(lastDelayTime << 1, delayTimeUpperBound); } lastDelayTime = delayTime; return delayTime; } @Override public void success() { lastDelayTime = 0; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/schedule/SchedulePolicy.java ================================================ package com.ctrip.framework.apollo.core.schedule; /** * Schedule policy * @author Jason Song(song_s@ctrip.com) */ public interface SchedulePolicy { long fail(); void success(); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ApolloThreadFactory.java ================================================ package com.ctrip.framework.apollo.core.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; public class ApolloThreadFactory implements ThreadFactory { private static Logger log = LoggerFactory.getLogger(ApolloThreadFactory.class); private final AtomicLong threadNumber = new AtomicLong(1); private final String namePrefix; private final boolean daemon; private static final ThreadGroup threadGroup = new ThreadGroup("Apollo"); public static ThreadGroup getThreadGroup() { return threadGroup; } public static ThreadFactory create(String namePrefix, boolean daemon) { return new ApolloThreadFactory(namePrefix, daemon); } public static boolean waitAllShutdown(int timeoutInMillis) { ThreadGroup group = getThreadGroup(); Thread[] activeThreads = new Thread[group.activeCount()]; group.enumerate(activeThreads); Set alives = new HashSet(Arrays.asList(activeThreads)); Set dies = new HashSet(); log.info("Current ACTIVE thread count is: {}", alives.size()); long expire = System.currentTimeMillis() + timeoutInMillis; while (System.currentTimeMillis() < expire) { classify(alives, dies, new ClassifyStandard() { @Override public boolean satisfy(Thread thread) { return !thread.isAlive() || thread.isInterrupted() || thread.isDaemon(); } }); if (alives.size() > 0) { log.info("Alive apollo threads: {}", alives); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException ex) { // ignore } } else { log.info("All apollo threads are shutdown."); return true; } } log.warn("Some apollo threads are still alive but expire time has reached, alive threads: {}", alives); return false; } private static interface ClassifyStandard { boolean satisfy(T thread); } private static void classify(Set src, Set des, ClassifyStandard standard) { Set set = new HashSet<>(); for (T t : src) { if (standard.satisfy(t)) { set.add(t); } } src.removeAll(set); des.addAll(set); } private ApolloThreadFactory(String namePrefix, boolean daemon) { this.namePrefix = namePrefix; this.daemon = daemon; } public Thread newThread(Runnable runnable) { Thread thread = new Thread(threadGroup, runnable,// threadGroup.getName() + "-" + namePrefix + "-" + threadNumber.getAndIncrement()); thread.setDaemon(daemon); if (thread.getPriority() != Thread.NORM_PRIORITY) { thread.setPriority(Thread.NORM_PRIORITY); } return thread; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ByteUtil.java ================================================ package com.ctrip.framework.apollo.core.utils; /** * @author Jason Song(song_s@ctrip.com) */ public class ByteUtil { private static final char[] HEX_CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static byte int3(final int x) { return (byte) (x >> 24); } public static byte int2(final int x) { return (byte) (x >> 16); } public static byte int1(final int x) { return (byte) (x >> 8); } public static byte int0(final int x) { return (byte) (x); } public static String toHexString(byte[] bytes) { char[] chars = new char[bytes.length * 2]; int i = 0; for (byte b : bytes) { chars[i++] = HEX_CHARS[b >> 4 & 0xF]; chars[i++] = HEX_CHARS[b & 0xF]; } return new String(chars); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ClassLoaderUtil.java ================================================ package com.ctrip.framework.apollo.core.utils; import com.google.common.base.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URL; import java.net.URLDecoder; /** * @author Jason Song(song_s@ctrip.com) */ public class ClassLoaderUtil { private static final Logger logger = LoggerFactory.getLogger(ClassLoaderUtil.class); private static ClassLoader loader = Thread.currentThread().getContextClassLoader(); private static String classPath = ""; static { if (loader == null) { logger.warn("Using system class loader"); loader = ClassLoader.getSystemClassLoader(); } try { URL url = loader.getResource(""); // get class path if (url != null) { classPath = url.getPath(); classPath = URLDecoder.decode(classPath, "utf-8"); } // 如果是jar包内的,则返回当前路径 if (Strings.isNullOrEmpty(classPath) || classPath.contains(".jar!")) { classPath = System.getProperty("user.dir"); } } catch (Throwable ex) { classPath = System.getProperty("user.dir"); logger.warn("Failed to locate class path, fallback to user.dir: {}", classPath, ex); } } public static ClassLoader getLoader() { return loader; } public static String getClassPath() { return classPath; } public static boolean isClassPresent(String className) { try { Class.forName(className); return true; } catch (ClassNotFoundException ex) { return false; } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/DNSUtil.java ================================================ package com.ctrip.framework.apollo.core.utils; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; public class DNSUtil { public static List resolve(String domainName) throws UnknownHostException { List result = new ArrayList(); InetAddress[] addresses = InetAddress.getAllByName(domainName); if (addresses != null) { for (InetAddress addr : addresses) { result.add(addr.getHostAddress()); } } return result; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/MachineUtil.java ================================================ package com.ctrip.framework.apollo.core.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.NetworkInterface; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.security.SecureRandom; import java.util.Enumeration; /** * @author Jason Song(song_s@ctrip.com) */ public class MachineUtil { private static final Logger logger = LoggerFactory.getLogger(MachineUtil.class); private static final int MACHINE_IDENTIFIER = createMachineIdentifier(); public static int getMachineIdentifier() { return MACHINE_IDENTIFIER; } /** * Get the machine identifier from mac address * * @see ObjectId.java */ private static int createMachineIdentifier() { // build a 2-byte machine piece based on NICs info int machinePiece; try { StringBuilder sb = new StringBuilder(); Enumeration e = NetworkInterface.getNetworkInterfaces(); if (e != null){ while (e.hasMoreElements()) { NetworkInterface ni = e.nextElement(); sb.append(ni.toString()); byte[] mac = ni.getHardwareAddress(); if (mac != null) { ByteBuffer bb = ByteBuffer.wrap(mac); try { sb.append(bb.getChar()); sb.append(bb.getChar()); sb.append(bb.getChar()); } catch (BufferUnderflowException shortHardwareAddressException) { //NOPMD // mac with less than 6 bytes. continue } } } } machinePiece = sb.toString().hashCode(); } catch (Throwable ex) { // exception sometimes happens with IBM JVM, use random machinePiece = (new SecureRandom().nextInt()); logger.warn( "Failed to get machine identifier from network interface, using random number instead", ex); } return machinePiece; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/PropertiesUtil.java ================================================ package com.ctrip.framework.apollo.core.utils; import java.io.IOException; import java.io.StringWriter; import java.util.Properties; /** * @author Jason Song(song_s@ctrip.com) */ public class PropertiesUtil { /** * Transform the properties to string format * @param properties the properties object * @return the string containing the properties * @throws IOException */ public static String toString(Properties properties) throws IOException { StringWriter writer = new StringWriter(); properties.store(writer, null); StringBuffer stringBuffer = writer.getBuffer(); filterPropertiesComment(stringBuffer); return stringBuffer.toString(); } /** * filter out the first comment line * @param stringBuffer the string buffer * @return true if filtered successfully, false otherwise */ static boolean filterPropertiesComment(StringBuffer stringBuffer) { //check whether has comment in the first line if (stringBuffer.charAt(0) != '#') { return false; } int commentLineIndex = stringBuffer.indexOf("\n"); if (commentLineIndex == -1) { return false; } stringBuffer.delete(0, commentLineIndex + 1); return true; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/ResourceUtils.java ================================================ package com.ctrip.framework.apollo.core.utils; import java.net.URL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.FileNotFoundException; import java.nio.file.Paths; import java.util.Properties; public class ResourceUtils { private static final Logger logger = LoggerFactory.getLogger(ResourceUtils.class); private static final String[] DEFAULT_FILE_SEARCH_LOCATIONS = new String[]{"./config/", "./"}; @SuppressWarnings("unchecked") public static Properties readConfigFile(String configPath, Properties defaults) { Properties props = new Properties(); if (defaults != null) { props.putAll(defaults); } InputStream in = loadConfigFileFromDefaultSearchLocations(configPath); try { if (in != null) { props.load(in); } } catch (IOException ex) { logger.warn("Reading config failed: {}", ex.getMessage()); } finally { if (in != null) { try { in.close(); } catch (IOException ex) { logger.warn("Close config failed: {}", ex.getMessage()); } } } if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); for (String propertyName : props.stringPropertyNames()) { sb.append(propertyName).append('=').append(props.getProperty(propertyName)).append('\n'); } if (sb.length() > 0) { logger.debug("Reading properties: \n" + sb.toString()); } else { logger.warn("No available properties"); } } return props; } private static InputStream loadConfigFileFromDefaultSearchLocations(String configPath) { try { // load from default search locations for (String searchLocation : DEFAULT_FILE_SEARCH_LOCATIONS) { File candidate = Paths.get(searchLocation, configPath).toFile(); if (candidate.exists() && candidate.isFile() && candidate.canRead()) { logger.debug("Reading config from resource {}", candidate.getAbsolutePath()); return new FileInputStream(candidate); } } // load from classpath URL url = ClassLoaderUtil.getLoader().getResource(configPath); if (url != null) { InputStream in = getResourceAsStream(url); if (in != null) { logger.debug("Reading config from resource {}", url.getPath()); return in; } } // load outside resource under current user path File candidate = new File(System.getProperty("user.dir"), configPath); if (candidate.exists() && candidate.isFile() && candidate.canRead()) { logger.debug("Reading config from resource {}", candidate.getAbsolutePath()); return new FileInputStream(candidate); } } catch (FileNotFoundException e) { //ignore } return null; } private static InputStream getResourceAsStream(URL url) { try { return url != null ? url.openStream() : null; } catch (IOException e) { return null; } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/StringUtils.java ================================================ package com.ctrip.framework.apollo.core.utils; import java.util.Collection; import java.util.Iterator; public class StringUtils { public static final String EMPTY = ""; /** *

* Checks if a String is empty ("") or null. *

* *
   * StringUtils.isEmpty(null)      = true
   * StringUtils.isEmpty("")        = true
   * StringUtils.isEmpty(" ")       = false
   * StringUtils.isEmpty("bob")     = false
   * StringUtils.isEmpty("  bob  ") = false
   * 
* *

* NOTE: This method changed in Lang version 2.0. It no longer trims the String. That functionality is available in isBlank(). *

* * @param str the String to check, may be null * @return true if the String is empty or null */ public static boolean isEmpty(String str) { return str == null || str.length() == 0; } public static boolean isContainEmpty(String... args){ if (args == null){ return false; } for (String arg: args){ if (arg == null || "".equals(arg)){ return true; } } return false; } /** *

* Checks if a String is whitespace, empty ("") or null. *

* *
   * StringUtils.isBlank(null)      = true
   * StringUtils.isBlank("")        = true
   * StringUtils.isBlank(" ")       = true
   * StringUtils.isBlank("bob")     = false
   * StringUtils.isBlank("  bob  ") = false
   * 
* * @param str the String to check, may be null * @return true if the String is null, empty or whitespace */ public static boolean isBlank(String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if (Character.isWhitespace(str.charAt(i)) == false) { return false; } } return true; } /** *

* Removes control characters (char <= 32) from both ends of this String returning null if the String is empty * ("") after the trim or if it is null. * *

* The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use * {@link #stripToNull(String)}. *

* *
   * StringUtils.trimToNull(null)          = null
   * StringUtils.trimToNull("")            = null
   * StringUtils.trimToNull("     ")       = null
   * StringUtils.trimToNull("abc")         = "abc"
   * StringUtils.trimToNull("    abc    ") = "abc"
   * 
* * @param str the String to be trimmed, may be null * @return the trimmed String, null if only chars <= 32, empty or null String input * @since 2.0 */ public static String trimToNull(String str) { String ts = trim(str); return isEmpty(ts) ? null : ts; } /** *

* Removes control characters (char <= 32) from both ends of this String returning an empty String ("") if the String is empty * ("") after the trim or if it is null. * *

* The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use * {@link #stripToEmpty(String)}. *

* *
   * StringUtils.trimToEmpty(null)          = ""
   * StringUtils.trimToEmpty("")            = ""
   * StringUtils.trimToEmpty("     ")       = ""
   * StringUtils.trimToEmpty("abc")         = "abc"
   * StringUtils.trimToEmpty("    abc    ") = "abc"
   * 
* * @param str the String to be trimmed, may be null * @return the trimmed String, or an empty String if null input * @since 2.0 */ public static String trimToEmpty(String str) { return str == null ? EMPTY : str.trim(); } /** *

* Removes control characters (char <= 32) from both ends of this String, handling null by returning * null. *

* *

* The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use * {@link #strip(String)}. *

* *

* To trim your choice of characters, use the {@link #strip(String, String)} methods. *

* *
   * StringUtils.trim(null)          = null
   * StringUtils.trim("")            = ""
   * StringUtils.trim("     ")       = ""
   * StringUtils.trim("abc")         = "abc"
   * StringUtils.trim("    abc    ") = "abc"
   * 
* * @param str the String to be trimmed, may be null * @return the trimmed string, null if null String input */ public static String trim(String str) { return str == null ? null : str.trim(); } /** *

* Compares two Strings, returning true if they are equal. *

* *

* nulls are handled without exceptions. Two null references are considered to be equal. The comparison * is case sensitive. *

* *
   * StringUtils.equals(null, null)   = true
   * StringUtils.equals(null, "abc")  = false
   * StringUtils.equals("abc", null)  = false
   * StringUtils.equals("abc", "abc") = true
   * StringUtils.equals("abc", "ABC") = false
   * 
* * @param str1 the first String, may be null * @param str2 the second String, may be null * @return true if the Strings are equal, case sensitive, or both null * @see java.lang.String#equals(Object) */ public static boolean equals(String str1, String str2) { return str1 == null ? str2 == null : str1.equals(str2); } /** *

* Compares two Strings, returning true if they are equal ignoring the case. *

* *

* nulls are handled without exceptions. Two null references are considered equal. Comparison is case * insensitive. *

* *
   * StringUtils.equalsIgnoreCase(null, null)   = true
   * StringUtils.equalsIgnoreCase(null, "abc")  = false
   * StringUtils.equalsIgnoreCase("abc", null)  = false
   * StringUtils.equalsIgnoreCase("abc", "abc") = true
   * StringUtils.equalsIgnoreCase("abc", "ABC") = true
   * 
* * @param str1 the first String, may be null * @param str2 the second String, may be null * @return true if the Strings are equal, case insensitive, or both null * @see java.lang.String#equalsIgnoreCase(String) */ public static boolean equalsIgnoreCase(String str1, String str2) { return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2); } /** *

* Check if a String starts with a specified prefix. *

* *

* nulls are handled without exceptions. Two null references are considered to be equal. The comparison * is case sensitive. *

* *
   * StringUtils.startsWith(null, null)      = true
   * StringUtils.startsWith(null, "abc")     = false
   * StringUtils.startsWith("abcdef", null)  = false
   * StringUtils.startsWith("abcdef", "abc") = true
   * StringUtils.startsWith("ABCDEF", "abc") = false
   * 
* * @param str the String to check, may be null * @param prefix the prefix to find, may be null * @return true if the String starts with the prefix, case sensitive, or both null * @see java.lang.String#startsWith(String) * @since 2.4 */ public static boolean startsWith(String str, String prefix) { return startsWith(str, prefix, false); } /** *

* Check if a String starts with a specified prefix (optionally case insensitive). *

* * @param str the String to check, may be null * @param prefix the prefix to find, may be null * @param ignoreCase inidicates whether the compare should ignore case (case insensitive) or not. * @return true if the String starts with the prefix or both null * @see java.lang.String#startsWith(String) */ private static boolean startsWith(String str, String prefix, boolean ignoreCase) { if (str == null || prefix == null) { return str == null && prefix == null; } if (prefix.length() > str.length()) { return false; } return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length()); } /** *

* Case insensitive check if a String starts with a specified prefix. *

* *

* nulls are handled without exceptions. Two null references are considered to be equal. The comparison * is case insensitive. *

* *
   * StringUtils.startsWithIgnoreCase(null, null)      = true
   * StringUtils.startsWithIgnoreCase(null, "abc")     = false
   * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
   * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
   * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
   * 
* * @param str the String to check, may be null * @param prefix the prefix to find, may be null * @return true if the String starts with the prefix, case insensitive, or both null * @see java.lang.String#startsWith(String) * @since 2.4 */ public static boolean startsWithIgnoreCase(String str, String prefix) { return startsWith(str, prefix, true); } /** *

* Checks if the String contains only unicode digits. A decimal point is not a unicode digit and returns false. *

* *

* null will return false. An empty String (length()=0) will return true. *

* *
   * StringUtils.isNumeric(null)   = false
   * StringUtils.isNumeric("")     = true
   * StringUtils.isNumeric("  ")   = false
   * StringUtils.isNumeric("123")  = true
   * StringUtils.isNumeric("12 3") = false
   * StringUtils.isNumeric("ab2c") = false
   * StringUtils.isNumeric("12-3") = false
   * StringUtils.isNumeric("12.3") = false
   * 
* * @param str the String to check, may be null * @return true if only contains digits, and is non-null */ public static boolean isNumeric(String str) { if (str == null) { return false; } int sz = str.length(); for (int i = 0; i < sz; i++) { if (Character.isDigit(str.charAt(i)) == false) { return false; } } return true; } public static interface StringFormatter { String format(T obj); } public static String join(Collection collection, String separator) { return join(collection, separator, new StringFormatter() { @Override public String format(T obj) { return obj.toString(); } }); } public static String join(Collection collection, String separator, StringFormatter formatter) { Iterator iterator = collection.iterator(); // handle null, zero and one elements before building a buffer if (iterator == null) { return null; } if (!iterator.hasNext()) { return EMPTY; } T first = iterator.next(); if (!iterator.hasNext()) { return first == null ? "" : formatter.format(first); } // two or more elements StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small if (first != null) { buf.append(formatter.format(first)); } while (iterator.hasNext()) { buf.append(separator); T obj = iterator.next(); if (obj != null) { buf.append(formatter.format(obj)); } } return buf.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/Tracer.java ================================================ package com.ctrip.framework.apollo.tracer; import com.ctrip.framework.apollo.tracer.internals.NullMessageProducerManager; import com.ctrip.framework.apollo.tracer.spi.MessageProducer; import com.ctrip.framework.apollo.tracer.spi.MessageProducerManager; import com.ctrip.framework.apollo.tracer.spi.Transaction; import com.ctrip.framework.foundation.internals.ServiceBootstrap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Jason Song(song_s@ctrip.com) */ public abstract class Tracer { private static final Logger logger = LoggerFactory.getLogger(Tracer.class); private static final MessageProducerManager NULL_MESSAGE_PRODUCER_MANAGER = new NullMessageProducerManager(); private static volatile MessageProducerManager producerManager; private static Object lock = new Object(); static { getProducer(); } private static MessageProducer getProducer() { try { if (producerManager == null) { synchronized (lock) { if (producerManager == null) { producerManager = ServiceBootstrap.loadFirst(MessageProducerManager.class); } } } } catch (Throwable ex) { logger.error( "Failed to initialize message producer manager, use null message producer manager.", ex); producerManager = NULL_MESSAGE_PRODUCER_MANAGER; } return producerManager.getProducer(); } public static void logError(String message, Throwable cause) { try { getProducer().logError(message, cause); } catch (Throwable ex) { logger.warn("Failed to log error for message: {}, cause: {}", message, cause, ex); } } public static void logError(Throwable cause) { try { getProducer().logError(cause); } catch (Throwable ex) { logger.warn("Failed to log error for cause: {}", cause, ex); } } public static void logEvent(String type, String name) { try { getProducer().logEvent(type, name); } catch (Throwable ex) { logger.warn("Failed to log event for type: {}, name: {}", type, name, ex); } } public static void logEvent(String type, String name, String status, String nameValuePairs) { try { getProducer().logEvent(type, name, status, nameValuePairs); } catch (Throwable ex) { logger.warn("Failed to log event for type: {}, name: {}, status: {}, nameValuePairs: {}", type, name, status, nameValuePairs, ex); } } public static Transaction newTransaction(String type, String name) { try { return getProducer().newTransaction(type, name); } catch (Throwable ex) { logger.warn("Failed to create transaction for type: {}, name: {}", type, name, ex); return NULL_MESSAGE_PRODUCER_MANAGER.getProducer().newTransaction(type, name); } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/DefaultMessageProducerManager.java ================================================ package com.ctrip.framework.apollo.tracer.internals; import com.ctrip.framework.apollo.core.utils.ClassLoaderUtil; import com.ctrip.framework.apollo.tracer.internals.cat.CatMessageProducer; import com.ctrip.framework.apollo.tracer.internals.cat.CatNames; import com.ctrip.framework.apollo.tracer.spi.MessageProducer; import com.ctrip.framework.apollo.tracer.spi.MessageProducerManager; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultMessageProducerManager implements MessageProducerManager { private static MessageProducer producer; public DefaultMessageProducerManager() { if (ClassLoaderUtil.isClassPresent(CatNames.CAT_CLASS)) { producer = new CatMessageProducer(); } else { producer = new NullMessageProducerManager().getProducer(); } } @Override public MessageProducer getProducer() { return producer; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/NullMessageProducer.java ================================================ package com.ctrip.framework.apollo.tracer.internals; import com.ctrip.framework.apollo.tracer.spi.MessageProducer; import com.ctrip.framework.apollo.tracer.spi.Transaction; /** * @author Jason Song(song_s@ctrip.com) */ public class NullMessageProducer implements MessageProducer { private static final Transaction NULL_TRANSACTION = new NullTransaction(); @Override public void logError(Throwable cause) { } @Override public void logError(String message, Throwable cause) { } @Override public void logEvent(String type, String name) { } @Override public void logEvent(String type, String name, String status, String nameValuePairs) { } @Override public Transaction newTransaction(String type, String name) { return NULL_TRANSACTION; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/NullMessageProducerManager.java ================================================ package com.ctrip.framework.apollo.tracer.internals; import com.ctrip.framework.apollo.tracer.spi.MessageProducer; import com.ctrip.framework.apollo.tracer.spi.MessageProducerManager; /** * @author Jason Song(song_s@ctrip.com) */ public class NullMessageProducerManager implements MessageProducerManager { private static final MessageProducer producer = new NullMessageProducer(); @Override public MessageProducer getProducer() { return producer; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/NullTransaction.java ================================================ package com.ctrip.framework.apollo.tracer.internals; import com.ctrip.framework.apollo.tracer.spi.Transaction; /** * @author Jason Song(song_s@ctrip.com) */ public class NullTransaction implements Transaction { @Override public void setStatus(String status) { } @Override public void setStatus(Throwable e) { } @Override public void addData(String key, Object value) { } @Override public void complete() { } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/cat/CatMessageProducer.java ================================================ package com.ctrip.framework.apollo.tracer.internals.cat; import com.ctrip.framework.apollo.tracer.spi.MessageProducer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import java.lang.reflect.Method; /** * @author Jason Song(song_s@ctrip.com) */ public class CatMessageProducer implements MessageProducer { private static Class CAT_CLASS; private static Method LOG_ERROR_WITH_CAUSE; private static Method LOG_ERROR_WITH_MESSAGE_AND_CAUSE; private static Method LOG_EVENT_WITH_TYPE_AND_NAME; private static Method LOG_EVENT_WITH_TYPE_AND_NAME_AND_STATUS_AND_NAME_VALUE_PAIRS; private static Method NEW_TRANSACTION_WITH_TYPE_AND_NAME; static { try { CAT_CLASS = Class.forName(CatNames.CAT_CLASS); LOG_ERROR_WITH_CAUSE = CAT_CLASS.getMethod(CatNames.LOG_ERROR_METHOD, Throwable.class); LOG_ERROR_WITH_MESSAGE_AND_CAUSE = CAT_CLASS.getMethod(CatNames.LOG_ERROR_METHOD, String.class, Throwable.class); LOG_EVENT_WITH_TYPE_AND_NAME = CAT_CLASS.getMethod(CatNames.LOG_EVENT_METHOD, String.class, String.class); LOG_EVENT_WITH_TYPE_AND_NAME_AND_STATUS_AND_NAME_VALUE_PAIRS = CAT_CLASS.getMethod(CatNames.LOG_EVENT_METHOD, String.class, String.class, String.class, String.class); NEW_TRANSACTION_WITH_TYPE_AND_NAME = CAT_CLASS.getMethod( CatNames.NEW_TRANSACTION_METHOD, String.class, String.class); //eager init CatTransaction CatTransaction.init(); } catch (Throwable ex) { throw new IllegalStateException("Initialize Cat message producer failed", ex); } } @Override public void logError(Throwable cause) { try { LOG_ERROR_WITH_CAUSE.invoke(null, cause); } catch (Throwable ex) { throw new IllegalStateException(ex); } } @Override public void logError(String message, Throwable cause) { try { LOG_ERROR_WITH_MESSAGE_AND_CAUSE.invoke(null, message, cause); } catch (Throwable ex) { throw new IllegalStateException(ex); } } @Override public void logEvent(String type, String name) { try { LOG_EVENT_WITH_TYPE_AND_NAME.invoke(null, type, name); } catch (Throwable ex) { throw new IllegalStateException(ex); } } @Override public void logEvent(String type, String name, String status, String nameValuePairs) { try { LOG_EVENT_WITH_TYPE_AND_NAME_AND_STATUS_AND_NAME_VALUE_PAIRS.invoke(null, type, name, status, nameValuePairs); } catch (Throwable ex) { throw new IllegalStateException(ex); } } @Override public Transaction newTransaction(String type, String name) { try { return new CatTransaction(NEW_TRANSACTION_WITH_TYPE_AND_NAME.invoke(null, type, name)); } catch (Throwable ex) { throw new IllegalStateException(ex); } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/cat/CatNames.java ================================================ package com.ctrip.framework.apollo.tracer.internals.cat; /** * @author Jason Song(song_s@ctrip.com) */ public interface CatNames { String CAT_CLASS = "com.dianping.cat.Cat"; String LOG_ERROR_METHOD = "logError"; String LOG_EVENT_METHOD = "logEvent"; String NEW_TRANSACTION_METHOD = "newTransaction"; String CAT_TRANSACTION_CLASS = "com.dianping.cat.message.Transaction"; String SET_STATUS_METHOD = "setStatus"; String ADD_DATA_METHOD = "addData"; String COMPLETE_METHOD = "complete"; } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/internals/cat/CatTransaction.java ================================================ package com.ctrip.framework.apollo.tracer.internals.cat; import com.ctrip.framework.apollo.tracer.spi.Transaction; import java.lang.reflect.Method; /** * @author Jason Song(song_s@ctrip.com) */ public class CatTransaction implements Transaction { private static Class CAT_TRANSACTION_CLASS; private static Method SET_STATUS_WITH_STRING; private static Method SET_STATUS_WITH_THROWABLE; private static Method ADD_DATA_WITH_KEY_AND_VALUE; private static Method COMPLETE; private Object catTransaction; static { try { CAT_TRANSACTION_CLASS = Class.forName(CatNames.CAT_TRANSACTION_CLASS); SET_STATUS_WITH_STRING = CAT_TRANSACTION_CLASS.getMethod(CatNames.SET_STATUS_METHOD, String.class); SET_STATUS_WITH_THROWABLE = CAT_TRANSACTION_CLASS.getMethod(CatNames.SET_STATUS_METHOD, Throwable.class); ADD_DATA_WITH_KEY_AND_VALUE = CAT_TRANSACTION_CLASS.getMethod(CatNames.ADD_DATA_METHOD, String.class, Object.class); COMPLETE = CAT_TRANSACTION_CLASS.getMethod(CatNames.COMPLETE_METHOD); } catch (Throwable ex) { throw new IllegalStateException("Initialize Cat transaction failed", ex); } } static void init() { //do nothing, just to initialize the static variables } public CatTransaction(Object catTransaction) { this.catTransaction = catTransaction; } @Override public void setStatus(String status) { try { SET_STATUS_WITH_STRING.invoke(catTransaction, status); } catch (Throwable ex) { throw new IllegalStateException(ex); } } @Override public void setStatus(Throwable status) { try { SET_STATUS_WITH_THROWABLE.invoke(catTransaction, status); } catch (Throwable ex) { throw new IllegalStateException(ex); } } @Override public void addData(String key, Object value) { try { ADD_DATA_WITH_KEY_AND_VALUE.invoke(catTransaction, key, value); } catch (Throwable ex) { throw new IllegalStateException(ex); } } @Override public void complete() { try { COMPLETE.invoke(catTransaction); } catch (Throwable ex) { throw new IllegalStateException(ex); } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/spi/MessageProducer.java ================================================ package com.ctrip.framework.apollo.tracer.spi; /** * @author Jason Song(song_s@ctrip.com) */ public interface MessageProducer { /** * Log an error. * * @param cause root cause exception */ public void logError(Throwable cause); /** * Log an error. * * @param cause root cause exception */ public void logError(String message, Throwable cause); /** * Log an event in one shot with SUCCESS status. * * @param type event type * @param name event name */ public void logEvent(String type, String name); /** * Log an event in one shot. * * @param type event type * @param name event name * @param status "0" means success, otherwise means error code * @param nameValuePairs name value pairs in the format of "a=1&b=2&..." */ public void logEvent(String type, String name, String status, String nameValuePairs); /** * Create a new transaction with given type and name. * * @param type transaction type * @param name transaction name */ public Transaction newTransaction(String type, String name); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/spi/MessageProducerManager.java ================================================ package com.ctrip.framework.apollo.tracer.spi; /** * @author Jason Song(song_s@ctrip.com) */ public interface MessageProducerManager { /** * @return the message producer */ MessageProducer getProducer(); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/apollo/tracer/spi/Transaction.java ================================================ package com.ctrip.framework.apollo.tracer.spi; /** * @author Jason Song(song_s@ctrip.com) */ public interface Transaction { String SUCCESS = "0"; /** * Set the message status. * * @param status message status. "0" means success, otherwise error code. */ public void setStatus(String status); /** * Set the message status with exception class name. * * @param e exception. */ public void setStatus(Throwable e); /** * add one key-value pair to the message. */ public void addData(String key, Object value); /** * Complete the message construction. */ public void complete(); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/Foundation.java ================================================ package com.ctrip.framework.foundation; import com.ctrip.framework.foundation.internals.NullProviderManager; import com.ctrip.framework.foundation.internals.ServiceBootstrap; import com.ctrip.framework.foundation.spi.ProviderManager; import com.ctrip.framework.foundation.spi.provider.ApplicationProvider; import com.ctrip.framework.foundation.spi.provider.NetworkProvider; import com.ctrip.framework.foundation.spi.provider.ServerProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class Foundation { private static final Logger logger = LoggerFactory.getLogger(Foundation.class); private static Object lock = new Object(); private static volatile ProviderManager s_manager; // Encourage early initialization and fail early if it happens. static { getManager(); } private static ProviderManager getManager() { try { if (s_manager == null) { // Double locking to make sure only one thread initializes ProviderManager. synchronized (lock) { if (s_manager == null) { s_manager = ServiceBootstrap.loadFirst(ProviderManager.class); } } } return s_manager; } catch (Throwable ex) { s_manager = new NullProviderManager(); logger.error("Initialize ProviderManager failed.", ex); return s_manager; } } public static String getProperty(String name, String defaultValue) { try { return getManager().getProperty(name, defaultValue); } catch (Throwable ex) { logger.error("getProperty for {} failed.", name, ex); return defaultValue; } } public static NetworkProvider net() { try { return getManager().provider(NetworkProvider.class); } catch (Exception ex) { logger.error("Initialize NetworkProvider failed.", ex); return NullProviderManager.provider; } } public static ServerProvider server() { try { return getManager().provider(ServerProvider.class); } catch (Exception ex) { logger.error("Initialize ServerProvider failed.", ex); return NullProviderManager.provider; } } public static ApplicationProvider app() { try { return getManager().provider(ApplicationProvider.class); } catch (Exception ex) { logger.error("Initialize ApplicationProvider failed.", ex); return NullProviderManager.provider; } } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/DefaultProviderManager.java ================================================ package com.ctrip.framework.foundation.internals; import java.util.LinkedHashMap; import java.util.Map; import com.ctrip.framework.foundation.internals.provider.DefaultApplicationProvider; import com.ctrip.framework.foundation.internals.provider.DefaultNetworkProvider; import com.ctrip.framework.foundation.internals.provider.DefaultServerProvider; import com.ctrip.framework.foundation.spi.ProviderManager; import com.ctrip.framework.foundation.spi.provider.Provider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DefaultProviderManager implements ProviderManager { private static final Logger logger = LoggerFactory.getLogger(DefaultProviderManager.class); private Map, Provider> m_providers = new LinkedHashMap, Provider>(); public DefaultProviderManager() { // Load per-application configuration, like app id, from classpath://META-INF/app.properties Provider applicationProvider = new DefaultApplicationProvider(); applicationProvider.initialize(); register(applicationProvider); // Load network parameters Provider networkProvider = new DefaultNetworkProvider(); networkProvider.initialize(); register(networkProvider); // Load environment (fat, fws, uat, prod ...) and dc, from /opt/settings/server.properties, JVM property and/or OS // environment variables. Provider serverProvider = new DefaultServerProvider(); serverProvider.initialize(); register(serverProvider); } public synchronized void register(Provider provider) { m_providers.put(provider.getType(), provider); } @Override @SuppressWarnings("unchecked") public T provider(Class clazz) { Provider provider = m_providers.get(clazz); if (provider != null) { return (T) provider; } else { logger.error("No provider [{}] found in DefaultProviderManager, please make sure it is registered in DefaultProviderManager ", clazz.getName()); return (T) NullProviderManager.provider; } } @Override public String getProperty(String name, String defaultValue) { for (Provider provider : m_providers.values()) { String value = provider.getProperty(name, null); if (value != null) { return value; } } return defaultValue; } @Override public String toString() { StringBuilder sb = new StringBuilder(512); if (null != m_providers) { for (Map.Entry, Provider> entry : m_providers.entrySet()) { sb.append(entry.getValue()).append("\n"); } } sb.append("(DefaultProviderManager)").append("\n"); return sb.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/NetworkInterfaceManager.java ================================================ package com.ctrip.framework.foundation.internals; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Objects; public enum NetworkInterfaceManager { INSTANCE; private InetAddress m_local; private InetAddress m_localHost; private NetworkInterfaceManager() { load(); } public InetAddress findValidateIp(List addresses) { InetAddress local = null; int maxWeight = -1; for (InetAddress address : addresses) { if (address instanceof Inet4Address) { int weight = 0; if (address.isSiteLocalAddress()) { weight += 8; } if (address.isLinkLocalAddress()) { weight += 4; } if (address.isLoopbackAddress()) { weight += 2; } // has host name // TODO fix performance issue when calling getHostName if (!Objects.equals(address.getHostName(), address.getHostAddress())) { weight += 1; } if (weight > maxWeight) { maxWeight = weight; local = address; } } } return local; } public String getLocalHostAddress() { return m_local.getHostAddress(); } public String getLocalHostName() { try { if (null == m_localHost) { m_localHost = InetAddress.getLocalHost(); } return m_localHost.getHostName(); } catch (UnknownHostException e) { return m_local.getHostName(); } } private String getProperty(String name) { String value = null; value = System.getProperty(name); if (value == null) { value = System.getenv(name); } return value; } private void load() { String ip = getProperty("host.ip"); if (ip != null) { try { m_local = InetAddress.getByName(ip); return; } catch (Exception e) { System.err.println(e); // ignore } } try { Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); List nis = interfaces == null ? Collections.emptyList() : Collections.list(interfaces); List addresses = new ArrayList(); InetAddress local = null; try { for (NetworkInterface ni : nis) { if (ni.isUp() && !ni.isLoopback()) { addresses.addAll(Collections.list(ni.getInetAddresses())); } } local = findValidateIp(addresses); } catch (Exception e) { // ignore } if (local != null) { m_local = local; return; } } catch (SocketException e) { // ignore it } m_local = InetAddress.getLoopbackAddress(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/NullProviderManager.java ================================================ package com.ctrip.framework.foundation.internals; import com.ctrip.framework.foundation.internals.provider.NullProvider; import com.ctrip.framework.foundation.spi.ProviderManager; public class NullProviderManager implements ProviderManager { public static final NullProvider provider = new NullProvider(); @Override public String getProperty(String name, String defaultValue) { return defaultValue; } @Override public NullProvider provider(Class clazz) { return provider; } @Override public String toString() { return provider.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/ServiceBootstrap.java ================================================ package com.ctrip.framework.foundation.internals; import java.util.Iterator; import java.util.ServiceLoader; public class ServiceBootstrap { public static S loadFirst(Class clazz) { Iterator iterator = loadAll(clazz); if (!iterator.hasNext()) { throw new IllegalStateException(String.format( "No implementation defined in /META-INF/services/%s, please check whether the file exists and has the right implementation class!", clazz.getName())); } return iterator.next(); } private static Iterator loadAll(Class clazz) { ServiceLoader loader = ServiceLoader.load(clazz); return loader.iterator(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/Utils.java ================================================ package com.ctrip.framework.foundation.internals; import com.google.common.base.Strings; public class Utils { public static boolean isBlank(String str) { return Strings.nullToEmpty(str).trim().isEmpty(); } public static boolean isOSWindows() { String osName = System.getProperty("os.name"); if (Utils.isBlank(osName)) { return false; } return osName.startsWith("Windows"); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/BOMInputStream.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.ctrip.framework.foundation.internals.io; import static com.ctrip.framework.foundation.internals.io.IOUtils.EOF; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Comparator; import java.util.List; /** * This class is used to wrap a stream that includes an encoded {@link ByteOrderMark} as its first bytes. * * This class detects these bytes and, if required, can automatically skip them and return the subsequent byte as the * first byte in the stream. * * The {@link ByteOrderMark} implementation has the following pre-defined BOMs: *
    *
  • UTF-8 - {@link ByteOrderMark#UTF_8}
  • *
  • UTF-16BE - {@link ByteOrderMark#UTF_16LE}
  • *
  • UTF-16LE - {@link ByteOrderMark#UTF_16BE}
  • *
  • UTF-32BE - {@link ByteOrderMark#UTF_32LE}
  • *
  • UTF-32LE - {@link ByteOrderMark#UTF_32BE}
  • *
* * *

Example 1 - Detect and exclude a UTF-8 BOM

* *
 * BOMInputStream bomIn = new BOMInputStream(in);
 * if (bomIn.hasBOM()) {
 *   // has a UTF-8 BOM
 * }
 * 
* *

Example 2 - Detect a UTF-8 BOM (but don't exclude it)

* *
 * boolean include = true;
 * BOMInputStream bomIn = new BOMInputStream(in, include);
 * if (bomIn.hasBOM()) {
 *   // has a UTF-8 BOM
 * }
 * 
* *

Example 3 - Detect Multiple BOMs

* *
 * BOMInputStream bomIn = new BOMInputStream(in, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE,
 *     ByteOrderMark.UTF_32BE);
 * if (bomIn.hasBOM() == false) {
 *   // No BOM found
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_16LE)) {
 *   // has a UTF-16LE BOM
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_16BE)) {
 *   // has a UTF-16BE BOM
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_32LE)) {
 *   // has a UTF-32LE BOM
 * } else if (bomIn.hasBOM(ByteOrderMark.UTF_32BE)) {
 *   // has a UTF-32BE BOM
 * }
 * 
* * @see ByteOrderMark * @see Wikipedia - Byte Order Mark * @version $Id: BOMInputStream.java 1686527 2015-06-20 06:31:39Z krosenvold $ * @since 2.0 */ public class BOMInputStream extends ProxyInputStream { private final boolean include; /** * BOMs are sorted from longest to shortest. */ private final List boms; private ByteOrderMark byteOrderMark; private int[] firstBytes; private int fbLength; private int fbIndex; private int markFbIndex; private boolean markedAtStart; /** * Constructs a new BOM InputStream that excludes a {@link ByteOrderMark#UTF_8} BOM. * * @param delegate the InputStream to delegate to */ public BOMInputStream(final InputStream delegate) { this(delegate, false, ByteOrderMark.UTF_8); } /** * Constructs a new BOM InputStream that detects a a {@link ByteOrderMark#UTF_8} and optionally includes it. * * @param delegate the InputStream to delegate to * @param include true to include the UTF-8 BOM or false to exclude it */ public BOMInputStream(final InputStream delegate, final boolean include) { this(delegate, include, ByteOrderMark.UTF_8); } /** * Constructs a new BOM InputStream that excludes the specified BOMs. * * @param delegate the InputStream to delegate to * @param boms The BOMs to detect and exclude */ public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) { this(delegate, false, boms); } /** * Compares ByteOrderMark objects in descending length order. */ private static final Comparator ByteOrderMarkLengthComparator = new Comparator() { public int compare(final ByteOrderMark bom1, final ByteOrderMark bom2) { final int len1 = bom1.length(); final int len2 = bom2.length(); if (len1 > len2) { return EOF; } if (len2 > len1) { return 1; } return 0; } }; /** * Constructs a new BOM InputStream that detects the specified BOMs and optionally includes them. * * @param delegate the InputStream to delegate to * @param include true to include the specified BOMs or false to exclude them * @param boms The BOMs to detect and optionally exclude */ public BOMInputStream(final InputStream delegate, final boolean include, final ByteOrderMark... boms) { super(delegate); if (boms == null || boms.length == 0) { throw new IllegalArgumentException("No BOMs specified"); } this.include = include; // Sort the BOMs to match the longest BOM first because some BOMs have the same starting two bytes. Arrays.sort(boms, ByteOrderMarkLengthComparator); this.boms = Arrays.asList(boms); } /** * Indicates whether the stream contains one of the specified BOMs. * * @return true if the stream has one of the specified BOMs, otherwise false if it does not * @throws IOException if an error reading the first bytes of the stream occurs */ public boolean hasBOM() throws IOException { return getBOM() != null; } /** * Indicates whether the stream contains the specified BOM. * * @param bom The BOM to check for * @return true if the stream has the specified BOM, otherwise false if it does not * @throws IllegalArgumentException if the BOM is not one the stream is configured to detect * @throws IOException if an error reading the first bytes of the stream occurs */ public boolean hasBOM(final ByteOrderMark bom) throws IOException { if (!boms.contains(bom)) { throw new IllegalArgumentException("Stream not configure to detect " + bom); } return byteOrderMark != null && getBOM().equals(bom); } /** * Return the BOM (Byte Order Mark). * * @return The BOM or null if none * @throws IOException if an error reading the first bytes of the stream occurs */ public ByteOrderMark getBOM() throws IOException { if (firstBytes == null) { fbLength = 0; // BOMs are sorted from longest to shortest final int maxBomSize = boms.get(0).length(); firstBytes = new int[maxBomSize]; // Read first maxBomSize bytes for (int i = 0; i < firstBytes.length; i++) { firstBytes[i] = in.read(); fbLength++; if (firstBytes[i] < 0) { break; } } // match BOM in firstBytes byteOrderMark = find(); if (byteOrderMark != null) { if (!include) { if (byteOrderMark.length() < firstBytes.length) { fbIndex = byteOrderMark.length(); } else { fbLength = 0; } } } } return byteOrderMark; } /** * Return the BOM charset Name - {@link ByteOrderMark#getCharsetName()}. * * @return The BOM charset Name or null if no BOM found * @throws IOException if an error reading the first bytes of the stream occurs * */ public String getBOMCharsetName() throws IOException { getBOM(); return byteOrderMark == null ? null : byteOrderMark.getCharsetName(); } /** * This method reads and either preserves or skips the first bytes in the stream. It behaves like the single-byte * read() method, either returning a valid byte or -1 to indicate that the initial bytes have been * processed already. * * @return the byte read (excluding BOM) or -1 if the end of stream * @throws IOException if an I/O error occurs */ private int readFirstBytes() throws IOException { getBOM(); return fbIndex < fbLength ? firstBytes[fbIndex++] : EOF; } /** * Find a BOM with the specified bytes. * * @return The matched BOM or null if none matched */ private ByteOrderMark find() { for (final ByteOrderMark bom : boms) { if (matches(bom)) { return bom; } } return null; } /** * Check if the bytes match a BOM. * * @param bom The BOM * @return true if the bytes match the bom, otherwise false */ private boolean matches(final ByteOrderMark bom) { // if (bom.length() != fbLength) { // return false; // } // firstBytes may be bigger than the BOM bytes for (int i = 0; i < bom.length(); i++) { if (bom.get(i) != firstBytes[i]) { return false; } } return true; } // ---------------------------------------------------------------------------- // Implementation of InputStream // ---------------------------------------------------------------------------- /** * Invokes the delegate's read() method, detecting and optionally skipping BOM. * * @return the byte read (excluding BOM) or -1 if the end of stream * @throws IOException if an I/O error occurs */ @Override public int read() throws IOException { final int b = readFirstBytes(); return b >= 0 ? b : in.read(); } /** * Invokes the delegate's read(byte[], int, int) method, detecting and optionally skipping BOM. * * @param buf the buffer to read the bytes into * @param off The start offset * @param len The number of bytes to read (excluding BOM) * @return the number of bytes read or -1 if the end of stream * @throws IOException if an I/O error occurs */ @Override public int read(final byte[] buf, int off, int len) throws IOException { int firstCount = 0; int b = 0; while (len > 0 && b >= 0) { b = readFirstBytes(); if (b >= 0) { buf[off++] = (byte) (b & 0xFF); len--; firstCount++; } } final int secondCount = in.read(buf, off, len); return secondCount < 0 ? firstCount > 0 ? firstCount : EOF : firstCount + secondCount; } /** * Invokes the delegate's read(byte[]) method, detecting and optionally skipping BOM. * * @param buf the buffer to read the bytes into * @return the number of bytes read (excluding BOM) or -1 if the end of stream * @throws IOException if an I/O error occurs */ @Override public int read(final byte[] buf) throws IOException { return read(buf, 0, buf.length); } /** * Invokes the delegate's mark(int) method. * * @param readlimit read ahead limit */ @Override public synchronized void mark(final int readlimit) { markFbIndex = fbIndex; markedAtStart = firstBytes == null; in.mark(readlimit); } /** * Invokes the delegate's reset() method. * * @throws IOException if an I/O error occurs */ @Override public synchronized void reset() throws IOException { fbIndex = markFbIndex; if (markedAtStart) { firstBytes = null; } in.reset(); } /** * Invokes the delegate's skip(long) method, detecting and optionallyskipping BOM. * * @param n the number of bytes to skip * @return the number of bytes to skipped or -1 if the end of stream * @throws IOException if an I/O error occurs */ @Override public long skip(long n) throws IOException { int skipped = 0; while ((n > skipped) && (readFirstBytes() >= 0)) { skipped++; } return in.skip(n - skipped) + skipped; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/ByteOrderMark.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.ctrip.framework.foundation.internals.io; import java.io.Serializable; /** * Byte Order Mark (BOM) representation - see {@link BOMInputStream}. * * @see BOMInputStream * @see Wikipedia: Byte Order Mark * @see W3C: Autodetection of Character Encodings * (Non-Normative) * @version $Id: ByteOrderMark.java 1586504 2014-04-10 23:34:37Z ggregory $ * @since 2.0 */ public class ByteOrderMark implements Serializable { private static final long serialVersionUID = 1L; /** UTF-8 BOM */ public static final ByteOrderMark UTF_8 = new ByteOrderMark("UTF-8", 0xEF, 0xBB, 0xBF); /** UTF-16BE BOM (Big-Endian) */ public static final ByteOrderMark UTF_16BE = new ByteOrderMark("UTF-16BE", 0xFE, 0xFF); /** UTF-16LE BOM (Little-Endian) */ public static final ByteOrderMark UTF_16LE = new ByteOrderMark("UTF-16LE", 0xFF, 0xFE); /** * UTF-32BE BOM (Big-Endian) * * @since 2.2 */ public static final ByteOrderMark UTF_32BE = new ByteOrderMark("UTF-32BE", 0x00, 0x00, 0xFE, 0xFF); /** * UTF-32LE BOM (Little-Endian) * * @since 2.2 */ public static final ByteOrderMark UTF_32LE = new ByteOrderMark("UTF-32LE", 0xFF, 0xFE, 0x00, 0x00); /** * Unicode BOM character; external form depends on the encoding. * * @see Byte Order Mark (BOM) FAQ * @since 2.5 */ public static final char UTF_BOM = '\uFEFF'; private final String charsetName; private final int[] bytes; /** * Construct a new BOM. * * @param charsetName The name of the charset the BOM represents * @param bytes The BOM's bytes * @throws IllegalArgumentException if the charsetName is null or zero length * @throws IllegalArgumentException if the bytes are null or zero length */ public ByteOrderMark(final String charsetName, final int... bytes) { if (charsetName == null || charsetName.isEmpty()) { throw new IllegalArgumentException("No charsetName specified"); } if (bytes == null || bytes.length == 0) { throw new IllegalArgumentException("No bytes specified"); } this.charsetName = charsetName; this.bytes = new int[bytes.length]; System.arraycopy(bytes, 0, this.bytes, 0, bytes.length); } /** * Return the name of the {@link java.nio.charset.Charset} the BOM represents. * * @return the character set name */ public String getCharsetName() { return charsetName; } /** * Return the length of the BOM's bytes. * * @return the length of the BOM's bytes */ public int length() { return bytes.length; } /** * The byte at the specified position. * * @param pos The position * @return The specified byte */ public int get(final int pos) { return bytes[pos]; } /** * Return a copy of the BOM's bytes. * * @return a copy of the BOM's bytes */ public byte[] getBytes() { final byte[] copy = new byte[bytes.length]; for (int i = 0; i < bytes.length; i++) { copy[i] = (byte) bytes[i]; } return copy; } /** * Indicates if this BOM's bytes equals another. * * @param obj The object to compare to * @return true if the bom's bytes are equal, otherwise false */ @Override public boolean equals(final Object obj) { if (!(obj instanceof ByteOrderMark)) { return false; } final ByteOrderMark bom = (ByteOrderMark) obj; if (bytes.length != bom.length()) { return false; } for (int i = 0; i < bytes.length; i++) { if (bytes[i] != bom.get(i)) { return false; } } return true; } /** * Return the hashcode for this BOM. * * @return the hashcode for this BOM. * @see Object#hashCode() */ @Override public int hashCode() { int hashCode = getClass().hashCode(); for (final int b : bytes) { hashCode += b; } return hashCode; } /** * Provide a String representation of the BOM. * * @return the length of the BOM's bytes */ @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(getClass().getSimpleName()); builder.append('['); builder.append(charsetName); builder.append(": "); for (int i = 0; i < bytes.length; i++) { if (i > 0) { builder.append(","); } builder.append("0x"); builder.append(Integer.toHexString(0xFF & bytes[i]).toUpperCase()); } builder.append(']'); return builder.toString(); } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/IOUtils.java ================================================ package com.ctrip.framework.foundation.internals.io; public class IOUtils { public static final int EOF = -1; } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/io/ProxyInputStream.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.ctrip.framework.foundation.internals.io; import static com.ctrip.framework.foundation.internals.io.IOUtils.EOF; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /** * A Proxy stream which acts as expected, that is it passes the method calls on to the proxied stream and doesn't change * which methods are being called. *

* It is an alternative base class to FilterInputStream to increase reusability, because FilterInputStream changes the * methods being called, such as read(byte[]) to read(byte[], int, int). *

* See the protected methods for ways in which a subclass can easily decorate a stream with custom pre-, post- or error * processing functionality. * * @version $Id: ProxyInputStream.java 1603493 2014-06-18 15:46:07Z ggregory $ */ public abstract class ProxyInputStream extends FilterInputStream { /** * Constructs a new ProxyInputStream. * * @param proxy the InputStream to delegate to */ public ProxyInputStream(final InputStream proxy) { super(proxy); // the proxy is stored in a protected superclass variable named 'in' } /** * Invokes the delegate's read() method. * * @return the byte read or -1 if the end of stream * @throws IOException if an I/O error occurs */ @Override public int read() throws IOException { try { beforeRead(1); final int b = in.read(); afterRead(b != EOF ? 1 : EOF); return b; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's read(byte[]) method. * * @param bts the buffer to read the bytes into * @return the number of bytes read or EOF if the end of stream * @throws IOException if an I/O error occurs */ @Override public int read(final byte[] bts) throws IOException { try { beforeRead(bts != null ? bts.length : 0); final int n = in.read(bts); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's read(byte[], int, int) method. * * @param bts the buffer to read the bytes into * @param off The start offset * @param len The number of bytes to read * @return the number of bytes read or -1 if the end of stream * @throws IOException if an I/O error occurs */ @Override public int read(final byte[] bts, final int off, final int len) throws IOException { try { beforeRead(len); final int n = in.read(bts, off, len); afterRead(n); return n; } catch (final IOException e) { handleIOException(e); return EOF; } } /** * Invokes the delegate's skip(long) method. * * @param ln the number of bytes to skip * @return the actual number of bytes skipped * @throws IOException if an I/O error occurs */ @Override public long skip(final long ln) throws IOException { try { return in.skip(ln); } catch (final IOException e) { handleIOException(e); return 0; } } /** * Invokes the delegate's available() method. * * @return the number of available bytes * @throws IOException if an I/O error occurs */ @Override public int available() throws IOException { try { return super.available(); } catch (final IOException e) { handleIOException(e); return 0; } } /** * Invokes the delegate's close() method. * * @throws IOException if an I/O error occurs */ @Override public void close() throws IOException { try { in.close(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's mark(int) method. * * @param readlimit read ahead limit */ @Override public synchronized void mark(final int readlimit) { in.mark(readlimit); } /** * Invokes the delegate's reset() method. * * @throws IOException if an I/O error occurs */ @Override public synchronized void reset() throws IOException { try { in.reset(); } catch (final IOException e) { handleIOException(e); } } /** * Invokes the delegate's markSupported() method. * * @return true if mark is supported, otherwise false */ @Override public boolean markSupported() { return in.markSupported(); } /** * Invoked by the read methods before the call is proxied. The number of bytes that the caller wanted to read (1 for * the {@link #read()} method, buffer length for {@link #read(byte[])}, etc.) is given as an argument. *

* Subclasses can override this method to add common pre-processing functionality without having to override all the * read methods. The default implementation does nothing. *

* Note this method is not called from {@link #skip(long)} or {@link #reset()}. You need to explicitly * override those methods if you want to add pre-processing steps also to them. * * @since 2.0 * @param n number of bytes that the caller asked to be read * @throws IOException if the pre-processing fails */ protected void beforeRead(final int n) throws IOException { // no-op } /** * Invoked by the read methods after the proxied call has returned successfully. The number of bytes returned to the * caller (or -1 if the end of stream was reached) is given as an argument. *

* Subclasses can override this method to add common post-processing functionality without having to override all the * read methods. The default implementation does nothing. *

* Note this method is not called from {@link #skip(long)} or {@link #reset()}. You need to explicitly * override those methods if you want to add post-processing steps also to them. * * @since 2.0 * @param n number of bytes read, or -1 if the end of stream was reached * @throws IOException if the post-processing fails */ protected void afterRead(final int n) throws IOException { // no-op } /** * Handle any IOExceptions thrown. *

* This method provides a point to implement custom exception handling. The default behaviour is to re-throw the * exception. * * @param e The IOException thrown * @throws IOException if an I/O error occurs * @since 2.0 */ protected void handleIOException(final IOException e) throws IOException { throw e; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/DefaultApplicationProvider.java ================================================ package com.ctrip.framework.foundation.internals.provider; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ctrip.framework.foundation.internals.Utils; import com.ctrip.framework.foundation.internals.io.BOMInputStream; import com.ctrip.framework.foundation.spi.provider.ApplicationProvider; import com.ctrip.framework.foundation.spi.provider.Provider; public class DefaultApplicationProvider implements ApplicationProvider { private static final Logger logger = LoggerFactory.getLogger(DefaultApplicationProvider.class); public static final String APP_PROPERTIES_CLASSPATH = "/META-INF/app.properties"; private Properties m_appProperties = new Properties(); private String m_appId; @Override public void initialize() { try { InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(APP_PROPERTIES_CLASSPATH); if (in == null) { in = DefaultApplicationProvider.class.getResourceAsStream(APP_PROPERTIES_CLASSPATH); } if (in == null) { logger.warn("{} not found from classpath!", APP_PROPERTIES_CLASSPATH); } initialize(in); } catch (Throwable ex) { logger.error("Initialize DefaultApplicationProvider failed.", ex); } } @Override public void initialize(InputStream in) { try { if (in != null) { try { m_appProperties.load(new InputStreamReader(new BOMInputStream(in), StandardCharsets.UTF_8)); } finally { in.close(); } } initAppId(); } catch (Throwable ex) { logger.error("Initialize DefaultApplicationProvider failed.", ex); } } @Override public String getAppId() { return m_appId; } @Override public boolean isAppIdSet() { return !Utils.isBlank(m_appId); } @Override public String getProperty(String name, String defaultValue) { if ("app.id".equals(name)) { String val = getAppId(); return val == null ? defaultValue : val; } else { String val = m_appProperties.getProperty(name, defaultValue); return val == null ? defaultValue : val; } } @Override public Class getType() { return ApplicationProvider.class; } private void initAppId() { // 1. Get app.id from System Property m_appId = System.getProperty("app.id"); if (!Utils.isBlank(m_appId)) { m_appId = m_appId.trim(); logger.info("App ID is set to {} by app.id property from System Property", m_appId); return; } // 2. Try to get app id from app.properties. m_appId = m_appProperties.getProperty("app.id"); if (!Utils.isBlank(m_appId)) { m_appId = m_appId.trim(); logger.info("App ID is set to {} by app.id property from {}", m_appId, APP_PROPERTIES_CLASSPATH); return; } m_appId = null; logger.warn("app.id is not available from System Property and {}. It is set to null", APP_PROPERTIES_CLASSPATH); } @Override public String toString() { return "appId [" + getAppId() + "] properties: " + m_appProperties + " (DefaultApplicationProvider)"; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/DefaultNetworkProvider.java ================================================ package com.ctrip.framework.foundation.internals.provider; import com.ctrip.framework.foundation.internals.NetworkInterfaceManager; import com.ctrip.framework.foundation.spi.provider.NetworkProvider; import com.ctrip.framework.foundation.spi.provider.Provider; public class DefaultNetworkProvider implements NetworkProvider { @Override public String getProperty(String name, String defaultValue) { if ("host.address".equalsIgnoreCase(name)) { String val = getHostAddress(); return val == null ? defaultValue : val; } else if ("host.name".equalsIgnoreCase(name)) { String val = getHostName(); return val == null ? defaultValue : val; } else { return defaultValue; } } @Override public void initialize() { } @Override public String getHostAddress() { return NetworkInterfaceManager.INSTANCE.getLocalHostAddress(); } @Override public String getHostName() { return NetworkInterfaceManager.INSTANCE.getLocalHostName(); } @Override public Class getType() { return NetworkProvider.class; } @Override public String toString() { return "hostName [" + getHostName() + "] hostIP [" + getHostAddress() + "] (DefaultNetworkProvider)"; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/DefaultServerProvider.java ================================================ package com.ctrip.framework.foundation.internals.provider; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Properties; import com.ctrip.framework.foundation.internals.Utils; import com.ctrip.framework.foundation.internals.io.BOMInputStream; import com.ctrip.framework.foundation.spi.provider.Provider; import com.ctrip.framework.foundation.spi.provider.ServerProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DefaultServerProvider implements ServerProvider { private static final Logger logger = LoggerFactory.getLogger(DefaultServerProvider.class); private static final String SERVER_PROPERTIES_LINUX = "/opt/settings/server.properties"; private static final String SERVER_PROPERTIES_WINDOWS = "C:/opt/settings/server.properties"; private String m_env; private String m_dc; private Properties m_serverProperties = new Properties(); @Override public void initialize() { try { String path = Utils.isOSWindows() ? SERVER_PROPERTIES_WINDOWS : SERVER_PROPERTIES_LINUX; File file = new File(path); if (file.exists() && file.canRead()) { logger.info("Loading {}", file.getAbsolutePath()); FileInputStream fis = new FileInputStream(file); initialize(fis); return; } logger.warn("{} does not exist or is not readable.", path); initialize(null); } catch (Throwable ex) { logger.error("Initialize DefaultServerProvider failed.", ex); } } @Override public void initialize(InputStream in) { try { if (in != null) { try { m_serverProperties.load(new InputStreamReader(new BOMInputStream(in), StandardCharsets.UTF_8)); } finally { in.close(); } } initEnvType(); initDataCenter(); } catch (Throwable ex) { logger.error("Initialize DefaultServerProvider failed.", ex); } } @Override public String getDataCenter() { return m_dc; } @Override public boolean isDataCenterSet() { return m_dc != null; } @Override public String getEnvType() { return m_env; } @Override public boolean isEnvTypeSet() { return m_env != null; } @Override public String getProperty(String name, String defaultValue) { if ("env".equalsIgnoreCase(name)) { String val = getEnvType(); return val == null ? defaultValue : val; } else if ("dc".equalsIgnoreCase(name)) { String val = getDataCenter(); return val == null ? defaultValue : val; } else { String val = m_serverProperties.getProperty(name, defaultValue); return val == null ? defaultValue : val.trim(); } } @Override public Class getType() { return ServerProvider.class; } private void initEnvType() { // 1. Try to get environment from JVM system property m_env = System.getProperty("env"); if (!Utils.isBlank(m_env)) { m_env = m_env.trim(); logger.info("Environment is set to [{}] by JVM system property 'env'.", m_env); return; } // 2. Try to get environment from OS environment variable m_env = System.getenv("ENV"); if (!Utils.isBlank(m_env)) { m_env = m_env.trim(); logger.info("Environment is set to [{}] by OS env variable 'ENV'.", m_env); return; } // 3. Try to get environment from file "server.properties" m_env = m_serverProperties.getProperty("env"); if (!Utils.isBlank(m_env)) { m_env = m_env.trim(); logger.info("Environment is set to [{}] by property 'env' in server.properties.", m_env); return; } // 4. Set environment to null. m_env = null; logger.warn("Environment is set to null. Because it is not available in either (1) JVM system property 'env', (2) OS env variable 'ENV' nor (3) property 'env' from the properties InputStream."); } private void initDataCenter() { // 1. Try to get environment from JVM system property m_dc = System.getProperty("idc"); if (!Utils.isBlank(m_dc)) { m_dc = m_dc.trim(); logger.info("Data Center is set to [{}] by JVM system property 'idc'.", m_dc); return; } // 2. Try to get idc from OS environment variable m_dc = System.getenv("IDC"); if (!Utils.isBlank(m_dc)) { m_dc = m_dc.trim(); logger.info("Data Center is set to [{}] by OS env variable 'IDC'.", m_dc); return; } // 3. Try to get idc from from file "server.properties" m_dc = m_serverProperties.getProperty("idc"); if (!Utils.isBlank(m_dc)) { m_dc = m_dc.trim(); logger.info("Data Center is set to [{}] by property 'idc' in server.properties.", m_dc); return; } // 4. Set Data Center to null. m_dc = null; logger.debug("Data Center is set to null. Because it is not available in either (1) JVM system property 'idc', (2) OS env variable 'IDC' nor (3) property 'idc' from the properties InputStream."); } @Override public String toString() { return "environment [" + getEnvType() + "] data center [" + getDataCenter() + "] properties: " + m_serverProperties + " (DefaultServerProvider)"; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/provider/NullProvider.java ================================================ package com.ctrip.framework.foundation.internals.provider; import java.io.InputStream; import com.ctrip.framework.foundation.spi.provider.ApplicationProvider; import com.ctrip.framework.foundation.spi.provider.NetworkProvider; import com.ctrip.framework.foundation.spi.provider.Provider; import com.ctrip.framework.foundation.spi.provider.ServerProvider; public class NullProvider implements ApplicationProvider, NetworkProvider, ServerProvider { @Override public Class getType() { return null; } @Override public String getProperty(String name, String defaultValue) { return defaultValue; } @Override public void initialize() { } @Override public String getAppId() { return null; } @Override public boolean isAppIdSet() { return false; } @Override public String getEnvType() { return null; } @Override public boolean isEnvTypeSet() { return false; } @Override public String getDataCenter() { return null; } @Override public boolean isDataCenterSet() { return false; } @Override public void initialize(InputStream in) { } @Override public String getHostAddress() { return null; } @Override public String getHostName() { return null; } @Override public String toString() { return "(NullProvider)"; } } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/ProviderManager.java ================================================ package com.ctrip.framework.foundation.spi; import com.ctrip.framework.foundation.spi.provider.Provider; public interface ProviderManager { public String getProperty(String name, String defaultValue); public T provider(Class clazz); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/ApplicationProvider.java ================================================ package com.ctrip.framework.foundation.spi.provider; import java.io.InputStream; /** * Provider for application related properties */ public interface ApplicationProvider extends Provider { /** * @return the application's app id */ public String getAppId(); /** * @return whether the application's app id is set or not */ public boolean isAppIdSet(); /** * Initialize the application provider with the specified input stream */ public void initialize(InputStream in); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/NetworkProvider.java ================================================ package com.ctrip.framework.foundation.spi.provider; /** * Provider for network related properties */ public interface NetworkProvider extends Provider { /** * @return the host address, i.e. ip */ public String getHostAddress(); /** * @return the host name */ public String getHostName(); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/Provider.java ================================================ package com.ctrip.framework.foundation.spi.provider; public interface Provider { /** * @return the current provider's type */ public Class getType(); /** * Return the property value with the given name, or {@code defaultValue} if the name doesn't exist. * * @param name the property name * @param defaultValue the default value when name is not found or any error occurred * @return the property value */ public String getProperty(String name, String defaultValue); /** * Initialize the provider */ public void initialize(); } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/java/com/ctrip/framework/foundation/spi/provider/ServerProvider.java ================================================ package com.ctrip.framework.foundation.spi.provider; import java.io.IOException; import java.io.InputStream; /** * Provider for server related properties */ public interface ServerProvider extends Provider { /** * @return current environment or {@code null} if not set */ public String getEnvType(); /** * @return whether current environment is set or not */ public boolean isEnvTypeSet(); /** * @return current data center or {@code null} if not set */ public String getDataCenter(); /** * @return whether data center is set or not */ public boolean isDataCenterSet(); /** * Initialize server provider with the specified input stream * * @throws IOException */ public void initialize(InputStream in) throws IOException; } ================================================ FILE: open-config-center/apollo/apollo-core/src/main/resources/META-INF/services/com.ctrip.framework.apollo.tracer.spi.MessageProducerManager ================================================ com.ctrip.framework.apollo.tracer.internals.DefaultMessageProducerManager ================================================ FILE: open-config-center/apollo/apollo-core/src/main/resources/META-INF/services/com.ctrip.framework.foundation.spi.ProviderManager ================================================ com.ctrip.framework.foundation.internals.DefaultProviderManager ================================================ FILE: open-config-center/apollo/apollo-core/src/main/resources/apollo-env.properties ================================================ local.meta=http://localhost:8080 #\u6307\u5411http://localhost:8080/services/config\u5730\u5740 dev.meta=http://127.0.0.1:8080 fat.meta=${fat_meta} uat.meta=${uat_meta} lpt.meta=${lpt_meta} pro.meta=${pro_meta} ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/app-with-utf8bom.properties ================================================ app.id=110402 ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/app.properties ================================================ app.id=110402 ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1 ================================================ com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1Impl ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface3 ================================================ ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface4 ================================================ com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface1Impl ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$Interface5 ================================================ com.ctrip.framework.apollo.foundation.internals.ServiceBootstrapTest$SomeImplNotExists ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.apollo.tracer.spi.MessageProducerManager ================================================ com.ctrip.framework.apollo.tracer.internals.MockMessageProducerManager ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/META-INF/some-invalid-app.properties ================================================ appid=110402 ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/apollo-env.properties ================================================ local.meta=http://localhost:8080 dev.meta=http://dev:8080 ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/log4j2.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/properties/server-with-utf8bom.properties ================================================ idc=SHAJQ env=DEV subenv=Dev123 bigdata=true tooling=true pci=true ================================================ FILE: open-config-center/apollo/apollo-core/src/test/resources/properties/server.properties ================================================ idc=SHAJQ env=DEV subenv=Dev123 bigdata=true tooling=true pci=true ================================================ FILE: open-config-center/apollo/apollo-portal/pom.xml ================================================ com.ctrip.framework.apollo apollo 0.10.0-SNAPSHOT 4.0.0 apollo-portal Apollo Portal ${project.artifactId} com.ctrip.framework.apollo apollo-common com.h2database h2 test mysql mysql-connector-java org.springframework.boot spring-boot-maven-plugin repackage apollo-portal ctrip com.ctrip.framework.apollo-sso apollo-sso-ctrip com.ctrip.framework.apollo-ctrip-service apollo-email-service ================================================ FILE: open-config-center/apollo/apollo-portal/src/assembly/assembly-descriptor.xml ================================================ apollo-assembly zip false src/main/scripts scripts *.sh 0755 unix src/main/config config apollo-portal.conf unix src/main/config / apollo-portal.conf unix target / ${project.artifactId}-*.jar 0755 ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/config/apollo-portal.conf ================================================ MODE=service PID_FOLDER=. LOG_FOLDER=/opt/logs/100003173/ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/config/app.properties ================================================ appId=100003173 jdkVersion=1.8 ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/docker/Dockerfile ================================================ # Dockerfile for apollo-portal # Build with: # docker build -t apollo-portal . # Run with: # docker run -p 8080:8080 -d -v /tmp/logs:/opt/logs --name apollo-portal apollo-portal # Or if 8080 was taken: # docker run -p 8070:8080 -d -v /tmp/logs:/opt/logs --name apollo-portal apollo-portal FROM openjdk:8-jre-alpine MAINTAINER ameizi ENV VERSION 0.9.0 RUN echo "http://mirrors.aliyun.com/alpine/v3.6/main" > /etc/apk/repositories \ && echo "http://mirrors.aliyun.com/alpine/v3.6/community" >> /etc/apk/repositories \ && apk update upgrade \ && apk add --no-cache procps unzip curl bash tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone ADD apollo-portal-${VERSION}-github.zip /apollo-portal/apollo-portal-${VERSION}-github.zip RUN unzip /apollo-portal/apollo-portal-${VERSION}-github.zip -d /apollo-portal \ && rm -rf /apollo-portal/apollo-portal-${VERSION}-github.zip \ && sed -i '$d' /apollo-portal/scripts/startup.sh \ && echo "tail -f /dev/null" >> /apollo-portal/scripts/startup.sh EXPOSE 8080 CMD ["/apollo-portal/scripts/startup.sh"] ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/PortalOpenApiConfig.java ================================================ package com.ctrip.framework.apollo.openapi; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @EnableAutoConfiguration @Configuration @ComponentScan(basePackageClasses = PortalOpenApiConfig.class) public class PortalOpenApiConfig { } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/auth/ConsumerPermissionValidator.java ================================================ package com.ctrip.framework.apollo.openapi.auth; import com.ctrip.framework.apollo.openapi.service.ConsumerRolePermissionService; import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil; import com.ctrip.framework.apollo.portal.constant.PermissionType; import com.ctrip.framework.apollo.portal.util.RoleUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component public class ConsumerPermissionValidator { @Autowired private ConsumerRolePermissionService permissionService; @Autowired private ConsumerAuthUtil consumerAuthUtil; public boolean hasModifyNamespacePermission(HttpServletRequest request, String appId, String namespaceName) { if (hasCreateNamespacePermission(request, appId)) { return true; } return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request), PermissionType.MODIFY_NAMESPACE, RoleUtils.buildNamespaceTargetId(appId, namespaceName)); } public boolean hasReleaseNamespacePermission(HttpServletRequest request, String appId, String namespaceName) { if (hasCreateNamespacePermission(request, appId)) { return true; } return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request), PermissionType.RELEASE_NAMESPACE, RoleUtils.buildNamespaceTargetId(appId, namespaceName)); } public boolean hasCreateNamespacePermission(HttpServletRequest request, String appId) { return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request), PermissionType.CREATE_NAMESPACE, appId); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenAppNamespaceDTO.java ================================================ package com.ctrip.framework.apollo.openapi.dto; import com.ctrip.framework.apollo.common.dto.BaseDTO; public class OpenAppNamespaceDTO extends BaseDTO { private String name; private String appId; private String format; private boolean isPublic; private String comment; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public boolean isPublic() { return isPublic; } public void setPublic(boolean aPublic) { isPublic = aPublic; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenEnvClusterDTO.java ================================================ package com.ctrip.framework.apollo.openapi.dto; import java.util.Set; public class OpenEnvClusterDTO { private String env; private Set clusters; public String getEnv() { return env; } public void setEnv(String env) { this.env = env; } public Set getClusters() { return clusters; } public void setClusters(Set clusters) { this.clusters = clusters; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenItemDTO.java ================================================ package com.ctrip.framework.apollo.openapi.dto; import com.ctrip.framework.apollo.common.dto.BaseDTO; public class OpenItemDTO extends BaseDTO { private String key; private String value; private String comment; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenNamespaceDTO.java ================================================ package com.ctrip.framework.apollo.openapi.dto; import com.ctrip.framework.apollo.common.dto.BaseDTO; import java.util.List; public class OpenNamespaceDTO extends BaseDTO { private String appId; private String clusterName; private String namespaceName; private String comment; private String format; private boolean isPublic; private List items; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public boolean isPublic() { return isPublic; } public void setPublic(boolean aPublic) { isPublic = aPublic; } public List getItems() { return items; } public void setItems(List items) { this.items = items; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenNamespaceLockDTO.java ================================================ package com.ctrip.framework.apollo.openapi.dto; public class OpenNamespaceLockDTO { private String namespaceName; private boolean isLocked; private String lockedBy; public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public boolean isLocked() { return isLocked; } public void setLocked(boolean locked) { isLocked = locked; } public String getLockedBy() { return lockedBy; } public void setLockedBy(String lockedBy) { this.lockedBy = lockedBy; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenReleaseDTO.java ================================================ package com.ctrip.framework.apollo.openapi.dto; import com.ctrip.framework.apollo.common.dto.BaseDTO; import java.util.Map; public class OpenReleaseDTO extends BaseDTO { private String appId; private String clusterName; private String namespaceName; private String name; private Map configurations; private String comment; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public Map getConfigurations() { return configurations; } public void setConfigurations(Map configurations) { this.configurations = configurations; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/Consumer.java ================================================ package com.ctrip.framework.apollo.openapi.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "Consumer") @SQLDelete(sql = "Update Consumer set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Consumer extends BaseEntity { @Column(name = "Name", nullable = false) private String name; @Column(name = "AppId", nullable = false) private String appId; @Column(name = "OrgId", nullable = false) private String orgId; @Column(name = "OrgName", nullable = false) private String orgName; @Column(name = "OwnerName", nullable = false) private String ownerName; @Column(name = "OwnerEmail", nullable = false) private String ownerEmail; public String getAppId() { return appId; } public String getName() { return name; } public String getOrgId() { return orgId; } public String getOrgName() { return orgName; } public String getOwnerEmail() { return ownerEmail; } public String getOwnerName() { return ownerName; } public void setAppId(String appId) { this.appId = appId; } public void setName(String name) { this.name = name; } public void setOrgId(String orgId) { this.orgId = orgId; } public void setOrgName(String orgName) { this.orgName = orgName; } public void setOwnerEmail(String ownerEmail) { this.ownerEmail = ownerEmail; } public void setOwnerName(String ownerName) { this.ownerName = ownerName; } @Override public String toString() { return toStringHelper().add("name", name).add("appId", appId) .add("orgId", orgId) .add("orgName", orgName) .add("ownerName", ownerName) .add("ownerEmail", ownerEmail).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/ConsumerAudit.java ================================================ package com.ctrip.framework.apollo.openapi.entity; import com.google.common.base.MoreObjects; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.PrePersist; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "ConsumerAudit") public class ConsumerAudit { @Id @GeneratedValue @Column(name = "Id") private long id; @Column(name = "ConsumerId", nullable = false) private long consumerId; @Column(name = "Uri", nullable = false) private String uri; @Column(name = "Method", nullable = false) private String method; @Column(name = "DataChange_CreatedTime") private Date dataChangeCreatedTime; @Column(name = "DataChange_LastTime") private Date dataChangeLastModifiedTime; @PrePersist protected void prePersist() { if (this.dataChangeCreatedTime == null) { this.dataChangeCreatedTime = new Date(); } if (this.dataChangeLastModifiedTime == null) { dataChangeLastModifiedTime = this.dataChangeCreatedTime; } } public long getId() { return id; } public void setId(long id) { this.id = id; } public long getConsumerId() { return consumerId; } public void setConsumerId(long consumerId) { this.consumerId = consumerId; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public Date getDataChangeCreatedTime() { return dataChangeCreatedTime; } public void setDataChangeCreatedTime(Date dataChangeCreatedTime) { this.dataChangeCreatedTime = dataChangeCreatedTime; } public Date getDataChangeLastModifiedTime() { return dataChangeLastModifiedTime; } public void setDataChangeLastModifiedTime(Date dataChangeLastModifiedTime) { this.dataChangeLastModifiedTime = dataChangeLastModifiedTime; } @Override public String toString() { return MoreObjects.toStringHelper(this) .omitNullValues() .add("id", id) .add("consumerId", consumerId) .add("uri", uri) .add("method", method) .add("dataChangeCreatedTime", dataChangeCreatedTime) .add("dataChangeLastModifiedTime", dataChangeLastModifiedTime) .toString(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/ConsumerRole.java ================================================ package com.ctrip.framework.apollo.openapi.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "ConsumerRole") @SQLDelete(sql = "Update ConsumerRole set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class ConsumerRole extends BaseEntity { @Column(name = "ConsumerId", nullable = false) private long consumerId; @Column(name = "RoleId", nullable = false) private long roleId; public long getConsumerId() { return consumerId; } public void setConsumerId(long consumerId) { this.consumerId = consumerId; } public long getRoleId() { return roleId; } public void setRoleId(long roleId) { this.roleId = roleId; } @Override public String toString() { return toStringHelper().add("consumerId", consumerId).add("roleId", roleId).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/entity/ConsumerToken.java ================================================ package com.ctrip.framework.apollo.openapi.entity; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "ConsumerToken") @SQLDelete(sql = "Update ConsumerToken set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class ConsumerToken extends BaseEntity { @Column(name = "ConsumerId", nullable = false) private long consumerId; @Column(name = "token", nullable = false) private String token; @Column(name = "Expires", nullable = false) private Date expires; public long getConsumerId() { return consumerId; } public void setConsumerId(long consumerId) { this.consumerId = consumerId; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public Date getExpires() { return expires; } public void setExpires(Date expires) { this.expires = expires; } @Override public String toString() { return toStringHelper().add("consumerId", consumerId).add("token", token) .add("expires", expires).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/filter/ConsumerAuthenticationFilter.java ================================================ package com.ctrip.framework.apollo.openapi.filter; import com.ctrip.framework.apollo.openapi.util.ConsumerAuditUtil; import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Jason Song(song_s@ctrip.com) */ public class ConsumerAuthenticationFilter implements Filter { private ConsumerAuthUtil consumerAuthUtil; private ConsumerAuditUtil consumerAuditUtil; public ConsumerAuthenticationFilter(ConsumerAuthUtil consumerAuthUtil, ConsumerAuditUtil consumerAuditUtil) { this.consumerAuthUtil = consumerAuthUtil; this.consumerAuditUtil = consumerAuditUtil; } @Override public void init(FilterConfig filterConfig) throws ServletException { //nothing } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String token = request.getHeader("Authorization"); Long consumerId = consumerAuthUtil.getConsumerId(token); if (consumerId == null) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); return; } consumerAuthUtil.storeConsumerId(request, consumerId); consumerAuditUtil.audit(request, consumerId); chain.doFilter(req, resp); } @Override public void destroy() { //nothing } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerAuditRepository.java ================================================ package com.ctrip.framework.apollo.openapi.repository; import com.ctrip.framework.apollo.openapi.entity.ConsumerAudit; import org.springframework.data.repository.PagingAndSortingRepository; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConsumerAuditRepository extends PagingAndSortingRepository { } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRepository.java ================================================ package com.ctrip.framework.apollo.openapi.repository; import com.ctrip.framework.apollo.openapi.entity.Consumer; import org.springframework.data.repository.PagingAndSortingRepository; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConsumerRepository extends PagingAndSortingRepository { Consumer findByAppId(String appId); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRoleRepository.java ================================================ package com.ctrip.framework.apollo.openapi.repository; import com.ctrip.framework.apollo.openapi.entity.ConsumerRole; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConsumerRoleRepository extends PagingAndSortingRepository { /** * find consumer roles by userId * * @param consumerId consumer id */ List findByConsumerId(long consumerId); /** * find consumer roles by roleId */ List findByRoleId(long roleId); ConsumerRole findByConsumerIdAndRoleId(long consumerId, long roleId); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerTokenRepository.java ================================================ package com.ctrip.framework.apollo.openapi.repository; import com.ctrip.framework.apollo.openapi.entity.ConsumerToken; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.Date; /** * @author Jason Song(song_s@ctrip.com) */ public interface ConsumerTokenRepository extends PagingAndSortingRepository { /** * find consumer token by token * * @param token the token * @param validDate the date when the token is valid */ ConsumerToken findTopByTokenAndExpiresAfter(String token, Date validDate); ConsumerToken findByConsumerId(Long consumerId); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/service/ConsumerRolePermissionService.java ================================================ package com.ctrip.framework.apollo.openapi.service; import com.google.common.collect.FluentIterable; import com.ctrip.framework.apollo.openapi.entity.ConsumerRole; import com.ctrip.framework.apollo.openapi.repository.ConsumerRoleRepository; import com.ctrip.framework.apollo.portal.entity.po.Permission; import com.ctrip.framework.apollo.portal.entity.po.RolePermission; import com.ctrip.framework.apollo.portal.repository.PermissionRepository; import com.ctrip.framework.apollo.portal.repository.RolePermissionRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ConsumerRolePermissionService { @Autowired private PermissionRepository permissionRepository; @Autowired private ConsumerRoleRepository consumerRoleRepository; @Autowired private RolePermissionRepository rolePermissionRepository; /** * Check whether user has the permission */ public boolean consumerHasPermission(long consumerId, String permissionType, String targetId) { Permission permission = permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId); if (permission == null) { return false; } List consumerRoles = consumerRoleRepository.findByConsumerId(consumerId); if (CollectionUtils.isEmpty(consumerRoles)) { return false; } Set roleIds = FluentIterable.from(consumerRoles).transform(consumerRole -> consumerRole.getRoleId()) .toSet(); List rolePermissions = rolePermissionRepository.findByRoleIdIn(roleIds); if (CollectionUtils.isEmpty(rolePermissions)) { return false; } for (RolePermission rolePermission : rolePermissions) { if (rolePermission.getPermissionId() == permission.getId()) { return true; } } return false; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/service/ConsumerService.java ================================================ package com.ctrip.framework.apollo.openapi.service; import com.google.common.base.Charsets; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.hash.Hashing; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.openapi.entity.Consumer; import com.ctrip.framework.apollo.openapi.entity.ConsumerAudit; import com.ctrip.framework.apollo.openapi.entity.ConsumerRole; import com.ctrip.framework.apollo.openapi.entity.ConsumerToken; import com.ctrip.framework.apollo.openapi.repository.ConsumerAuditRepository; import com.ctrip.framework.apollo.openapi.repository.ConsumerRepository; import com.ctrip.framework.apollo.openapi.repository.ConsumerRoleRepository; import com.ctrip.framework.apollo.openapi.repository.ConsumerTokenRepository; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.po.Role; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.portal.util.RoleUtils; import org.apache.commons.lang.time.FastDateFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; import java.util.Date; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ConsumerService { private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss"); private static final Joiner KEY_JOINER = Joiner.on("|"); @Autowired private UserInfoHolder userInfoHolder; @Autowired private ConsumerTokenRepository consumerTokenRepository; @Autowired private ConsumerRepository consumerRepository; @Autowired private ConsumerAuditRepository consumerAuditRepository; @Autowired private ConsumerRoleRepository consumerRoleRepository; @Autowired private PortalConfig portalConfig; @Autowired private RolePermissionService rolePermissionService; @Autowired private UserService userService; public Consumer createConsumer(Consumer consumer) { String appId = consumer.getAppId(); Consumer managedConsumer = consumerRepository.findByAppId(appId); if (managedConsumer != null) { throw new BadRequestException("Consumer already exist"); } String ownerName = consumer.getOwnerName(); UserInfo owner = userService.findByUserId(ownerName); if (owner == null) { throw new BadRequestException(String.format("User does not exist. UserId = %s", ownerName)); } consumer.setOwnerEmail(owner.getEmail()); String operator = userInfoHolder.getUser().getUserId(); consumer.setDataChangeCreatedBy(operator); consumer.setDataChangeLastModifiedBy(operator); return consumerRepository.save(consumer); } public ConsumerToken generateAndSaveConsumerToken(Consumer consumer, Date expires) { Preconditions.checkArgument(consumer != null, "Consumer can not be null"); ConsumerToken consumerToken = generateConsumerToken(consumer, expires); consumerToken.setId(0); return consumerTokenRepository.save(consumerToken); } public ConsumerToken getConsumerTokenByAppId(String appId) { Consumer consumer = consumerRepository.findByAppId(appId); if (consumer == null) { return null; } return consumerTokenRepository.findByConsumerId(consumer.getId()); } public Long getConsumerIdByToken(String token) { if (Strings.isNullOrEmpty(token)) { return null; } ConsumerToken consumerToken = consumerTokenRepository.findTopByTokenAndExpiresAfter(token, new Date()); return consumerToken == null ? null : consumerToken.getConsumerId(); } public Consumer getConsumerByConsumerId(long consumerId) { return consumerRepository.findOne(consumerId); } @Transactional public List assignNamespaceRoleToConsumer(String token, String appId, String namespaceName) { Long consumerId = getConsumerIdByToken(token); if (consumerId == null) { throw new BadRequestException("Token is Illegal"); } Role namespaceModifyRole = rolePermissionService.findRoleByRoleName(RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName)); Role namespaceReleaseRole = rolePermissionService.findRoleByRoleName(RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName)); if (namespaceModifyRole == null || namespaceReleaseRole == null) { throw new BadRequestException("Namespace's role does not exist. Please check whether namespace has created."); } long namespaceModifyRoleId = namespaceModifyRole.getId(); long namespaceReleaseRoleId = namespaceReleaseRole.getId(); ConsumerRole managedModifyRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, namespaceModifyRoleId); ConsumerRole managedReleaseRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, namespaceReleaseRoleId); if (managedModifyRole != null && managedReleaseRole != null) { return Arrays.asList(managedModifyRole, managedReleaseRole); } String operator = userInfoHolder.getUser().getUserId(); ConsumerRole namespaceModifyConsumerRole = createConsumerRole(consumerId, namespaceModifyRoleId, operator); ConsumerRole namespaceReleaseConsumerRole = createConsumerRole(consumerId, namespaceReleaseRoleId, operator); ConsumerRole createdModifyConsumerRole = consumerRoleRepository.save(namespaceModifyConsumerRole); ConsumerRole createdReleaseConsumerRole = consumerRoleRepository.save(namespaceReleaseConsumerRole); return Arrays.asList(createdModifyConsumerRole, createdReleaseConsumerRole); } @Transactional public ConsumerRole assignAppRoleToConsumer(String token, String appId) { Long consumerId = getConsumerIdByToken(token); if (consumerId == null) { throw new BadRequestException("Token is Illegal"); } Role masterRole = rolePermissionService.findRoleByRoleName(RoleUtils.buildAppMasterRoleName(appId)); if (masterRole == null) { throw new BadRequestException("App's role does not exist. Please check whether app has created."); } long roleId = masterRole.getId(); ConsumerRole managedModifyRole = consumerRoleRepository.findByConsumerIdAndRoleId(consumerId, roleId); if (managedModifyRole != null) { return managedModifyRole; } String operator = userInfoHolder.getUser().getUserId(); ConsumerRole consumerRole = createConsumerRole(consumerId, roleId, operator); return consumerRoleRepository.save(consumerRole); } @Transactional public void createConsumerAudits(Iterable consumerAudits) { consumerAuditRepository.save(consumerAudits); } @Transactional public ConsumerToken createConsumerToken(ConsumerToken entity) { entity.setId(0); //for protection return consumerTokenRepository.save(entity); } private ConsumerToken generateConsumerToken(Consumer consumer, Date expires) { long consumerId = consumer.getId(); String createdBy = userInfoHolder.getUser().getUserId(); Date createdTime = new Date(); ConsumerToken consumerToken = new ConsumerToken(); consumerToken.setConsumerId(consumerId); consumerToken.setExpires(expires); consumerToken.setDataChangeCreatedBy(createdBy); consumerToken.setDataChangeCreatedTime(createdTime); consumerToken.setDataChangeLastModifiedBy(createdBy); consumerToken.setDataChangeLastModifiedTime(createdTime); generateAndEnrichToken(consumer, consumerToken); return consumerToken; } void generateAndEnrichToken(Consumer consumer, ConsumerToken consumerToken) { Preconditions.checkArgument(consumer != null); if (consumerToken.getDataChangeCreatedTime() == null) { consumerToken.setDataChangeCreatedTime(new Date()); } consumerToken.setToken(generateToken(consumer.getAppId(), consumerToken .getDataChangeCreatedTime(), portalConfig.consumerTokenSalt())); } String generateToken(String consumerAppId, Date generationTime, String consumerTokenSalt) { return Hashing.sha1().hashString(KEY_JOINER.join(consumerAppId, TIMESTAMP_FORMAT.format (generationTime), consumerTokenSalt), Charsets.UTF_8).toString(); } ConsumerRole createConsumerRole(Long consumerId, Long roleId, String operator) { ConsumerRole consumerRole = new ConsumerRole(); consumerRole.setConsumerId(consumerId); consumerRole.setRoleId(roleId); consumerRole.setDataChangeCreatedBy(operator); consumerRole.setDataChangeLastModifiedBy(operator); return consumerRole; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/ConsumerAuditUtil.java ================================================ package com.ctrip.framework.apollo.openapi.util; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Queues; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.openapi.entity.ConsumerAudit; import com.ctrip.framework.apollo.openapi.service.ConsumerService; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.servlet.http.HttpServletRequest; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ConsumerAuditUtil implements InitializingBean { private static final int CONSUMER_AUDIT_MAX_SIZE = 10000; private BlockingQueue audits = Queues.newLinkedBlockingQueue(CONSUMER_AUDIT_MAX_SIZE); private final ExecutorService auditExecutorService; private final AtomicBoolean auditStopped; private int BATCH_SIZE = 100; private long BATCH_TIMEOUT = 5; private TimeUnit BATCH_TIMEUNIT = TimeUnit.SECONDS; @Autowired private ConsumerService consumerService; public ConsumerAuditUtil() { auditExecutorService = Executors.newSingleThreadExecutor( ApolloThreadFactory.create("ConsumerAuditUtil", true)); auditStopped = new AtomicBoolean(false); } public boolean audit(HttpServletRequest request, long consumerId) { //ignore GET request if ("GET".equalsIgnoreCase(request.getMethod())) { return true; } String uri = request.getRequestURI(); if (!Strings.isNullOrEmpty(request.getQueryString())) { uri += "?" + request.getQueryString(); } ConsumerAudit consumerAudit = new ConsumerAudit(); Date now = new Date(); consumerAudit.setConsumerId(consumerId); consumerAudit.setUri(uri); consumerAudit.setMethod(request.getMethod()); consumerAudit.setDataChangeCreatedTime(now); consumerAudit.setDataChangeLastModifiedTime(now); //throw away audits if exceeds the max size return this.audits.offer(consumerAudit); } @Override public void afterPropertiesSet() throws Exception { auditExecutorService.submit(() -> { while (!auditStopped.get() && !Thread.currentThread().isInterrupted()) { List toAudit = Lists.newArrayList(); try { Queues.drain(audits, toAudit, BATCH_SIZE, BATCH_TIMEOUT, BATCH_TIMEUNIT); if (!toAudit.isEmpty()) { consumerService.createConsumerAudits(toAudit); } } catch (Throwable ex) { Tracer.logError(ex); } } }); } public void stopAudit() { auditStopped.set(true); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/ConsumerAuthUtil.java ================================================ package com.ctrip.framework.apollo.openapi.util; import com.ctrip.framework.apollo.openapi.service.ConsumerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; /** * @author Jason Song(song_s@ctrip.com) */ @Service public class ConsumerAuthUtil { static final String CONSUMER_ID = "ApolloConsumerId"; @Autowired private ConsumerService consumerService; public Long getConsumerId(String token) { return consumerService.getConsumerIdByToken(token); } public void storeConsumerId(HttpServletRequest request, Long consumerId) { request.setAttribute(CONSUMER_ID, consumerId); } public long retrieveConsumerId(HttpServletRequest request) { Object value = request.getAttribute(CONSUMER_ID); try { return Long.parseLong(value.toString()); } catch (Throwable ex) { throw new IllegalStateException("No consumer id!", ex); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/OpenApiBeanUtils.java ================================================ package com.ctrip.framework.apollo.openapi.util; import com.google.common.base.Preconditions; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.ctrip.framework.apollo.common.dto.AppNamespaceDTO; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO; import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO; import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO; import com.ctrip.framework.apollo.portal.entity.bo.ItemBO; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import org.springframework.util.CollectionUtils; import java.lang.reflect.Type; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class OpenApiBeanUtils { private static Gson gson = new Gson(); private static Type type = new TypeToken>() { }.getType(); public static OpenItemDTO transformFromItemDTO(ItemDTO item) { Preconditions.checkArgument(item != null); return BeanUtils.transfrom(OpenItemDTO.class, item); } public static ItemDTO transformToItemDTO(OpenItemDTO openItemDTO) { Preconditions.checkArgument(openItemDTO != null); return BeanUtils.transfrom(ItemDTO.class, openItemDTO); } public static OpenAppNamespaceDTO transformToOpenAppNamespaceDTO(AppNamespace appNamespace) { Preconditions.checkArgument(appNamespace != null); return BeanUtils.transfrom(OpenAppNamespaceDTO.class, appNamespace); } public static AppNamespace transformToAppNamespace(OpenAppNamespaceDTO openAppNamespaceDTO) { Preconditions.checkArgument(openAppNamespaceDTO != null); return BeanUtils.transfrom(AppNamespace.class, openAppNamespaceDTO); } public static OpenReleaseDTO transformFromReleaseDTO(ReleaseDTO release) { Preconditions.checkArgument(release != null); OpenReleaseDTO openReleaseDTO = BeanUtils.transfrom(OpenReleaseDTO.class, release); Map configs = gson.fromJson(release.getConfigurations(), type); openReleaseDTO.setConfigurations(configs); return openReleaseDTO; } public static OpenNamespaceDTO transformFromNamespaceBO(NamespaceBO namespaceBO) { Preconditions.checkArgument(namespaceBO != null); OpenNamespaceDTO openNamespaceDTO = BeanUtils.transfrom(OpenNamespaceDTO.class, namespaceBO .getBaseInfo()); //app namespace info openNamespaceDTO.setFormat(namespaceBO.getFormat()); openNamespaceDTO.setComment(namespaceBO.getComment()); openNamespaceDTO.setPublic(namespaceBO.isPublic()); //items List items = new LinkedList<>(); List itemBOs = namespaceBO.getItems(); if (!CollectionUtils.isEmpty(itemBOs)) { items.addAll(itemBOs.stream().map(itemBO -> transformFromItemDTO(itemBO.getItem())).collect (Collectors.toList())); } openNamespaceDTO.setItems(items); return openNamespaceDTO; } public static List batchTransformFromNamespaceBOs(List namespaceBOs) { if (CollectionUtils.isEmpty(namespaceBOs)) { return Collections.emptyList(); } List openNamespaceDTOs = namespaceBOs.stream().map(OpenApiBeanUtils::transformFromNamespaceBO) .collect(Collectors.toCollection(LinkedList::new)); return openNamespaceDTOs; } public static OpenNamespaceLockDTO transformFromNamespaceLockDTO(String namespaceName, NamespaceLockDTO namespaceLock) { OpenNamespaceLockDTO lock = new OpenNamespaceLockDTO(); lock.setNamespaceName(namespaceName); if (namespaceLock == null) { lock.setLocked(false); } else { lock.setLocked(true); lock.setLockedBy(namespaceLock.getDataChangeCreatedBy()); } return lock; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/AppController.java ================================================ package com.ctrip.framework.apollo.openapi.v1.controller; import com.ctrip.framework.apollo.common.dto.ClusterDTO; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.openapi.dto.OpenEnvClusterDTO; import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.portal.service.ClusterService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.LinkedList; import java.util.List; @RestController("openapiAppController") @RequestMapping("/openapi/v1") public class AppController { @Autowired private PortalSettings portalSettings; @Autowired private ClusterService clusterService; @RequestMapping(value = "/apps/{appId}/envclusters", method = RequestMethod.GET) public List loadEnvClusterInfo(@PathVariable String appId){ List envClusters = new LinkedList<>(); List envs = portalSettings.getActiveEnvs(); for (Env env : envs) { OpenEnvClusterDTO envCluster = new OpenEnvClusterDTO(); envCluster.setEnv(env.name()); List clusterDTOs = clusterService.findClusters(env, appId); envCluster.setClusters(BeanUtils.toPropertySet("name", clusterDTOs)); envClusters.add(envCluster); } return envClusters; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java ================================================ package com.ctrip.framework.apollo.openapi.v1.controller; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils; import com.ctrip.framework.apollo.portal.service.ItemService; import com.ctrip.framework.apollo.portal.spi.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; @RestController("openapiItemController") @RequestMapping("/openapi/v1/envs/{env}") public class ItemController { @Autowired private ItemService itemService; @Autowired private UserService userService; @PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST) public OpenItemDTO createItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody OpenItemDTO item, HttpServletRequest request) { RequestPrecondition.checkArguments( !StringUtils.isContainEmpty(item.getKey(), item.getValue(), item.getDataChangeCreatedBy()), "key,value,dataChangeCreatedBy 字段不能为空"); if (userService.findByUserId(item.getDataChangeCreatedBy()) == null) { throw new BadRequestException("用户不存在."); } ItemDTO toCreate = OpenApiBeanUtils.transformToItemDTO(item); //protect toCreate.setLineNum(0); toCreate.setId(0); toCreate.setDataChangeLastModifiedBy(toCreate.getDataChangeCreatedBy()); toCreate.setDataChangeLastModifiedTime(null); toCreate.setDataChangeCreatedTime(null); ItemDTO createdItem = itemService.createItem(appId, Env.fromString(env), clusterName, namespaceName, toCreate); return OpenApiBeanUtils.transformFromItemDTO(createdItem); } @PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}", method = RequestMethod.PUT) public void updateItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String key, @RequestBody OpenItemDTO item, HttpServletRequest request) { RequestPrecondition.checkArguments(item != null, "item payload can not be empty"); RequestPrecondition.checkArguments( !StringUtils.isContainEmpty(item.getKey(), item.getValue(), item.getDataChangeLastModifiedBy()), "key,value,dataChangeLastModifiedBy can not be empty"); RequestPrecondition.checkArguments(item.getKey().equals(key), "Key in path and payload is not consistent"); if (userService.findByUserId(item.getDataChangeLastModifiedBy()) == null) { throw new BadRequestException("user(dataChangeLastModifiedBy) not exists"); } ItemDTO toUpdateItem = itemService.loadItem(Env.fromString(env), appId, clusterName, namespaceName, item.getKey()); if (toUpdateItem == null) { throw new BadRequestException("item not exists"); } //protect. only value,comment,lastModifiedBy can be modified toUpdateItem.setComment(item.getComment()); toUpdateItem.setValue(item.getValue()); toUpdateItem.setDataChangeLastModifiedBy(item.getDataChangeLastModifiedBy()); itemService.updateItem(appId, Env.fromString(env), clusterName, namespaceName, toUpdateItem); } @PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}", method = RequestMethod.DELETE) public void deleteItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String key, @RequestParam String operator, HttpServletRequest request) { if (userService.findByUserId(operator) == null) { throw new BadRequestException("user(operator) not exists"); } ItemDTO toDeleteItem = itemService.loadItem(Env.fromString(env), appId, clusterName, namespaceName, key); if (toDeleteItem == null){ throw new BadRequestException("item not exists"); } itemService.deleteItem(Env.fromString(env), toDeleteItem.getId(), operator); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/NamespaceController.java ================================================ package com.ctrip.framework.apollo.openapi.v1.controller; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.InputValidator; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO; import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO; import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO; import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import com.ctrip.framework.apollo.portal.listener.AppNamespaceCreationEvent; import com.ctrip.framework.apollo.portal.service.AppNamespaceService; import com.ctrip.framework.apollo.portal.service.NamespaceLockService; import com.ctrip.framework.apollo.portal.service.NamespaceService; import com.ctrip.framework.apollo.portal.spi.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Objects; import javax.servlet.http.HttpServletRequest; @RestController("openapiNamespaceController") public class NamespaceController { @Autowired private NamespaceLockService namespaceLockService; @Autowired private NamespaceService namespaceService; @Autowired private AppNamespaceService appNamespaceService; @Autowired private ApplicationEventPublisher publisher; @Autowired private UserService userService; @PreAuthorize(value = "@consumerPermissionValidator.hasCreateNamespacePermission(#request, #appId)") @RequestMapping(value = "/openapi/v1/apps/{appId}/appnamespaces", method = RequestMethod.POST) public OpenAppNamespaceDTO createNamespace(@PathVariable String appId, @RequestBody OpenAppNamespaceDTO appNamespaceDTO, HttpServletRequest request) { if (!Objects.equals(appId, appNamespaceDTO.getAppId())) { throw new BadRequestException(String.format("AppId not equal. AppId in path = %s, AppId in payload = %s", appId, appNamespaceDTO.getAppId())); } RequestPrecondition.checkArgumentsNotEmpty(appNamespaceDTO.getAppId(), appNamespaceDTO.getName(), appNamespaceDTO.getFormat(), appNamespaceDTO.getDataChangeCreatedBy()); if (!InputValidator.isValidAppNamespace(appNamespaceDTO.getName())) { throw new BadRequestException(String.format("Namespace格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE + " & " + InputValidator.INVALID_NAMESPACE_NAMESPACE_MESSAGE)); } if (!ConfigFileFormat.isValidFormat(appNamespaceDTO.getFormat())) { throw new BadRequestException(String.format("Invalid namespace format. format = %s", appNamespaceDTO.getFormat())); } String operator = appNamespaceDTO.getDataChangeCreatedBy(); if (userService.findByUserId(operator) == null) { throw new BadRequestException(String.format("Illegal user. user = %s", operator)); } AppNamespace appNamespace = OpenApiBeanUtils.transformToAppNamespace(appNamespaceDTO); AppNamespace createdAppNamespace = appNamespaceService.createAppNamespaceInLocal(appNamespace); publisher.publishEvent(new AppNamespaceCreationEvent(createdAppNamespace)); return OpenApiBeanUtils.transformToOpenAppNamespaceDTO(createdAppNamespace); } @RequestMapping(value = "/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces", method = RequestMethod.GET) public List findNamespaces(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName) { return OpenApiBeanUtils .batchTransformFromNamespaceBOs(namespaceService.findNamespaceBOs(appId, Env .fromString(env), clusterName)); } @RequestMapping(value = "/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}", method = RequestMethod.GET) public OpenNamespaceDTO loadNamespace(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { NamespaceBO namespaceBO = namespaceService.loadNamespaceBO(appId, Env.fromString (env), clusterName, namespaceName); if (namespaceBO == null) { return null; } return OpenApiBeanUtils.transformFromNamespaceBO(namespaceBO); } @RequestMapping(value = "/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock", method = RequestMethod.GET) public OpenNamespaceLockDTO getNamespaceLock(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { NamespaceDTO namespace = namespaceService.loadNamespaceBaseInfo(appId, Env .fromString(env), clusterName, namespaceName); NamespaceLockDTO lockDTO = namespaceLockService.getNamespaceLock(appId, Env .fromString(env), clusterName, namespaceName); return OpenApiBeanUtils.transformFromNamespaceLockDTO(namespace.getNamespaceName(), lockDTO); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ReleaseController.java ================================================ package com.ctrip.framework.apollo.openapi.v1.controller; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO; import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils; import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel; import com.ctrip.framework.apollo.portal.service.ReleaseService; import com.ctrip.framework.apollo.portal.spi.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel; @RestController("openapiReleaseController") @RequestMapping("/openapi/v1/envs/{env}") public class ReleaseController { @Autowired private ReleaseService releaseService; @Autowired private UserService userService; @PreAuthorize(value = "@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases", method = RequestMethod.POST) public OpenReleaseDTO createRelease(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model, HttpServletRequest request) { checkModel(model != null); RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(model.getReleasedBy(), model .getReleaseTitle()), "Params(releaseTitle and releasedBy) can not be empty"); if (userService.findByUserId(model.getReleasedBy()) == null) { throw new BadRequestException("user(releaseBy) not exists"); } model.setAppId(appId); model.setEnv(Env.fromString(env).toString()); model.setClusterName(clusterName); model.setNamespaceName(namespaceName); return OpenApiBeanUtils.transformFromReleaseDTO(releaseService.publish(model)); } @RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest", method = RequestMethod.GET) public OpenReleaseDTO loadLatestActiveRelease(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { ReleaseDTO releaseDTO = releaseService.loadLatestRelease(appId, Env.fromString (env), clusterName, namespaceName); if (releaseDTO == null) { return null; } return OpenApiBeanUtils.transformFromReleaseDTO(releaseDTO); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/PortalApplication.java ================================================ package com.ctrip.framework.apollo.portal; import com.ctrip.framework.apollo.common.ApolloCommonConfig; import com.ctrip.framework.apollo.openapi.PortalOpenApiConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.actuate.system.ApplicationPidFileWriter; import org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; @EnableAspectJAutoProxy @Configuration @PropertySource(value = {"classpath:portal.properties"}) @EnableAutoConfiguration @EnableTransactionManagement @ComponentScan(basePackageClasses = {ApolloCommonConfig.class, PortalApplication.class, PortalOpenApiConfig.class}) public class PortalApplication { public static void main(String[] args) throws Exception { ConfigurableApplicationContext context = SpringApplication.run(PortalApplication.class, args); context.addApplicationListener(new ApplicationPidFileWriter()); context.addApplicationListener(new EmbeddedServerPortFileWriter()); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/API.java ================================================ package com.ctrip.framework.apollo.portal.api; import com.ctrip.framework.apollo.portal.component.RetryableRestTemplate; import org.springframework.beans.factory.annotation.Autowired; public abstract class API { @Autowired protected RetryableRestTemplate restTemplate; } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java ================================================ package com.ctrip.framework.apollo.portal.api; import com.google.common.base.Joiner; import com.ctrip.framework.apollo.common.dto.AppDTO; import com.ctrip.framework.apollo.common.dto.AppNamespaceDTO; import com.ctrip.framework.apollo.common.dto.ClusterDTO; import com.ctrip.framework.apollo.common.dto.CommitDTO; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO; import com.ctrip.framework.apollo.common.dto.InstanceDTO; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO; import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.dto.ReleaseHistoryDTO; import com.ctrip.framework.apollo.core.enums.Env; import org.springframework.boot.actuate.health.Health; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @Service public class AdminServiceAPI { @Service public static class HealthAPI extends API { public Health health(Env env) { return restTemplate.get(env, "/health", Health.class); } } @Service public static class AppAPI extends API { public AppDTO loadApp(Env env, String appId) { return restTemplate.get(env, "apps/{appId}", AppDTO.class, appId); } public AppDTO createApp(Env env, AppDTO app) { return restTemplate.post(env, "apps", app, AppDTO.class); } public void updateApp(Env env, AppDTO app) { restTemplate.put(env, "apps/{appId}", app, app.getAppId()); } } @Service public static class NamespaceAPI extends API { private ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() { }; public List findNamespaceByCluster(String appId, Env env, String clusterName) { NamespaceDTO[] namespaceDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces", NamespaceDTO[].class, appId, clusterName); return Arrays.asList(namespaceDTOs); } public NamespaceDTO loadNamespace(String appId, Env env, String clusterName, String namespaceName) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}", NamespaceDTO.class, appId, clusterName, namespaceName); } public NamespaceDTO findPublicNamespaceForAssociatedNamespace(Env env, String appId, String clusterName, String namespaceName) { return restTemplate .get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace", NamespaceDTO.class, appId, clusterName, namespaceName); } public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) { return restTemplate .post(env, "apps/{appId}/clusters/{clusterName}/namespaces", namespace, NamespaceDTO.class, namespace.getAppId(), namespace.getClusterName()); } public AppNamespaceDTO createAppNamespace(Env env, AppNamespaceDTO appNamespace) { return restTemplate .post(env, "apps/{appId}/appnamespaces", appNamespace, AppNamespaceDTO.class, appNamespace.getAppId()); } public void deleteNamespace(Env env, String appId, String clusterName, String namespaceName, String operator) { restTemplate .delete(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}?operator={operator}", appId, clusterName, namespaceName, operator); } public Map getNamespacePublishInfo(Env env, String appId) { return restTemplate.get(env, "apps/{appId}/namespaces/publish_info", typeReference, appId).getBody(); } public List getPublicAppNamespaceAllNamespaces(Env env, String publicNamespaceName, int page, int size) { NamespaceDTO[] namespaceDTOs = restTemplate.get(env, "/appnamespaces/{publicNamespaceName}/namespaces?page={page}&size={size}", NamespaceDTO[].class, publicNamespaceName, page, size); return Arrays.asList(namespaceDTOs); } public int countPublicAppNamespaceAssociatedNamespaces(Env env, String publicNamesapceName) { Integer count = restTemplate.get(env, "/appnamespaces/{publicNamespaceName}/associated-namespaces/count", Integer.class, publicNamesapceName); return count == null ? 0 : count; } } @Service public static class ItemAPI extends API { public List findItems(String appId, Env env, String clusterName, String namespaceName) { ItemDTO[] itemDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", ItemDTO[].class, appId, clusterName, namespaceName); return Arrays.asList(itemDTOs); } public ItemDTO loadItem(Env env, String appId, String clusterName, String namespaceName, String key) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key}", ItemDTO.class, appId, clusterName, namespaceName, key); } public void updateItemsByChangeSet(String appId, Env env, String clusterName, String namespace, ItemChangeSets changeSets) { restTemplate.post(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset", changeSets, Void.class, appId, clusterName, namespace); } public void updateItem(String appId, Env env, String clusterName, String namespace, long itemId, ItemDTO item) { restTemplate.put(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", item, appId, clusterName, namespace, itemId); } public ItemDTO createItem(String appId, Env env, String clusterName, String namespace, ItemDTO item) { return restTemplate.post(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", item, ItemDTO.class, appId, clusterName, namespace); } public void deleteItem(Env env, long itemId, String operator) { restTemplate.delete(env, "items/{itemId}?operator={operator}", itemId, operator); } } @Service public static class ClusterAPI extends API { public List findClustersByApp(String appId, Env env) { ClusterDTO[] clusterDTOs = restTemplate.get(env, "apps/{appId}/clusters", ClusterDTO[].class, appId); return Arrays.asList(clusterDTOs); } public ClusterDTO loadCluster(String appId, Env env, String clusterName) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}", ClusterDTO.class, appId, clusterName); } public boolean isClusterUnique(String appId, Env env, String clusterName) { return restTemplate .get(env, "apps/{appId}/cluster/{clusterName}/unique", Boolean.class, appId, clusterName); } public ClusterDTO create(Env env, ClusterDTO cluster) { return restTemplate.post(env, "apps/{appId}/clusters", cluster, ClusterDTO.class, cluster.getAppId()); } public void delete(Env env, String appId, String clusterName, String operator) { restTemplate.delete(env, "apps/{appId}/clusters/{clusterName}?operator={operator}", appId, clusterName, operator); } } @Service public static class ReleaseAPI extends API { private static final Joiner JOINER = Joiner.on(","); public ReleaseDTO loadRelease(Env env, long releaseId) { return restTemplate.get(env, "releases/{releaseId}", ReleaseDTO.class, releaseId); } public List findReleaseByIds(Env env, Set releaseIds) { if (CollectionUtils.isEmpty(releaseIds)) { return Collections.emptyList(); } ReleaseDTO[] releases = restTemplate.get(env, "/releases?releaseIds={releaseIds}", ReleaseDTO[].class, JOINER.join(releaseIds)); return Arrays.asList(releases); } public List findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page, int size) { ReleaseDTO[] releaseDTOs = restTemplate.get( env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all?page={page}&size={size}", ReleaseDTO[].class, appId, clusterName, namespaceName, page, size); return Arrays.asList(releaseDTOs); } public List findActiveReleases(String appId, Env env, String clusterName, String namespaceName, int page, int size) { ReleaseDTO[] releaseDTOs = restTemplate.get( env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active?page={page}&size={size}", ReleaseDTO[].class, appId, clusterName, namespaceName, page, size); return Arrays.asList(releaseDTOs); } public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName, String namespace) { ReleaseDTO releaseDTO = restTemplate .get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest", ReleaseDTO.class, appId, clusterName, namespace); return releaseDTO; } public ReleaseDTO createRelease(String appId, Env env, String clusterName, String namespace, String releaseName, String releaseComment, String operator, boolean isEmergencyPublish) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); MultiValueMap parameters = new LinkedMultiValueMap<>(); parameters.add("name", releaseName); parameters.add("comment", releaseComment); parameters.add("operator", operator); parameters.add("isEmergencyPublish", String.valueOf(isEmergencyPublish)); HttpEntity> entity = new HttpEntity<>(parameters, headers); ReleaseDTO response = restTemplate.post( env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases", entity, ReleaseDTO.class, appId, clusterName, namespace); return response; } public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespace, String releaseName, String releaseComment, String branchName, boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) { return restTemplate.post(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish?" + "releaseName={releaseName}&releaseComment={releaseComment}&branchName={branchName}" + "&deleteBranch={deleteBranch}&isEmergencyPublish={isEmergencyPublish}", changeSets, ReleaseDTO.class, appId, clusterName, namespace, releaseName, releaseComment, branchName, deleteBranch, isEmergencyPublish); } public void rollback(Env env, long releaseId, String operator) { restTemplate.put(env, "releases/{releaseId}/rollback?operator={operator}", null, releaseId, operator); } } @Service public static class CommitAPI extends API { public List find(String appId, Env env, String clusterName, String namespaceName, int page, int size) { CommitDTO[] commitDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit?page={page}&size={size}", CommitDTO[].class, appId, clusterName, namespaceName, page, size); return Arrays.asList(commitDTOs); } } @Service public static class NamespaceLockAPI extends API { public NamespaceLockDTO getNamespaceLockOwner(String appId, Env env, String clusterName, String namespaceName) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock", NamespaceLockDTO.class, appId, clusterName, namespaceName); } } @Service public static class InstanceAPI extends API { private Joiner joiner = Joiner.on(","); private ParameterizedTypeReference> pageInstanceDtoType = new ParameterizedTypeReference>() { }; public PageDTO getByRelease(Env env, long releaseId, int page, int size) { ResponseEntity> entity = restTemplate .get(env, "/instances/by-release?releaseId={releaseId}&page={page}&size={size}", pageInstanceDtoType, releaseId, page, size); return entity.getBody(); } public List getByReleasesNotIn(String appId, Env env, String clusterName, String namespaceName, Set releaseIds) { InstanceDTO[] instanceDTOs = restTemplate.get(env, "/instances/by-namespace-and-releases-not-in?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}&releaseIds={releaseIds}", InstanceDTO[].class, appId, clusterName, namespaceName, joiner.join(releaseIds)); return Arrays.asList(instanceDTOs); } public PageDTO getByNamespace(String appId, Env env, String clusterName, String namespaceName, String instanceAppId, int page, int size) { ResponseEntity> entity = restTemplate.get(env, "/instances/by-namespace?appId={appId}" + "&clusterName={clusterName}&namespaceName={namespaceName}&instanceAppId={instanceAppId}" + "&page={page}&size={size}", pageInstanceDtoType, appId, clusterName, namespaceName, instanceAppId, page, size); return entity.getBody(); } public int getInstanceCountByNamespace(String appId, Env env, String clusterName, String namespaceName) { Integer count = restTemplate.get(env, "/instances/by-namespace/count?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}", Integer.class, appId, clusterName, namespaceName); if (count == null) { return 0; } return count; } } @Service public static class NamespaceBranchAPI extends API { public NamespaceDTO createBranch(String appId, Env env, String clusterName, String namespaceName, String operator) { return restTemplate .post(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches?operator={operator}", null, NamespaceDTO.class, appId, clusterName, namespaceName, operator); } public NamespaceDTO findBranch(String appId, Env env, String clusterName, String namespaceName) { return restTemplate.get(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches", NamespaceDTO.class, appId, clusterName, namespaceName); } public GrayReleaseRuleDTO findBranchGrayRules(String appId, Env env, String clusterName, String namespaceName, String branchName) { return restTemplate .get(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", GrayReleaseRuleDTO.class, appId, clusterName, namespaceName, branchName); } public void updateBranchGrayRules(String appId, Env env, String clusterName, String namespaceName, String branchName, GrayReleaseRuleDTO rules) { restTemplate .put(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", rules, appId, clusterName, namespaceName, branchName); } public void deleteBranch(String appId, Env env, String clusterName, String namespaceName, String branchName, String operator) { restTemplate.delete(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}?operator={operator}", appId, clusterName, namespaceName, branchName, operator); } } @Service public static class ReleaseHistoryAPI extends API { private ParameterizedTypeReference> type = new ParameterizedTypeReference>() { }; public PageDTO findReleaseHistoriesByNamespace(String appId, Env env, String clusterName, String namespaceName, int page, int size) { return restTemplate.get(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories?page={page}&size={size}", type, appId, clusterName, namespaceName, page, size).getBody(); } public PageDTO findByReleaseIdAndOperation(Env env, long releaseId, int operation, int page, int size) { return restTemplate.get(env, "/releases/histories/by_release_id_and_operation?releaseId={releaseId}&operation={operation}&page={page}&size={size}", type, releaseId, operation, page, size).getBody(); } public PageDTO findByPreviousReleaseIdAndOperation(Env env, long previousReleaseId, int operation, int page, int size) { return restTemplate.get(env, "/releases/histories/by_previous_release_id_and_operation?previousReleaseId={releaseId}&operation={operation}&page={page}&size={size}", type, previousReleaseId, operation, page, size).getBody(); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/AdminServiceAddressLocator.java ================================================ package com.ctrip.framework.apollo.portal.component; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.core.MetaDomainConsts; import com.ctrip.framework.apollo.core.dto.ServiceDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.web.HttpMessageConverters; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; @Component public class AdminServiceAddressLocator { private static final long NORMAL_REFRESH_INTERVAL = 5 * 60 * 1000; private static final long OFFLINE_REFRESH_INTERVAL = 10 * 1000; private static final int RETRY_TIMES = 3; private static final String ADMIN_SERVICE_URL_PATH = "/services/admin"; private static final Logger logger = LoggerFactory.getLogger(AdminServiceAddressLocator.class); private ScheduledExecutorService refreshServiceAddressService; private RestTemplate restTemplate; private List allEnvs; private Map> cache = new ConcurrentHashMap<>(); @Autowired private HttpMessageConverters httpMessageConverters; @Autowired private PortalSettings portalSettings; @Autowired private RestTemplateFactory restTemplateFactory; @PostConstruct public void init() { allEnvs = portalSettings.getAllEnvs(); //init restTemplate restTemplate = restTemplateFactory.getObject(); refreshServiceAddressService = Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("ServiceLocator", true)); refreshServiceAddressService.schedule(new RefreshAdminServerAddressTask(), 1, TimeUnit.MILLISECONDS); } public List getServiceList(Env env) { List services = cache.get(env); if (CollectionUtils.isEmpty(services)) { return Collections.emptyList(); } List randomConfigServices = Lists.newArrayList(services); Collections.shuffle(randomConfigServices); return randomConfigServices; } //maintain admin server address private class RefreshAdminServerAddressTask implements Runnable { @Override public void run() { boolean refreshSuccess = true; //refresh fail if get any env address fail for (Env env : allEnvs) { boolean currentEnvRefreshResult = refreshServerAddressCache(env); refreshSuccess = refreshSuccess && currentEnvRefreshResult; } if (refreshSuccess) { refreshServiceAddressService .schedule(new RefreshAdminServerAddressTask(), NORMAL_REFRESH_INTERVAL, TimeUnit.MILLISECONDS); } else { refreshServiceAddressService .schedule(new RefreshAdminServerAddressTask(), OFFLINE_REFRESH_INTERVAL, TimeUnit.MILLISECONDS); } } } private boolean refreshServerAddressCache(Env env) { for (int i = 0; i < RETRY_TIMES; i++) { try { ServiceDTO[] services = getAdminServerAddress(env); if (services == null || services.length == 0) { continue; } cache.put(env, Arrays.asList(services)); return true; } catch (Throwable e) { logger.error(String.format("Get admin server address from meta server failed. env: %s, meta server address:%s", env, MetaDomainConsts.getDomain(env)), e); Tracer .logError(String.format("Get admin server address from meta server failed. env: %s, meta server address:%s", env, MetaDomainConsts.getDomain(env)), e); } } return false; } private ServiceDTO[] getAdminServerAddress(Env env) { String domainName = MetaDomainConsts.getDomain(env); String url = domainName + ADMIN_SERVICE_URL_PATH; return restTemplate.getForObject(url, ServiceDTO[].class); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/ItemsComparator.java ================================================ package com.ctrip.framework.apollo.portal.component; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @Component public class ItemsComparator { public ItemChangeSets compareIgnoreBlankAndCommentItem(long baseNamespaceId, List baseItems, List targetItems){ List filteredSourceItems = filterBlankAndCommentItem(baseItems); List filteredTargetItems = filterBlankAndCommentItem(targetItems); Map sourceItemMap = BeanUtils.mapByKey("key", filteredSourceItems); Map targetItemMap = BeanUtils.mapByKey("key", filteredTargetItems); ItemChangeSets changeSets = new ItemChangeSets(); for (ItemDTO item: targetItems){ String key = item.getKey(); ItemDTO sourceItem = sourceItemMap.get(key); if (sourceItem == null){//add ItemDTO copiedItem = copyItem(item); copiedItem.setNamespaceId(baseNamespaceId); changeSets.addCreateItem(copiedItem); }else if (!Objects.equals(sourceItem.getValue(), item.getValue())){//update //only value & comment can be update sourceItem.setValue(item.getValue()); sourceItem.setComment(item.getComment()); changeSets.addUpdateItem(sourceItem); } } for (ItemDTO item: baseItems){ String key = item.getKey(); ItemDTO targetItem = targetItemMap.get(key); if(targetItem == null){//delete changeSets.addDeleteItem(item); } } return changeSets; } private List filterBlankAndCommentItem(List items){ List result = new LinkedList<>(); if (CollectionUtils.isEmpty(items)){ return result; } for (ItemDTO item: items){ if (!StringUtils.isEmpty(item.getKey())){ result.add(item); } } return result; } private ItemDTO copyItem(ItemDTO sourceItem){ ItemDTO copiedItem = new ItemDTO(); copiedItem.setKey(sourceItem.getKey()); copiedItem.setValue(sourceItem.getValue()); copiedItem.setComment(sourceItem.getComment()); return copiedItem; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PermissionValidator.java ================================================ package com.ctrip.framework.apollo.portal.component; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.constant.PermissionType; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.util.RoleUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component("permissionValidator") public class PermissionValidator { @Autowired private UserInfoHolder userInfoHolder; @Autowired private RolePermissionService rolePermissionService; @Autowired private PortalConfig portalConfig; public boolean hasModifyNamespacePermission(String appId, String namespaceName) { return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), PermissionType.MODIFY_NAMESPACE, RoleUtils.buildNamespaceTargetId(appId, namespaceName)); } public boolean hasReleaseNamespacePermission(String appId, String namespaceName) { return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), PermissionType.RELEASE_NAMESPACE, RoleUtils.buildNamespaceTargetId(appId, namespaceName)); } public boolean hasDeleteNamespacePermission(String appId) { return hasAssignRolePermission(appId) || isSuperAdmin(); } public boolean hasOperateNamespacePermission(String appId, String namespaceName) { return hasModifyNamespacePermission(appId, namespaceName) || hasReleaseNamespacePermission(appId, namespaceName); } public boolean hasAssignRolePermission(String appId) { return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), PermissionType.ASSIGN_ROLE, appId); } public boolean hasCreateNamespacePermission(String appId) { return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), PermissionType.CREATE_NAMESPACE, appId); } public boolean hasCreateAppNamespacePermission(String appId, AppNamespace appNamespace) { boolean isPublicAppNamespace = appNamespace.isPublic(); if (portalConfig.canAppAdminCreatePrivateNamespace() || isPublicAppNamespace) { return hasCreateNamespacePermission(appId); } return isSuperAdmin(); } public boolean hasCreateClusterPermission(String appId) { return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), PermissionType.CREATE_CLUSTER, appId); } public boolean isAppAdmin(String appId) { return isSuperAdmin() || hasAssignRolePermission(appId); } public boolean isSuperAdmin() { return rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId()); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PortalSettings.java ================================================ package com.ctrip.framework.apollo.portal.component; import com.ctrip.framework.apollo.core.MetaDomainConsts; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.health.Health; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; @Component public class PortalSettings { private static final Logger logger = LoggerFactory.getLogger(PortalSettings.class); private static final int HEALTH_CHECK_INTERVAL = 10 * 1000; @Autowired ApplicationContext applicationContext; @Autowired private PortalConfig portalConfig; private List allEnvs = new ArrayList<>(); //mark env up or down private Map envStatusMark = new ConcurrentHashMap<>(); @PostConstruct private void postConstruct() { allEnvs = portalConfig.portalSupportedEnvs(); for (Env env : allEnvs) { envStatusMark.put(env, true); } ScheduledExecutorService healthCheckService = Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("EnvHealthChecker", true)); healthCheckService .scheduleWithFixedDelay(new HealthCheckTask(applicationContext), 1000, HEALTH_CHECK_INTERVAL, TimeUnit.MILLISECONDS); } public List getAllEnvs() { return allEnvs; } public List getActiveEnvs() { List activeEnvs = new LinkedList<>(); for (Env env : allEnvs) { if (envStatusMark.get(env)) { activeEnvs.add(env); } } return activeEnvs; } public boolean isEnvActive(Env env) { Boolean mark = envStatusMark.get(env); return mark == null ? false : mark; } private class HealthCheckTask implements Runnable { private static final int ENV_DOWN_THRESHOLD = 2; private Map healthCheckFailedCounter = new HashMap<>(); private AdminServiceAPI.HealthAPI healthAPI; public HealthCheckTask(ApplicationContext context) { healthAPI = context.getBean(AdminServiceAPI.HealthAPI.class); for (Env env : allEnvs) { healthCheckFailedCounter.put(env, 0); } } public void run() { for (Env env : allEnvs) { try { if (isUp(env)) { //revive if (!envStatusMark.get(env)) { envStatusMark.put(env, true); healthCheckFailedCounter.put(env, 0); logger.info("Env revived because env health check success. env: {}", env); } } else { logger.error("Env health check failed, maybe because of admin server down. env: {}, meta server address: {}", env, MetaDomainConsts.getDomain(env)); handleEnvDown(env); } } catch (Exception e) { logger.error("Env health check failed, maybe because of meta server down " + "or configure wrong meta server address. env: {}, meta server address: {}", env, MetaDomainConsts.getDomain(env), e); handleEnvDown(env); } } } private boolean isUp(Env env) { Health health = healthAPI.health(env); return "UP".equals(health.getStatus().getCode()); } private void handleEnvDown(Env env) { int failedTimes = healthCheckFailedCounter.get(env); healthCheckFailedCounter.put(env, ++failedTimes); if (!envStatusMark.get(env)) { logger.error("Env is down. env: {}, failed times: {}, meta server address: {}", env, failedTimes, MetaDomainConsts.getDomain(env)); } else { if (failedTimes >= ENV_DOWN_THRESHOLD) { envStatusMark.put(env, false); logger.error("Env is down because health check failed for {} times, " + "which equals to down threshold. env: {}, meta server address: {}", ENV_DOWN_THRESHOLD, env, MetaDomainConsts.getDomain(env)); } else { logger.error( "Env health check failed for {} times which less than down threshold. down threshold:{}, env: {}, meta server address: {}", failedTimes, ENV_DOWN_THRESHOLD, env, MetaDomainConsts.getDomain(env)); } } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/RestTemplateFactory.java ================================================ package com.ctrip.framework.apollo.portal.component; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.web.HttpMessageConverters; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.io.UnsupportedEncodingException; @Component public class RestTemplateFactory implements FactoryBean, InitializingBean { @Autowired private HttpMessageConverters httpMessageConverters; @Autowired private PortalConfig portalConfig; private RestTemplate restTemplate; public RestTemplate getObject() { return restTemplate; } public Class getObjectType() { return RestTemplate.class; } public boolean isSingleton() { return true; } public void afterPropertiesSet() throws UnsupportedEncodingException { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); restTemplate = new RestTemplate(httpMessageConverters.getConverters()); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); requestFactory.setConnectTimeout(portalConfig.connectTimeout()); requestFactory.setReadTimeout(portalConfig.readTimeout()); restTemplate.setRequestFactory(requestFactory); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/RetryableRestTemplate.java ================================================ package com.ctrip.framework.apollo.portal.component; import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.core.MetaDomainConsts; import com.ctrip.framework.apollo.core.dto.ServiceDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.spi.Transaction; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.HttpHostConnectException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriTemplateHandler; import org.springframework.web.util.UriTemplateHandler; import java.net.SocketTimeoutException; import java.util.List; import javax.annotation.PostConstruct; /** * 封装RestTemplate. admin server集群在某些机器宕机或者超时的情况下轮询重试 */ @Component public class RetryableRestTemplate { private Logger logger = LoggerFactory.getLogger(RetryableRestTemplate.class); private UriTemplateHandler uriTemplateHandler = new DefaultUriTemplateHandler(); private RestTemplate restTemplate; @Autowired private RestTemplateFactory restTemplateFactory; @Autowired private AdminServiceAddressLocator adminServiceAddressLocator; @PostConstruct private void postConstruct() { restTemplate = restTemplateFactory.getObject(); } public T get(Env env, String path, Class responseType, Object... urlVariables) throws RestClientException { return execute(HttpMethod.GET, env, path, null, responseType, urlVariables); } public ResponseEntity get(Env env, String path, ParameterizedTypeReference reference, Object... uriVariables) throws RestClientException { return exchangeGet(env, path, reference, uriVariables); } public T post(Env env, String path, Object request, Class responseType, Object... uriVariables) throws RestClientException { return execute(HttpMethod.POST, env, path, request, responseType, uriVariables); } public void put(Env env, String path, Object request, Object... urlVariables) throws RestClientException { execute(HttpMethod.PUT, env, path, request, null, urlVariables); } public void delete(Env env, String path, Object... urlVariables) throws RestClientException { execute(HttpMethod.DELETE, env, path, null, null, urlVariables); } private T execute(HttpMethod method, Env env, String path, Object request, Class responseType, Object... uriVariables) { if (path.startsWith("/")) { path = path.substring(1, path.length()); } String uri = uriTemplateHandler.expand(path, uriVariables).getPath(); Transaction ct = Tracer.newTransaction("AdminAPI", uri); ct.addData("Env", env); List services = getAdminServices(env, ct); for (ServiceDTO serviceDTO : services) { try { T result = doExecute(method, serviceDTO, path, request, responseType, uriVariables); ct.setStatus(Transaction.SUCCESS); ct.complete(); return result; } catch (Throwable t) { logger.error("Http request failed, uri: {}, method: {}", uri, method, t); Tracer.logError(t); if (canRetry(t, method)) { Tracer.logEvent(TracerEventType.API_RETRY, uri); } else {//biz exception rethrow ct.setStatus(t); ct.complete(); throw t; } } } //all admin server down ServiceException e = new ServiceException(String.format("Admin servers are unresponsive. meta server address: %s, admin servers: %s", MetaDomainConsts.getDomain(env), services)); ct.setStatus(e); ct.complete(); throw e; } private ResponseEntity exchangeGet(Env env, String path, ParameterizedTypeReference reference, Object... uriVariables) { if (path.startsWith("/")) { path = path.substring(1, path.length()); } String uri = uriTemplateHandler.expand(path, uriVariables).getPath(); Transaction ct = Tracer.newTransaction("AdminAPI", uri); ct.addData("Env", env); List services = getAdminServices(env, ct); for (ServiceDTO serviceDTO : services) { try { ResponseEntity result = restTemplate.exchange(parseHost(serviceDTO) + path, HttpMethod.GET, null, reference, uriVariables); ct.setStatus(Transaction.SUCCESS); ct.complete(); return result; } catch (Throwable t) { logger.error("Http request failed, uri: {}, method: {}", uri, HttpMethod.GET, t); Tracer.logError(t); if (canRetry(t, HttpMethod.GET)) { Tracer.logEvent(TracerEventType.API_RETRY, uri); } else {// biz exception rethrow ct.setStatus(t); ct.complete(); throw t; } } } //all admin server down ServiceException e = new ServiceException(String.format("Admin servers are unresponsive. meta server address: %s, admin servers: %s", MetaDomainConsts.getDomain(env), services)); ct.setStatus(e); ct.complete(); throw e; } private List getAdminServices(Env env, Transaction ct) { List services = adminServiceAddressLocator.getServiceList(env); if (CollectionUtils.isEmpty(services)) { ServiceException e = new ServiceException(String.format("No available admin server." + " Maybe because of meta server down or all admin server down. " + "Meta server address: %s", MetaDomainConsts.getDomain(env))); ct.setStatus(e); ct.complete(); throw e; } return services; } private T doExecute(HttpMethod method, ServiceDTO service, String path, Object request, Class responseType, Object... uriVariables) { T result = null; switch (method) { case GET: result = restTemplate.getForObject(parseHost(service) + path, responseType, uriVariables); break; case POST: result = restTemplate.postForEntity(parseHost(service) + path, request, responseType, uriVariables).getBody(); break; case PUT: restTemplate.put(parseHost(service) + path, request, uriVariables); break; case DELETE: restTemplate.delete(parseHost(service) + path, uriVariables); break; default: throw new UnsupportedOperationException(String.format("unsupported http method(method=%s)", method)); } return result; } private String parseHost(ServiceDTO serviceAddress) { return serviceAddress.getHomepageUrl() + "/"; } //post,delete,put请求在admin server处理超时情况下不重试 private boolean canRetry(Throwable e, HttpMethod method) { Throwable nestedException = e.getCause(); if (method == HttpMethod.GET) { return nestedException instanceof SocketTimeoutException || nestedException instanceof HttpHostConnectException || nestedException instanceof ConnectTimeoutException; } else { return nestedException instanceof HttpHostConnectException || nestedException instanceof ConnectTimeoutException; } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/config/PortalConfig.java ================================================ package com.ctrip.framework.apollo.portal.component.config; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.ctrip.framework.apollo.common.config.RefreshableConfig; import com.ctrip.framework.apollo.common.config.RefreshablePropertySource; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.vo.Organization; import com.ctrip.framework.apollo.portal.service.PortalDBPropertySource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.lang.reflect.Type; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @Component public class PortalConfig extends RefreshableConfig { private Gson gson = new Gson(); private static final Type ORGANIZATION = new TypeToken>() { }.getType(); @Autowired private PortalDBPropertySource portalDBPropertySource; @Override public List getRefreshablePropertySources() { return Collections.singletonList(portalDBPropertySource); } /*** * Level: important **/ public List portalSupportedEnvs() { String[] configurations = getArrayProperty("apollo.portal.envs", new String[]{"FAT", "UAT", "PRO"}); List envs = Lists.newLinkedList(); for (String env : configurations) { envs.add(Env.fromString(env)); } return envs; } public List superAdmins() { String superAdminConfig = getValue("superAdmin", ""); if (Strings.isNullOrEmpty(superAdminConfig)) { return Collections.emptyList(); } return splitter.splitToList(superAdminConfig); } public Set emailSupportedEnvs() { String[] configurations = getArrayProperty("email.supported.envs", null); Set result = Sets.newHashSet(); if (configurations == null || configurations.length == 0) { return result; } for (String env : configurations) { result.add(Env.fromString(env)); } return result; } /*** * Level: normal **/ public int connectTimeout() { return getIntProperty("api.connectTimeout", 3000); } public int readTimeout() { return getIntProperty("api.readTimeout", 10000); } public List organizations() { String organizations = getValue("organizations"); return organizations == null ? Collections.emptyList() : gson.fromJson(organizations, ORGANIZATION); } public String portalAddress() { return getValue("apollo.portal.address"); } public boolean isEmergencyPublishAllowed(Env env) { String targetEnv = env.name(); String[] emergencyPublishSupportedEnvs = getArrayProperty("emergencyPublish.supported.envs", new String[0]); for (String supportedEnv : emergencyPublishSupportedEnvs) { if (Objects.equals(targetEnv, supportedEnv.toUpperCase().trim())) { return true; } } return false; } /*** * Level: low **/ public Set publishTipsSupportedEnvs() { String[] configurations = getArrayProperty("namespace.publish.tips.supported.envs", null); Set result = Sets.newHashSet(); if (configurations == null || configurations.length == 0) { return result; } for (String env : configurations) { result.add(Env.fromString(env)); } return result; } public String consumerTokenSalt() { return getValue("consumer.token.salt", "apollo-portal"); } public String emailSender() { return getValue("email.sender"); } public String emailTemplateFramework() { return getValue("email.template.framework", ""); } public String emailReleaseDiffModuleTemplate() { return getValue("email.template.release.module.diff", ""); } public String emailRollbackDiffModuleTemplate() { return getValue("email.template.rollback.module.diff", ""); } public String emailGrayRulesModuleTemplate() { return getValue("email.template.release.module.rules", ""); } public String wikiAddress() { return getValue("wiki.address", "https://github.com/ctripcorp/apollo/wiki"); } public boolean canAppAdminCreatePrivateNamespace() { return getBooleanProperty("admin.createPrivateNamespace.switch", true); } /*** * The following configurations are used in ctrip profile **/ public int appId() { return getIntProperty("ctrip.appid", 0); } //send code & template id. apply from ewatch public String sendCode() { return getValue("ctrip.email.send.code"); } public int templateId() { return getIntProperty("ctrip.email.template.id", 0); } //email retention time in email server queue.TimeUnit: hour public int survivalDuration() { return getIntProperty("ctrip.email.survival.duration", 5); } public boolean isSendEmailAsync() { return getBooleanProperty("email.send.async", true); } public String portalServerName() { return getValue("serverName"); } public String casServerLoginUrl() { return getValue("casServerLoginUrl"); } public String casServerUrlPrefix() { return getValue("casServerUrlPrefix"); } public String credisServiceUrl() { return getValue("credisServiceUrl"); } public String userServiceUrl() { return getValue("userService.url"); } public String userServiceAccessToken() { return getValue("userService.accessToken"); } public String soaServerAddress() { return getValue("soa.server.address"); } public String cloggingUrl() { return getValue("clogging.server.url"); } public String cloggingPort() { return getValue("clogging.server.port"); } public String hermesServerAddress() { return getValue("hermes.server.address"); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/ConfigPublishEmailBuilder.java ================================================ package com.ctrip.framework.apollo.portal.component.emailbuilder; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.common.constants.ReleaseOperation; import com.ctrip.framework.apollo.common.constants.ReleaseOperationContext; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.constant.RoleType; import com.ctrip.framework.apollo.portal.entity.bo.Email; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.vo.Change; import com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult; import com.ctrip.framework.apollo.portal.service.AppNamespaceService; import com.ctrip.framework.apollo.portal.service.ReleaseService; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.portal.util.RoleUtils; import org.apache.commons.lang.time.FastDateFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; public abstract class ConfigPublishEmailBuilder { private static final String EMERGENCY_PUBLISH_TAG = "(紧急发布)"; //email content common field placeholder private static final String EMAIL_CONTENT_FIELD_APPID = "#\\{appId\\}"; private static final String EMAIL_CONTENT_FIELD_ENV = "#\\{env}"; private static final String EMAIL_CONTENT_FIELD_CLUSTER = "#\\{clusterName}"; private static final String EMAIL_CONTENT_FIELD_NAMESPACE = "#\\{namespaceName}"; private static final String EMAIL_CONTENT_FIELD_OPERATOR = "#\\{operator}"; private static final String EMAIL_CONTENT_FIELD_RELEASE_TIME = "#\\{releaseTime}"; private static final String EMAIL_CONTENT_FIELD_RELEASE_ID = "#\\{releaseId}"; private static final String EMAIL_CONTENT_FIELD_RELEASE_HISTORY_ID = "#\\{releaseHistoryId}"; private static final String EMAIL_CONTENT_FIELD_RELEASE_TITLE = "#\\{releaseTitle}"; private static final String EMAIL_CONTENT_FIELD_RELEASE_COMMENT = "#\\{releaseComment}"; private static final String EMAIL_CONTENT_FIELD_APOLLO_SERVER_ADDRESS = "#\\{apollo.portal.address}"; private static final String EMAIL_CONTENT_FIELD_DIFF_CONTENT = "#\\{diffContent}"; private static final String EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH = "#\\{emergencyPublish}"; private static final String EMAIL_CONTENT_DIFF_MODULE = "#\\{diffModule}"; protected static final String EMAIL_CONTENT_GRAY_RULES_MODULE = "#\\{rulesModule}"; //email content special field placeholder protected static final String EMAIL_CONTENT_GRAY_RULES_CONTENT = "#\\{rulesContent}"; //set config's value max length to protect email. protected static final int VALUE_MAX_LENGTH = 100; protected FastDateFormat dateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss"); @Autowired private RolePermissionService rolePermissionService; @Autowired private ReleaseService releaseService; @Autowired private AppNamespaceService appNamespaceService; @Autowired private UserService userService; @Autowired protected PortalConfig portalConfig; /** * email subject */ protected abstract String subject(); /** * email body content */ protected abstract String emailContent(Env env, ReleaseHistoryBO releaseHistory); /** * email body template framework */ protected abstract String getTemplateFramework(); /** * email body diff module template */ protected abstract String getDiffModuleTemplate(); public Email build(Env env, ReleaseHistoryBO releaseHistory) { Email email = new Email(); email.setSubject(subject()); email.setSenderEmailAddress(portalConfig.emailSender()); email.setRecipients(recipients(releaseHistory.getAppId(), releaseHistory.getNamespaceName())); String emailBody = emailContent(env, releaseHistory); //clear not used module emailBody = emailBody.replaceAll(EMAIL_CONTENT_DIFF_MODULE, ""); emailBody = emailBody.replaceAll(EMAIL_CONTENT_GRAY_RULES_MODULE, ""); email.setBody(emailBody); return email; } protected String renderEmailCommonContent(Env env, ReleaseHistoryBO releaseHistory) { String template = getTemplateFramework(); String renderResult = renderReleaseBasicInfo(template, env, releaseHistory); renderResult = renderDiffModule(renderResult, env, releaseHistory); return renderResult; } private String renderReleaseBasicInfo(String template, Env env, ReleaseHistoryBO releaseHistory) { String renderResult = template; Map operationContext = releaseHistory.getOperationContext(); boolean isEmergencyPublish = operationContext.containsKey(ReleaseOperationContext.IS_EMERGENCY_PUBLISH) && (boolean) operationContext.get(ReleaseOperationContext.IS_EMERGENCY_PUBLISH); if (isEmergencyPublish) { renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH, Matcher.quoteReplacement(EMERGENCY_PUBLISH_TAG)); } else { renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_EMERGENCY_PUBLISH, ""); } renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_APPID, Matcher.quoteReplacement(releaseHistory.getAppId())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_ENV, Matcher.quoteReplacement(env.toString())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_CLUSTER, Matcher.quoteReplacement(releaseHistory.getClusterName())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_NAMESPACE, Matcher.quoteReplacement(releaseHistory.getNamespaceName())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_OPERATOR, Matcher.quoteReplacement(releaseHistory.getOperator())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_TITLE, Matcher.quoteReplacement(releaseHistory.getReleaseTitle())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_ID, String.valueOf(releaseHistory.getReleaseId())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_HISTORY_ID, String.valueOf(releaseHistory.getId())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_RELEASE_COMMENT, Matcher.quoteReplacement(releaseHistory.getReleaseComment())); renderResult = renderResult.replaceAll(EMAIL_CONTENT_FIELD_APOLLO_SERVER_ADDRESS, getApolloPortalAddress()); return renderResult .replaceAll(EMAIL_CONTENT_FIELD_RELEASE_TIME, dateFormat.format(releaseHistory.getReleaseTime())); } private String renderDiffModule(String bodyTemplate, Env env, ReleaseHistoryBO releaseHistory) { String appId = releaseHistory.getAppId(); String namespaceName = releaseHistory.getNamespaceName(); AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(appId, namespaceName); if (appNamespace == null) { appNamespace = appNamespaceService.findPublicAppNamespace(namespaceName); } //don't show diff content if namespace's format is file if (appNamespace == null || !appNamespace.getFormat().equals(ConfigFileFormat.Properties.getValue())) { return bodyTemplate.replaceAll(EMAIL_CONTENT_DIFF_MODULE, "

变更内容请点击链接到Apollo上查看

"); } ReleaseCompareResult result = getReleaseCompareResult(env, releaseHistory); if (!result.hasContent()) { return bodyTemplate.replaceAll(EMAIL_CONTENT_DIFF_MODULE, "

无配置变更

"); } List changes = result.getChanges(); StringBuilder changesHtmlBuilder = new StringBuilder(); for (Change change : changes) { String key = change.getEntity().getFirstEntity().getKey(); String oldValue = change.getEntity().getFirstEntity().getValue(); String newValue = change.getEntity().getSecondEntity().getValue(); newValue = newValue == null ? "" : newValue; changesHtmlBuilder.append(""); changesHtmlBuilder.append("").append(change.getType().toString()).append(""); changesHtmlBuilder.append("").append(cutOffString(key)).append(""); changesHtmlBuilder.append("").append(cutOffString(oldValue)).append(""); changesHtmlBuilder.append("").append(cutOffString(newValue)).append(""); changesHtmlBuilder.append(""); } String diffContent = Matcher.quoteReplacement(changesHtmlBuilder.toString()); String diffModuleTemplate = getDiffModuleTemplate(); String diffModuleRenderResult = diffModuleTemplate.replaceAll(EMAIL_CONTENT_FIELD_DIFF_CONTENT, diffContent); return bodyTemplate.replaceAll(EMAIL_CONTENT_DIFF_MODULE, diffModuleRenderResult); } private ReleaseCompareResult getReleaseCompareResult(Env env, ReleaseHistoryBO releaseHistory) { if (releaseHistory.getOperation() == ReleaseOperation.GRAY_RELEASE && releaseHistory.getPreviousReleaseId() == 0) { ReleaseDTO masterLatestActiveRelease = releaseService.loadLatestRelease( releaseHistory.getAppId(), env, releaseHistory.getClusterName(), releaseHistory.getNamespaceName()); ReleaseDTO branchLatestActiveRelease = releaseService.findReleaseById(env, releaseHistory.getReleaseId()); return releaseService.compare(masterLatestActiveRelease, branchLatestActiveRelease); } return releaseService.compare(env, releaseHistory.getPreviousReleaseId(), releaseHistory.getReleaseId()); } private List recipients(String appId, String namespaceName) { Set modifyRoleUsers = rolePermissionService .queryUsersWithRole(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.MODIFY_NAMESPACE)); Set releaseRoleUsers = rolePermissionService .queryUsersWithRole(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.RELEASE_NAMESPACE)); Set owners = rolePermissionService.queryUsersWithRole(RoleUtils.buildAppMasterRoleName(appId)); Set userIds = new HashSet<>(modifyRoleUsers.size() + releaseRoleUsers.size() + owners.size()); for (UserInfo userInfo : modifyRoleUsers) { userIds.add(userInfo.getUserId()); } for (UserInfo userInfo : releaseRoleUsers) { userIds.add(userInfo.getUserId()); } for (UserInfo userInfo : owners) { userIds.add(userInfo.getUserId()); } List userInfos = userService.findByUserIds(Lists.newArrayList(userIds)); if (CollectionUtils.isEmpty(userInfos)) { return Collections.emptyList(); } List recipients = new ArrayList<>(userInfos.size()); for (UserInfo userInfo : userInfos) { recipients.add(userInfo.getEmail()); } return recipients; } protected String getApolloPortalAddress() { return portalConfig.portalAddress(); } private String cutOffString(String source) { if (source.length() > VALUE_MAX_LENGTH) { return source.substring(0, VALUE_MAX_LENGTH) + "..."; } return source; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/GrayPublishEmailBuilder.java ================================================ package com.ctrip.framework.apollo.portal.component.emailbuilder; import com.google.common.base.Joiner; import com.google.gson.Gson; import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleItemDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; @Component public class GrayPublishEmailBuilder extends ConfigPublishEmailBuilder { private static final String EMAIL_SUBJECT = "[Apollo] 灰度发布"; private Gson gson = new Gson(); private Joiner IP_JOINER = Joiner.on(", "); @Override protected String subject() { return EMAIL_SUBJECT; } @Override public String emailContent(Env env, ReleaseHistoryBO releaseHistory) { String result = renderEmailCommonContent(env, releaseHistory); return renderGrayReleaseRuleContent(result, releaseHistory); } @Override protected String getTemplateFramework() { return portalConfig.emailTemplateFramework(); } @Override protected String getDiffModuleTemplate() { return portalConfig.emailReleaseDiffModuleTemplate(); } private String renderGrayReleaseRuleContent(String bodyTemplate, ReleaseHistoryBO releaseHistory) { Map context = releaseHistory.getOperationContext(); Object rules = context.get("rules"); List ruleItems = rules == null ? null : gson.fromJson(rules.toString(), GsonType.RULE_ITEMS); if (CollectionUtils.isEmpty(ruleItems)) { return bodyTemplate.replaceAll(EMAIL_CONTENT_GRAY_RULES_MODULE, "

无灰度规则

"); } else { StringBuilder rulesHtmlBuilder = new StringBuilder(); for (GrayReleaseRuleItemDTO ruleItem : ruleItems) { String clientAppId = ruleItem.getClientAppId(); Set ips = ruleItem.getClientIpList(); rulesHtmlBuilder.append("AppId: ") .append(clientAppId) .append("   IP: "); IP_JOINER.appendTo(rulesHtmlBuilder, ips); } String grayRulesModuleContent = portalConfig.emailGrayRulesModuleTemplate().replaceAll(EMAIL_CONTENT_GRAY_RULES_CONTENT, Matcher.quoteReplacement(rulesHtmlBuilder.toString())); return bodyTemplate.replaceAll(EMAIL_CONTENT_GRAY_RULES_MODULE, Matcher.quoteReplacement(grayRulesModuleContent)); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/MergeEmailBuilder.java ================================================ package com.ctrip.framework.apollo.portal.component.emailbuilder; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import org.springframework.stereotype.Component; @Component public class MergeEmailBuilder extends ConfigPublishEmailBuilder { private static final String EMAIL_SUBJECT = "[Apollo] 全量发布"; @Override protected String subject() { return EMAIL_SUBJECT; } @Override protected String emailContent(Env env, ReleaseHistoryBO releaseHistory) { return renderEmailCommonContent(env, releaseHistory); } @Override protected String getTemplateFramework() { return portalConfig.emailTemplateFramework(); } @Override protected String getDiffModuleTemplate() { return portalConfig.emailReleaseDiffModuleTemplate(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/NormalPublishEmailBuilder.java ================================================ package com.ctrip.framework.apollo.portal.component.emailbuilder; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import org.springframework.stereotype.Component; @Component public class NormalPublishEmailBuilder extends ConfigPublishEmailBuilder { private static final String EMAIL_SUBJECT = "[Apollo] 配置发布"; @Override protected String subject() { return EMAIL_SUBJECT; } @Override protected String emailContent(Env env, ReleaseHistoryBO releaseHistory) { return renderEmailCommonContent(env, releaseHistory); } @Override protected String getTemplateFramework() { return portalConfig.emailTemplateFramework(); } @Override protected String getDiffModuleTemplate() { return portalConfig.emailReleaseDiffModuleTemplate(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/emailbuilder/RollbackEmailBuilder.java ================================================ package com.ctrip.framework.apollo.portal.component.emailbuilder; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import org.springframework.stereotype.Component; @Component public class RollbackEmailBuilder extends ConfigPublishEmailBuilder { private static final String EMAIL_SUBJECT = "[Apollo] 配置回滚"; @Override protected String subject() { return EMAIL_SUBJECT; } @Override protected String emailContent(Env env, ReleaseHistoryBO releaseHistory) { return renderEmailCommonContent(env, releaseHistory); } @Override protected String getTemplateFramework() { return portalConfig.emailTemplateFramework(); } @Override protected String getDiffModuleTemplate() { return portalConfig.emailRollbackDiffModuleTemplate(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/ConfigTextResolver.java ================================================ package com.ctrip.framework.apollo.portal.component.txtresolver; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import java.util.List; /** * users can modify config in text mode.so need resolve text. */ public interface ConfigTextResolver { ItemChangeSets resolve(long namespaceId, String configText, List baseItems); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/FileTextResolver.java ================================================ package com.ctrip.framework.apollo.portal.component.txtresolver; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.utils.StringUtils; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; @Component("fileTextResolver") public class FileTextResolver implements ConfigTextResolver { @Override public ItemChangeSets resolve(long namespaceId, String configText, List baseItems) { ItemChangeSets changeSets = new ItemChangeSets(); if (StringUtils.isEmpty(configText)) { return changeSets; } if (CollectionUtils.isEmpty(baseItems)) { changeSets.addCreateItem(createItem(namespaceId, 0, configText)); } else { ItemDTO beforeItem = baseItems.get(0); if (!configText.equals(beforeItem.getValue())) {//update changeSets.addUpdateItem(createItem(namespaceId, beforeItem.getId(), configText)); } } return changeSets; } private ItemDTO createItem(long namespaceId, long itemId, String value) { ItemDTO item = new ItemDTO(); item.setId(itemId); item.setNamespaceId(namespaceId); item.setValue(value); item.setLineNum(1); item.setKey(ConfigConsts.CONFIG_FILE_CONTENT_KEY); return item; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/txtresolver/PropertyResolver.java ================================================ package com.ctrip.framework.apollo.portal.component.txtresolver; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * normal property file resolver. * update comment and blank item implement by create new item and delete old item. * update normal key/value item implement by update. */ @Component("propertyResolver") public class PropertyResolver implements ConfigTextResolver { private static final String KV_SEPARATOR = "="; private static final String ITEM_SEPARATOR = "\n"; @Override public ItemChangeSets resolve(long namespaceId, String configText, List baseItems) { Map oldLineNumMapItem = BeanUtils.mapByKey("lineNum", baseItems); Map oldKeyMapItem = BeanUtils.mapByKey("key", baseItems); //remove comment and blank item map. oldKeyMapItem.remove(""); String[] newItems = configText.split(ITEM_SEPARATOR); if (isHasRepeatKey(newItems)) { throw new BadRequestException("config text has repeat key please check."); } ItemChangeSets changeSets = new ItemChangeSets(); Map newLineNumMapItem = new HashMap();//use for delete blank and comment item int lineCounter = 1; for (String newItem : newItems) { newItem = newItem.trim(); newLineNumMapItem.put(lineCounter, newItem); ItemDTO oldItemByLine = oldLineNumMapItem.get(lineCounter); //comment item if (isCommentItem(newItem)) { handleCommentLine(namespaceId, oldItemByLine, newItem, lineCounter, changeSets); //blank item } else if (isBlankItem(newItem)) { handleBlankLine(namespaceId, oldItemByLine, lineCounter, changeSets); //normal item } else { handleNormalLine(namespaceId, oldKeyMapItem, newItem, lineCounter, changeSets); } lineCounter++; } deleteCommentAndBlankItem(oldLineNumMapItem, newLineNumMapItem, changeSets); deleteNormalKVItem(oldKeyMapItem, changeSets); return changeSets; } private boolean isHasRepeatKey(String[] newItems) { Set keys = new HashSet<>(); int lineCounter = 1; int keyCount = 0; for (String item : newItems) { if (!isCommentItem(item) && !isBlankItem(item)) { keyCount++; String[] kv = parseKeyValueFromItem(item); if (kv != null) { keys.add(kv[0]); } else { throw new BadRequestException("line:" + lineCounter + " key value must separate by '='"); } } lineCounter++; } return keyCount > keys.size(); } private String[] parseKeyValueFromItem(String item) { int kvSeparator = item.indexOf(KV_SEPARATOR); if (kvSeparator == -1) { return null; } String[] kv = new String[2]; kv[0] = item.substring(0, kvSeparator).trim(); kv[1] = item.substring(kvSeparator + 1, item.length()).trim(); return kv; } private void handleCommentLine(Long namespaceId, ItemDTO oldItemByLine, String newItem, int lineCounter, ItemChangeSets changeSets) { String oldComment = oldItemByLine == null ? "" : oldItemByLine.getComment(); //create comment. implement update comment by delete old comment and create new comment if (!(isCommentItem(oldItemByLine) && newItem.equals(oldComment))) { changeSets.addCreateItem(buildCommentItem(0l, namespaceId, newItem, lineCounter)); } } private void handleBlankLine(Long namespaceId, ItemDTO oldItem, int lineCounter, ItemChangeSets changeSets) { if (!isBlankItem(oldItem)) { changeSets.addCreateItem(buildBlankItem(0l, namespaceId, lineCounter)); } } private void handleNormalLine(Long namespaceId, Map keyMapOldItem, String newItem, int lineCounter, ItemChangeSets changeSets) { String[] kv = parseKeyValueFromItem(newItem); if (kv == null) { throw new BadRequestException("line:" + lineCounter + " key value must separate by '='"); } String newKey = kv[0]; String newValue = kv[1].replace("\\n", "\n"); //handle user input \n ItemDTO oldItem = keyMapOldItem.get(newKey); if (oldItem == null) {//new item changeSets.addCreateItem(buildNormalItem(0l, namespaceId, newKey, newValue, "", lineCounter)); } else if (!newValue.equals(oldItem.getValue()) || lineCounter != oldItem.getLineNum()) {//update item changeSets.addUpdateItem( buildNormalItem(oldItem.getId(), namespaceId, newKey, newValue, oldItem.getComment(), lineCounter)); } keyMapOldItem.remove(newKey); } private boolean isCommentItem(ItemDTO item) { return item != null && "".equals(item.getKey()) && (item.getComment().startsWith("#") || item.getComment().startsWith("!")); } private boolean isCommentItem(String line) { return line != null && (line.startsWith("#") || line.startsWith("!")); } private boolean isBlankItem(ItemDTO item) { return item != null && "".equals(item.getKey()) && "".equals(item.getComment()); } private boolean isBlankItem(String line) { return "".equals(line); } private void deleteNormalKVItem(Map baseKeyMapItem, ItemChangeSets changeSets) { //surplus item is to be deleted for (Map.Entry entry : baseKeyMapItem.entrySet()) { changeSets.addDeleteItem(entry.getValue()); } } private void deleteCommentAndBlankItem(Map oldLineNumMapItem, Map newLineNumMapItem, ItemChangeSets changeSets) { for (Map.Entry entry : oldLineNumMapItem.entrySet()) { int lineNum = entry.getKey(); ItemDTO oldItem = entry.getValue(); String newItem = newLineNumMapItem.get(lineNum); //1. old is blank by now is not //2.old is comment by now is not exist or modified if ((isBlankItem(oldItem) && !isBlankItem(newItem)) || isCommentItem(oldItem) && (newItem == null || !newItem.equals(oldItem.getComment()))) { changeSets.addDeleteItem(oldItem); } } } private ItemDTO buildCommentItem(Long id, Long namespaceId, String comment, int lineNum) { return buildNormalItem(id, namespaceId, "", "", comment, lineNum); } private ItemDTO buildBlankItem(Long id, Long namespaceId, int lineNum) { return buildNormalItem(id, namespaceId, "", "", "", lineNum); } private ItemDTO buildNormalItem(Long id, Long namespaceId, String key, String value, String comment, int lineNum) { ItemDTO item = new ItemDTO(key, value, comment, lineNum); item.setId(id); item.setNamespaceId(namespaceId); return item; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/constant/PermissionType.java ================================================ package com.ctrip.framework.apollo.portal.constant; public interface PermissionType { /** * APP level permission */ String CREATE_NAMESPACE = "CreateNamespace"; String CREATE_CLUSTER = "CreateCluster"; /** * 分配用户权限的权限 */ String ASSIGN_ROLE = "AssignRole"; /** * namespace level permission */ String MODIFY_NAMESPACE = "ModifyNamespace"; String RELEASE_NAMESPACE = "ReleaseNamespace"; } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/constant/RoleType.java ================================================ package com.ctrip.framework.apollo.portal.constant; public class RoleType { public static final String MASTER = "Master"; public static final String MODIFY_NAMESPACE = "ModifyNamespace"; public static final String RELEASE_NAMESPACE = "ReleaseNamespace"; public static boolean isValidRoleType(String roleType) { return MASTER.equals(roleType) || MODIFY_NAMESPACE.equals(roleType) || RELEASE_NAMESPACE.equals(roleType); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/constant/TracerEventType.java ================================================ package com.ctrip.framework.apollo.portal.constant; public interface TracerEventType { String RELEASE_NAMESPACE = "Namespace.Release"; String MODIFY_NAMESPACE_BY_TEXT = "Namespace.Modify.Text"; String MODIFY_NAMESPACE = "Namespace.Modify"; String SYNC_NAMESPACE = "Namespace.Sync"; String CREATE_APP = "App.Create"; String CREATE_CLUSTER = "Cluster.Create"; String CREATE_NAMESPACE = "Namespace.Create"; String API_RETRY = "API.Retry"; String USER_ACCESS = "User.Access"; String CREATE_GRAY_RELEASE = "GrayRelease.Create"; String DELETE_GRAY_RELEASE = "GrayRelease.Delete"; String MERGE_GRAY_RELEASE = "GrayRelease.Merge"; String UPDATE_GRAY_RELEASE_RULE = "GrayReleaseRule.Update"; } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.http.MultiResponseEntity; import com.ctrip.framework.apollo.common.http.RichResponseEntity; import com.ctrip.framework.apollo.common.utils.InputValidator; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.portal.entity.model.AppModel; import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo; import com.ctrip.framework.apollo.portal.listener.AppCreationEvent; import com.ctrip.framework.apollo.portal.listener.AppInfoChangedEvent; import com.ctrip.framework.apollo.portal.service.AppService; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.util.RoleUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.HttpClientErrorException; import java.util.List; import java.util.Objects; import java.util.Set; @RestController @RequestMapping("/apps") public class AppController { @Autowired private UserInfoHolder userInfoHolder; @Autowired private AppService appService; @Autowired private PortalSettings portalSettings; @Autowired private ApplicationEventPublisher publisher; @Autowired private RolePermissionService rolePermissionService; @RequestMapping(value = "", method = RequestMethod.GET) public List findApps(@RequestParam(value = "appIds", required = false) String appIds) { if (StringUtils.isEmpty(appIds)) { return appService.findAll(); } else { return appService.findByAppIds(Sets.newHashSet(appIds.split(","))); } } @RequestMapping(value = "/by-owner", method = RequestMethod.GET) public List findAppsByOwner(@RequestParam("owner") String owner, Pageable page) { return appService.findByOwnerName(owner, page); } @RequestMapping(value = "", method = RequestMethod.POST) public App create(@RequestBody AppModel appModel) { App app = transformToApp(appModel); App createdApp = appService.createAppInLocal(app); publisher.publishEvent(new AppCreationEvent(createdApp)); Set admins = appModel.getAdmins(); if (!CollectionUtils.isEmpty(admins)) { rolePermissionService.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()), admins, userInfoHolder.getUser().getUserId()); } return createdApp; } @PreAuthorize(value = "@permissionValidator.isAppAdmin(#appId)") @RequestMapping(value = "/{appId:.+}", method = RequestMethod.PUT) public void update(@PathVariable String appId, @RequestBody AppModel appModel) { if (!Objects.equals(appId, appModel.getAppId())) { throw new BadRequestException("The App Id of path variable and request body is different"); } App app = transformToApp(appModel); App updatedApp = appService.updateAppInLocal(app); publisher.publishEvent(new AppInfoChangedEvent(updatedApp)); } @RequestMapping(value = "/{appId}/navtree", method = RequestMethod.GET) public MultiResponseEntity nav(@PathVariable String appId) { MultiResponseEntity response = MultiResponseEntity.ok(); List envs = portalSettings.getActiveEnvs(); for (Env env : envs) { try { response.addResponseEntity(RichResponseEntity.ok(appService.createEnvNavNode(env, appId))); } catch (Exception e) { response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, "load env:" + env.name() + " cluster error." + e .getMessage())); } } return response; } @RequestMapping(value = "/envs/{env}", method = RequestMethod.POST, consumes = { "application/json"}) public ResponseEntity create(@PathVariable String env, @RequestBody App app) { RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(), app.getOrgId(), app.getOrgName()); if (!InputValidator.isValidClusterNamespace(app.getAppId())) { throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE); } appService.createAppInRemote(Env.valueOf(env), app); return ResponseEntity.ok().build(); } @RequestMapping(value = "/{appId:.+}", method = RequestMethod.GET) public App load(@PathVariable String appId) { return appService.load(appId); } @RequestMapping(value = "/{appId}/miss_envs", method = RequestMethod.GET) public MultiResponseEntity findMissEnvs(@PathVariable String appId) { MultiResponseEntity response = MultiResponseEntity.ok(); for (Env env : portalSettings.getActiveEnvs()) { try { appService.load(env, appId); } catch (Exception e) { if (e instanceof HttpClientErrorException && ((HttpClientErrorException) e).getStatusCode() == HttpStatus.NOT_FOUND) { response.addResponseEntity(RichResponseEntity.ok(env)); } else { response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, String.format("load appId:%s from env %s error.", appId, env) + e.getMessage())); } } } return response; } private App transformToApp(AppModel appModel) { String appId = appModel.getAppId(); String appName = appModel.getName(); String ownerName = appModel.getOwnerName(); String orgId = appModel.getOrgId(); String orgName = appModel.getOrgName(); RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName); if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) { throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); } return App.builder() .appId(appId) .name(appName) .ownerName(ownerName) .orgId(orgId) .orgName(orgName) .build(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ClusterController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.dto.ClusterDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.InputValidator; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.service.ClusterService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.Objects; import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel; @RestController public class ClusterController { @Autowired private ClusterService clusterService; @Autowired private UserInfoHolder userInfoHolder; @PreAuthorize(value = "@permissionValidator.hasCreateClusterPermission(#appId)") @RequestMapping(value = "apps/{appId}/envs/{env}/clusters", method = RequestMethod.POST) public ClusterDTO createCluster(@PathVariable String appId, @PathVariable String env, @RequestBody ClusterDTO cluster) { checkModel(Objects.nonNull(cluster)); RequestPrecondition.checkArgumentsNotEmpty(cluster.getAppId(), cluster.getName()); if (!InputValidator.isValidClusterNamespace(cluster.getName())) { throw new BadRequestException(String.format("Cluster格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); } String operator = userInfoHolder.getUser().getUserId(); cluster.setDataChangeLastModifiedBy(operator); cluster.setDataChangeCreatedBy(operator); return clusterService.createCluster(Env.valueOf(env), cluster); } @PreAuthorize(value = "@permissionValidator.isSuperAdmin()") @RequestMapping(value = "apps/{appId}/envs/{env}/clusters/{clusterName:.+}", method = RequestMethod.DELETE) public ResponseEntity deleteCluster(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName){ clusterService.deleteCluster(Env.valueOf(env), appId, clusterName); return ResponseEntity.ok().build(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/CommitController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.dto.CommitDTO; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.service.CommitService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class CommitController { @Autowired private CommitService commitService; @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/commits", method = RequestMethod.GET) public List find(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size) { RequestPrecondition.checkNumberPositive(size); RequestPrecondition.checkNumberNotNegative(page); return commitService.find(appId, Env.valueOf(env), clusterName, namespaceName, page, size); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ConsumerController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.openapi.entity.Consumer; import com.ctrip.framework.apollo.openapi.entity.ConsumerRole; import com.ctrip.framework.apollo.openapi.entity.ConsumerToken; import com.ctrip.framework.apollo.openapi.service.ConsumerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.Objects; /** * @author Jason Song(song_s@ctrip.com) */ @RestController public class ConsumerController { private static final Date DEFAULT_EXPIRES = new GregorianCalendar(2099, Calendar.JANUARY, 1).getTime(); @Autowired private ConsumerService consumerService; @Transactional @PreAuthorize(value = "@permissionValidator.isSuperAdmin()") @RequestMapping(value = "/consumers", method = RequestMethod.POST) public ConsumerToken createConsumer(@RequestBody Consumer consumer, @RequestParam(value = "expires", required = false) @DateTimeFormat(pattern = "yyyyMMddHHmmss") Date expires) { if (StringUtils.isContainEmpty(consumer.getAppId(), consumer.getName(), consumer.getOwnerName(), consumer.getOrgId())) { throw new BadRequestException("Params(appId、name、ownerName、orgId) can not be empty."); } Consumer createdConsumer = consumerService.createConsumer(consumer); if (Objects.isNull(expires)) { expires = DEFAULT_EXPIRES; } return consumerService.generateAndSaveConsumerToken(createdConsumer, expires); } @RequestMapping(value = "/consumers/by-appId", method = RequestMethod.GET) public ConsumerToken getConsumerTokenByAppId(@RequestParam String appId) { return consumerService.getConsumerTokenByAppId(appId); } @PreAuthorize(value = "@permissionValidator.isSuperAdmin()") @RequestMapping(value = "/consumers/{token}/assign-role", method = RequestMethod.POST) public List assignNamespaceRoleToConsumer(@PathVariable String token, @RequestParam String type, @RequestBody NamespaceDTO namespace) { String appId = namespace.getAppId(); String namespaceName = namespace.getNamespaceName(); if (StringUtils.isEmpty(appId)) { throw new BadRequestException("Params(AppId) can not be empty."); } if (Objects.equals("AppRole", type)) { return Collections.singletonList(consumerService.assignAppRoleToConsumer(token, appId)); } else { if (StringUtils.isEmpty(namespaceName)) { throw new BadRequestException("Params(NamespaceName) can not be empty."); } return consumerService.assignNamespaceRoleToConsumer(token, appId, namespaceName); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/EnvController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.component.PortalSettings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @RequestMapping("/envs") public class EnvController { @Autowired private PortalSettings portalSettings; @RequestMapping(value = "", method = RequestMethod.GET) public List envs() { return portalSettings.getActiveEnvs(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/FavoriteController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.portal.entity.po.Favorite; import com.ctrip.framework.apollo.portal.service.FavoriteService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class FavoriteController { @Autowired private FavoriteService favoriteService; @RequestMapping(value = "/favorites", method = RequestMethod.POST) public Favorite addFavorite(@RequestBody Favorite favorite) { return favoriteService.addFavorite(favorite); } @RequestMapping(value = "/favorites", method = RequestMethod.GET) public List findFavorites(@RequestParam(value = "userId", required = false) String userId, @RequestParam(value = "appId", required = false) String appId, Pageable page) { return favoriteService.search(userId, appId, page); } @RequestMapping(value = "/favorites/{favoriteId}", method = RequestMethod.DELETE) public void deleteFavorite(@PathVariable long favoriteId) { favoriteService.deleteFavorite(favoriteId); } @RequestMapping(value = "/favorites/{favoriteId}", method = RequestMethod.PUT) public void toTop(@PathVariable long favoriteId) { favoriteService.adjustFavoriteToFirst(favoriteId); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/InstanceController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.google.common.base.Splitter; import com.ctrip.framework.apollo.common.dto.InstanceDTO; import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.vo.Number; import com.ctrip.framework.apollo.portal.service.InstanceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @RestController public class InstanceController { private static final Splitter RELEASES_SPLITTER = Splitter.on(",").omitEmptyStrings() .trimResults(); @Autowired private InstanceService instanceService; @RequestMapping(value = "/envs/{env}/instances/by-release", method = RequestMethod.GET) public PageDTO getByRelease(@PathVariable String env, @RequestParam long releaseId, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size) { return instanceService.getByRelease(Env.valueOf(env), releaseId, page, size); } @RequestMapping(value = "/envs/{env}/instances/by-namespace", method = RequestMethod.GET) public PageDTO getByNamespace(@PathVariable String env, @RequestParam String appId, @RequestParam String clusterName, @RequestParam String namespaceName, @RequestParam(required = false) String instanceAppId, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size) { return instanceService.getByNamespace(Env.valueOf(env), appId, clusterName, namespaceName, instanceAppId, page, size); } @RequestMapping(value = "/envs/{env}/instances/by-namespace/count", method = RequestMethod.GET) public ResponseEntity getInstanceCountByNamespace(@PathVariable String env, @RequestParam String appId, @RequestParam String clusterName, @RequestParam String namespaceName) { int count = instanceService.getInstanceCountByNamepsace(appId, Env.valueOf(env), clusterName, namespaceName); return ResponseEntity.ok(new Number(count)); } @RequestMapping(value = "/envs/{env}/instances/by-namespace-and-releases-not-in", method = RequestMethod.GET) public List getByReleasesNotIn(@PathVariable String env, @RequestParam String appId, @RequestParam String clusterName, @RequestParam String namespaceName, @RequestParam String releaseIds) { Set releaseIdSet = RELEASES_SPLITTER.splitToList(releaseIds).stream().map(Long::parseLong) .collect(Collectors.toSet()); if (CollectionUtils.isEmpty(releaseIdSet)) { throw new BadRequestException("release ids can not be empty"); } return instanceService.getByReleasesNotIn(Env.valueOf(env), appId, clusterName, namespaceName, releaseIdSet); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ItemController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.entity.model.NamespaceSyncModel; import com.ctrip.framework.apollo.portal.entity.model.NamespaceTextModel; import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs; import com.ctrip.framework.apollo.portal.service.ItemService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Collections; import java.util.List; import java.util.Objects; import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel; @RestController public class ItemController { @Autowired private ItemService configService; @Autowired private UserInfoHolder userInfoHolder; @PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = { "application/json"}) public void modifyItemsByText(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody NamespaceTextModel model) { checkModel(model != null); model.setAppId(appId); model.setClusterName(clusterName); model.setEnv(env); model.setNamespaceName(namespaceName); configService.updateConfigItemByText(model); } @PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.POST) public ItemDTO createItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody ItemDTO item) { checkModel(isValidItem(item)); //protect item.setLineNum(0); item.setId(0); String userId = userInfoHolder.getUser().getUserId(); item.setDataChangeCreatedBy(userId); item.setDataChangeLastModifiedBy(userId); item.setDataChangeCreatedTime(null); item.setDataChangeLastModifiedTime(null); return configService.createItem(appId, Env.valueOf(env), clusterName, namespaceName, item); } @PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.PUT) public void updateItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody ItemDTO item) { checkModel(isValidItem(item)); String username = userInfoHolder.getUser().getUserId(); item.setDataChangeLastModifiedBy(username); configService.updateItem(appId, Env.valueOf(env), clusterName, namespaceName, item); } @PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", method = RequestMethod.DELETE) public void deleteItem(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable long itemId) { if (itemId <= 0) { throw new BadRequestException("item id invalid"); } configService.deleteItem(Env.valueOf(env), itemId, userInfoHolder.getUser().getUserId()); } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.GET) public List findItems(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestParam(defaultValue = "lineNum") String orderBy) { List items = configService.findItems(appId, Env.valueOf(env), clusterName, namespaceName); if ("lastModifiedTime".equals(orderBy)) { Collections.sort(items, (o1, o2) -> { if (o1.getDataChangeLastModifiedTime().after(o2.getDataChangeLastModifiedTime())) { return -1; } if (o1.getDataChangeLastModifiedTime().before(o2.getDataChangeLastModifiedTime())) { return 1; } return 0; }); } return items; } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/items", method = RequestMethod.GET) public List findBranchItems(@PathVariable("appId") String appId, @PathVariable String env, @PathVariable("clusterName") String clusterName, @PathVariable("namespaceName") String namespaceName, @PathVariable("branchName") String branchName) { return findItems(appId, env, branchName, namespaceName, "lastModifiedTime"); } @RequestMapping(value = "/namespaces/{namespaceName}/diff", method = RequestMethod.POST, consumes = { "application/json"}) public List diff(@RequestBody NamespaceSyncModel model) { checkModel(Objects.nonNull(model) && !model.isInvalid()); return configService.compare(model.getSyncToNamespaces(), model.getSyncItems()); } @PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = { "application/json"}) public ResponseEntity update(@PathVariable String appId, @PathVariable String namespaceName, @RequestBody NamespaceSyncModel model) { checkModel(Objects.nonNull(model) && !model.isInvalid()); configService.syncItems(model.getSyncToNamespaces(), model.getSyncItems()); return ResponseEntity.status(HttpStatus.OK).build(); } private boolean isValidItem(ItemDTO item) { return Objects.nonNull(item) && !StringUtils.isContainEmpty(item.getKey()); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceBranchController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.component.PermissionValidator; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent; import com.ctrip.framework.apollo.portal.service.NamespaceBranchService; import com.ctrip.framework.apollo.portal.service.ReleaseService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class NamespaceBranchController { @Autowired private PermissionValidator permissionValidator; @Autowired private ReleaseService releaseService; @Autowired private NamespaceBranchService namespaceBranchService; @Autowired private ApplicationEventPublisher publisher; @Autowired private PortalConfig portalConfig; @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches", method = RequestMethod.GET) public NamespaceBO findBranch(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { return namespaceBranchService.findBranch(appId, Env.valueOf(env), clusterName, namespaceName); } @PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches", method = RequestMethod.POST) public NamespaceDTO createBranch(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { return namespaceBranchService.createBranch(appId, Env.valueOf(env), clusterName, namespaceName); } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}", method = RequestMethod.DELETE) public void deleteBranch(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName) { boolean canDelete = permissionValidator.hasReleaseNamespacePermission(appId, namespaceName) || (permissionValidator.hasModifyNamespacePermission(appId, namespaceName) && releaseService.loadLatestRelease(appId, Env.valueOf(env), branchName, namespaceName) == null); if (!canDelete) { throw new AccessDeniedException("Forbidden operation. " + "Caused by: 1.you don't have release permission " + "or 2. you don't have modification permission " + "or 3. you have modification permission but branch has been released"); } namespaceBranchService.deleteBranch(appId, Env.valueOf(env), clusterName, namespaceName, branchName); } @PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/merge", method = RequestMethod.POST) public ReleaseDTO merge(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName, @RequestParam(value = "deleteBranch", defaultValue = "true") boolean deleteBranch, @RequestBody NamespaceReleaseModel model) { if (model.isEmergencyPublish() && !portalConfig.isEmergencyPublishAllowed(Env.fromString(env))) { throw new BadRequestException(String.format("Env: %s is not supported emergency publish now", env)); } ReleaseDTO createdRelease = namespaceBranchService.merge(appId, Env.valueOf(env), clusterName, namespaceName, branchName, model.getReleaseTitle(), model.getReleaseComment(), model.isEmergencyPublish(), deleteBranch); ConfigPublishEvent event = ConfigPublishEvent.instance(); event.withAppId(appId) .withCluster(clusterName) .withNamespace(namespaceName) .withReleaseId(createdRelease.getId()) .setMergeEvent(true) .setEnv(Env.valueOf(env)); publisher.publishEvent(event); return createdRelease; } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", method = RequestMethod.GET) public GrayReleaseRuleDTO getBranchGrayRules(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName) { return namespaceBranchService.findBranchGrayRules(appId, Env.valueOf(env), clusterName, namespaceName, branchName); } @PreAuthorize(value = "@permissionValidator.hasOperateNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", method = RequestMethod.PUT) public void updateBranchRules(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName, @RequestBody GrayReleaseRuleDTO rules) { namespaceBranchService .updateBranchGrayRules(appId, Env.valueOf(env), clusterName, namespaceName, branchName, rules); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.InputValidator; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.constant.RoleType; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import com.ctrip.framework.apollo.portal.entity.model.NamespaceCreationModel; import com.ctrip.framework.apollo.portal.listener.AppNamespaceCreationEvent; import com.ctrip.framework.apollo.portal.service.AppNamespaceService; import com.ctrip.framework.apollo.portal.service.NamespaceService; import com.ctrip.framework.apollo.portal.service.RoleInitializationService; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.util.RoleUtils; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel; @RestController public class NamespaceController { private static final Logger logger = LoggerFactory.getLogger(NamespaceController.class); @Autowired private ApplicationEventPublisher publisher; @Autowired private UserInfoHolder userInfoHolder; @Autowired private NamespaceService namespaceService; @Autowired private AppNamespaceService appNamespaceService; @Autowired private RoleInitializationService roleInitializationService; @Autowired private RolePermissionService rolePermissionService; @Autowired private PortalConfig portalConfig; @RequestMapping(value = "/appnamespaces/public", method = RequestMethod.GET) public List findPublicAppNamespaces() { return appNamespaceService.findPublicAppNamespaces(); } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces", method = RequestMethod.GET) public List findNamespaces(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName) { return namespaceService.findNamespaceBOs(appId, Env.valueOf(env), clusterName); } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName:.+}", method = RequestMethod.GET) public NamespaceBO findNamespace(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { return namespaceService.loadNamespaceBO(appId, Env.valueOf(env), clusterName, namespaceName); } @RequestMapping(value = "/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace", method = RequestMethod.GET) public NamespaceBO findPublicNamespaceForAssociatedNamespace(@PathVariable String env, @PathVariable String appId, @PathVariable String namespaceName, @PathVariable String clusterName) { return namespaceService.findPublicNamespaceForAssociatedNamespace(Env.valueOf(env), appId, clusterName, namespaceName); } @PreAuthorize(value = "@permissionValidator.hasCreateNamespacePermission(#appId)") @RequestMapping(value = "/apps/{appId}/namespaces", method = RequestMethod.POST) public ResponseEntity createNamespace(@PathVariable String appId, @RequestBody List models) { checkModel(!CollectionUtils.isEmpty(models)); String namespaceName = models.get(0).getNamespace().getNamespaceName(); String operator = userInfoHolder.getUser().getUserId(); roleInitializationService.initNamespaceRoles(appId, namespaceName, operator); for (NamespaceCreationModel model : models) { NamespaceDTO namespace = model.getNamespace(); RequestPrecondition.checkArgumentsNotEmpty(model.getEnv(), namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName()); try { namespaceService.createNamespace(Env.valueOf(model.getEnv()), namespace); } catch (Exception e) { logger.error("create namespace fail.", e); Tracer.logError( String.format("create namespace fail. (env=%s namespace=%s)", model.getEnv(), namespace.getNamespaceName()), e); } } assignNamespaceRoleToOperator(appId, namespaceName); return ResponseEntity.ok().build(); } @PreAuthorize(value = "@permissionValidator.hasDeleteNamespacePermission(#appId)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName:.+}", method = RequestMethod.DELETE) public ResponseEntity deleteNamespace(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { namespaceService.deleteNamespace(appId, Env.valueOf(env), clusterName, namespaceName); return ResponseEntity.ok().build(); } @PreAuthorize(value = "@permissionValidator.hasCreateAppNamespacePermission(#appId, #appNamespace)") @RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST) public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody AppNamespace appNamespace) { RequestPrecondition.checkArgumentsNotEmpty(appNamespace.getAppId(), appNamespace.getName()); if (!InputValidator.isValidAppNamespace(appNamespace.getName())) { throw new BadRequestException(String.format("Namespace格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE + " & " + InputValidator.INVALID_NAMESPACE_NAMESPACE_MESSAGE)); } AppNamespace createdAppNamespace = appNamespaceService.createAppNamespaceInLocal(appNamespace); if (portalConfig.canAppAdminCreatePrivateNamespace() || createdAppNamespace.isPublic()) { assignNamespaceRoleToOperator(appId, appNamespace.getName()); } publisher.publishEvent(new AppNamespaceCreationEvent(createdAppNamespace)); return createdAppNamespace; } /** * env -> cluster -> cluster has not published namespace? * Example: * dev -> * default -> true (default cluster has not published namespace) * customCluster -> false (customCluster cluster's all namespaces had published) */ @RequestMapping(value = "/apps/{appId}/namespaces/publish_info", method = RequestMethod.GET) public Map> getNamespacesPublishInfo(@PathVariable String appId) { return namespaceService.getNamespacesPublishInfo(appId); } @RequestMapping(value = "/envs/{env}/appnamespaces/{publicNamespaceName}/namespaces", method = RequestMethod.GET) public List getPublicAppNamespaceAllNamespaces(@PathVariable String env, @PathVariable String publicNamespaceName, @RequestParam(name = "page", defaultValue = "0") int page, @RequestParam(name = "size", defaultValue = "10") int size) { return namespaceService.getPublicAppNamespaceAllNamespaces(Env.fromString(env), publicNamespaceName, page, size); } private void assignNamespaceRoleToOperator(String appId, String namespaceName) { //default assign modify、release namespace role to namespace creator String operator = userInfoHolder.getUser().getUserId(); rolePermissionService .assignRoleToUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.MODIFY_NAMESPACE), Sets.newHashSet(operator), operator); rolePermissionService .assignRoleToUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, RoleType.RELEASE_NAMESPACE), Sets.newHashSet(operator), operator); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceLockController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.vo.LockInfo; import com.ctrip.framework.apollo.portal.service.NamespaceLockService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class NamespaceLockController { @Autowired private NamespaceLockService namespaceLockService; @Deprecated @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/lock", method = RequestMethod.GET) public NamespaceLockDTO getNamespaceLock(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { return namespaceLockService.getNamespaceLock(appId, Env.valueOf(env), clusterName, namespaceName); } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/lock-info", method = RequestMethod.GET) public LockInfo getNamespaceLockInfo(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName) { return namespaceLockService.getNamespaceLockInfo(appId, Env.fromString(env), clusterName, namespaceName); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/OrganizationController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.vo.Organization; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ @RestController @RequestMapping("/organizations") public class OrganizationController { @Autowired private PortalConfig portalConfig; @RequestMapping public List loadOrganization() { return portalConfig.organizations(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PageSettingController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.vo.PageSetting; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class PageSettingController { @Autowired private PortalConfig portalConfig; @RequestMapping(value = "/page-settings", method = RequestMethod.GET) public PageSetting getPageSetting() { PageSetting setting = new PageSetting(); setting.setWikiAddress(portalConfig.wikiAddress()); setting.setCanAppAdminCreatePrivateNamespace(portalConfig.canAppAdminCreatePrivateNamespace()); return setting; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PermissionController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.portal.constant.RoleType; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.vo.AppRolesAssignedUsers; import com.ctrip.framework.apollo.portal.entity.vo.NamespaceRolesAssignedUsers; import com.ctrip.framework.apollo.portal.entity.vo.PermissionCondition; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.portal.util.RoleUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Set; @RestController public class PermissionController { @Autowired private UserInfoHolder userInfoHolder; @Autowired private RolePermissionService rolePermissionService; @Autowired private UserService userService; @RequestMapping(value = "/apps/{appId}/permissions/{permissionType}", method = RequestMethod.GET) public ResponseEntity hasPermission(@PathVariable String appId, @PathVariable String permissionType) { PermissionCondition permissionCondition = new PermissionCondition(); permissionCondition.setHasPermission( rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), permissionType, appId)); return ResponseEntity.ok().body(permissionCondition); } @RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/permissions/{permissionType}", method = RequestMethod.GET) public ResponseEntity hasPermission(@PathVariable String appId, @PathVariable String namespaceName, @PathVariable String permissionType) { PermissionCondition permissionCondition = new PermissionCondition(); permissionCondition.setHasPermission( rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), permissionType, RoleUtils.buildNamespaceTargetId(appId, namespaceName))); return ResponseEntity.ok().body(permissionCondition); } @RequestMapping(value = "/permissions/root", method = RequestMethod.GET) public ResponseEntity hasRootPermission() { PermissionCondition permissionCondition = new PermissionCondition(); permissionCondition.setHasPermission(rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId())); return ResponseEntity.ok().body(permissionCondition); } @RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/role_users", method = RequestMethod.GET) public NamespaceRolesAssignedUsers getNamespaceRoles(@PathVariable String appId, @PathVariable String namespaceName) { NamespaceRolesAssignedUsers assignedUsers = new NamespaceRolesAssignedUsers(); assignedUsers.setNamespaceName(namespaceName); assignedUsers.setAppId(appId); Set releaseNamespaceUsers = rolePermissionService.queryUsersWithRole(RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName)); assignedUsers.setReleaseRoleUsers(releaseNamespaceUsers); Set modifyNamespaceUsers = rolePermissionService.queryUsersWithRole(RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName)); assignedUsers.setModifyRoleUsers(modifyNamespaceUsers); return assignedUsers; } @PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)") @RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}", method = RequestMethod.POST) public ResponseEntity assignNamespaceRoleToUser(@PathVariable String appId, @PathVariable String namespaceName, @PathVariable String roleType, @RequestBody String user) { checkUserExists(user); RequestPrecondition.checkArgumentsNotEmpty(user); if (!RoleType.isValidRoleType(roleType)) { throw new BadRequestException("role type is illegal"); } Set assignedUser = rolePermissionService.assignRoleToUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, roleType), Sets.newHashSet(user), userInfoHolder.getUser().getUserId()); if (CollectionUtils.isEmpty(assignedUser)) { throw new BadRequestException(user + "已授权"); } return ResponseEntity.ok().build(); } @PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)") @RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}", method = RequestMethod.DELETE) public ResponseEntity removeNamespaceRoleFromUser(@PathVariable String appId, @PathVariable String namespaceName, @PathVariable String roleType, @RequestParam String user) { RequestPrecondition.checkArgumentsNotEmpty(user); if (!RoleType.isValidRoleType(roleType)) { throw new BadRequestException("role type is illegal"); } rolePermissionService.removeRoleFromUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, roleType), Sets.newHashSet(user), userInfoHolder.getUser().getUserId()); return ResponseEntity.ok().build(); } @RequestMapping(value = "/apps/{appId}/role_users", method = RequestMethod.GET) public AppRolesAssignedUsers getAppRoles(@PathVariable String appId) { AppRolesAssignedUsers users = new AppRolesAssignedUsers(); users.setAppId(appId); Set masterUsers = rolePermissionService.queryUsersWithRole(RoleUtils.buildAppMasterRoleName(appId)); users.setMasterUsers(masterUsers); return users; } @PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)") @RequestMapping(value = "/apps/{appId}/roles/{roleType}", method = RequestMethod.POST) public ResponseEntity assignAppRoleToUser(@PathVariable String appId, @PathVariable String roleType, @RequestBody String user) { checkUserExists(user); RequestPrecondition.checkArgumentsNotEmpty(user); if (!RoleType.isValidRoleType(roleType)) { throw new BadRequestException("role type is illegal"); } Set assignedUsers = rolePermissionService.assignRoleToUsers(RoleUtils.buildAppRoleName(appId, roleType), Sets.newHashSet(user), userInfoHolder.getUser().getUserId()); if (CollectionUtils.isEmpty(assignedUsers)) { throw new BadRequestException(user + "已授权"); } return ResponseEntity.ok().build(); } @PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)") @RequestMapping(value = "/apps/{appId}/roles/{roleType}", method = RequestMethod.DELETE) public ResponseEntity removeAppRoleFromUser(@PathVariable String appId, @PathVariable String roleType, @RequestParam String user) { RequestPrecondition.checkArgumentsNotEmpty(user); if (!RoleType.isValidRoleType(roleType)) { throw new BadRequestException("role type is illegal"); } rolePermissionService.removeRoleFromUsers(RoleUtils.buildAppRoleName(appId, roleType), Sets.newHashSet(user), userInfoHolder.getUser().getUserId()); return ResponseEntity.ok().build(); } private void checkUserExists(String userId) { if (userService.findByUserId(userId) == null) { throw new BadRequestException(String.format("User %s does not exist!", userId)); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel; import com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseBO; import com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent; import com.ctrip.framework.apollo.portal.service.ReleaseService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Objects; import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel; @RestController public class ReleaseController { @Autowired private ReleaseService releaseService; @Autowired private ApplicationEventPublisher publisher; @Autowired private PortalConfig portalConfig; @PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases", method = RequestMethod.POST) public ReleaseDTO createRelease(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) { checkModel(Objects.nonNull(model)); model.setAppId(appId); model.setEnv(env); model.setClusterName(clusterName); model.setNamespaceName(namespaceName); if (model.isEmergencyPublish() && !portalConfig.isEmergencyPublishAllowed(Env.valueOf(env))) { throw new BadRequestException(String.format("Env: %s is not supported emergency publish now", env)); } ReleaseDTO createdRelease = releaseService.publish(model); ConfigPublishEvent event = ConfigPublishEvent.instance(); event.withAppId(appId) .withCluster(clusterName) .withNamespace(namespaceName) .withReleaseId(createdRelease.getId()) .setNormalPublishEvent(true) .setEnv(Env.valueOf(env)); publisher.publishEvent(event); return createdRelease; } @PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/releases", method = RequestMethod.POST) public ReleaseDTO createGrayRelease(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String branchName, @RequestBody NamespaceReleaseModel model) { checkModel(Objects.nonNull(model)); model.setAppId(appId); model.setEnv(env); model.setClusterName(branchName); model.setNamespaceName(namespaceName); if (model.isEmergencyPublish() && !portalConfig.isEmergencyPublishAllowed(Env.valueOf(env))) { throw new BadRequestException(String.format("Env: %s is not supported emergency publish now", env)); } ReleaseDTO createdRelease = releaseService.publish(model); ConfigPublishEvent event = ConfigPublishEvent.instance(); event.withAppId(appId) .withCluster(clusterName) .withNamespace(namespaceName) .withReleaseId(createdRelease.getId()) .setGrayPublishEvent(true) .setEnv(Env.valueOf(env)); publisher.publishEvent(event); return createdRelease; } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all", method = RequestMethod.GET) public List findAllReleases(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "5") int size) { RequestPrecondition.checkNumberPositive(size); RequestPrecondition.checkNumberNotNegative(page); return releaseService.findAllReleases(appId, Env.valueOf(env), clusterName, namespaceName, page, size); } @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active", method = RequestMethod.GET) public List findActiveReleases(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "5") int size) { RequestPrecondition.checkNumberPositive(size); RequestPrecondition.checkNumberNotNegative(page); return releaseService.findActiveReleases(appId, Env.valueOf(env), clusterName, namespaceName, page, size); } @RequestMapping(value = "/envs/{env}/releases/compare", method = RequestMethod.GET) public ReleaseCompareResult compareRelease(@PathVariable String env, @RequestParam long baseReleaseId, @RequestParam long toCompareReleaseId) { return releaseService.compare(Env.valueOf(env), baseReleaseId, toCompareReleaseId); } @RequestMapping(path = "/envs/{env}/releases/{releaseId}/rollback", method = RequestMethod.PUT) public void rollback(@PathVariable String env, @PathVariable long releaseId) { releaseService.rollback(Env.valueOf(env), releaseId); ReleaseDTO release = releaseService.findReleaseById(Env.valueOf(env), releaseId); if (Objects.isNull(release)) { return; } ConfigPublishEvent event = ConfigPublishEvent.instance(); event.withAppId(release.getAppId()) .withCluster(release.getClusterName()) .withNamespace(release.getNamespaceName()) .withPreviousReleaseId(releaseId) .setRollbackEvent(true) .setEnv(Env.valueOf(env)); publisher.publishEvent(event); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseHistoryController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import com.ctrip.framework.apollo.portal.service.ReleaseHistoryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class ReleaseHistoryController { @Autowired private ReleaseHistoryService releaseHistoryService; @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories", method = RequestMethod.GET) public List findReleaseHistoriesByNamespace(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName, @PathVariable String namespaceName, @RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "size", defaultValue = "10") int size) { return releaseHistoryService.findNamespaceReleaseHistory(appId, Env.valueOf(env), clusterName ,namespaceName, page, size); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ServerConfigController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; import com.ctrip.framework.apollo.portal.entity.po.ServerConfig; import com.ctrip.framework.apollo.portal.repository.ServerConfigRepository; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.Objects; import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel; /** * 配置中心本身需要一些配置,这些配置放在数据库里面 */ @RestController public class ServerConfigController { @Autowired private ServerConfigRepository serverConfigRepository; @Autowired private UserInfoHolder userInfoHolder; @PreAuthorize(value = "@permissionValidator.isSuperAdmin()") @RequestMapping(value = "/server/config", method = RequestMethod.POST) public ServerConfig createOrUpdate(@RequestBody ServerConfig serverConfig) { checkModel(Objects.nonNull(serverConfig)); RequestPrecondition.checkArgumentsNotEmpty(serverConfig.getKey(), serverConfig.getValue()); String modifiedBy = userInfoHolder.getUser().getUserId(); ServerConfig storedConfig = serverConfigRepository.findByKey(serverConfig.getKey()); if (Objects.isNull(storedConfig)) {//create serverConfig.setDataChangeCreatedBy(modifiedBy); serverConfig.setDataChangeLastModifiedBy(modifiedBy); return serverConfigRepository.save(serverConfig); } else {//update BeanUtils.copyEntityProperties(serverConfig, storedConfig); storedConfig.setDataChangeLastModifiedBy(modifiedBy); return serverConfigRepository.save(storedConfig); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/SignInController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; /** * @author lepdou 2017-08-30 */ @Controller public class SignInController { @RequestMapping(value = "/signin", method = RequestMethod.GET) public String login(@RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout", required = false) String logout) { return "login.html"; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/SsoHeartbeatController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Since sso auth information has a limited expiry time, so we need to do sso heartbeat to keep the * information refreshed when unavailable * * @author Jason Song(song_s@ctrip.com) */ @Controller @RequestMapping("/sso_heartbeat") public class SsoHeartbeatController { @Autowired private SsoHeartbeatHandler handler; @RequestMapping(value = "", method = RequestMethod.GET) public void heartbeat(HttpServletRequest request, HttpServletResponse response) { handler.doHeartbeat(request, response); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/UserInfoController.java ================================================ package com.ctrip.framework.apollo.portal.controller; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.po.UserPO; import com.ctrip.framework.apollo.portal.spi.LogoutHandler; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @RestController public class UserInfoController { @Autowired private UserInfoHolder userInfoHolder; @Autowired private LogoutHandler logoutHandler; @Autowired private UserService userService; @PreAuthorize(value = "@permissionValidator.isSuperAdmin()") @RequestMapping(value = "/users", method = RequestMethod.POST) public void createOrUpdateUser(@RequestBody UserPO user) { if (StringUtils.isContainEmpty(user.getUsername(), user.getPassword())) { throw new BadRequestException("Username and password can not be empty."); } if (userService instanceof SpringSecurityUserService) { ((SpringSecurityUserService) userService).createOrUpdate(user); } else { throw new UnsupportedOperationException("Create or update user operation is unsupported"); } } @RequestMapping(value = "/user", method = RequestMethod.GET) public UserInfo getCurrentUserName() { return userInfoHolder.getUser(); } @RequestMapping(value = "/user/logout", method = RequestMethod.GET) public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException { logoutHandler.logout(request, response); } @RequestMapping(value = "/users", method = RequestMethod.GET) public List searchUsersByKeyword(@RequestParam(value = "keyword") String keyword, @RequestParam(value = "offset", defaultValue = "0") int offset, @RequestParam(value = "limit", defaultValue = "10") int limit) { return userService.searchUsers(keyword, offset, limit); } @RequestMapping(value = "/users/{userId}", method = RequestMethod.GET) public UserInfo getUserByUserId(@PathVariable String userId) { return userService.findByUserId(userId); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/Email.java ================================================ package com.ctrip.framework.apollo.portal.entity.bo; import java.util.List; public class Email { private String senderEmailAddress; private List recipients; private String subject; private String body; public String getSenderEmailAddress() { return senderEmailAddress; } public void setSenderEmailAddress(String senderEmailAddress) { this.senderEmailAddress = senderEmailAddress; } public List getRecipients() { return recipients; } public void setRecipients(List recipients) { this.recipients = recipients; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ItemBO.java ================================================ package com.ctrip.framework.apollo.portal.entity.bo; import com.ctrip.framework.apollo.common.dto.ItemDTO; public class ItemBO { private ItemDTO item; private boolean isModified; private boolean isDeleted; private String oldValue; private String newValue; public ItemDTO getItem() { return item; } public void setItem(ItemDTO item) { this.item = item; } public boolean isDeleted() { return isDeleted; } public void setDeleted(boolean deleted) { isDeleted = deleted; } public boolean isModified() { return isModified; } public void setModified(boolean isModified) { this.isModified = isModified; } public String getOldValue() { return oldValue; } public void setOldValue(String oldValue) { this.oldValue = oldValue; } public String getNewValue() { return newValue; } public void setNewValue(String newValue) { this.newValue = newValue; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/KVEntity.java ================================================ package com.ctrip.framework.apollo.portal.entity.bo; public class KVEntity { private String key; private String value; public KVEntity(String key, String value) { this.key = key; this.value = value; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/NamespaceBO.java ================================================ package com.ctrip.framework.apollo.portal.entity.bo; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import java.util.List; public class NamespaceBO { private NamespaceDTO baseInfo; private int itemModifiedCnt; private List items; private String format; private boolean isPublic; private String parentAppId; private String comment; public NamespaceDTO getBaseInfo() { return baseInfo; } public void setBaseInfo(NamespaceDTO baseInfo) { this.baseInfo = baseInfo; } public int getItemModifiedCnt() { return itemModifiedCnt; } public void setItemModifiedCnt(int itemModifiedCnt) { this.itemModifiedCnt = itemModifiedCnt; } public List getItems() { return items; } public void setItems(List items) { this.items = items; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public boolean isPublic() { return isPublic; } public void setPublic(boolean aPublic) { isPublic = aPublic; } public String getParentAppId() { return parentAppId; } public void setParentAppId(String parentAppId) { this.parentAppId = parentAppId; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ReleaseBO.java ================================================ package com.ctrip.framework.apollo.portal.entity.bo; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.portal.entity.bo.KVEntity; import java.util.Set; public class ReleaseBO { private ReleaseDTO baseInfo; private Set items; public ReleaseDTO getBaseInfo() { return baseInfo; } public void setBaseInfo(ReleaseDTO baseInfo) { this.baseInfo = baseInfo; } public Set getItems() { return items; } public void setItems(Set items) { this.items = items; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ReleaseHistoryBO.java ================================================ package com.ctrip.framework.apollo.portal.entity.bo; import com.ctrip.framework.apollo.common.entity.EntityPair; import java.util.Date; import java.util.List; import java.util.Map; public class ReleaseHistoryBO { private long id; private String appId; private String clusterName; private String namespaceName; private String branchName; private String operator; private long releaseId; private String releaseTitle; private String releaseComment; private Date releaseTime; private String releaseTimeFormatted; private List> configuration; private long previousReleaseId; private int operation; private Map operationContext; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getBranchName() { return branchName; } public void setBranchName(String branchName) { this.branchName = branchName; } public long getReleaseId() { return releaseId; } public void setReleaseId(long releaseId) { this.releaseId = releaseId; } public long getPreviousReleaseId() { return previousReleaseId; } public void setPreviousReleaseId(long previousReleaseId) { this.previousReleaseId = previousReleaseId; } public int getOperation() { return operation; } public void setOperation(int operation) { this.operation = operation; } public Map getOperationContext() { return operationContext; } public void setOperationContext(Map operationContext) { this.operationContext = operationContext; } public String getOperator() { return operator; } public void setOperator(String operator) { this.operator = operator; } public String getReleaseTitle() { return releaseTitle; } public void setReleaseTitle(String releaseTitle) { this.releaseTitle = releaseTitle; } public String getReleaseComment() { return releaseComment; } public void setReleaseComment(String releaseComment) { this.releaseComment = releaseComment; } public Date getReleaseTime() { return releaseTime; } public void setReleaseTime(Date releaseTime) { this.releaseTime = releaseTime; } public String getReleaseTimeFormatted() { return releaseTimeFormatted; } public void setReleaseTimeFormatted(String releaseTimeFormatted) { this.releaseTimeFormatted = releaseTimeFormatted; } public List> getConfiguration() { return configuration; } public void setConfiguration( List> configuration) { this.configuration = configuration; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/UserInfo.java ================================================ package com.ctrip.framework.apollo.portal.entity.bo; public class UserInfo { private String userId; private String name; private String email; public UserInfo() { } public UserInfo(String userId) { this.userId = userId; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public boolean equals(Object o) { if (o instanceof UserInfo) { if (o == this){ return true; } UserInfo anotherUser = (UserInfo) o; return userId.equals(anotherUser.userId); } else { return false; } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/AppModel.java ================================================ package com.ctrip.framework.apollo.portal.entity.model; import java.util.Set; public class AppModel { private String name; private String appId; private String orgId; private String orgName; private String ownerName; private Set admins; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getOrgId() { return orgId; } public void setOrgId(String orgId) { this.orgId = orgId; } public String getOrgName() { return orgName; } public void setOrgName(String orgName) { this.orgName = orgName; } public String getOwnerName() { return ownerName; } public void setOwnerName(String ownerName) { this.ownerName = ownerName; } public Set getAdmins() { return admins; } public void setAdmins(Set admins) { this.admins = admins; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceCreationModel.java ================================================ package com.ctrip.framework.apollo.portal.entity.model; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; public class NamespaceCreationModel { private String env; private NamespaceDTO namespace; public String getEnv() { return env; } public void setEnv(String env) { this.env = env; } public NamespaceDTO getNamespace() { return namespace; } public void setNamespace(NamespaceDTO namespace) { this.namespace = namespace; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceReleaseModel.java ================================================ package com.ctrip.framework.apollo.portal.entity.model; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; public class NamespaceReleaseModel implements Verifiable { private String appId; private String env; private String clusterName; private String namespaceName; private String releaseTitle; private String releaseComment; private String releasedBy; private boolean isEmergencyPublish; @Override public boolean isInvalid() { return StringUtils.isContainEmpty(appId, env, clusterName, namespaceName, releaseTitle); } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public Env getEnv() { return Env.valueOf(env); } public void setEnv(String env) { this.env = env; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public String getReleaseTitle() { return releaseTitle; } public void setReleaseTitle(String releaseTitle) { this.releaseTitle = releaseTitle; } public String getReleaseComment() { return releaseComment; } public void setReleaseComment(String releaseComment) { this.releaseComment = releaseComment; } public String getReleasedBy() { return releasedBy; } public void setReleasedBy(String releasedBy) { this.releasedBy = releasedBy; } public boolean isEmergencyPublish() { return isEmergencyPublish; } public void setEmergencyPublish(boolean emergencyPublish) { isEmergencyPublish = emergencyPublish; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceSyncModel.java ================================================ package com.ctrip.framework.apollo.portal.entity.model; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifier; import org.springframework.util.CollectionUtils; import java.util.List; public class NamespaceSyncModel implements Verifiable { private List syncToNamespaces; private List syncItems; @Override public boolean isInvalid() { if (CollectionUtils.isEmpty(syncToNamespaces) || CollectionUtils.isEmpty(syncItems)) { return true; } for (NamespaceIdentifier namespaceIdentifier : syncToNamespaces) { if (namespaceIdentifier.isInvalid()) { return true; } } return false; } public List getSyncToNamespaces() { return syncToNamespaces; } public void setSyncToNamespaces(List syncToNamespaces) { this.syncToNamespaces = syncToNamespaces; } public List getSyncItems() { return syncItems; } public void setSyncItems(List syncItems) { this.syncItems = syncItems; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/NamespaceTextModel.java ================================================ package com.ctrip.framework.apollo.portal.entity.model; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; public class NamespaceTextModel implements Verifiable { private String appId; private String env; private String clusterName; private String namespaceName; private int namespaceId; private String format; private String configText; @Override public boolean isInvalid() { return StringUtils.isContainEmpty(appId, env, clusterName, namespaceName) || namespaceId <= 0; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public Env getEnv() { return Env.valueOf(env); } public void setEnv(String env) { this.env = env; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public int getNamespaceId() { return namespaceId; } public void setNamespaceId(int namespaceId) { this.namespaceId = namespaceId; } public String getConfigText() { return configText; } public void setConfigText(String configText) { this.configText = configText; } public ConfigFileFormat getFormat() { return ConfigFileFormat.fromString(this.format); } public void setFormat(String format) { this.format = format; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/model/Verifiable.java ================================================ package com.ctrip.framework.apollo.portal.entity.model; public interface Verifiable { boolean isInvalid(); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/Favorite.java ================================================ package com.ctrip.framework.apollo.portal.entity.po; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "Favorite") @SQLDelete(sql = "Update Favorite set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Favorite extends BaseEntity { @Column(name = "AppId", nullable = false) private String appId; @Column(name = "UserId", nullable = false) private String userId; @Column(name = "Position") private long position; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public long getPosition() { return position; } public void setPosition(long position) { this.position = position; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/Permission.java ================================================ package com.ctrip.framework.apollo.portal.entity.po; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "Permission") @SQLDelete(sql = "Update Permission set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Permission extends BaseEntity { @Column(name = "PermissionType", nullable = false) private String permissionType; @Column(name = "TargetId", nullable = false) private String targetId; public String getPermissionType() { return permissionType; } public void setPermissionType(String permissionType) { this.permissionType = permissionType; } public String getTargetId() { return targetId; } public void setTargetId(String targetId) { this.targetId = targetId; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/Role.java ================================================ package com.ctrip.framework.apollo.portal.entity.po; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "Role") @SQLDelete(sql = "Update Role set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class Role extends BaseEntity { @Column(name = "RoleName", nullable = false) private String roleName; public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/RolePermission.java ================================================ package com.ctrip.framework.apollo.portal.entity.po; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "RolePermission") @SQLDelete(sql = "Update RolePermission set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class RolePermission extends BaseEntity { @Column(name = "RoleId", nullable = false) private long roleId; @Column(name = "PermissionId", nullable = false) private long permissionId; public long getRoleId() { return roleId; } public void setRoleId(long roleId) { this.roleId = roleId; } public long getPermissionId() { return permissionId; } public void setPermissionId(long permissionId) { this.permissionId = permissionId; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/ServerConfig.java ================================================ package com.ctrip.framework.apollo.portal.entity.po; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "ServerConfig") @SQLDelete(sql = "Update ServerConfig set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class ServerConfig extends BaseEntity { @Column(name = "Key", nullable = false) private String key; @Column(name = "Value", nullable = false) private String value; @Column(name = "Comment", nullable = false) private String comment; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public String toString() { return toStringHelper().add("key", key).add("value", value).add("comment", comment).toString(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/UserPO.java ================================================ package com.ctrip.framework.apollo.portal.entity.po; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; /** * @author lepdou 2017-04-08 */ @Entity @Table(name = "Users") public class UserPO { @Id @GeneratedValue @Column(name = "Id") private long id; @Column(name = "Username", nullable = false) private String username; @Column(name = "Password", nullable = false) private String password; @Column(name = "Email", nullable = false) private String email; @Column(name = "Enabled", nullable = false) private int enabled; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getEnabled() { return enabled; } public void setEnabled(int enabled) { this.enabled = enabled; } public UserInfo toUserInfo() { UserInfo userInfo = new UserInfo(); userInfo.setName(this.getUsername()); userInfo.setUserId(this.getUsername()); userInfo.setEmail(this.getEmail()); return userInfo; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/po/UserRole.java ================================================ package com.ctrip.framework.apollo.portal.entity.po; import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * @author Jason Song(song_s@ctrip.com) */ @Entity @Table(name = "UserRole") @SQLDelete(sql = "Update UserRole set isDeleted = 1 where id = ?") @Where(clause = "isDeleted = 0") public class UserRole extends BaseEntity { @Column(name = "UserId", nullable = false) private String userId; @Column(name = "RoleId", nullable = false) private long roleId; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public long getRoleId() { return roleId; } public void setRoleId(long roleId) { this.roleId = roleId; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/AppRolesAssignedUsers.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import java.util.Set; public class AppRolesAssignedUsers { private String appId; private Set masterUsers; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public Set getMasterUsers() { return masterUsers; } public void setMasterUsers(Set masterUsers) { this.masterUsers = masterUsers; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Change.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; import com.ctrip.framework.apollo.common.entity.EntityPair; import com.ctrip.framework.apollo.portal.entity.bo.KVEntity; import com.ctrip.framework.apollo.portal.enums.ChangeType; public class Change { private ChangeType type; private EntityPair entity; public Change(ChangeType type, EntityPair entity) { this.type = type; this.entity = entity; } public ChangeType getType() { return type; } public void setType(ChangeType type) { this.type = type; } public EntityPair getEntity() { return entity; } public void setEntity(EntityPair entity) { this.entity = entity; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/EnvClusterInfo.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; import com.ctrip.framework.apollo.common.dto.ClusterDTO; import com.ctrip.framework.apollo.core.enums.Env; import java.util.List; public class EnvClusterInfo { private Env env; private List clusters; public EnvClusterInfo(Env env) { this.env = env; } public Env getEnv() { return env; } public void setEnv(Env env) { this.env = env; } public List getClusters() { return clusters; } public void setClusters(List clusters) { this.clusters = clusters; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/ItemDiffs.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; public class ItemDiffs { private NamespaceIdentifier namespace; private ItemChangeSets diffs; private String extInfo; public ItemDiffs(NamespaceIdentifier namespace) { this.namespace = namespace; } public NamespaceIdentifier getNamespace() { return namespace; } public void setNamespace(NamespaceIdentifier namespace) { this.namespace = namespace; } public ItemChangeSets getDiffs() { return diffs; } public void setDiffs(ItemChangeSets diffs) { this.diffs = diffs; } public String getExtInfo() { return extInfo; } public void setExtInfo(String extInfo) { this.extInfo = extInfo; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/LockInfo.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; public class LockInfo { private String lockOwner; private boolean isEmergencyPublishAllowed; public String getLockOwner() { return lockOwner; } public void setLockOwner(String lockOwner) { this.lockOwner = lockOwner; } public boolean isEmergencyPublishAllowed() { return isEmergencyPublishAllowed; } public void setEmergencyPublishAllowed(boolean emergencyPublishAllowed) { isEmergencyPublishAllowed = emergencyPublishAllowed; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/NamespaceIdentifier.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.entity.model.Verifiable; public class NamespaceIdentifier implements Verifiable { private String appId; private String env; private String clusterName; private String namespaceName; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public Env getEnv() { return Env.valueOf(env); } public void setEnv(String env) { this.env = env; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } @Override public boolean isInvalid() { return StringUtils.isContainEmpty(env, clusterName, namespaceName); } @Override public String toString() { return "NamespaceIdentifer{" + "appId='" + appId + '\'' + ", env='" + env + '\'' + ", clusterName='" + clusterName + '\'' + ", namespaceName='" + namespaceName + '\'' + '}'; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/NamespaceRolesAssignedUsers.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import java.util.Set; public class NamespaceRolesAssignedUsers { private String appId; private String namespaceName; private Set modifyRoleUsers; private Set releaseRoleUsers; public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public Set getModifyRoleUsers() { return modifyRoleUsers; } public void setModifyRoleUsers( Set modifyRoleUsers) { this.modifyRoleUsers = modifyRoleUsers; } public Set getReleaseRoleUsers() { return releaseRoleUsers; } public void setReleaseRoleUsers( Set releaseRoleUsers) { this.releaseRoleUsers = releaseRoleUsers; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Number.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; public class Number { private int num; public Number(int num){ this.num = num; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Organization.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; /** * @author Jason Song(song_s@ctrip.com) */ public class Organization { private String orgId; private String orgName; public String getOrgId() { return orgId; } public void setOrgId(String orgId) { this.orgId = orgId; } public String getOrgName() { return orgName; } public void setOrgName(String orgName) { this.orgName = orgName; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/PageSetting.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; public class PageSetting { private String wikiAddress; private boolean canAppAdminCreatePrivateNamespace; public String getWikiAddress() { return wikiAddress; } public void setWikiAddress(String wikiAddress) { this.wikiAddress = wikiAddress; } public boolean isCanAppAdminCreatePrivateNamespace() { return canAppAdminCreatePrivateNamespace; } public void setCanAppAdminCreatePrivateNamespace(boolean canAppAdminCreatePrivateNamespace) { this.canAppAdminCreatePrivateNamespace = canAppAdminCreatePrivateNamespace; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/PermissionCondition.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; public class PermissionCondition { private boolean hasPermission; public boolean hasPermission() { return hasPermission; } public void setHasPermission(boolean hasPermission) { this.hasPermission = hasPermission; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/ReleaseCompareResult.java ================================================ package com.ctrip.framework.apollo.portal.entity.vo; import com.ctrip.framework.apollo.common.entity.EntityPair; import com.ctrip.framework.apollo.portal.entity.bo.KVEntity; import com.ctrip.framework.apollo.portal.enums.ChangeType; import java.util.LinkedList; import java.util.List; public class ReleaseCompareResult { private List changes = new LinkedList<>(); public void addEntityPair(ChangeType type, KVEntity firstEntity, KVEntity secondEntity) { changes.add(new Change(type, new EntityPair<>(firstEntity, secondEntity))); } public boolean hasContent(){ return !changes.isEmpty(); } public List getChanges() { return changes; } public void setChanges(List changes) { this.changes = changes; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/enums/ChangeType.java ================================================ package com.ctrip.framework.apollo.portal.enums; public enum ChangeType { ADDED, MODIFIED, DELETED } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppCreationEvent.java ================================================ package com.ctrip.framework.apollo.portal.listener; import com.google.common.base.Preconditions; import com.ctrip.framework.apollo.common.entity.App; import org.springframework.context.ApplicationEvent; public class AppCreationEvent extends ApplicationEvent { public AppCreationEvent(Object source) { super(source); } public App getApp() { Preconditions.checkState(source != null); return (App) this.source; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedEvent.java ================================================ package com.ctrip.framework.apollo.portal.listener; import com.google.common.base.Preconditions; import com.ctrip.framework.apollo.common.entity.App; import org.springframework.context.ApplicationEvent; public class AppInfoChangedEvent extends ApplicationEvent{ public AppInfoChangedEvent(Object source) { super(source); } public App getApp() { Preconditions.checkState(source != null); return (App) this.source; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java ================================================ package com.ctrip.framework.apollo.portal.listener; import com.ctrip.framework.apollo.common.dto.AppDTO; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import java.util.List; @Component public class AppInfoChangedListener { private static final Logger logger = LoggerFactory.getLogger(AppInfoChangedListener.class); @Autowired private AdminServiceAPI.AppAPI appAPI; @Autowired private PortalSettings portalSettings; @EventListener public void onAppInfoChange(AppInfoChangedEvent event) { AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp()); String appId = appDTO.getAppId(); List envs = portalSettings.getActiveEnvs(); for (Env env : envs) { try { appAPI.updateApp(env, appDTO); } catch (Throwable e) { logger.error("Update app's info failed. Env = {}, AppId = {}", env, appId, e); Tracer.logError(String.format("Update app's info failed. Env = %s, AppId = %s", env, appId), e); } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppNamespaceCreationEvent.java ================================================ package com.ctrip.framework.apollo.portal.listener; import com.google.common.base.Preconditions; import com.ctrip.framework.apollo.common.entity.AppNamespace; import org.springframework.context.ApplicationEvent; public class AppNamespaceCreationEvent extends ApplicationEvent { public AppNamespaceCreationEvent(Object source) { super(source); } public AppNamespace getAppNamespace() { Preconditions.checkState(source != null); return (AppNamespace) this.source; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/ConfigPublishEvent.java ================================================ package com.ctrip.framework.apollo.portal.listener; import com.ctrip.framework.apollo.core.enums.Env; import org.springframework.context.ApplicationEvent; public class ConfigPublishEvent extends ApplicationEvent { private ConfigPublishInfo configPublishInfo; public ConfigPublishEvent(Object source) { super(source); configPublishInfo = (ConfigPublishInfo) source; } public static ConfigPublishEvent instance() { ConfigPublishInfo info = new ConfigPublishInfo(); return new ConfigPublishEvent(info); } public ConfigPublishInfo getConfigPublishInfo(){ return configPublishInfo; } public ConfigPublishEvent withAppId(String appId) { configPublishInfo.setAppId(appId); return this; } public ConfigPublishEvent withCluster(String clusterName) { configPublishInfo.setClusterName(clusterName); return this; } public ConfigPublishEvent withNamespace(String namespaceName) { configPublishInfo.setNamespaceName(namespaceName); return this; } public ConfigPublishEvent withReleaseId(long releaseId){ configPublishInfo.setReleaseId(releaseId); return this; } public ConfigPublishEvent withPreviousReleaseId(long previousReleaseId){ configPublishInfo.setPreviousReleaseId(previousReleaseId); return this; } public ConfigPublishEvent setNormalPublishEvent(boolean isNormalPublishEvent) { configPublishInfo.setNormalPublishEvent(isNormalPublishEvent); return this; } public ConfigPublishEvent setGrayPublishEvent(boolean isGrayPublishEvent) { configPublishInfo.setGrayPublishEvent(isGrayPublishEvent); return this; } public ConfigPublishEvent setRollbackEvent(boolean isRollbackEvent) { configPublishInfo.setRollbackEvent(isRollbackEvent); return this; } public ConfigPublishEvent setMergeEvent(boolean isMergeEvent) { configPublishInfo.setMergeEvent(isMergeEvent); return this; } public ConfigPublishEvent setEnv(Env env) { configPublishInfo.setEnv(env); return this; } public static class ConfigPublishInfo { private Env env; private String appId; private String clusterName; private String namespaceName; private long releaseId; private long previousReleaseId; private boolean isRollbackEvent; private boolean isMergeEvent; private boolean isNormalPublishEvent; private boolean isGrayPublishEvent; public Env getEnv() { return env; } public void setEnv(Env env) { this.env = env; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getClusterName() { return clusterName; } public void setClusterName(String clusterName) { this.clusterName = clusterName; } public String getNamespaceName() { return namespaceName; } public void setNamespaceName(String namespaceName) { this.namespaceName = namespaceName; } public long getReleaseId() { return releaseId; } public void setReleaseId(long releaseId) { this.releaseId = releaseId; } public long getPreviousReleaseId() { return previousReleaseId; } public void setPreviousReleaseId(long previousReleaseId) { this.previousReleaseId = previousReleaseId; } public boolean isRollbackEvent() { return isRollbackEvent; } public void setRollbackEvent(boolean rollbackEvent) { isRollbackEvent = rollbackEvent; } public boolean isMergeEvent() { return isMergeEvent; } public void setMergeEvent(boolean mergeEvent) { isMergeEvent = mergeEvent; } public boolean isNormalPublishEvent() { return isNormalPublishEvent; } public void setNormalPublishEvent(boolean normalPublishEvent) { isNormalPublishEvent = normalPublishEvent; } public boolean isGrayPublishEvent() { return isGrayPublishEvent; } public void setGrayPublishEvent(boolean grayPublishEvent) { isGrayPublishEvent = grayPublishEvent; } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/ConfigPublishListener.java ================================================ package com.ctrip.framework.apollo.portal.listener; import com.ctrip.framework.apollo.common.constants.ReleaseOperation; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.component.emailbuilder.GrayPublishEmailBuilder; import com.ctrip.framework.apollo.portal.component.emailbuilder.MergeEmailBuilder; import com.ctrip.framework.apollo.portal.component.emailbuilder.NormalPublishEmailBuilder; import com.ctrip.framework.apollo.portal.component.emailbuilder.RollbackEmailBuilder; import com.ctrip.framework.apollo.portal.entity.bo.Email; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import com.ctrip.framework.apollo.portal.service.ReleaseHistoryService; import com.ctrip.framework.apollo.portal.spi.EmailService; import com.ctrip.framework.apollo.portal.spi.MQService; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.annotation.PostConstruct; @Component public class ConfigPublishListener { @Autowired private ReleaseHistoryService releaseHistoryService; @Autowired private EmailService emailService; @Autowired private NormalPublishEmailBuilder normalPublishEmailBuilder; @Autowired private GrayPublishEmailBuilder grayPublishEmailBuilder; @Autowired private RollbackEmailBuilder rollbackEmailBuilder; @Autowired private MergeEmailBuilder mergeEmailBuilder; @Autowired private PortalConfig portalConfig; @Autowired private MQService mqService; private ExecutorService executorService; @PostConstruct public void init() { executorService = Executors.newSingleThreadExecutor(ApolloThreadFactory.create("ConfigPublishNotify", true)); } @EventListener public void onConfigPublish(ConfigPublishEvent event) { executorService.submit(new ConfigPublishNotifyTask(event.getConfigPublishInfo())); } private class ConfigPublishNotifyTask implements Runnable { private ConfigPublishEvent.ConfigPublishInfo publishInfo; ConfigPublishNotifyTask(ConfigPublishEvent.ConfigPublishInfo publishInfo) { this.publishInfo = publishInfo; } @Override public void run() { ReleaseHistoryBO releaseHistory = getReleaseHistory(); if (releaseHistory == null) { Tracer.logError("Load release history failed", null); return; } sendPublishEmail(releaseHistory); sendPublishMsg(releaseHistory); } private ReleaseHistoryBO getReleaseHistory() { Env env = publishInfo.getEnv(); int operation = publishInfo.isMergeEvent() ? ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER : publishInfo.isRollbackEvent() ? ReleaseOperation.ROLLBACK : publishInfo.isNormalPublishEvent() ? ReleaseOperation.NORMAL_RELEASE : publishInfo.isGrayPublishEvent() ? ReleaseOperation.GRAY_RELEASE : -1; if (operation == -1) { return null; } if (publishInfo.isRollbackEvent()) { return releaseHistoryService .findLatestByPreviousReleaseIdAndOperation(env, publishInfo.getPreviousReleaseId(), operation); } else { return releaseHistoryService.findLatestByReleaseIdAndOperation(env, publishInfo.getReleaseId(), operation); } } private void sendPublishEmail(ReleaseHistoryBO releaseHistory) { Env env = publishInfo.getEnv(); if (!portalConfig.emailSupportedEnvs().contains(env)) { return; } int realOperation = releaseHistory.getOperation(); Email email = null; try { email = buildEmail(env, releaseHistory, realOperation); } catch (Throwable e) { Tracer.logError("build email failed.", e); } if (email != null) { emailService.send(email); } } private void sendPublishMsg(ReleaseHistoryBO releaseHistory) { mqService.sendPublishMsg(publishInfo.getEnv(), releaseHistory); } private Email buildEmail(Env env, ReleaseHistoryBO releaseHistory, int operation) { switch (operation) { case ReleaseOperation.GRAY_RELEASE: { return grayPublishEmailBuilder.build(env, releaseHistory); } case ReleaseOperation.NORMAL_RELEASE: { return normalPublishEmailBuilder.build(env, releaseHistory); } case ReleaseOperation.ROLLBACK: { return rollbackEmailBuilder.build(env, releaseHistory); } case ReleaseOperation.GRAY_RELEASE_MERGE_TO_MASTER: { return mergeEmailBuilder.build(env, releaseHistory); } default: return null; } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java ================================================ package com.ctrip.framework.apollo.portal.listener; import com.ctrip.framework.apollo.common.dto.AppDTO; import com.ctrip.framework.apollo.common.dto.AppNamespaceDTO; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import java.util.List; @Component public class CreationListener { private static Logger logger = LoggerFactory.getLogger(CreationListener.class); @Autowired private PortalSettings portalSettings; @Autowired private AdminServiceAPI.AppAPI appAPI; @Autowired private AdminServiceAPI.NamespaceAPI namespaceAPI; @EventListener public void onAppCreationEvent(AppCreationEvent event) { AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp()); List envs = portalSettings.getActiveEnvs(); for (Env env : envs) { try { appAPI.createApp(env, appDTO); } catch (Throwable e) { logger.error("Create app failed. appId = {}, env = {})", appDTO.getAppId(), env, e); Tracer.logError(String.format("Create app failed. appId = %s, env = %s", appDTO.getAppId(), env), e); } } } @EventListener public void onAppNamespaceCreationEvent(AppNamespaceCreationEvent event) { AppNamespaceDTO appNamespace = BeanUtils.transfrom(AppNamespaceDTO.class, event.getAppNamespace()); List envs = portalSettings.getActiveEnvs(); for (Env env : envs) { try { namespaceAPI.createAppNamespace(env, appNamespace); } catch (Throwable e) { logger.error("Create appNamespace failed. appId = {}, env = {}", appNamespace.getAppId(), env, e); Tracer.logError(String.format("Create appNamespace failed. appId = %s, env = %s", appNamespace.getAppId(), env), e); } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.common.entity.AppNamespace; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; public interface AppNamespaceRepository extends PagingAndSortingRepository { AppNamespace findByAppIdAndName(String appId, String namespaceName); AppNamespace findByName(String namespaceName); AppNamespace findByNameAndIsPublic(String namespaceName, boolean isPublic); List findByIsPublicTrue(); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.common.entity.App; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; import java.util.Set; public interface AppRepository extends PagingAndSortingRepository { App findByAppId(String appId); List findByOwnerName(String ownerName, Pageable page); List findByAppIdIn(Set appIds); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/FavoriteRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.Favorite; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; public interface FavoriteRepository extends PagingAndSortingRepository { List findByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId, Pageable page); List findByAppIdOrderByPositionAscDataChangeCreatedTimeAsc(String appId, Pageable page); Favorite findFirstByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId); Favorite findByUserIdAndAppId(String userId, String appId); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/PermissionRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.Permission; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.Collection; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public interface PermissionRepository extends PagingAndSortingRepository { /** * find permission by permission type and targetId */ Permission findTopByPermissionTypeAndTargetId(String permissionType, String targetId); /** * find permissions by permission types and targetId */ List findByPermissionTypeInAndTargetId(Collection permissionTypes, String targetId); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RolePermissionRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.RolePermission; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.Collection; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public interface RolePermissionRepository extends PagingAndSortingRepository { /** * find role permissions by role ids */ List findByRoleIdIn(Collection roleId); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RoleRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.Role; import org.springframework.data.repository.PagingAndSortingRepository; /** * @author Jason Song(song_s@ctrip.com) */ public interface RoleRepository extends PagingAndSortingRepository { /** * find role by role name */ Role findTopByRoleName(String roleName); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/ServerConfigRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.ServerConfig; import org.springframework.data.repository.PagingAndSortingRepository; public interface ServerConfigRepository extends PagingAndSortingRepository { ServerConfig findByKey(String key); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.UserPO; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; /** * @author lepdou 2017-04-08 */ public interface UserRepository extends PagingAndSortingRepository { List findFirst20ByEnabled(int enabled); List findByUsernameLikeAndEnabled(String username, int enabled); UserPO findByUsername(String username); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRoleRepository.java ================================================ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.UserRole; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.Collection; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public interface UserRoleRepository extends PagingAndSortingRepository { /** * find user roles by userId */ List findByUserId(String userId); /** * find user roles by roleId */ List findByRoleId(long roleId); /** * find user roles by userIds and roleId */ List findByUserIdInAndRoleId(Collection userId, long roleId); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.repository.AppNamespaceRepository; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Objects; @Service public class AppNamespaceService { @Autowired private UserInfoHolder userInfoHolder; @Autowired private AppNamespaceRepository appNamespaceRepository; @Autowired private RoleInitializationService roleInitializationService; @Autowired private AppService appService; /** * 公共的app ns,能被其它项目关联到的app ns */ public List findPublicAppNamespaces() { return appNamespaceRepository.findByIsPublicTrue(); } public AppNamespace findPublicAppNamespace(String namespaceName) { return appNamespaceRepository.findByNameAndIsPublic(namespaceName, true); } public AppNamespace findByAppIdAndName(String appId, String namespaceName) { return appNamespaceRepository.findByAppIdAndName(appId, namespaceName); } @Transactional public void createDefaultAppNamespace(String appId) { if (!isAppNamespaceNameUnique(appId, ConfigConsts.NAMESPACE_APPLICATION)) { throw new BadRequestException(String.format("App already has application namespace. AppId = %s", appId)); } AppNamespace appNs = new AppNamespace(); appNs.setAppId(appId); appNs.setName(ConfigConsts.NAMESPACE_APPLICATION); appNs.setComment("default app namespace"); appNs.setFormat(ConfigFileFormat.Properties.getValue()); String userId = userInfoHolder.getUser().getUserId(); appNs.setDataChangeCreatedBy(userId); appNs.setDataChangeLastModifiedBy(userId); appNamespaceRepository.save(appNs); } public boolean isAppNamespaceNameUnique(String appId, String namespaceName) { Objects.requireNonNull(appId, "AppId must not be null"); Objects.requireNonNull(namespaceName, "Namespace must not be null"); return Objects.isNull(appNamespaceRepository.findByAppIdAndName(appId, namespaceName)); } @Transactional public AppNamespace createAppNamespaceInLocal(AppNamespace appNamespace) { String appId = appNamespace.getAppId(); //add app org id as prefix App app = appService.load(appId); if (app == null) { throw new BadRequestException("App not exist. AppId = " + appId); } StringBuilder appNamespaceName = new StringBuilder(); //add prefix postfix appNamespaceName .append(appNamespace.isPublic() ? app.getOrgId() + "." : "") .append(appNamespace.getName()) .append(appNamespace.formatAsEnum() == ConfigFileFormat.Properties ? "" : "." + appNamespace.getFormat()); appNamespace.setName(appNamespaceName.toString()); if (appNamespace.getComment() == null) { appNamespace.setComment(""); } if (!ConfigFileFormat.isValidFormat(appNamespace.getFormat())) { throw new BadRequestException("Invalid namespace format. format must be properties、json、yaml、yml、xml"); } String operator = appNamespace.getDataChangeCreatedBy(); if (StringUtils.isEmpty(operator)) { operator = userInfoHolder.getUser().getUserId(); appNamespace.setDataChangeCreatedBy(operator); } appNamespace.setDataChangeLastModifiedBy(operator); // unique check if (appNamespace.isPublic() && findPublicAppNamespace(appNamespace.getName()) != null) { throw new BadRequestException(appNamespace.getName() + "已存在"); } if (!appNamespace.isPublic() && appNamespaceRepository.findByAppIdAndName(appNamespace.getAppId(), appNamespace.getName()) != null) { throw new BadRequestException(appNamespace.getName() + "已存在"); } AppNamespace createdAppNamespace = appNamespaceRepository.save(appNamespace); roleInitializationService.initNamespaceRoles(appNamespace.getAppId(), appNamespace.getName(), operator); return createdAppNamespace; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.common.dto.AppDTO; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo; import com.ctrip.framework.apollo.portal.repository.AppRepository; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; import java.util.Set; @Service public class AppService { @Autowired private UserInfoHolder userInfoHolder; @Autowired private AdminServiceAPI.AppAPI appAPI; @Autowired private AppRepository appRepository; @Autowired private ClusterService clusterService; @Autowired private AppNamespaceService appNamespaceService; @Autowired private RoleInitializationService roleInitializationService; @Autowired private UserService userService; public List findAll() { Iterable apps = appRepository.findAll(); if (apps == null) { return Collections.emptyList(); } return Lists.newArrayList((apps)); } public List findByAppIds(Set appIds) { return appRepository.findByAppIdIn(appIds); } public List findByOwnerName(String ownerName, Pageable page) { return appRepository.findByOwnerName(ownerName, page); } public App load(String appId) { return appRepository.findByAppId(appId); } public AppDTO load(Env env, String appId) { return appAPI.loadApp(env, appId); } public void createAppInRemote(Env env, App app) { String username = userInfoHolder.getUser().getUserId(); app.setDataChangeCreatedBy(username); app.setDataChangeLastModifiedBy(username); AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, app); appAPI.createApp(env, appDTO); } @Transactional public App createAppInLocal(App app) { String appId = app.getAppId(); App managedApp = appRepository.findByAppId(appId); if (managedApp != null) { throw new BadRequestException(String.format("App already exists. AppId = %s", appId)); } UserInfo owner = userService.findByUserId(app.getOwnerName()); if (owner == null) { throw new BadRequestException("Application's owner not exist."); } app.setOwnerEmail(owner.getEmail()); String operator = userInfoHolder.getUser().getUserId(); app.setDataChangeCreatedBy(operator); app.setDataChangeLastModifiedBy(operator); App createdApp = appRepository.save(app); appNamespaceService.createDefaultAppNamespace(appId); roleInitializationService.initAppRoles(createdApp); Tracer.logEvent(TracerEventType.CREATE_APP, appId); return createdApp; } @Transactional public App updateAppInLocal(App app) { String appId = app.getAppId(); App managedApp = appRepository.findByAppId(appId); if (managedApp == null) { throw new BadRequestException(String.format("App not exists. AppId = %s", appId)); } managedApp.setName(app.getName()); managedApp.setOrgId(app.getOrgId()); managedApp.setOrgName(app.getOrgName()); String ownerName = app.getOwnerName(); UserInfo owner = userService.findByUserId(ownerName); if (owner == null) { throw new BadRequestException(String.format("App's owner not exists. owner = %s", ownerName)); } managedApp.setOwnerName(owner.getUserId()); managedApp.setOwnerEmail(owner.getEmail()); String operator = userInfoHolder.getUser().getUserId(); managedApp.setDataChangeLastModifiedBy(operator); return appRepository.save(managedApp); } public EnvClusterInfo createEnvNavNode(Env env, String appId) { EnvClusterInfo node = new EnvClusterInfo(env); node.setClusters(clusterService.findClusters(env, appId)); return node; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ClusterService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.dto.ClusterDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class ClusterService { @Autowired private UserInfoHolder userInfoHolder; @Autowired private AdminServiceAPI.ClusterAPI clusterAPI; public List findClusters(Env env, String appId) { return clusterAPI.findClustersByApp(appId, env); } public ClusterDTO createCluster(Env env, ClusterDTO cluster) { if (!clusterAPI.isClusterUnique(cluster.getAppId(), env, cluster.getName())) { throw new BadRequestException(String.format("cluster %s already exists.", cluster.getName())); } ClusterDTO clusterDTO = clusterAPI.create(env, cluster); Tracer.logEvent(TracerEventType.CREATE_CLUSTER, cluster.getAppId(), "0", cluster.getName()); return clusterDTO; } public void deleteCluster(Env env, String appId, String clusterName){ clusterAPI.delete(env, appId, clusterName, userInfoHolder.getUser().getUserId()); } public ClusterDTO loadCluster(String appId, Env env, String clusterName){ return clusterAPI.loadCluster(appId, env, clusterName); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/CommitService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.dto.CommitDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class CommitService { @Autowired private AdminServiceAPI.CommitAPI commitAPI; public List find(String appId, Env env, String clusterName, String namespaceName, int page, int size) { return commitAPI.find(appId, env, clusterName, namespaceName, page, size); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/FavoriteService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.portal.entity.po.Favorite; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.repository.FavoriteRepository; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.Arrays; import java.util.List; import java.util.Objects; @Service public class FavoriteService { public static final long POSITION_DEFAULT = 10000; @Autowired private UserInfoHolder userInfoHolder; @Autowired private FavoriteRepository favoriteRepository; @Autowired private UserService userService; public Favorite addFavorite(Favorite favorite) { UserInfo user = userService.findByUserId(favorite.getUserId()); if (user == null) { throw new BadRequestException("user not exist"); } UserInfo loginUser = userInfoHolder.getUser(); //user can only add himself favorite app if (!loginUser.equals(user)) { throw new BadRequestException("add favorite fail. " + "because favorite's user is not current login user."); } Favorite checkedFavorite = favoriteRepository.findByUserIdAndAppId(loginUser.getUserId(), favorite.getAppId()); if (checkedFavorite != null) { return checkedFavorite; } favorite.setPosition(POSITION_DEFAULT); favorite.setDataChangeCreatedBy(user.getUserId()); favorite.setDataChangeLastModifiedBy(user.getUserId()); return favoriteRepository.save(favorite); } public List search(String userId, String appId, Pageable page) { boolean isUserIdEmpty = StringUtils.isEmpty(userId); boolean isAppIdEmpty = StringUtils.isEmpty(appId); if (isAppIdEmpty && isUserIdEmpty) { throw new BadRequestException("user id and app id can't be empty at the same time"); } //search by userId if (isAppIdEmpty && !isUserIdEmpty) { return favoriteRepository.findByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(userId, page); } //search by appId if (!isAppIdEmpty && isUserIdEmpty) { return favoriteRepository.findByAppIdOrderByPositionAscDataChangeCreatedTimeAsc(appId, page); } //search by userId and appId return Arrays.asList(favoriteRepository.findByUserIdAndAppId(userId, appId)); } public void deleteFavorite(long favoriteId) { Favorite favorite = favoriteRepository.findOne(favoriteId); checkUserOperatePermission(favorite); favoriteRepository.delete(favorite); } public void adjustFavoriteToFirst(long favoriteId) { Favorite favorite = favoriteRepository.findOne(favoriteId); checkUserOperatePermission(favorite); String userId = favorite.getUserId(); Favorite firstFavorite = favoriteRepository.findFirstByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(userId); long minPosition = firstFavorite.getPosition(); favorite.setPosition(minPosition - 1); favoriteRepository.save(favorite); } private void checkUserOperatePermission(Favorite favorite) { if (favorite == null) { throw new BadRequestException("favorite not exist"); } if (!Objects.equals(userInfoHolder.getUser().getUserId(), favorite.getUserId())) { throw new BadRequestException("can not operate other person's favorite"); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/InstanceService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.dto.InstanceDTO; import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Set; @Service public class InstanceService { @Autowired private AdminServiceAPI.InstanceAPI instanceAPI; public PageDTO getByRelease(Env env, long releaseId, int page, int size){ return instanceAPI.getByRelease(env, releaseId, page, size); } public PageDTO getByNamespace(Env env, String appId, String clusterName, String namespaceName, String instanceAppId, int page, int size){ return instanceAPI.getByNamespace(appId, env, clusterName, namespaceName, instanceAppId, page, size); } public int getInstanceCountByNamepsace(String appId, Env env, String clusterName, String namespaceName){ return instanceAPI.getInstanceCountByNamespace(appId, env, clusterName, namespaceName); } public List getByReleasesNotIn(Env env, String appId, String clusterName, String namespaceName, Set releaseIds){ return instanceAPI.getByReleasesNotIn(appId, env, clusterName, namespaceName, releaseIds); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ItemService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.txtresolver.ConfigTextResolver; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.portal.entity.model.NamespaceTextModel; import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs; import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifier; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.client.HttpClientErrorException; import java.util.LinkedList; import java.util.List; import java.util.Map; @Service public class ItemService { @Autowired private UserInfoHolder userInfoHolder; @Autowired private AdminServiceAPI.NamespaceAPI namespaceAPI; @Autowired private AdminServiceAPI.ItemAPI itemAPI; @Autowired @Qualifier("fileTextResolver") private ConfigTextResolver fileTextResolver; @Autowired @Qualifier("propertyResolver") private ConfigTextResolver propertyResolver; /** * parse config text and update config items * * @return parse result */ public void updateConfigItemByText(NamespaceTextModel model) { String appId = model.getAppId(); Env env = model.getEnv(); String clusterName = model.getClusterName(); String namespaceName = model.getNamespaceName(); long namespaceId = model.getNamespaceId(); String configText = model.getConfigText(); ConfigTextResolver resolver = model.getFormat() == ConfigFileFormat.Properties ? propertyResolver : fileTextResolver; ItemChangeSets changeSets = resolver.resolve(namespaceId, configText, itemAPI.findItems(appId, env, clusterName, namespaceName)); if (changeSets.isEmpty()) { return; } changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId()); updateItems(appId, env, clusterName, namespaceName, changeSets); Tracer.logEvent(TracerEventType.MODIFY_NAMESPACE_BY_TEXT, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); Tracer.logEvent(TracerEventType.MODIFY_NAMESPACE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); } public void updateItems(String appId, Env env, String clusterName, String namespaceName, ItemChangeSets changeSets){ itemAPI.updateItemsByChangeSet(appId, env, clusterName, namespaceName, changeSets); } public ItemDTO createItem(String appId, Env env, String clusterName, String namespaceName, ItemDTO item) { NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName); if (namespace == null) { throw new BadRequestException( "namespace:" + namespaceName + " not exist in env:" + env + ", cluster:" + clusterName); } item.setNamespaceId(namespace.getId()); ItemDTO itemDTO = itemAPI.createItem(appId, env, clusterName, namespaceName, item); Tracer.logEvent(TracerEventType.MODIFY_NAMESPACE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); return itemDTO; } public void updateItem(String appId, Env env, String clusterName, String namespaceName, ItemDTO item) { itemAPI.updateItem(appId, env, clusterName, namespaceName, item.getId(), item); } public void deleteItem(Env env, long itemId, String userId) { itemAPI.deleteItem(env, itemId, userId); } public List findItems(String appId, Env env, String clusterName, String namespaceName) { return itemAPI.findItems(appId, env, clusterName, namespaceName); } public ItemDTO loadItem(Env env, String appId, String clusterName, String namespaceName, String key) { return itemAPI.loadItem(env, appId, clusterName, namespaceName, key); } public void syncItems(List comparedNamespaces, List sourceItems) { List itemDiffs = compare(comparedNamespaces, sourceItems); for (ItemDiffs itemDiff : itemDiffs) { NamespaceIdentifier namespaceIdentifier = itemDiff.getNamespace(); ItemChangeSets changeSets = itemDiff.getDiffs(); changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId()); String appId = namespaceIdentifier.getAppId(); Env env = namespaceIdentifier.getEnv(); String clusterName = namespaceIdentifier.getClusterName(); String namespaceName = namespaceIdentifier.getNamespaceName(); itemAPI.updateItemsByChangeSet(appId, env, clusterName, namespaceName, changeSets); Tracer.logEvent(TracerEventType.SYNC_NAMESPACE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); } } public List compare(List comparedNamespaces, List sourceItems) { List result = new LinkedList<>(); for (NamespaceIdentifier namespace : comparedNamespaces) { ItemDiffs itemDiffs = new ItemDiffs(namespace); try { itemDiffs.setDiffs(parseChangeSets(namespace, sourceItems)); } catch (BadRequestException e) { itemDiffs.setDiffs(new ItemChangeSets()); itemDiffs.setExtInfo("该集群下没有名为 " + namespace.getNamespaceName() + " 的namespace"); } result.add(itemDiffs); } return result; } private long getNamespaceId(NamespaceIdentifier namespaceIdentifier) { String appId = namespaceIdentifier.getAppId(); String clusterName = namespaceIdentifier.getClusterName(); String namespaceName = namespaceIdentifier.getNamespaceName(); Env env = namespaceIdentifier.getEnv(); NamespaceDTO namespaceDTO = null; try { namespaceDTO = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName); } catch (HttpClientErrorException e) { if (e.getStatusCode() == HttpStatus.NOT_FOUND) { throw new BadRequestException(String.format( "namespace not exist. appId:%s, env:%s, clusterName:%s, namespaceName:%s", appId, env, clusterName, namespaceName)); } } return namespaceDTO.getId(); } private ItemChangeSets parseChangeSets(NamespaceIdentifier namespace, List sourceItems) { ItemChangeSets changeSets = new ItemChangeSets(); List targetItems = itemAPI.findItems(namespace.getAppId(), namespace.getEnv(), namespace.getClusterName(), namespace.getNamespaceName()); long namespaceId = getNamespaceId(namespace); if (CollectionUtils.isEmpty(targetItems)) {//all source items is added int lineNum = 1; for (ItemDTO sourceItem : sourceItems) { changeSets.addCreateItem(buildItem(namespaceId, lineNum++, sourceItem)); } } else { Map targetItemMap = BeanUtils.mapByKey("key", targetItems); String key, sourceValue, sourceComment; ItemDTO targetItem = null; int maxLineNum = targetItems.size();//append to last for (ItemDTO sourceItem : sourceItems) { key = sourceItem.getKey(); sourceValue = sourceItem.getValue(); sourceComment = sourceItem.getComment(); targetItem = targetItemMap.get(key); if (targetItem == null) {//added items changeSets.addCreateItem(buildItem(namespaceId, ++maxLineNum, sourceItem)); } else if (isModified(sourceValue, targetItem.getValue(), sourceComment, targetItem.getComment())) {//modified items targetItem.setValue(sourceValue); targetItem.setComment(sourceComment); changeSets.addUpdateItem(targetItem); } } } return changeSets; } private ItemDTO buildItem(long namespaceId, int lineNum, ItemDTO sourceItem) { ItemDTO createdItem = new ItemDTO(); BeanUtils.copyEntityProperties(sourceItem, createdItem); createdItem.setLineNum(lineNum); createdItem.setNamespaceId(namespaceId); return createdItem; } private boolean isModified(String sourceValue, String targetValue, String sourceComment, String targetComment) { if (!sourceValue.equals(targetValue)) { return true; } if (sourceComment == null) { return !StringUtils.isEmpty(targetComment); } else if (targetComment != null) { return !sourceComment.equals(targetComment); } else { return false; } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceBranchService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.dto.GrayReleaseRuleDTO; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.ItemsComparator; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; @Service public class NamespaceBranchService { @Autowired private ItemsComparator itemsComparator; @Autowired private UserInfoHolder userInfoHolder; @Autowired private NamespaceService namespaceService; @Autowired private ItemService itemService; @Autowired private AdminServiceAPI.NamespaceBranchAPI namespaceBranchAPI; @Autowired private ReleaseService releaseService; @Transactional public NamespaceDTO createBranch(String appId, Env env, String parentClusterName, String namespaceName) { NamespaceDTO createdBranch = namespaceBranchAPI.createBranch(appId, env, parentClusterName, namespaceName, userInfoHolder.getUser().getUserId()); Tracer.logEvent(TracerEventType.CREATE_GRAY_RELEASE, String.format("%s+%s+%s+%s", appId, env, parentClusterName, namespaceName)); return createdBranch; } public GrayReleaseRuleDTO findBranchGrayRules(String appId, Env env, String clusterName, String namespaceName, String branchName) { return namespaceBranchAPI.findBranchGrayRules(appId, env, clusterName, namespaceName, branchName); } public void updateBranchGrayRules(String appId, Env env, String clusterName, String namespaceName, String branchName, GrayReleaseRuleDTO rules) { String operator = userInfoHolder.getUser().getUserId(); rules.setDataChangeCreatedBy(operator); rules.setDataChangeLastModifiedBy(operator); namespaceBranchAPI.updateBranchGrayRules(appId, env, clusterName, namespaceName, branchName, rules); Tracer.logEvent(TracerEventType.UPDATE_GRAY_RELEASE_RULE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); } public void deleteBranch(String appId, Env env, String clusterName, String namespaceName, String branchName) { String operator = userInfoHolder.getUser().getUserId(); namespaceBranchAPI.deleteBranch(appId, env, clusterName, namespaceName, branchName, operator); Tracer.logEvent(TracerEventType.DELETE_GRAY_RELEASE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); } public ReleaseDTO merge(String appId, Env env, String clusterName, String namespaceName, String branchName, String title, String comment, boolean isEmergencyPublish, boolean deleteBranch) { ItemChangeSets changeSets = calculateBranchChangeSet(appId, env, clusterName, namespaceName, branchName); ReleaseDTO mergedResult = releaseService.updateAndPublish(appId, env, clusterName, namespaceName, title, comment, branchName, isEmergencyPublish, deleteBranch, changeSets); Tracer.logEvent(TracerEventType.MERGE_GRAY_RELEASE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); return mergedResult; } private ItemChangeSets calculateBranchChangeSet(String appId, Env env, String clusterName, String namespaceName, String branchName) { NamespaceBO parentNamespace = namespaceService.loadNamespaceBO(appId, env, clusterName, namespaceName); if (parentNamespace == null) { throw new BadRequestException("base namespace not existed"); } if (parentNamespace.getItemModifiedCnt() > 0) { throw new BadRequestException("Merge operation failed. Because master has modified items"); } List masterItems = itemService.findItems(appId, env, clusterName, namespaceName); List branchItems = itemService.findItems(appId, env, branchName, namespaceName); ItemChangeSets changeSets = itemsComparator.compareIgnoreBlankAndCommentItem(parentNamespace.getBaseInfo().getId(), masterItems, branchItems); changeSets.setDeleteItems(Collections.emptyList()); changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId()); return changeSets; } public NamespaceDTO findBranchBaseInfo(String appId, Env env, String clusterName, String namespaceName) { return namespaceBranchAPI.findBranch(appId, env, clusterName, namespaceName); } public NamespaceBO findBranch(String appId, Env env, String clusterName, String namespaceName) { NamespaceDTO namespaceDTO = findBranchBaseInfo(appId, env, clusterName, namespaceName); if (namespaceDTO == null) { return null; } return namespaceService.loadNamespaceBO(appId, env, namespaceDTO.getClusterName(), namespaceName); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceLockService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.vo.LockInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class NamespaceLockService { @Autowired private AdminServiceAPI.NamespaceLockAPI namespaceLockAPI; @Autowired private PortalConfig portalConfig; public NamespaceLockDTO getNamespaceLock(String appId, Env env, String clusterName, String namespaceName) { return namespaceLockAPI.getNamespaceLockOwner(appId, env, clusterName, namespaceName); } public LockInfo getNamespaceLockInfo(String appId, Env env, String clusterName, String namespaceName) { LockInfo lockInfo = new LockInfo(); NamespaceLockDTO namespaceLockDTO = namespaceLockAPI.getNamespaceLockOwner(appId, env, clusterName, namespaceName); String lockOwner = namespaceLockDTO == null ? "" : namespaceLockDTO.getDataChangeCreatedBy(); lockInfo.setLockOwner(lockOwner); lockInfo.setEmergencyPublishAllowed(portalConfig.isEmergencyPublishAllowed(env)); return lockInfo; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.dto.NamespaceDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.portal.entity.bo.ItemBO; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; @Service public class NamespaceService { private Logger logger = LoggerFactory.getLogger(NamespaceService.class); private Gson gson = new Gson(); @Autowired private PortalConfig portalConfig; @Autowired private PortalSettings portalSettings; @Autowired private UserInfoHolder userInfoHolder; @Autowired private AdminServiceAPI.NamespaceAPI namespaceAPI; @Autowired private ItemService itemService; @Autowired private ReleaseService releaseService; @Autowired private AppNamespaceService appNamespaceService; @Autowired private InstanceService instanceService; @Autowired private NamespaceBranchService branchService; public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) { if (StringUtils.isEmpty(namespace.getDataChangeCreatedBy())) { namespace.setDataChangeCreatedBy(userInfoHolder.getUser().getUserId()); } namespace.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId()); NamespaceDTO createdNamespace = namespaceAPI.createNamespace(env, namespace); Tracer.logEvent(TracerEventType.CREATE_NAMESPACE, String.format("%s+%s+%s+%s", namespace.getAppId(), env, namespace.getClusterName(), namespace.getNamespaceName())); return createdNamespace; } @Transactional public void deleteNamespace(String appId, Env env, String clusterName, String namespaceName) { //1. check private namespace AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(appId, namespaceName); if (appNamespace != null && !appNamespace.isPublic()) { throw new BadRequestException("Private namespace can not be deleted"); } //2. check parent namespace has not instances if (namespaceHasInstances(appId, env, clusterName, namespaceName)) { throw new BadRequestException("Can not delete namespace because namespace has active instances"); } //3. check child namespace has not instances NamespaceDTO childNamespace = branchService.findBranchBaseInfo(appId, env, clusterName, namespaceName); if (childNamespace != null && namespaceHasInstances(appId, env, childNamespace.getClusterName(), namespaceName)) { throw new BadRequestException("Can not delete namespace because namespace's branch has active instances"); } //4. check public namespace has not associated namespace if (appNamespace != null && publicAppNamespaceHasAssociatedNamespace(namespaceName, env)) { throw new BadRequestException("Can not delete public namespace which has associated namespaces"); } String operator = userInfoHolder.getUser().getUserId(); namespaceAPI.deleteNamespace(env, appId, clusterName, namespaceName, operator); } public NamespaceDTO loadNamespaceBaseInfo(String appId, Env env, String clusterName, String namespaceName) { NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName); if (namespace == null) { throw new BadRequestException("namespaces not exist"); } return namespace; } /** * load cluster all namespace info with items */ public List findNamespaceBOs(String appId, Env env, String clusterName) { List namespaces = namespaceAPI.findNamespaceByCluster(appId, env, clusterName); if (namespaces == null || namespaces.size() == 0) { throw new BadRequestException("namespaces not exist"); } List namespaceBOs = new LinkedList<>(); for (NamespaceDTO namespace : namespaces) { NamespaceBO namespaceBO; try { namespaceBO = transformNamespace2BO(env, namespace); namespaceBOs.add(namespaceBO); } catch (Exception e) { logger.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}", appId, env, clusterName, namespace.getNamespaceName(), e); throw e; } } return namespaceBOs; } public List getPublicAppNamespaceAllNamespaces(Env env, String publicNamespaceName, int page, int size) { return namespaceAPI.getPublicAppNamespaceAllNamespaces(env, publicNamespaceName, page, size); } public NamespaceBO loadNamespaceBO(String appId, Env env, String clusterName, String namespaceName) { NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName); if (namespace == null) { throw new BadRequestException("namespaces not exist"); } return transformNamespace2BO(env, namespace); } public boolean namespaceHasInstances(String appId, Env env, String clusterName, String namespaceName) { return instanceService.getInstanceCountByNamepsace(appId, env, clusterName, namespaceName) > 0; } public boolean publicAppNamespaceHasAssociatedNamespace(String publicNamespaceName, Env env) { return namespaceAPI.countPublicAppNamespaceAssociatedNamespaces(env, publicNamespaceName) > 0; } public NamespaceBO findPublicNamespaceForAssociatedNamespace(Env env, String appId, String clusterName, String namespaceName) { NamespaceDTO namespace = namespaceAPI.findPublicNamespaceForAssociatedNamespace(env, appId, clusterName, namespaceName); return transformNamespace2BO(env, namespace); } public Map> getNamespacesPublishInfo(String appId) { Map> result = Maps.newHashMap(); Set envs = portalConfig.publishTipsSupportedEnvs(); for (Env env : envs) { if (portalSettings.isEnvActive(env)) { result.put(env.toString(), namespaceAPI.getNamespacePublishInfo(env, appId)); } } return result; } private NamespaceBO transformNamespace2BO(Env env, NamespaceDTO namespace) { NamespaceBO namespaceBO = new NamespaceBO(); namespaceBO.setBaseInfo(namespace); String appId = namespace.getAppId(); String clusterName = namespace.getClusterName(); String namespaceName = namespace.getNamespaceName(); fillAppNamespaceProperties(namespaceBO); List itemBOs = new LinkedList<>(); namespaceBO.setItems(itemBOs); //latest Release ReleaseDTO latestRelease; Map releaseItems = new HashMap<>(); latestRelease = releaseService.loadLatestRelease(appId, env, clusterName, namespaceName); if (latestRelease != null) { releaseItems = gson.fromJson(latestRelease.getConfigurations(), GsonType.CONFIG); } //not Release config items List items = itemService.findItems(appId, env, clusterName, namespaceName); int modifiedItemCnt = 0; for (ItemDTO itemDTO : items) { ItemBO itemBO = transformItem2BO(itemDTO, releaseItems); if (itemBO.isModified()) { modifiedItemCnt++; } itemBOs.add(itemBO); } //deleted items List deletedItems = parseDeletedItems(items, releaseItems); itemBOs.addAll(deletedItems); modifiedItemCnt += deletedItems.size(); namespaceBO.setItemModifiedCnt(modifiedItemCnt); return namespaceBO; } private void fillAppNamespaceProperties(NamespaceBO namespace) { NamespaceDTO namespaceDTO = namespace.getBaseInfo(); //先从当前appId下面找,包含私有的和公共的 AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(namespaceDTO.getAppId(), namespaceDTO.getNamespaceName()); //再从公共的app namespace里面找 if (appNamespace == null) { appNamespace = appNamespaceService.findPublicAppNamespace(namespaceDTO.getNamespaceName()); } String format; boolean isPublic; if (appNamespace == null) { format = ConfigFileFormat.Properties.getValue(); isPublic = false; } else { format = appNamespace.getFormat(); isPublic = appNamespace.isPublic(); namespace.setParentAppId(appNamespace.getAppId()); namespace.setComment(appNamespace.getComment()); } namespace.setFormat(format); namespace.setPublic(isPublic); } private List parseDeletedItems(List newItems, Map releaseItems) { Map newItemMap = BeanUtils.mapByKey("key", newItems); List deletedItems = new LinkedList<>(); for (Map.Entry entry : releaseItems.entrySet()) { String key = entry.getKey(); if (newItemMap.get(key) == null) { ItemBO deletedItem = new ItemBO(); deletedItem.setDeleted(true); ItemDTO deletedItemDto = new ItemDTO(); deletedItemDto.setKey(key); String oldValue = entry.getValue(); deletedItem.setItem(deletedItemDto); deletedItemDto.setValue(oldValue); deletedItem.setModified(true); deletedItem.setOldValue(oldValue); deletedItem.setNewValue(""); deletedItems.add(deletedItem); } } return deletedItems; } private ItemBO transformItem2BO(ItemDTO itemDTO, Map releaseItems) { String key = itemDTO.getKey(); ItemBO itemBO = new ItemBO(); itemBO.setItem(itemDTO); String newValue = itemDTO.getValue(); String oldValue = releaseItems.get(key); //new item or modified if (!StringUtils.isEmpty(key) && (oldValue == null || !newValue.equals(oldValue))) { itemBO.setModified(true); itemBO.setOldValue(oldValue == null ? "" : oldValue); itemBO.setNewValue(newValue); } return itemBO; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalDBPropertySource.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.google.common.collect.Maps; import com.ctrip.framework.apollo.common.config.RefreshablePropertySource; import com.ctrip.framework.apollo.portal.entity.po.ServerConfig; import com.ctrip.framework.apollo.portal.repository.ServerConfigRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Map; import java.util.Objects; /** * @author Jason Song(song_s@ctrip.com) */ @Component public class PortalDBPropertySource extends RefreshablePropertySource { private static final Logger logger = LoggerFactory.getLogger(PortalDBPropertySource.class); @Autowired private ServerConfigRepository serverConfigRepository; public PortalDBPropertySource(String name, Map source) { super(name, source); } public PortalDBPropertySource() { super("DBConfig", Maps.newConcurrentMap()); } @Override protected void refresh() { Iterable dbConfigs = serverConfigRepository.findAll(); for (ServerConfig config: dbConfigs) { String key = config.getKey(); Object value = config.getValue(); if (this.source.isEmpty()) { logger.info("Load config from DB : {} = {}", key, value); } else if (!Objects.equals(this.source.get(key), value)) { logger.info("Load config from DB : {} = {}. Old value = {}", key, value, this.source.get(key)); } this.source.put(key, value); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseHistoryService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.google.gson.Gson; import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.dto.ReleaseHistoryDTO; import com.ctrip.framework.apollo.common.entity.EntityPair; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import com.ctrip.framework.apollo.portal.util.RelativeDateFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @Service public class ReleaseHistoryService { private Gson gson = new Gson(); @Autowired private AdminServiceAPI.ReleaseHistoryAPI releaseHistoryAPI; @Autowired private ReleaseService releaseService; public ReleaseHistoryBO findLatestByReleaseIdAndOperation(Env env, long releaseId, int operation){ PageDTO pageDTO = releaseHistoryAPI.findByReleaseIdAndOperation(env, releaseId, operation, 0, 1); if (pageDTO != null && pageDTO.hasContent()){ ReleaseHistoryDTO releaseHistory = pageDTO.getContent().get(0); ReleaseDTO release = releaseService.findReleaseById(env, releaseHistory.getReleaseId()); return transformReleaseHistoryDTO2BO(releaseHistory, release); } return null; } public ReleaseHistoryBO findLatestByPreviousReleaseIdAndOperation(Env env, long previousReleaseId, int operation){ PageDTO pageDTO = releaseHistoryAPI.findByPreviousReleaseIdAndOperation(env, previousReleaseId, operation, 0, 1); if (pageDTO != null && pageDTO.hasContent()){ ReleaseHistoryDTO releaseHistory = pageDTO.getContent().get(0); ReleaseDTO release = releaseService.findReleaseById(env, releaseHistory.getReleaseId()); return transformReleaseHistoryDTO2BO(releaseHistory, release); } return null; } public List findNamespaceReleaseHistory(String appId, Env env, String clusterName, String namespaceName, int page, int size) { PageDTO result = releaseHistoryAPI.findReleaseHistoriesByNamespace(appId, env, clusterName, namespaceName, page, size); if (result == null || !result.hasContent()) { return Collections.emptyList(); } List content = result.getContent(); Set releaseIds = new HashSet<>(); for (ReleaseHistoryDTO releaseHistoryDTO : content) { long releaseId = releaseHistoryDTO.getReleaseId(); if (releaseId != 0) { releaseIds.add(releaseId); } } List releases = releaseService.findReleaseByIds(env, releaseIds); return transformReleaseHistoryDTO2BO(content, releases); } private List transformReleaseHistoryDTO2BO(List source, List releases) { Map releasesMap = BeanUtils.mapByKey("id", releases); List bos = new ArrayList<>(source.size()); for (ReleaseHistoryDTO dto : source) { ReleaseDTO release = releasesMap.get(dto.getReleaseId()); bos.add(transformReleaseHistoryDTO2BO(dto, release)); } return bos; } private ReleaseHistoryBO transformReleaseHistoryDTO2BO(ReleaseHistoryDTO dto, ReleaseDTO release){ ReleaseHistoryBO bo = new ReleaseHistoryBO(); bo.setId(dto.getId()); bo.setAppId(dto.getAppId()); bo.setClusterName(dto.getClusterName()); bo.setNamespaceName(dto.getNamespaceName()); bo.setBranchName(dto.getBranchName()); bo.setReleaseId(dto.getReleaseId()); bo.setPreviousReleaseId(dto.getPreviousReleaseId()); bo.setOperator(dto.getDataChangeCreatedBy()); bo.setOperation(dto.getOperation()); Date releaseTime = dto.getDataChangeLastModifiedTime(); bo.setReleaseTime(releaseTime); bo.setReleaseTimeFormatted(RelativeDateFormat.format(releaseTime)); bo.setOperationContext(dto.getOperationContext()); //set release info setReleaseInfoToReleaseHistoryBO(bo, release); return bo; } private void setReleaseInfoToReleaseHistoryBO(ReleaseHistoryBO bo, ReleaseDTO release) { if (release != null) { bo.setReleaseTitle(release.getName()); bo.setReleaseComment(release.getComment()); Map configuration = gson.fromJson(release.getConfigurations(), GsonType.CONFIG); List> items = new ArrayList<>(configuration.size()); for (Map.Entry entry : configuration.entrySet()) { EntityPair entityPair = new EntityPair<>(entry.getKey(), entry.getValue()); items.add(entityPair); } bo.setConfiguration(items); } else { bo.setReleaseTitle("no release information"); bo.setConfiguration(null); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.google.common.base.Objects; import com.google.gson.Gson; import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.dto.ItemChangeSets; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel; import com.ctrip.framework.apollo.portal.entity.bo.KVEntity; import com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseBO; import com.ctrip.framework.apollo.portal.enums.ChangeType; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @Service public class ReleaseService { private static final Gson gson = new Gson(); @Autowired private UserInfoHolder userInfoHolder; @Autowired private AdminServiceAPI.ReleaseAPI releaseAPI; public ReleaseDTO publish(NamespaceReleaseModel model) { Env env = model.getEnv(); boolean isEmergencyPublish = model.isEmergencyPublish(); String appId = model.getAppId(); String clusterName = model.getClusterName(); String namespaceName = model.getNamespaceName(); String releaseBy = StringUtils.isEmpty(model.getReleasedBy()) ? userInfoHolder.getUser().getUserId() : model.getReleasedBy(); ReleaseDTO releaseDTO = releaseAPI.createRelease(appId, env, clusterName, namespaceName, model.getReleaseTitle(), model.getReleaseComment(), releaseBy, isEmergencyPublish); Tracer.logEvent(TracerEventType.RELEASE_NAMESPACE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName)); return releaseDTO; } public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespaceName, String releaseTitle, String releaseComment, String branchName, boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) { return releaseAPI.updateAndPublish(appId, env, clusterName, namespaceName, releaseTitle, releaseComment, branchName, isEmergencyPublish, deleteBranch, changeSets); } public List findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page, int size) { List releaseDTOs = releaseAPI.findAllReleases(appId, env, clusterName, namespaceName, page, size); if (CollectionUtils.isEmpty(releaseDTOs)) { return Collections.emptyList(); } List releases = new LinkedList<>(); for (ReleaseDTO releaseDTO : releaseDTOs) { ReleaseBO release = new ReleaseBO(); release.setBaseInfo(releaseDTO); Set kvEntities = new LinkedHashSet<>(); Map configurations = gson.fromJson(releaseDTO.getConfigurations(), GsonType.CONFIG); Set> entries = configurations.entrySet(); for (Map.Entry entry : entries) { kvEntities.add(new KVEntity(entry.getKey(), entry.getValue())); } release.setItems(kvEntities); //为了减少数据量 releaseDTO.setConfigurations(""); releases.add(release); } return releases; } public List findActiveReleases(String appId, Env env, String clusterName, String namespaceName, int page, int size) { return releaseAPI.findActiveReleases(appId, env, clusterName, namespaceName, page, size); } public ReleaseDTO findReleaseById(Env env, long releaseId) { Set releaseIds = new HashSet<>(1); releaseIds.add(releaseId); List releases = findReleaseByIds(env, releaseIds); if (CollectionUtils.isEmpty(releases)) { return null; } else { return releases.get(0); } } public List findReleaseByIds(Env env, Set releaseIds) { return releaseAPI.findReleaseByIds(env, releaseIds); } public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName, String namespaceName) { return releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName); } public void rollback(Env env, long releaseId) { releaseAPI.rollback(env, releaseId, userInfoHolder.getUser().getUserId()); } public ReleaseCompareResult compare(Env env, long baseReleaseId, long toCompareReleaseId) { ReleaseDTO baseRelease = null; ReleaseDTO toCompareRelease = null; if (baseReleaseId != 0) { baseRelease = releaseAPI.loadRelease(env, baseReleaseId); } if (toCompareReleaseId != 0) { toCompareRelease = releaseAPI.loadRelease(env, toCompareReleaseId); } return compare(baseRelease, toCompareRelease); } public ReleaseCompareResult compare(ReleaseDTO baseRelease, ReleaseDTO toCompareRelease) { Map baseReleaseConfiguration = baseRelease == null ? new HashMap<>() : gson.fromJson(baseRelease.getConfigurations(), GsonType.CONFIG); Map toCompareReleaseConfiguration = toCompareRelease == null ? new HashMap<>() : gson.fromJson(toCompareRelease.getConfigurations(), GsonType.CONFIG); ReleaseCompareResult compareResult = new ReleaseCompareResult(); //added and modified in firstRelease for (Map.Entry entry : baseReleaseConfiguration.entrySet()) { String key = entry.getKey(); String firstValue = entry.getValue(); String secondValue = toCompareReleaseConfiguration.get(key); //added if (secondValue == null) { compareResult.addEntityPair(ChangeType.DELETED, new KVEntity(key, firstValue), new KVEntity(key, null)); } else if (!Objects.equal(firstValue, secondValue)) { compareResult.addEntityPair(ChangeType.MODIFIED, new KVEntity(key, firstValue), new KVEntity(key, secondValue)); } } //deleted in firstRelease for (Map.Entry entry : toCompareReleaseConfiguration.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); if (baseReleaseConfiguration.get(key) == null) { compareResult .addEntityPair(ChangeType.ADDED, new KVEntity(key, ""), new KVEntity(key, value)); } } return compareResult; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RoleInitializationService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.entity.App; public interface RoleInitializationService { public void initAppRoles(App app); public void initNamespaceRoles(String appId, String namespaceName, String operator); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java ================================================ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.po.Permission; import com.ctrip.framework.apollo.portal.entity.po.Role; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ public interface RolePermissionService { /** * Create role with permissions, note that role name should be unique */ public Role createRoleWithPermissions(Role role, Set permissionIds); /** * Assign role to users * * @return the users assigned roles */ public Set assignRoleToUsers(String roleName, Set userIds, String operatorUserId); /** * Remove role from users */ public void removeRoleFromUsers(String roleName, Set userIds, String operatorUserId); /** * Query users with role */ public Set queryUsersWithRole(String roleName); /** * Find role by role name, note that roleName should be unique */ public Role findRoleByRoleName(String roleName); /** * Check whether user has the permission */ public boolean userHasPermission(String userId, String permissionType, String targetId); public boolean isSuperAdmin(String userId); /** * Create permission, note that permissionType + targetId should be unique */ public Permission createPermission(Permission permission); /** * Create permissions, note that permissionType + targetId should be unique */ public Set createPermissions(Set permissions); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/EmailService.java ================================================ package com.ctrip.framework.apollo.portal.spi; import com.ctrip.framework.apollo.portal.entity.bo.Email; public interface EmailService { void send(Email email); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/LogoutHandler.java ================================================ package com.ctrip.framework.apollo.portal.spi; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface LogoutHandler { void logout(HttpServletRequest request, HttpServletResponse response); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/MQService.java ================================================ package com.ctrip.framework.apollo.portal.spi; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; public interface MQService { void sendPublishMsg(Env env, ReleaseHistoryBO releaseHistory); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/SsoHeartbeatHandler.java ================================================ package com.ctrip.framework.apollo.portal.spi; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Jason Song(song_s@ctrip.com) */ public interface SsoHeartbeatHandler { void doHeartbeat(HttpServletRequest request, HttpServletResponse response); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/UserInfoHolder.java ================================================ package com.ctrip.framework.apollo.portal.spi; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; /** * Get access to the user's information, * different companies should have a different implementation */ public interface UserInfoHolder { UserInfo getUser(); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/UserService.java ================================================ package com.ctrip.framework.apollo.portal.spi; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import java.util.List; import java.util.Set; /** * @author Jason Song(song_s@ctrip.com) */ public interface UserService { List searchUsers(String keyword, int offset, int limit); UserInfo findByUserId(String userId); List findByUserIds(List userIds); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/AuthConfiguration.java ================================================ package com.ctrip.framework.apollo.portal.spi.configuration; import com.google.common.collect.Maps; import com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.spi.LogoutHandler; import com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.portal.spi.ctrip.CtripLogoutHandler; import com.ctrip.framework.apollo.portal.spi.ctrip.CtripSsoHeartbeatHandler; import com.ctrip.framework.apollo.portal.spi.ctrip.CtripUserInfoHolder; import com.ctrip.framework.apollo.portal.spi.ctrip.CtripUserService; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultLogoutHandler; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultSsoHeartbeatHandler; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultUserInfoHolder; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultUserService; import com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserInfoHolder; import com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserService; import org.apache.tomcat.jdbc.pool.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.embedded.ServletListenerRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.provisioning.JdbcUserDetailsManager; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import javax.servlet.Filter; import java.util.EventListener; import java.util.Map; @Configuration public class AuthConfiguration { /** * spring.profiles.active = ctrip */ @Configuration @Profile("ctrip") static class CtripAuthAutoConfiguration { @Autowired private PortalConfig portalConfig; @Bean public ServletListenerRegistrationBean redisAppSettingListner() { ServletListenerRegistrationBean redisAppSettingListener = new ServletListenerRegistrationBean(); redisAppSettingListener.setListener(listener("org.jasig.cas.client.credis.CRedisAppSettingListner")); return redisAppSettingListener; } @Bean public ServletListenerRegistrationBean singleSignOutHttpSessionListener() { ServletListenerRegistrationBean singleSignOutHttpSessionListener = new ServletListenerRegistrationBean(); singleSignOutHttpSessionListener .setListener(listener("org.jasig.cas.client.session.SingleSignOutHttpSessionListener")); return singleSignOutHttpSessionListener; } @Bean public FilterRegistrationBean casFilter() { FilterRegistrationBean singleSignOutFilter = new FilterRegistrationBean(); singleSignOutFilter.setFilter(filter("org.jasig.cas.client.session.SingleSignOutFilter")); singleSignOutFilter.addUrlPatterns("/*"); singleSignOutFilter.setOrder(1); return singleSignOutFilter; } @Bean public FilterRegistrationBean authenticationFilter() { FilterRegistrationBean casFilter = new FilterRegistrationBean(); Map filterInitParam = Maps.newHashMap(); filterInitParam.put("redisClusterName", "casClientPrincipal"); filterInitParam.put("serverName", portalConfig.portalServerName()); filterInitParam.put("casServerLoginUrl", portalConfig.casServerLoginUrl()); //we don't want to use session to store login information, since we will be deployed to a cluster, not a single instance filterInitParam.put("useSession", "false"); filterInitParam.put("/openapi.*", "exclude"); casFilter.setInitParameters(filterInitParam); casFilter.setFilter(filter("com.ctrip.framework.apollo.sso.filter.ApolloAuthenticationFilter")); casFilter.addUrlPatterns("/*"); casFilter.setOrder(2); return casFilter; } @Bean public FilterRegistrationBean casValidationFilter() { FilterRegistrationBean casValidationFilter = new FilterRegistrationBean(); Map filterInitParam = Maps.newHashMap(); filterInitParam.put("casServerUrlPrefix", portalConfig.casServerUrlPrefix()); filterInitParam.put("serverName", portalConfig.portalServerName()); filterInitParam.put("encoding", "UTF-8"); //we don't want to use session to store login information, since we will be deployed to a cluster, not a single instance filterInitParam.put("useSession", "false"); filterInitParam.put("useRedis", "true"); filterInitParam.put("redisClusterName", "casClientPrincipal"); casValidationFilter .setFilter(filter("org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter")); casValidationFilter.setInitParameters(filterInitParam); casValidationFilter.addUrlPatterns("/*"); casValidationFilter.setOrder(3); return casValidationFilter; } @Bean public FilterRegistrationBean assertionHolder() { FilterRegistrationBean assertionHolderFilter = new FilterRegistrationBean(); Map filterInitParam = Maps.newHashMap(); filterInitParam.put("/openapi.*", "exclude"); assertionHolderFilter.setInitParameters(filterInitParam); assertionHolderFilter.setFilter(filter("com.ctrip.framework.apollo.sso.filter.ApolloAssertionThreadLocalFilter")); assertionHolderFilter.addUrlPatterns("/*"); assertionHolderFilter.setOrder(4); return assertionHolderFilter; } @Bean public CtripUserInfoHolder ctripUserInfoHolder() { return new CtripUserInfoHolder(); } @Bean public CtripLogoutHandler logoutHandler() { return new CtripLogoutHandler(); } private Filter filter(String className) { Class clazz = null; try { clazz = Class.forName(className); Object obj = clazz.newInstance(); return (Filter) obj; } catch (Exception e) { throw new RuntimeException("instance filter fail", e); } } private EventListener listener(String className) { Class clazz = null; try { clazz = Class.forName(className); Object obj = clazz.newInstance(); return (EventListener) obj; } catch (Exception e) { throw new RuntimeException("instance listener fail", e); } } @Bean public UserService ctripUserService(PortalConfig portalConfig) { return new CtripUserService(portalConfig); } @Bean public SsoHeartbeatHandler ctripSsoHeartbeatHandler() { return new CtripSsoHeartbeatHandler(); } } /** * spring.profiles.active = auth */ @Configuration @Profile("auth") static class SpringSecurityAuthAutoConfiguration { @Bean @ConditionalOnMissingBean(SsoHeartbeatHandler.class) public SsoHeartbeatHandler defaultSsoHeartbeatHandler() { return new DefaultSsoHeartbeatHandler(); } @Bean @ConditionalOnMissingBean(UserInfoHolder.class) public UserInfoHolder springSecurityUserInfoHolder() { return new SpringSecurityUserInfoHolder(); } @Bean @ConditionalOnMissingBean(LogoutHandler.class) public LogoutHandler logoutHandler() { return new DefaultLogoutHandler(); } @Bean public JdbcUserDetailsManager jdbcUserDetailsManager(AuthenticationManagerBuilder auth, DataSource datasource) throws Exception { JdbcUserDetailsManager jdbcUserDetailsManager = auth.jdbcAuthentication().passwordEncoder(new BCryptPasswordEncoder()).dataSource(datasource) .usersByUsernameQuery("select Username,Password,Enabled from `Users` where Username = ?") .authoritiesByUsernameQuery("select Username,Authority from `Authorities` where Username = ?") .getUserDetailsService(); jdbcUserDetailsManager.setUserExistsSql("select Username from `Users` where Username = ?"); jdbcUserDetailsManager.setCreateUserSql("insert into `Users` (Username, Password, Enabled) values (?,?,?)"); jdbcUserDetailsManager.setUpdateUserSql("update `Users` set Password = ?, Enabled = ? where Username = ?"); jdbcUserDetailsManager.setDeleteUserSql("delete from `Users` where Username = ?"); jdbcUserDetailsManager.setCreateAuthoritySql("insert into `Authorities` (Username, Authority) values (?,?)"); jdbcUserDetailsManager.setDeleteUserAuthoritiesSql("delete from `Authorities` where Username = ?"); jdbcUserDetailsManager.setChangePasswordSql("update `Users` set Password = ? where Username = ?"); return jdbcUserDetailsManager; } @Bean @ConditionalOnMissingBean(UserService.class) public UserService springSecurityUserService() { return new SpringSecurityUserService(); } } @Order(99) @Profile("auth") @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) static class SpringSecurityConfigurer extends WebSecurityConfigurerAdapter { public static final String USER_ROLE = "user"; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.headers().frameOptions().disable(); http.authorizeRequests().antMatchers("/openapi/**", "/vendor/**", "/styles/**", "/scripts/**", "/views/**", "/img/**","/**").permitAll() .antMatchers("/**").hasAnyRole(USER_ROLE); http.formLogin().loginPage("/signin").permitAll().failureUrl("/signin?#/error").and().httpBasic(); http.logout().invalidateHttpSession(true).clearAuthentication(true).logoutSuccessUrl("/signin?#/logout"); http.exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/signin")); } } /** * default profile */ @Configuration @ConditionalOnMissingProfile({"ctrip", "auth"}) static class DefaultAuthAutoConfiguration { @Bean @ConditionalOnMissingBean(SsoHeartbeatHandler.class) public SsoHeartbeatHandler defaultSsoHeartbeatHandler() { return new DefaultSsoHeartbeatHandler(); } @Bean @ConditionalOnMissingBean(UserInfoHolder.class) public DefaultUserInfoHolder defaultUserInfoHolder() { return new DefaultUserInfoHolder(); } @Bean @ConditionalOnMissingBean(LogoutHandler.class) public DefaultLogoutHandler logoutHandler() { return new DefaultLogoutHandler(); } @Bean @ConditionalOnMissingBean(UserService.class) public UserService defaultUserService() { return new DefaultUserService(); } } @ConditionalOnMissingProfile("auth") @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) static class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.headers().frameOptions().disable(); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/AuthFilterConfiguration.java ================================================ package com.ctrip.framework.apollo.portal.spi.configuration; import com.ctrip.framework.apollo.openapi.filter.ConsumerAuthenticationFilter; import com.ctrip.framework.apollo.openapi.util.ConsumerAuditUtil; import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil; import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AuthFilterConfiguration { @Bean public FilterRegistrationBean openApiAuthenticationFilter(ConsumerAuthUtil consumerAuthUtil, ConsumerAuditUtil consumerAuditUtil) { FilterRegistrationBean openApiFilter = new FilterRegistrationBean(); openApiFilter.setFilter(new ConsumerAuthenticationFilter(consumerAuthUtil, consumerAuditUtil)); openApiFilter.addUrlPatterns("/openapi/*"); return openApiFilter; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/EmailConfiguration.java ================================================ package com.ctrip.framework.apollo.portal.spi.configuration; import com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile; import com.ctrip.framework.apollo.portal.spi.EmailService; import com.ctrip.framework.apollo.portal.spi.ctrip.CtripEmailService; import com.ctrip.framework.apollo.portal.spi.ctrip.CtripEmailRequestBuilder; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultEmailService; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @Configuration public class EmailConfiguration { /** * spring.profiles.active = ctrip */ @Configuration @Profile("ctrip") public static class CtripEmailConfiguration { @Bean public EmailService ctripEmailService() { return new CtripEmailService(); } @Bean public CtripEmailRequestBuilder emailRequestBuilder() { return new CtripEmailRequestBuilder(); } } /** * spring.profiles.active != ctrip */ @Configuration @ConditionalOnMissingProfile({"ctrip"}) public static class DefaultEmailConfiguration { @Bean @ConditionalOnMissingBean(EmailService.class) public EmailService defaultEmailService() { return new DefaultEmailService(); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/MQConfiguration.java ================================================ package com.ctrip.framework.apollo.portal.spi.configuration; import com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile; import com.ctrip.framework.apollo.portal.spi.ctrip.CtripMQService; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultMQService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @Configuration public class MQConfiguration { @Configuration @Profile("ctrip") public static class CtripMQConfiguration { @Bean public CtripMQService mqService() { return new CtripMQService(); } } /** * spring.profiles.active != ctrip */ @Configuration @ConditionalOnMissingProfile({"ctrip"}) public static class DefaultMQConfiguration { @Bean public DefaultMQService mqService() { return new DefaultMQService(); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/configuration/RoleConfiguration.java ================================================ package com.ctrip.framework.apollo.portal.spi.configuration; import com.ctrip.framework.apollo.portal.service.RoleInitializationService; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultRoleInitializationService; import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultRolePermissionService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author Timothy Liu(timothy.liu@cvte.com) */ @Configuration public class RoleConfiguration { @Bean public RoleInitializationService roleInitializationService() { return new DefaultRoleInitializationService(); } @Bean public RolePermissionService rolePermissionService() { return new DefaultRolePermissionService(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/BizLoggingCustomizer.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.ctrip.framework.apollo.common.customize.LoggingCustomizer; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @Component @Profile("ctrip") public class BizLoggingCustomizer extends LoggingCustomizer { @Autowired private PortalConfig portalConfig; @Override protected String cloggingUrl() { return portalConfig.cloggingUrl(); } @Override protected String cloggingPort() { return portalConfig.cloggingPort(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripEmailRequestBuilder.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.bo.Email; import com.ctrip.framework.apollo.tracer.Tracer; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.lang.reflect.Method; import java.util.Calendar; import java.util.Date; import java.util.List; import javax.annotation.PostConstruct; public class CtripEmailRequestBuilder { private static final Logger logger = LoggerFactory.getLogger(CtripEmailRequestBuilder.class); private static Class sendEmailRequestClazz; private static Method setBodyContent; private static Method setRecipient; private static Method setSendCode; private static Method setBodyTemplateID; private static Method setSender; private static Method setSubject; private static Method setIsBodyHtml; private static Method setCharset; private static Method setExpiredTime; private static Method setAppID; @Autowired private PortalConfig portalConfig; @PostConstruct public void init() { try { sendEmailRequestClazz = Class.forName("com.ctrip.framework.apolloctripservice.emailservice.SendEmailRequest"); setSendCode = sendEmailRequestClazz.getMethod("setSendCode", String.class); setBodyTemplateID = sendEmailRequestClazz.getMethod("setBodyTemplateID", Integer.class); setSender = sendEmailRequestClazz.getMethod("setSender", String.class); setBodyContent = sendEmailRequestClazz.getMethod("setBodyContent", String.class); setRecipient = sendEmailRequestClazz.getMethod("setRecipient", List.class); setSubject = sendEmailRequestClazz.getMethod("setSubject", String.class); setIsBodyHtml = sendEmailRequestClazz.getMethod("setIsBodyHtml", Boolean.class); setCharset = sendEmailRequestClazz.getMethod("setCharset", String.class); setExpiredTime = sendEmailRequestClazz.getMethod("setExpiredTime", Calendar.class); setAppID = sendEmailRequestClazz.getMethod("setAppID", Integer.class); } catch (Throwable e) { logger.error("init email request build failed", e); Tracer.logError("init email request build failed", e); } } public Object buildEmailRequest(Email email) throws Exception { Object emailRequest = createBasicEmailRequest(); setSender.invoke(emailRequest, email.getSenderEmailAddress()); setSubject.invoke(emailRequest, email.getSubject()); String emailBodyBuilder = "" + email.getBody() + "]]>"; setBodyContent.invoke(emailRequest, emailBodyBuilder); setRecipient.invoke(emailRequest, email.getRecipients()); return emailRequest; } private Object createBasicEmailRequest() throws Exception { Object request = sendEmailRequestClazz.newInstance(); setSendCode.invoke(request, portalConfig.sendCode()); setBodyTemplateID.invoke(request, portalConfig.templateId()); setIsBodyHtml.invoke(request, true); setCharset.invoke(request, "UTF-8"); setExpiredTime.invoke(request, calExpiredTime()); setAppID.invoke(request, portalConfig.appId()); return request; } private Calendar calExpiredTime() { Calendar calendar = Calendar.getInstance(); calendar.setTime(DateUtils.addHours(new Date(), portalConfig.survivalDuration())); return calendar; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripEmailService.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.bo.Email; import com.ctrip.framework.apollo.portal.spi.EmailService; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.lang.reflect.Method; import javax.annotation.PostConstruct; public class CtripEmailService implements EmailService { private static final Logger logger = LoggerFactory.getLogger(CtripEmailService.class); private Object emailServiceClient; private Method sendEmailAsync; private Method sendEmail; @Autowired private CtripEmailRequestBuilder emailRequestBuilder; @Autowired private PortalConfig portalConfig; @PostConstruct public void init() { try { initServiceClientConfig(); Class emailServiceClientClazz = Class.forName("com.ctrip.framework.apolloctripservice.emailservice.EmailServiceClient"); Method getInstanceMethod = emailServiceClientClazz.getMethod("getInstance"); emailServiceClient = getInstanceMethod.invoke(null); Class sendEmailRequestClazz = Class.forName("com.ctrip.framework.apolloctripservice.emailservice.SendEmailRequest"); sendEmailAsync = emailServiceClientClazz.getMethod("sendEmailAsync", sendEmailRequestClazz); sendEmail = emailServiceClientClazz.getMethod("sendEmail", sendEmailRequestClazz); } catch (Throwable e) { logger.error("init ctrip email service failed", e); Tracer.logError("init ctrip email service failed", e); } } private void initServiceClientConfig() throws Exception { Class serviceClientConfigClazz = Class.forName("com.ctriposs.baiji.rpc.client.ServiceClientConfig"); Object serviceClientConfig = serviceClientConfigClazz.newInstance(); Method setFxConfigServiceUrlMethod = serviceClientConfigClazz.getMethod("setFxConfigServiceUrl", String.class); setFxConfigServiceUrlMethod.invoke(serviceClientConfig, portalConfig.soaServerAddress()); Class serviceClientBaseClazz = Class.forName("com.ctriposs.baiji.rpc.client.ServiceClientBase"); Method initializeMethod = serviceClientBaseClazz.getMethod("initialize", serviceClientConfigClazz); initializeMethod.invoke(null, serviceClientConfig); } @Override public void send(Email email) { try { Object emailRequest = emailRequestBuilder.buildEmailRequest(email); Object sendResponse = portalConfig.isSendEmailAsync() ? sendEmailAsync.invoke(emailServiceClient, emailRequest) : sendEmail.invoke(emailServiceClient, emailRequest); logger.info("Email server response: " + sendResponse); } catch (Throwable e) { logger.error("send email failed", e); Tracer.logError("send email failed", e); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripLogoutHandler.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.spi.LogoutHandler; import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class CtripLogoutHandler implements LogoutHandler { @Autowired private PortalConfig portalConfig; @Override public void logout(HttpServletRequest request, HttpServletResponse response) { //将session销毁 HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); } Cookie cookie = new Cookie("memCacheAssertionID", null); //将cookie的有效期设置为0,命令浏览器删除该cookie cookie.setMaxAge(0); cookie.setPath(request.getContextPath() + "/"); response.addCookie(cookie); //重定向到SSO的logout地址 String casServerUrl = portalConfig.casServerUrlPrefix(); String serverName = portalConfig.portalServerName(); try { response.sendRedirect(casServerUrl + "/logout?service=" + serverName); } catch (IOException e) { throw new RuntimeException(e); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripMQService.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.google.gson.Gson; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import com.ctrip.framework.apollo.portal.service.AppService; import com.ctrip.framework.apollo.portal.service.ReleaseService; import com.ctrip.framework.apollo.portal.spi.MQService; import com.ctrip.framework.apollo.tracer.Tracer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.RestTemplate; import java.util.Arrays; import javax.annotation.PostConstruct; public class CtripMQService implements MQService { private static final org.apache.commons.lang.time.FastDateFormat TIMESTAMP_FORMAT = org.apache.commons.lang.time.FastDateFormat.getInstance("yyyy-MM-dd hh:mm:ss"); private static final String CONFIG_PUBLISH_NOTIFY_TO_NOC_TOPIC = "ops.noc.record.created"; private Gson gson = new Gson(); @Autowired private AppService appService; @Autowired private ReleaseService releaseService; @Autowired private PortalConfig portalConfig; private RestTemplate restTemplate; @PostConstruct public void init() { restTemplate = new RestTemplate(); SimpleClientHttpRequestFactory rf = (SimpleClientHttpRequestFactory) restTemplate.getRequestFactory(); rf.setReadTimeout(portalConfig.readTimeout()); rf.setConnectTimeout(portalConfig.connectTimeout()); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes( Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM)); restTemplate.setMessageConverters(Arrays.asList(converter, new FormHttpMessageConverter())); } @Override public void sendPublishMsg(Env env, ReleaseHistoryBO releaseHistory) { if (releaseHistory == null) { return; } PublishMsg msg = buildPublishMsg(env, releaseHistory); sendMsg(portalConfig.hermesServerAddress(), CONFIG_PUBLISH_NOTIFY_TO_NOC_TOPIC, msg); } private PublishMsg buildPublishMsg(Env env, ReleaseHistoryBO releaseHistory) { PublishMsg msg = new PublishMsg(); msg.setPriority("中"); msg.setTool_origin("Apollo"); String appId = releaseHistory.getAppId(); App app = appService.load(appId); msg.setInfluence_bu(app.getOrgName()); msg.setAppid(appId); msg.setAssginee(releaseHistory.getOperator()); msg.setOperation_time(TIMESTAMP_FORMAT.format(releaseHistory.getReleaseTime())); msg.setDesc(gson.toJson(releaseService.compare(env, releaseHistory.getPreviousReleaseId(), releaseHistory.getReleaseId()))); return msg; } private void sendMsg(String serverAddress, String topic, Object msg) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM + ";charset=UTF-8")); HttpEntity request = new HttpEntity<>(msg, headers); try { //send msg by hermes RestAPI restTemplate.postForObject(serverAddress + "/topics/" + topic, request, Object.class); } catch (Exception e) { Tracer.logError("Send publish msg to hermes failed", e); } } private class PublishMsg { private String assginee; private String desc; private String operation_time; private String tool_origin; private String priority; private String influence_bu; private String appid; public String getAssginee() { return assginee; } public void setAssginee(String assginee) { this.assginee = assginee; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getOperation_time() { return operation_time; } public void setOperation_time(String operation_time) { this.operation_time = operation_time; } public String getTool_origin() { return tool_origin; } public void setTool_origin(String tool_origin) { this.tool_origin = tool_origin; } public String getPriority() { return priority; } public void setPriority(String priority) { this.priority = priority; } public String getInfluence_bu() { return influence_bu; } public void setInfluence_bu(String influence_bu) { this.influence_bu = influence_bu; } public String getAppid() { return appid; } public void setAppid(String appid) { this.appid = appid; } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripSsoHeartbeatHandler.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Jason Song(song_s@ctrip.com) */ public class CtripSsoHeartbeatHandler implements SsoHeartbeatHandler { @Override public void doHeartbeat(HttpServletRequest request, HttpServletResponse response) { try { response.sendRedirect("ctrip_sso_heartbeat.html"); } catch (IOException e) { } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripUserInfoHolder.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import java.lang.reflect.Method; /** * ctrip内部实现的获取用户信息 */ public class CtripUserInfoHolder implements UserInfoHolder { private Object assertionHolder; private Method getAssertion; public CtripUserInfoHolder() { Class clazz = null; try { clazz = Class.forName("org.jasig.cas.client.util.AssertionHolder"); assertionHolder = clazz.newInstance(); getAssertion = assertionHolder.getClass().getMethod("getAssertion"); } catch (Exception e) { throw new RuntimeException("init AssertionHolder fail", e); } } @Override public UserInfo getUser() { try { Object assertion = getAssertion.invoke(assertionHolder); Method getPrincipal = assertion.getClass().getMethod("getPrincipal"); Object principal = getPrincipal.invoke(assertion); Method getName = principal.getClass().getMethod("getName"); String name = (String) getName.invoke(principal); UserInfo userInfo = new UserInfo(); userInfo.setUserId(name); return userInfo; } catch (Exception e) { throw new RuntimeException("get user info from assertion holder error", e); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/CtripUserService.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.spi.UserService; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author Jason Song(song_s@ctrip.com) */ public class CtripUserService implements UserService { private RestTemplate restTemplate; private List searchUserMatchFields; private ParameterizedTypeReference>> responseType; private PortalConfig portalConfig; public CtripUserService(PortalConfig portalConfig) { this.portalConfig = portalConfig; this.restTemplate = new RestTemplate(clientHttpRequestFactory()); this.searchUserMatchFields = Lists.newArrayList("empcode", "empaccount", "displayname", "c_name", "pinyin"); this.responseType = new ParameterizedTypeReference>>() { }; } private ClientHttpRequestFactory clientHttpRequestFactory() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(portalConfig.connectTimeout()); factory.setReadTimeout(portalConfig.readTimeout()); return factory; } @Override public List searchUsers(String keyword, int offset, int limit) { UserServiceRequest request = assembleSearchUserRequest(keyword, offset, limit); HttpEntity entity = new HttpEntity<>(request); ResponseEntity>> response = restTemplate.exchange(portalConfig.userServiceUrl(), HttpMethod.POST, entity, responseType); if (!response.getBody().containsKey("result")) { return Collections.emptyList(); } List result = Lists.newArrayList(); result.addAll( response.getBody().get("result").stream().map(this::transformUserServiceResponseToUserInfo) .collect(Collectors.toList())); return result; } @Override public UserInfo findByUserId(String userId) { List userInfoList = this.findByUserIds(Lists.newArrayList(userId)); if (CollectionUtils.isEmpty(userInfoList)) { return null; } return userInfoList.get(0); } public List findByUserIds(List userIds) { UserServiceRequest request = assembleFindUserRequest(Lists.newArrayList(userIds)); HttpEntity entity = new HttpEntity<>(request); ResponseEntity>> response = restTemplate.exchange(portalConfig.userServiceUrl(), HttpMethod.POST, entity, responseType); if (!response.getBody().containsKey("result")) { return Collections.emptyList(); } List result = Lists.newArrayList(); result.addAll( response.getBody().get("result").stream().map(this::transformUserServiceResponseToUserInfo) .collect(Collectors.toList())); return result; } private UserInfo transformUserServiceResponseToUserInfo(UserServiceResponse userServiceResponse) { UserInfo userInfo = new UserInfo(); userInfo.setUserId(userServiceResponse.getEmpaccount()); userInfo.setName(userServiceResponse.getDisplayname()); userInfo.setEmail(userServiceResponse.getEmail()); return userInfo; } UserServiceRequest assembleSearchUserRequest(String keyword, int offset, int limit) { Map query = Maps.newHashMap(); Map multiMatchMap = Maps.newHashMap(); multiMatchMap.put("fields", searchUserMatchFields); multiMatchMap.put("operator", "and"); multiMatchMap.put("query", keyword); multiMatchMap.put("type", "best_fields"); query.put("multi_match", multiMatchMap); return assembleUserServiceRequest(query, offset, limit); } UserServiceRequest assembleFindUserRequest(List userIds) { Map query = ImmutableMap.of("filtered", ImmutableMap .of("filter", ImmutableMap.of("terms", ImmutableMap.of("empaccount", userIds)))); return assembleUserServiceRequest(query, 0, userIds.size()); } private UserServiceRequest assembleUserServiceRequest(Map query, int offset, int limit) { UserServiceRequest request = new UserServiceRequest(); request.setAccess_token(portalConfig.userServiceAccessToken()); UserServiceRequestBody requestBody = new UserServiceRequestBody(); requestBody.setIndexAlias("itdb_emloyee"); requestBody.setType("emloyee"); request.setRequest_body(requestBody); Map queryJson = Maps.newHashMap(); requestBody.setQueryJson(queryJson); queryJson.put("query", query); queryJson.put("from", offset); queryJson.put("size", limit); return request; } static class UserServiceRequest { private String access_token; private UserServiceRequestBody request_body; public String getAccess_token() { return access_token; } public void setAccess_token(String access_token) { this.access_token = access_token; } public UserServiceRequestBody getRequest_body() { return request_body; } public void setRequest_body( UserServiceRequestBody request_body) { this.request_body = request_body; } } static class UserServiceRequestBody { private String indexAlias; private String type; private Map queryJson; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getIndexAlias() { return indexAlias; } public void setIndexAlias(String indexAlias) { this.indexAlias = indexAlias; } public Map getQueryJson() { return queryJson; } public void setQueryJson(Map queryJson) { this.queryJson = queryJson; } } static class UserServiceResponse { private String empaccount; private String displayname; private String email; public String getEmpaccount() { return empaccount; } public void setEmpaccount(String empaccount) { this.empaccount = empaccount; } public String getDisplayname() { return displayname; } public void setDisplayname(String displayname) { this.displayname = displayname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/WebContextConfiguration.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip; import com.ctrip.framework.apollo.portal.spi.ctrip.filters.UserAccessFilter; import com.google.common.base.Strings; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.embedded.ServletContextInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import javax.servlet.ServletContext; import javax.servlet.ServletException; @Configuration @Profile("ctrip") public class WebContextConfiguration { @Autowired private PortalConfig portalConfig; @Autowired private UserInfoHolder userInfoHolder; @Bean public ServletContextInitializer servletContextInitializer() { return new ServletContextInitializer() { @Override public void onStartup(ServletContext servletContext) throws ServletException { String loggingServerIP = portalConfig.cloggingUrl(); String loggingServerPort = portalConfig.cloggingPort(); String credisServiceUrl = portalConfig.credisServiceUrl(); servletContext.setInitParameter("loggingServerIP", Strings.isNullOrEmpty(loggingServerIP) ? "" : loggingServerIP); servletContext.setInitParameter("loggingServerPort", Strings.isNullOrEmpty(loggingServerPort) ? "" : loggingServerPort); servletContext.setInitParameter("credisServiceUrl", Strings.isNullOrEmpty(credisServiceUrl) ? "" : credisServiceUrl); } }; } @Bean public FilterRegistrationBean userAccessFilter() { FilterRegistrationBean filter = new FilterRegistrationBean(); filter.setFilter(new UserAccessFilter(userInfoHolder)); filter.addUrlPatterns("/*"); return filter; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ctrip/filters/UserAccessFilter.java ================================================ package com.ctrip.framework.apollo.portal.spi.ctrip.filters; import com.ctrip.framework.apollo.portal.constant.TracerEventType; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.tracer.Tracer; import com.google.common.base.Strings; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class UserAccessFilter implements Filter { private static final String STATIC_RESOURCE_REGEX = ".*\\.(js|html|htm|png|css|woff2)$"; private UserInfoHolder userInfoHolder; public UserAccessFilter(UserInfoHolder userInfoHolder) { this.userInfoHolder = userInfoHolder; } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String requestUri = ((HttpServletRequest) request).getRequestURI(); try { if (!isOpenAPIRequest(requestUri) && !isStaticResource(requestUri)) { UserInfo userInfo = userInfoHolder.getUser(); if (userInfo != null) { Tracer.logEvent(TracerEventType.USER_ACCESS, userInfo.getUserId()); } } } catch (Throwable e) { Tracer.logError("Record user access info error.", e); } chain.doFilter(request, response); } @Override public void destroy() { } private boolean isOpenAPIRequest(String uri) { return !Strings.isNullOrEmpty(uri) && uri.startsWith("/openapi"); } private boolean isStaticResource(String uri) { return !Strings.isNullOrEmpty(uri) && uri.matches(STATIC_RESOURCE_REGEX); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultEmailService.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.ctrip.framework.apollo.portal.entity.bo.Email; import com.ctrip.framework.apollo.portal.spi.EmailService; public class DefaultEmailService implements EmailService{ @Override public void send(Email email){ //do nothing } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultLogoutHandler.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.ctrip.framework.apollo.portal.spi.LogoutHandler; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DefaultLogoutHandler implements LogoutHandler { @Override public void logout(HttpServletRequest request, HttpServletResponse response) { try { response.sendRedirect("/"); } catch (IOException e) { throw new RuntimeException(e); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultMQService.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO; import com.ctrip.framework.apollo.portal.spi.MQService; public class DefaultMQService implements MQService{ @Override public void sendPublishMsg(Env env, ReleaseHistoryBO releaseHistory) { //do nothing } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRoleInitializationService.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.portal.constant.PermissionType; import com.ctrip.framework.apollo.portal.constant.RoleType; import com.ctrip.framework.apollo.portal.entity.po.Permission; import com.ctrip.framework.apollo.portal.entity.po.Role; import com.ctrip.framework.apollo.portal.service.RoleInitializationService; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.util.RoleUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import java.util.Set; /** * Created by timothy on 2017/4/26. */ public class DefaultRoleInitializationService implements RoleInitializationService { @Autowired private UserInfoHolder userInfoHolder; @Autowired private RolePermissionService rolePermissionService; @Transactional public void initAppRoles(App app) { String appId = app.getAppId(); String appMasterRoleName = RoleUtils.buildAppMasterRoleName(appId); //has created before if (rolePermissionService.findRoleByRoleName(appMasterRoleName) != null) { return; } String operator = app.getDataChangeCreatedBy(); //create app permissions createAppMasterRole(appId, operator); //assign master role to user rolePermissionService .assignRoleToUsers(RoleUtils.buildAppMasterRoleName(appId), Sets.newHashSet(app.getOwnerName()), operator); initNamespaceRoles(appId, ConfigConsts.NAMESPACE_APPLICATION, operator); //assign modify、release namespace role to user rolePermissionService.assignRoleToUsers( RoleUtils.buildNamespaceRoleName(appId, ConfigConsts.NAMESPACE_APPLICATION, RoleType.MODIFY_NAMESPACE), Sets.newHashSet(operator), operator); rolePermissionService.assignRoleToUsers( RoleUtils.buildNamespaceRoleName(appId, ConfigConsts.NAMESPACE_APPLICATION, RoleType.RELEASE_NAMESPACE), Sets.newHashSet(operator), operator); } @Transactional public void initNamespaceRoles(String appId, String namespaceName, String operator) { String modifyNamespaceRoleName = RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName); if (rolePermissionService.findRoleByRoleName(modifyNamespaceRoleName) == null) { createNamespaceRole(appId, namespaceName, PermissionType.MODIFY_NAMESPACE, RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName), operator); } String releaseNamespaceRoleName = RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName); if (rolePermissionService.findRoleByRoleName(releaseNamespaceRoleName) == null) { createNamespaceRole(appId, namespaceName, PermissionType.RELEASE_NAMESPACE, RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName), operator); } } private void createAppMasterRole(String appId, String operator) { Set appPermissions = FluentIterable.from(Lists.newArrayList( PermissionType.CREATE_CLUSTER, PermissionType.CREATE_NAMESPACE, PermissionType.ASSIGN_ROLE)) .transform(permissionType -> createPermission(appId, permissionType, operator)).toSet(); Set createdAppPermissions = rolePermissionService.createPermissions(appPermissions); Set appPermissionIds = FluentIterable.from(createdAppPermissions).transform(permission -> permission.getId()).toSet(); //create app master role Role appMasterRole = createRole(RoleUtils.buildAppMasterRoleName(appId), operator); rolePermissionService.createRoleWithPermissions(appMasterRole, appPermissionIds); } private Permission createPermission(String targetId, String permissionType, String operator) { Permission permission = new Permission(); permission.setPermissionType(permissionType); permission.setTargetId(targetId); permission.setDataChangeCreatedBy(operator); permission.setDataChangeLastModifiedBy(operator); return permission; } private Role createRole(String roleName, String operator) { Role role = new Role(); role.setRoleName(roleName); role.setDataChangeCreatedBy(operator); role.setDataChangeLastModifiedBy(operator); return role; } private void createNamespaceRole(String appId, String namespaceName, String permissionType, String roleName, String operator) { Permission permission = createPermission(RoleUtils.buildNamespaceTargetId(appId, namespaceName), permissionType, operator); Permission createdPermission = rolePermissionService.createPermission(permission); Role role = createRole(roleName, operator); rolePermissionService .createRoleWithPermissions(role, Sets.newHashSet(createdPermission.getId())); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRolePermissionService.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.po.Permission; import com.ctrip.framework.apollo.portal.entity.po.Role; import com.ctrip.framework.apollo.portal.entity.po.RolePermission; import com.ctrip.framework.apollo.portal.entity.po.UserRole; import com.ctrip.framework.apollo.portal.repository.PermissionRepository; import com.ctrip.framework.apollo.portal.repository.RolePermissionRepository; import com.ctrip.framework.apollo.portal.repository.RoleRepository; import com.ctrip.framework.apollo.portal.repository.UserRoleRepository; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.google.common.base.Preconditions; import com.google.common.collect.FluentIterable; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.*; /** * Created by timothy on 2017/4/26. */ public class DefaultRolePermissionService implements RolePermissionService { @Autowired private RoleRepository roleRepository; @Autowired private RolePermissionRepository rolePermissionRepository; @Autowired private UserRoleRepository userRoleRepository; @Autowired private PermissionRepository permissionRepository; @Autowired private PortalConfig portalConfig; /** * Create role with permissions, note that role name should be unique */ @Transactional public Role createRoleWithPermissions(Role role, Set permissionIds) { Role current = findRoleByRoleName(role.getRoleName()); Preconditions.checkState(current == null, "Role %s already exists!", role.getRoleName()); Role createdRole = roleRepository.save(role); if (!CollectionUtils.isEmpty(permissionIds)) { Iterable rolePermissions = FluentIterable.from(permissionIds).transform( permissionId -> { RolePermission rolePermission = new RolePermission(); rolePermission.setRoleId(createdRole.getId()); rolePermission.setPermissionId(permissionId); rolePermission.setDataChangeCreatedBy(createdRole.getDataChangeCreatedBy()); rolePermission.setDataChangeLastModifiedBy(createdRole.getDataChangeLastModifiedBy()); return rolePermission; }); rolePermissionRepository.save(rolePermissions); } return createdRole; } /** * Assign role to users * * @return the users assigned roles */ @Transactional public Set assignRoleToUsers(String roleName, Set userIds, String operatorUserId) { Role role = findRoleByRoleName(roleName); Preconditions.checkState(role != null, "Role %s doesn't exist!", roleName); List existedUserRoles = userRoleRepository.findByUserIdInAndRoleId(userIds, role.getId()); Set existedUserIds = FluentIterable.from(existedUserRoles).transform(userRole -> userRole.getUserId()).toSet(); Set toAssignUserIds = Sets.difference(userIds, existedUserIds); Iterable toCreate = FluentIterable.from(toAssignUserIds).transform(userId -> { UserRole userRole = new UserRole(); userRole.setRoleId(role.getId()); userRole.setUserId(userId); userRole.setDataChangeCreatedBy(operatorUserId); userRole.setDataChangeLastModifiedBy(operatorUserId); return userRole; }); userRoleRepository.save(toCreate); return toAssignUserIds; } /** * Remove role from users */ @Transactional public void removeRoleFromUsers(String roleName, Set userIds, String operatorUserId) { Role role = findRoleByRoleName(roleName); Preconditions.checkState(role != null, "Role %s doesn't exist!", roleName); List existedUserRoles = userRoleRepository.findByUserIdInAndRoleId(userIds, role.getId()); for (UserRole userRole : existedUserRoles) { userRole.setDeleted(true); userRole.setDataChangeLastModifiedTime(new Date()); userRole.setDataChangeLastModifiedBy(operatorUserId); } userRoleRepository.save(existedUserRoles); } /** * Query users with role */ public Set queryUsersWithRole(String roleName) { Role role = findRoleByRoleName(roleName); if (role == null) { return Collections.emptySet(); } List userRoles = userRoleRepository.findByRoleId(role.getId()); Set users = FluentIterable.from(userRoles).transform(userRole -> { UserInfo userInfo = new UserInfo(); userInfo.setUserId(userRole.getUserId()); return userInfo; }).toSet(); return users; } /** * Find role by role name, note that roleName should be unique */ public Role findRoleByRoleName(String roleName) { return roleRepository.findTopByRoleName(roleName); } /** * Check whether user has the permission */ public boolean userHasPermission(String userId, String permissionType, String targetId) { Permission permission = permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId); if (permission == null) { return false; } if (isSuperAdmin(userId)) { return true; } List userRoles = userRoleRepository.findByUserId(userId); if (CollectionUtils.isEmpty(userRoles)) { return false; } Set roleIds = FluentIterable.from(userRoles).transform(userRole -> userRole.getRoleId()).toSet(); List rolePermissions = rolePermissionRepository.findByRoleIdIn(roleIds); if (CollectionUtils.isEmpty(rolePermissions)) { return false; } for (RolePermission rolePermission : rolePermissions) { if (rolePermission.getPermissionId() == permission.getId()) { return true; } } return false; } public boolean isSuperAdmin(String userId) { return portalConfig.superAdmins().contains(userId); } /** * Create permission, note that permissionType + targetId should be unique */ @Transactional public Permission createPermission(Permission permission) { String permissionType = permission.getPermissionType(); String targetId = permission.getTargetId(); Permission current = permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId); Preconditions.checkState(current == null, "Permission with permissionType %s targetId %s already exists!", permissionType, targetId); return permissionRepository.save(permission); } /** * Create permissions, note that permissionType + targetId should be unique */ @Transactional public Set createPermissions(Set permissions) { Multimap targetIdPermissionTypes = HashMultimap.create(); for (Permission permission : permissions) { targetIdPermissionTypes.put(permission.getTargetId(), permission.getPermissionType()); } for (String targetId : targetIdPermissionTypes.keySet()) { Collection permissionTypes = targetIdPermissionTypes.get(targetId); List current = permissionRepository.findByPermissionTypeInAndTargetId(permissionTypes, targetId); Preconditions.checkState(CollectionUtils.isEmpty(current), "Permission with permissionType %s targetId %s already exists!", permissionTypes, targetId); } Iterable results = permissionRepository.save(permissions); return FluentIterable.from(results).toSet(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultSsoHeartbeatHandler.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultSsoHeartbeatHandler implements SsoHeartbeatHandler { @Override public void doHeartbeat(HttpServletRequest request, HttpServletResponse response) { try { response.sendRedirect("default_sso_heartbeat.html"); } catch (IOException e) { } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultUserInfoHolder.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; /** * 不是ctrip的公司默认提供一个假用户 */ public class DefaultUserInfoHolder implements UserInfoHolder { public DefaultUserInfoHolder() { } @Override public UserInfo getUser() { UserInfo userInfo = new UserInfo(); userInfo.setUserId("apollo"); return userInfo; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultUserService.java ================================================ package com.ctrip.framework.apollo.portal.spi.defaultimpl; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.spi.UserService; import java.util.Arrays; import java.util.List; /** * @author Jason Song(song_s@ctrip.com) */ public class DefaultUserService implements UserService { @Override public List searchUsers(String keyword, int offset, int limit) { return Arrays.asList(assembleDefaultUser()); } @Override public UserInfo findByUserId(String userId) { if (userId.equals("apollo")) { return assembleDefaultUser(); } return null; } @Override public List findByUserIds(List userIds) { if (userIds.contains("apollo")) { return Lists.newArrayList(assembleDefaultUser()); } return null; } private UserInfo assembleDefaultUser() { UserInfo defaultUser = new UserInfo(); defaultUser.setUserId("apollo"); defaultUser.setName("apollo"); defaultUser.setEmail("apollo@acme.com"); return defaultUser; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/package-info.java ================================================ /** * This package defines common interfaces so that each company could provide their own implementations.
* Currently we provide 2 implementations: Ctrip and Default.
* Ctrip implementation will be activated only when spring.profiles.active = ctrip. * So if spring.profiles.active is not ctrip, the default implementation will be activated. * You may refer com.ctrip.framework.apollo.portal.spi.configuration.AuthConfiguration when providing your own implementation. * * @see com.ctrip.framework.apollo.portal.spi.configuration.AuthConfiguration */ package com.ctrip.framework.apollo.portal.spi; ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/springsecurity/SpringSecurityUserInfoHolder.java ================================================ package com.ctrip.framework.apollo.portal.spi.springsecurity; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import java.security.Principal; public class SpringSecurityUserInfoHolder implements UserInfoHolder { @Override public UserInfo getUser() { UserInfo userInfo = new UserInfo(); userInfo.setUserId(getCurrentUsername()); return userInfo; } private String getCurrentUsername() { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { return ((UserDetails) principal).getUsername(); } if (principal instanceof Principal) { return ((Principal) principal).getName(); } return String.valueOf(principal); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/springsecurity/SpringSecurityUserService.java ================================================ package com.ctrip.framework.apollo.portal.spi.springsecurity; import com.google.common.collect.Lists; import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.po.UserPO; import com.ctrip.framework.apollo.portal.repository.UserRepository; import com.ctrip.framework.apollo.portal.spi.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.JdbcUserDetailsManager; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import javax.annotation.PostConstruct; /** * @author lepdou 2017-03-10 */ public class SpringSecurityUserService implements UserService { private PasswordEncoder encoder = new BCryptPasswordEncoder(); private List authorities; @Autowired private JdbcUserDetailsManager userDetailsManager; @Autowired private UserRepository userRepository; @PostConstruct public void init() { authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority("ROLE_user")); } @Transactional public void createOrUpdate(UserPO user) { String username = user.getUsername(); User userDetails = new User(username, encoder.encode(user.getPassword()), authorities); if (userDetailsManager.userExists(username)) { userDetailsManager.updateUser(userDetails); } else { userDetailsManager.createUser(userDetails); } UserPO managedUser = userRepository.findByUsername(username); managedUser.setEmail(user.getEmail()); userRepository.save(managedUser); } @Override public List searchUsers(String keyword, int offset, int limit) { List users; if (StringUtils.isEmpty(keyword)) { users = userRepository.findFirst20ByEnabled(1); } else { users = userRepository.findByUsernameLikeAndEnabled("%" + keyword + "%", 1); } List result = Lists.newArrayList(); if (CollectionUtils.isEmpty(users)) { return result; } result.addAll(users.stream().map(UserPO::toUserInfo).collect(Collectors.toList())); return result; } @Override public UserInfo findByUserId(String userId) { UserPO userPO = userRepository.findByUsername(userId); return userPO == null ? null : userPO.toUserInfo(); } @Override public List findByUserIds(List userIds) { return null; } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/util/RelativeDateFormat.java ================================================ package com.ctrip.framework.apollo.portal.util; import org.apache.commons.lang.time.FastDateFormat; import java.util.Calendar; import java.util.Date; public class RelativeDateFormat { private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd"); private static final long ONE_MINUTE = 60000L; private static final long ONE_HOUR = 3600000L; private static final long ONE_DAY = 86400000L; private static final String ONE_SECOND_AGO = "秒前"; private static final String ONE_MINUTE_AGO = "分钟前"; private static final String ONE_HOUR_AGO = "小时前"; private static final String ONE_DAY_AGO = "天前"; private static final String ONE_MONTH_AGO = "月前"; public static String format(Date date) { if (date.after(new Date())) { return "now"; } long delta = new Date().getTime() - date.getTime(); if (delta < ONE_MINUTE) { long seconds = toSeconds(delta); return (seconds <= 0 ? 1 : seconds) + ONE_SECOND_AGO; } if (delta < 45L * ONE_MINUTE) { long minutes = toMinutes(delta); return (minutes <= 0 ? 1 : minutes) + ONE_MINUTE_AGO; } if (delta < 24L * ONE_HOUR) { long hours = toHours(delta); return (hours <= 0 ? 1 : hours) + ONE_HOUR_AGO; } Date lastDayBeginTime = getDateOffset(-1); if (date.after(lastDayBeginTime)) { return "昨天"; } Date lastTwoDaysBeginTime = getDateOffset(-2); if (date.after(lastTwoDaysBeginTime)) { return "前天"; } if (delta < 30L * ONE_DAY) { long days = toDays(delta); return (days <= 0 ? 1 : days) + ONE_DAY_AGO; } long months = toMonths(delta); if (months <= 3) { return (months <= 0 ? 1 : months) + ONE_MONTH_AGO; } else { return TIMESTAMP_FORMAT.format(date); } } private static long toSeconds(long date) { return date / 1000L; } private static long toMinutes(long date) { return toSeconds(date) / 60L; } private static long toHours(long date) { return toMinutes(date) / 60L; } private static long toDays(long date) { return toHours(date) / 24L; } private static long toMonths(long date) { return toDays(date) / 30L; } public static Date getDateOffset(int offset) { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(calendar.DATE, offset); return getDayBeginTime(calendar.getTime()); } private static Date getDayBeginTime(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return new Date(calendar.getTime().getTime()); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/util/RoleUtils.java ================================================ package com.ctrip.framework.apollo.portal.util; import com.google.common.base.Joiner; import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.portal.constant.RoleType; public class RoleUtils { private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR); public static String buildAppMasterRoleName(String appId) { return STRING_JOINER.join(RoleType.MASTER, appId); } public static String buildAppRoleName(String appId, String roleType) { return STRING_JOINER.join(roleType, appId); } public static String buildModifyNamespaceRoleName(String appId, String namespaceName) { return STRING_JOINER.join(RoleType.MODIFY_NAMESPACE, appId, namespaceName); } public static String buildModifyDefaultNamespaceRoleName(String appId) { return STRING_JOINER.join(RoleType.MODIFY_NAMESPACE, appId, ConfigConsts.NAMESPACE_APPLICATION); } public static String buildReleaseNamespaceRoleName(String appId, String namespaceName) { return STRING_JOINER.join(RoleType.RELEASE_NAMESPACE, appId, namespaceName); } public static String buildNamespaceRoleName(String appId, String namespaceName, String roleType) { return STRING_JOINER.join(roleType, appId, namespaceName); } public static String buildReleaseDefaultNamespaceRoleName(String appId) { return STRING_JOINER.join(RoleType.RELEASE_NAMESPACE, appId, ConfigConsts.NAMESPACE_APPLICATION); } public static String buildNamespaceTargetId(String appId, String namespaceName) { return STRING_JOINER.join(appId, namespaceName); } public static String buildDefaultNamespaceTargetId(String appId) { return STRING_JOINER.join(appId, ConfigConsts.NAMESPACE_APPLICATION); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/META-INF/app.properties ================================================ app.id=100003173 jdkVersion=1.8 ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/application-ctrip.yml ================================================ ctrip: appid: 100003173 email: send: code: 37030033 template: id: 37030033 survival: duration: 5 ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/application.yml ================================================ spring: application: name: apollo-portal profiles: active: ${apollo_profile} server: port: 8070 logging: level: com.ctrip: INFO endpoints: health: sensitive: false management: security: enabled: false health: status: order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/logback.xml ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/portal.properties ================================================ apollo_profile=github,auth dev_meta=http://134.224.240.170:8080 server.port=8070 spring.datasource.url=jdbc:mysql://47.94.252.160:3306/ApolloPortalDB?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false spring.datasource.username=root spring.datasource.password=root #spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/app/setting.html ================================================ 项目管理
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/app.html ================================================ 新建项目
创建项目
(应用唯一标识)
(建议格式 xx-yy-zz 例:apollo-server)

(应用负责人默认具有项目管理员权限,
项目管理员可以创建Namespace和集群、分配用户权限)
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/cluster.html ================================================ 新建集群
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/config/history.html ================================================ 发布历史
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/config/sync.html ================================================ 同步配置
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/config.html ================================================ Apollo配置中心

当前操作环境:{{pageContext.env}}, 集群:{{pageContext.clusterName}}

注意: 以下环境/集群有未发布的配置,客户端获取不到未发布的配置,请及时发布。

================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/ctrip_sso_heartbeat.html ================================================ SSO Heartbeat ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/default_sso_heartbeat.html ================================================ SSO Heartbeat ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/index.html ================================================ Apollo配置中心
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/java/com/example/demo/EcvoicesystemDemoApplicationTests.java ================================================ package com.example.demo; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class EcvoicesystemDemoApplicationTests { @Test public void contextLoads() { } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/login.html ================================================ Apollo配置中心
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/namespace/role.html ================================================ 权限管理

您没有权限哟!

================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/namespace.html ================================================ 新建Namespace
================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/open/manage.html ================================================ 开放平台
创建第三方应用 (说明: 第三方应用可以通过Apollo开放平台来对配置进行管理)

(创建前请先查询第三方应用是否已经申请过)

(建议格式 xx-yy-zz 例:apollo-server)
赋权 (Namespace级别权限包括: 修改、发布Namespace。应用级别权限包括: 创建Namespace、修改或发布应用下任何Namespace)

(非properties类型的namespace请加上类型后缀,例如apollo.xml)

当前页面只对Apollo管理员开放

================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/AppUtils.js ================================================ appUtil.service('AppUtil', ['toastr', '$window', '$q', function (toastr, $window, $q) { function parseErrorMsg(response) { if (response.status == -1) { return "您的登录信息已过期,请刷新页面后重试"; } var msg = "Code:" + response.status; if (response.data.message != null) { msg += " Msg:" + response.data.message; } return msg; } function ajax(resource, requestParams, requestBody) { var d = $q.defer(); if (requestBody) { resource(requestParams, requestBody, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); } else { resource(requestParams, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); } return d.promise; } return { errorMsg: parseErrorMsg, ajax: ajax, showErrorMsg: function (response, title) { toastr.error(parseErrorMsg(response), title); }, parseParams: function (query, notJumpToHomePage) { if (!query) { //如果不传这个参数或者false则返回到首页(参数出错) if (!notJumpToHomePage) { $window.location.href = '/index.html'; } else { return {}; } } if (query.indexOf('/') == 0) { query = query.substring(1, query.length); } var anchorIndex = query.indexOf('#'); if (anchorIndex >= 0) { query = query.substring(0, anchorIndex); } var params = query.split("&"); var result = {}; params.forEach(function (param) { var kv = param.split("="); result[kv[0]] = decodeURIComponent(kv[1]); }); return result; }, collectData: function (response) { var data = []; response.entities.forEach(function (entity) { if (entity.code == 200) { data.push(entity.body); } else { toastr.warning(entity.message); } }); return data; }, showModal: function (modal) { $(modal).modal("show"); }, hideModal: function (modal) { $(modal).modal("hide"); }, checkIPV4:function (ip) { return /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(ip); } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/PageCommon.js ================================================ $(document).ready(function () { // nicescroll $("html").niceScroll({ styler: "fb", cursorcolor: "#e8403f", cursorwidth: '6', cursorborderradius: '10px', background: '#404040', spacebarenabled: false, cursorborder: '', zindex: '1000' }); // bootstrap tooltip & textarea scroll setInterval(function () { $('[data-tooltip="tooltip"]').tooltip({ trigger : 'hover' }); $("textarea").niceScroll({cursoropacitymax: 0}); $("pre").niceScroll({cursoropacitymax: 0}); }, 1000); setTimeout(function () { $(".release-history-list").niceScroll({cursoropacitymax: 0}); }, 2500); }); // (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 // (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18 Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); } for (var k in o) { if (new RegExp("(" + k + ")").test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); } } return fmt; }; ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/app.js ================================================ /**utils*/ var appUtil = angular.module('app.util', ['toastr']); /**service module 定义*/ var appService = angular.module('app.service', ['ngResource']); /** directive */ var directive_module = angular.module('apollo.directive', ['app.service', 'app.util', 'toastr']); /** page module 定义*/ // 首页 var index_module = angular.module('index', ['toastr', 'app.service', 'apollo.directive', 'app.util', 'angular-loading-bar']); //项目主页 var application_module = angular.module('application', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr', 'ui.ace']); //创建项目页面 var app_module = angular.module('create_app', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar', 'valdr']); //配置同步页面 var sync_item_module = angular.module('sync_item', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); //namespace var namespace_module = angular.module('namespace', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']); //server config var server_config_module = angular.module('server_config', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); //setting var setting_module = angular.module('setting', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']); //role var role_module = angular.module('role', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); //cluster var cluster_module = angular.module('cluster', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar' , 'valdr']); //release history var release_history_module = angular.module('release_history', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); //open manage var open_manage_module = angular.module('open_manage', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); //user var user_module = angular.module('user', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar', 'valdr']); //login var login_module = angular.module('login', ['toastr', 'app.util']); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/AppController.js ================================================ app_module.controller('CreateAppController', ['$scope', '$window', 'toastr', 'AppService', 'AppUtil', 'OrganizationService', createAppController]); function createAppController($scope, $window, toastr, AppService, AppUtil, OrganizationService) { $scope.app = {}; $scope.submitBtnDisabled = false; $scope.create = create; init(); function init() { initOrganization(); } function initOrganization() { OrganizationService.find_organizations().then(function (result) { var organizations = []; result.forEach(function (item) { var org = {}; org.id = item.orgId; org.text = item.orgName + '(' + item.orgId + ')'; org.name = item.orgName; organizations.push(org); }); $('#organization').select2({ placeholder: '请选择部门', width: '100%', data: organizations }); }, function (result) { toastr.error(AppUtil.errorMsg(result), "load organizations error"); }); } function create() { $scope.submitBtnDisabled = true; var selectedOrg = $('#organization').select2('data')[0]; if (!selectedOrg.id) { toastr.warning("请选择部门"); return; } $scope.app.orgId = selectedOrg.id; $scope.app.orgName = selectedOrg.name; // owner var owner = $('.ownerSelector').select2('data')[0]; if (!owner) { toastr.warning("请选择应用负责人"); return; } $scope.app.ownerName = owner.id; //admins $scope.app.admins = []; var admins = $(".adminSelector").select2('data'); if (admins) { admins.forEach(function (admin) { $scope.app.admins.push(admin.id); }) } AppService.create($scope.app).then(function (result) { toastr.success('创建成功!'); setInterval(function () { $scope.submitBtnDisabled = false; $window.location.href = '/config.html?#appid=' + result.appId; }, 1000); }, function (result) { $scope.submitBtnDisabled = false; toastr.error(AppUtil.errorMsg(result), '创建失败!'); }); } $(".J_ownerSelectorPanel").on("select2:select", ".ownerSelector", selectEventHandler); var $adminSelectorPanel = $(".J_adminSelectorPanel"); $adminSelectorPanel.on("select2:select", ".adminSelector", selectEventHandler); $adminSelectorPanel.on("select2:unselect", ".adminSelector", selectEventHandler); function selectEventHandler() { $('.J_owner').remove(); var owner = $('.ownerSelector').select2('data')[0]; if (owner) { $(".adminSelector").parent().find(".select2-selection__rendered").prepend( '
  • ' + owner.text + '
  • ') } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/ClusterController.js ================================================ cluster_module.controller('ClusterController', ['$scope', '$location', '$window', 'toastr', 'AppService', 'EnvService', 'ClusterService', 'AppUtil', function ($scope, $location, $window, toastr, AppService, EnvService, ClusterService, AppUtil) { var params = AppUtil.parseParams($location.$$url); $scope.appId = params.appid; $scope.step = 1; $scope.submitBtnDisabled = false; EnvService.find_all_envs().then(function (result) { $scope.envs = []; result.forEach(function (env) { $scope.envs.push({name: env, checked: false}); }); $(".apollo-container").removeClass("hidden"); }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载环境信息出错"); }); $scope.clusterName = ''; $scope.switchChecked = function (env, $event) { env.checked = !env.checked; $event.stopPropagation(); }; $scope.toggleEnvCheckedStatus = function (env) { env.checked = !env.checked; }; $scope.create = function () { var noEnvChecked = true; $scope.envs.forEach(function (env) { if (env.checked) { noEnvChecked = false; $scope.submitBtnDisabled = true; ClusterService.create_cluster($scope.appId, env.name, { name: $scope.clusterName, appId: $scope.appId }).then(function (result) { toastr.success(env.name, "集群创建成功"); $scope.step = 2; $scope.submitBtnDisabled = false; }, function (result) { toastr.error(AppUtil.errorMsg(result), "集群创建失败"); $scope.submitBtnDisabled = false; }) } }); if (noEnvChecked){ toastr.warning("请选择环境"); } }; }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/IndexController.js ================================================ index_module.controller('IndexController', ['$scope', '$window', 'toastr', 'AppUtil', 'AppService', 'UserService', 'FavoriteService', IndexController]); function IndexController($scope, $window, toastr, AppUtil, AppService, UserService, FavoriteService) { $scope.userId = ''; $scope.getUserCreatedApps = getUserCreatedApps; $scope.getUserFavorites = getUserFavorites; $scope.goToAppHomePage = goToAppHomePage; $scope.goToCreateAppPage = goToCreateAppPage; $scope.toggleOperationBtn = toggleOperationBtn; $scope.toTop = toTop; $scope.deleteFavorite = deleteFavorite; UserService.load_user().then(function (result) { $scope.userId = result.userId; $scope.createdAppPage = 0; $scope.createdApps = []; $scope.hasMoreCreatedApps = true; $scope.favoritesPage = 0; $scope.favorites = []; $scope.hasMoreFavorites = true; $scope.visitedApps = []; getUserCreatedApps(); getUserFavorites(); initUserVisitedApps(); }); function getUserCreatedApps() { var size = 10; AppService.find_app_by_owner($scope.userId, $scope.createdAppPage, size) .then(function (result) { $scope.createdAppPage += 1; $scope.hasMoreCreatedApps = result.length == size; if (!result || result.length == 0) { return; } result.forEach(function (app) { $scope.createdApps.push(app); }); }) } function getUserFavorites() { var size = 11; FavoriteService.findFavorites($scope.userId, '', $scope.favoritesPage, size) .then(function (result) { $scope.favoritesPage += 1; $scope.hasMoreFavorites = result.length == size; if ($scope.favoritesPage == 1){ $("#app-list").removeClass("hidden"); } if (!result || result.length == 0) { return; } var appIds = []; result.forEach(function (favorite) { appIds.push(favorite.appId); }); AppService.find_apps(appIds.join(",")) .then(function (apps) { //sort var appIdMapApp = {}; apps.forEach(function (app) { appIdMapApp[app.appId] = app; }); result.forEach(function (favorite) { var app = appIdMapApp[favorite.appId]; if (!app){ return; } app.favoriteId = favorite.id; $scope.favorites.push(app); }); }); }) } function initUserVisitedApps() { var VISITED_APPS_STORAGE_KEY = "VisitedAppsV2"; var visitedAppsObject = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY)); if (!visitedAppsObject) { visitedAppsObject = {}; } var userVisitedApps = visitedAppsObject[$scope.userId]; if (userVisitedApps && userVisitedApps.length > 0) { AppService.find_apps(userVisitedApps.join(",")) .then(function (apps) { //sort var appIdMapApp = {}; apps.forEach(function (app) { appIdMapApp[app.appId] = app; }); userVisitedApps.forEach(function (appId) { var app = appIdMapApp[appId]; if (app){ $scope.visitedApps.push(app); } }); }); } } function goToCreateAppPage() { $window.location.href = "/app.html"; } function goToAppHomePage(appId) { $window.location.href = "/config.html?#/appid=" + appId; } function toggleOperationBtn(app) { app.showOperationBtn = !app.showOperationBtn; } function toTop(favoriteId) { FavoriteService.toTop(favoriteId).then(function () { toastr.success("置顶成功"); refreshFavorites(); }) } function deleteFavorite(favoriteId) { FavoriteService.deleteFavorite(favoriteId).then(function () { toastr.success("取消收藏成功"); refreshFavorites(); }) } function refreshFavorites() { $scope.favoritesPage = 0; $scope.favorites = []; $scope.hasMoreFavorites = true; getUserFavorites(); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/LoginController.js ================================================ login_module.controller('LoginController', ['$scope', '$window', '$location', 'toastr', 'AppUtil', LoginController]); function LoginController($scope, $window, $location, toastr, AppUtil) { if ($location.$$url) { var params = AppUtil.parseParams($location.$$url); if (params.error) { $scope.info = "用户名或密码错误"; } if (params.logout) { $scope.info = "登出成功"; } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/NamespaceController.js ================================================ namespace_module.controller("LinkNamespaceController", ['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil', 'NamespaceService', 'PermissionService', 'CommonService', function ($scope, $location, $window, toastr, AppService, AppUtil, NamespaceService, PermissionService, CommonService) { var params = AppUtil.parseParams($location.$$url); $scope.appId = params.appid; $scope.type = 'link'; $scope.step = 1; $scope.submitBtnDisabled = false; PermissionService.has_root_permission().then(function (result) { $scope.hasRootPermission = result.hasPermission; }); CommonService.getPageSetting().then(function (setting) { $scope.pageSetting = setting; }); NamespaceService.find_public_namespaces().then(function (result) { var publicNamespaces = []; result.forEach(function (item) { var namespace = {}; namespace.id = item.name; namespace.text = item.name; publicNamespaces.push(namespace); }); $('#namespaces').select2({ placeholder: '请选择Namespace', width: '100%', data: publicNamespaces }); $(".apollo-container").removeClass("hidden"); }, function (result) { toastr.error(AppUtil.errorMsg(result), "load public namespace error"); }); AppService.load($scope.appId).then(function (result) { $scope.appBaseInfo = result; $scope.appBaseInfo.namespacePrefix = result.orgId + '.'; }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载App信息出错"); }); $scope.appNamespace = { appId: $scope.appId, name: '', comment: '', isPublic: true, format: 'properties' }; $scope.switchNSType = function (type) { $scope.appNamespace.isPublic = type; }; $scope.concatNamespace = function () { if (!$scope.appBaseInfo) { return ''; } return $scope.appBaseInfo.namespacePrefix + ($scope.appNamespace.name ? $scope.appNamespace.name : ''); }; var selectedClusters = []; $scope.collectSelectedClusters = function (data) { selectedClusters = data; }; $scope.createNamespace = function () { if ($scope.type == 'link') { if (selectedClusters.length == 0) { toastr.warning("请选择集群"); return; } if ($scope.namespaceType == 1) { var selectedNamespaceName = $('#namespaces').select2('data')[0].id; if (!selectedNamespaceName) { toastr.warning("请选择Namespace"); return; } $scope.namespaceName = selectedNamespaceName; } var namespaceCreationModels = []; selectedClusters.forEach(function (cluster) { namespaceCreationModels.push({ env: cluster.env, namespace: { appId: $scope.appId, clusterName: cluster.clusterName, namespaceName: $scope.namespaceName } }); }); $scope.submitBtnDisabled = true; NamespaceService.createNamespace($scope.appId, namespaceCreationModels) .then(function (result) { toastr.success("创建成功"); $scope.step = 2; setInterval(function () { $scope.submitBtnDisabled = false; $window.location.href = '/namespace/role.html?#appid=' + $scope.appId + "&namespaceName=" + $scope.namespaceName; }, 1000); }, function (result) { $scope.submitBtnDisabled = false; toastr.error(AppUtil.errorMsg(result)); }); } else { var namespaceNameLength = $scope.concatNamespace().length; if (namespaceNameLength > 32) { toastr.error("namespace名称不能大于32个字符. 部门前缀" + (namespaceNameLength - $scope.appNamespace.name.length) + "个字符, 名称" + $scope.appNamespace.name.length + "个字符" ); return; } $scope.submitBtnDisabled = true; NamespaceService.createAppNamespace($scope.appId, $scope.appNamespace).then( function (result) { $scope.step = 2; setTimeout(function () { $scope.submitBtnDisabled = false; $window.location.href = "/namespace/role.html?#/appid=" + $scope.appId + "&namespaceName=" + result.name; }, 1000); }, function (result) { $scope.submitBtnDisabled = false; toastr.error(AppUtil.errorMsg(result), "创建失败"); }); } }; $scope.namespaceType = 1; $scope.selectNamespaceType = function (type) { $scope.namespaceType = type; }; $scope.back = function () { $window.location.href = '/config.html?#appid=' + $scope.appId; }; $scope.switchType = function (type) { $scope.type = type; }; }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/ServerConfigController.js ================================================ server_config_module.controller('ServerConfigController', ['$scope', '$window', 'toastr', 'ServerConfigService', 'AppUtil', function ($scope, $window, toastr, ServerConfigService, AppUtil) { $scope.serverConfig = {}; $scope.create = function () { ServerConfigService.create($scope.serverConfig).then(function (result) { toastr.success("添加成功"); }, function (result) { toastr.error(AppUtil.errorMsg(result), "添加失败"); }); }; }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/SettingController.js ================================================ setting_module.controller('SettingController', ['$scope', '$location', 'toastr', 'AppService', 'AppUtil', 'PermissionService', 'OrganizationService', SettingController]); function SettingController($scope, $location, toastr, AppService, AppUtil, PermissionService, OrganizationService) { var params = AppUtil.parseParams($location.$$url); var $orgWidget = $('#organization'); $scope.pageContext = { appId: params.appid }; $scope.display = { app: { edit: false } }; $scope.submitBtnDisabled = false; $scope.userSelectWidgetId = 'toAssignMasterRoleUser'; $scope.assignMasterRoleToUser = assignMasterRoleToUser; $scope.removeMasterRoleFromUser = removeMasterRoleFromUser; $scope.toggleEditStatus = toggleEditStatus; $scope.updateAppInfo = updateAppInfo; init(); function init() { initOrganization(); initPermission(); initAdmins(); initApplication(); } function initOrganization() { OrganizationService.find_organizations().then(function (result) { var organizations = []; result.forEach(function (item) { var org = {}; org.id = item.orgId; org.text = item.orgName + '(' + item.orgId + ')'; org.name = item.orgName; organizations.push(org); }); $orgWidget.select2({ placeholder: '请选择部门', width: '100%', data: organizations }); }, function (result) { toastr.error(AppUtil.errorMsg(result), "load organizations error"); }); } function initPermission() { PermissionService.has_assign_user_permission($scope.pageContext.appId) .then(function (result) { $scope.hasAssignUserPermission = result.hasPermission; }); } function initAdmins() { PermissionService.get_app_role_users($scope.pageContext.appId) .then(function (result) { $scope.appRoleUsers = result; $scope.admins = []; $scope.appRoleUsers.masterUsers.forEach(function (user) { $scope.admins.push(user.userId); }); }); } function initApplication() { AppService.load($scope.pageContext.appId).then(function (app) { $scope.app = app; $scope.viewApp = _.clone(app); initAppForm(app); $('.project-setting .panel').removeClass('hidden'); }) } function initAppForm(app) { $orgWidget.val(app.orgId).trigger("change"); var $ownerSelector = $('.ownerSelector'); var defaultSelectedDOM = ''; $ownerSelector.append(defaultSelectedDOM); $ownerSelector.trigger('change'); } function assignMasterRoleToUser() { var user = $('.' + $scope.userSelectWidgetId).select2('data')[0]; if (!user) { toastr.warning("请选择用户"); return; } var toAssignMasterRoleUser = user.id; $scope.submitBtnDisabled = true; PermissionService.assign_master_role($scope.pageContext.appId, toAssignMasterRoleUser) .then(function (result) { $scope.submitBtnDisabled = false; toastr.success("添加成功"); $scope.appRoleUsers.masterUsers.push({userId: toAssignMasterRoleUser}); $('.' + $scope.userSelectWidgetId).select2("val", ""); }, function (result) { $scope.submitBtnDisabled = false; toastr.error(AppUtil.errorMsg(result), "添加失败"); }); } function removeMasterRoleFromUser(user) { if ($scope.appRoleUsers.masterUsers.length <= 1) { $('#warning').modal('show'); return; } PermissionService.remove_master_role($scope.pageContext.appId, user) .then(function (result) { toastr.success("删除成功"); removeUserFromList($scope.appRoleUsers.masterUsers, user); }, function (result) { toastr.error(AppUtil.errorMsg(result), "删除失败"); }); } function removeUserFromList(list, user) { var index = 0; for (var i = 0; i < list.length; i++) { if (list[i].userId == user) { index = i; break; } } list.splice(index, 1); } function toggleEditStatus() { if ($scope.display.app.edit) {//cancel edit $scope.viewApp = _.clone($scope.app); initAppForm($scope.viewApp); } else {//edit } $scope.display.app.edit = !$scope.display.app.edit; } function updateAppInfo() { $scope.submitBtnDisabled = true; var app = $scope.viewApp; var selectedOrg = $orgWidget.select2('data')[0]; if (!selectedOrg.id) { toastr.warning("请选择部门"); return; } app.orgId = selectedOrg.id; app.orgName = selectedOrg.name; // owner var owner = $('.ownerSelector').select2('data')[0]; if (!owner) { toastr.warning("请选择应用负责人"); return; } app.ownerName = owner.id; AppService.update(app).then(function (app) { toastr.success("修改成功"); initApplication(); $scope.display.app.edit = false; $scope.submitBtnDisabled = false; }, function (result) { AppUtil.showErrorMsg(result); $scope.submitBtnDisabled = false; }) } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/UserController.js ================================================ user_module.controller('UserController', ['$scope', '$window', 'toastr', 'AppUtil', 'UserService', UserController]); function UserController($scope, $window, toastr, AppUtil, UserService) { $scope.user = {}; $scope.createOrUpdateUser = function () { UserService.createOrUpdateUser($scope.user).then(function (result) { toastr.success("创建用户成功"); }, function (result) { AppUtil.showErrorMsg(result, "创建用户失败"); }) } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/ConfigBaseInfoController.js ================================================ application_module.controller("ConfigBaseInfoController", ['$rootScope', '$scope', '$window', '$location', 'toastr', 'EventManager', 'UserService', 'AppService', 'FavoriteService', 'PermissionService', 'AppUtil', ConfigBaseInfoController]); function ConfigBaseInfoController($rootScope, $scope, $window, $location, toastr, EventManager, UserService, AppService, FavoriteService, PermissionService, AppUtil) { var urlParams = AppUtil.parseParams($location.$$url); var appId = urlParams.appid; if (!appId) { $window.location.href = '/index.html'; return; } initPage(); function initPage() { $rootScope.hideTip = JSON.parse(localStorage.getItem("hideTip")); //load session storage to recovery scene var scene = JSON.parse(sessionStorage.getItem(appId)); $rootScope.pageContext = { appId: appId, env: urlParams.env ? urlParams.env : (scene ? scene.env : ''), clusterName: urlParams.cluster ? urlParams.cluster : (scene ? scene.cluster : 'default') }; //storage page context to session storage sessionStorage.setItem( $rootScope.pageContext.appId, JSON.stringify({ env: $rootScope.pageContext.env, cluster: $rootScope.pageContext.clusterName })); UserService.load_user().then(function (result) { $rootScope.pageContext.userId = result.userId; loadAppInfo(); handleFavorite(); }, function (result) { toastr.error(AppUtil.errorMsg(result), "获取用户登录信息失败"); }); handlePermission(); } function loadAppInfo() { $scope.notFoundApp = true; AppService.load($rootScope.pageContext.appId).then(function (result) { $scope.notFoundApp = false; $scope.appBaseInfo = result; $scope.appBaseInfo.orgInfo = result.orgName + '(' + result.orgId + ')'; loadNavTree(); recordVisitApp(); findMissEnvs(); $(".J_appFound").removeClass("hidden"); }, function (result) { $(".J_appNotFound").removeClass("hidden"); }); } $scope.createAppInMissEnv = function () { var count = 0; $scope.missEnvs.forEach(function (env) { AppService.create_remote(env, $scope.appBaseInfo).then(function (result) { toastr.success(env, '创建成功'); count++; if (count == $scope.missEnvs.length) { location.reload(true); } }, function (result) { toastr.error(AppUtil.errorMsg(result), '创建失败:' + env); count++; if (count == $scope.missEnvs.length) { location.reload(true); } }); }); }; function findMissEnvs() { $scope.missEnvs = []; AppService.find_miss_envs($rootScope.pageContext.appId).then(function (result) { $scope.missEnvs = AppUtil.collectData(result); }); } function recordVisitApp() { //save user recent visited apps var VISITED_APPS_STORAGE_KEY = "VisitedAppsV2"; var visitedAppsObject = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY)); var hasSaved = false; if (!visitedAppsObject) { visitedAppsObject = {}; } if (!visitedAppsObject[$rootScope.pageContext.userId]) { visitedAppsObject[$rootScope.pageContext.userId] = []; } var visitedApps = visitedAppsObject[$rootScope.pageContext.userId]; if (visitedApps && visitedApps.length > 0) { visitedApps.forEach(function (app) { if (app == appId) { hasSaved = true; return; } }); } var currentUserVisitedApps = visitedAppsObject[$rootScope.pageContext.userId]; if (!hasSaved) { //if queue's length bigger than 6 will remove oldest app if (currentUserVisitedApps.length >= 6) { currentUserVisitedApps.splice(0, 1); } currentUserVisitedApps.push($rootScope.pageContext.appId); localStorage.setItem(VISITED_APPS_STORAGE_KEY, JSON.stringify(visitedAppsObject)); } } function loadNavTree() { AppService.load_nav_tree($rootScope.pageContext.appId).then(function (result) { var navTree = []; var nodes = AppUtil.collectData(result); if (!nodes || nodes.length == 0) { toastr.error("系统出错,请重试或联系系统负责人"); return; } //default first env if session storage is empty if (!$rootScope.pageContext.env) { $rootScope.pageContext.env = nodes[0].env; } EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE); nodes.forEach(function (env) { if (!env.clusters || env.clusters.length == 0) { return; } var node = {}; node.text = env.env; var clusterNodes = []; //如果env下面只有一个default集群则不显示集群列表 if (env.clusters && env.clusters.length == 1 && env.clusters[0].name == 'default') { if ($rootScope.pageContext.env == env.env) { node.state = {}; node.state.selected = true; } node.selectable = true; } else { node.selectable = false; //cluster list env.clusters.forEach(function (cluster) { var clusterNode = {}, parentNode = []; //default selection from session storage or first env & first cluster if ($rootScope.pageContext.env == env.env && $rootScope.pageContext.clusterName == cluster.name) { clusterNode.state = {}; clusterNode.state.selected = true; } clusterNode.text = cluster.name; parentNode.push(node.text); clusterNode.tags = ['集群']; clusterNode.parentNode = parentNode; clusterNodes.push(clusterNode); }); } node.nodes = clusterNodes; navTree.push(node); }); //init treeview $('#treeview').treeview({ color: "#797979", showBorder: true, data: navTree, levels: 99, expandIcon: '', collapseIcon: '', showTags: true, onNodeSelected: function (event, data) { if (!data.parentNode) {//first nav node $rootScope.pageContext.env = data.text; $rootScope.pageContext.clusterName = 'default'; } else {//second cluster node $rootScope.pageContext.env = data.parentNode[0]; $rootScope.pageContext.clusterName = data.text; } //storage scene sessionStorage.setItem( $rootScope.pageContext.appId, JSON.stringify({ env: $rootScope.pageContext.env, cluster: $rootScope.pageContext.clusterName })); $window.location.href = "/config.html#/appid=" + $rootScope.pageContext.appId + "&env=" + $rootScope.pageContext.env + "&cluster=" + $rootScope.pageContext.clusterName; EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE); $rootScope.showSideBar = false; } }); var envMapClusters = {}; navTree.forEach(function (node) { if (node.nodes && node.nodes.length > 0) { var clusterNames = []; node.nodes.forEach(function (cluster) { if (cluster.text != 'default') { clusterNames.push(cluster.text); } }); envMapClusters[node.text] = clusterNames.join(","); } }); $rootScope.envMapClusters = envMapClusters; }, function (result) { toastr.error(AppUtil.errorMsg(result), "系统出错,请重试或联系系统负责人"); }); } function handleFavorite() { FavoriteService.findFavorites($rootScope.pageContext.userId, $rootScope.pageContext.appId) .then(function (result) { if (result && result.length) { $scope.favoriteId = result[0].id; } }); $scope.addFavorite = function () { var favorite = { userId: $rootScope.pageContext.userId, appId: $rootScope.pageContext.appId }; FavoriteService.addFavorite(favorite) .then(function (result) { $scope.favoriteId = result.id; toastr.success("收藏成功"); }, function (result) { toastr.error(AppUtil.errorMsg(result), "收藏失败"); }) }; $scope.deleteFavorite = function () { FavoriteService.deleteFavorite($scope.favoriteId) .then(function (result) { $scope.favoriteId = 0; toastr.success("取消收藏成功"); }, function (result) { toastr.error(AppUtil.errorMsg(result), "取消收藏失败"); }) }; } function handlePermission() { //permission PermissionService.has_create_namespace_permission(appId).then(function (result) { $scope.hasCreateNamespacePermission = result.hasPermission; }, function (result) { }); PermissionService.has_create_cluster_permission(appId).then(function (result) { $scope.hasCreateClusterPermission = result.hasPermission; }, function (result) { }); PermissionService.has_assign_user_permission(appId).then(function (result) { $scope.hasAssignUserPermission = result.hasPermission; }, function (result) { }); $scope.showMasterPermissionTips = function () { $("#masterNoPermissionDialog").modal('show'); }; } var VIEW_MODE_SWITCH_WIDTH = 1156; if (window.innerWidth <= VIEW_MODE_SWITCH_WIDTH) { $rootScope.viewMode = 2; $rootScope.showSideBar = false; } else { $rootScope.viewMode = 1; } $rootScope.adaptScreenSize = function () { if (window.innerWidth <= VIEW_MODE_SWITCH_WIDTH) { $rootScope.viewMode = 2; } else { $rootScope.viewMode = 1; $rootScope.showSideBar = false; } }; $(window).resize(function () { $scope.$apply(function () { $rootScope.adaptScreenSize(); }); }); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/ConfigNamespaceController.js ================================================ application_module.controller("ConfigNamespaceController", ['$rootScope', '$scope', 'toastr', 'AppUtil', 'EventManager', 'ConfigService', 'PermissionService', 'UserService', 'NamespaceBranchService', 'NamespaceService', controller]); function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigService, PermissionService, UserService, NamespaceBranchService, NamespaceService) { $scope.rollback = rollback; $scope.preDeleteItem = preDeleteItem; $scope.deleteItem = deleteItem; $scope.editItem = editItem; $scope.createItem = createItem; $scope.closeTip = closeTip; $scope.showText = showText; $scope.createBranch = createBranch; $scope.preCreateBranch = preCreateBranch; $scope.preDeleteBranch = preDeleteBranch; $scope.deleteBranch = deleteBranch; $scope.showNoModifyPermissionDialog = showNoModifyPermissionDialog; $scope.lockCheck = lockCheck; $scope.emergencyPublish = emergencyPublish; init(); function init() { initRole(); initUser(); initPublishInfo(); } function initRole() { PermissionService.get_app_role_users($rootScope.pageContext.appId) .then(function (result) { var masterUsers = ''; result.masterUsers.forEach(function (user) { masterUsers += user.userId + ','; }); $scope.masterUsers = masterUsers.substring(0, masterUsers.length - 1); }, function (result) { }); } function initUser() { UserService.load_user().then(function (result) { $scope.currentUser = result.userId; }); } function initPublishInfo() { NamespaceService.getNamespacePublishInfo($rootScope.pageContext.appId) .then(function (result) { if (!result) { return; } $scope.hasNotPublishNamespace = false; var namespacePublishInfo = []; Object.keys(result).forEach(function (env) { if (env.indexOf("$") >= 0) { return; } var envPublishInfo = result[env]; Object.keys(envPublishInfo).forEach(function (cluster) { var clusterPublishInfo = envPublishInfo[cluster]; if (clusterPublishInfo) { $scope.hasNotPublishNamespace = true; if (Object.keys(envPublishInfo).length > 1) { namespacePublishInfo.push("[" + env + ", " + cluster + "]"); } else { namespacePublishInfo.push("[" + env + "]"); } } }) }); $scope.namespacePublishInfo = namespacePublishInfo; }); } EventManager.subscribe(EventManager.EventType.REFRESH_NAMESPACE, function (context) { if (context.namespace) { refreshSingleNamespace(context.namespace); } else { refreshAllNamespaces(); } }); function refreshAllNamespaces() { if ($rootScope.pageContext.env == '') { return; } ConfigService.load_all_namespaces($rootScope.pageContext.appId, $rootScope.pageContext.env, $rootScope.pageContext.clusterName).then( function (result) { $scope.namespaces = result; $('.config-item-container').removeClass('hide'); initPublishInfo(); }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载配置信息出错"); }); } function refreshSingleNamespace(namespace) { if ($rootScope.pageContext.env == '') { return; } ConfigService.load_namespace($rootScope.pageContext.appId, $rootScope.pageContext.env, $rootScope.pageContext.clusterName, namespace.baseInfo.namespaceName).then( function (result) { $scope.namespaces.forEach(function (namespace, index) { if (namespace.baseInfo.namespaceName == result.baseInfo.namespaceName) { $scope.namespaces[index] = result; } }); initPublishInfo(); }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载配置信息出错"); }); } function rollback() { EventManager.emit(EventManager.EventType.ROLLBACK_NAMESPACE); } $scope.tableViewOperType = '', $scope.item = {}; $scope.toOperationNamespace; var toDeleteItemId = 0; function preDeleteItem(namespace, itemId) { if (!lockCheck(namespace)) { return; } $scope.toOperationNamespace = namespace; toDeleteItemId = itemId; $("#deleteConfirmDialog").modal("show"); } function deleteItem() { ConfigService.delete_item($rootScope.pageContext.appId, $rootScope.pageContext.env, $rootScope.pageContext.clusterName, $scope.toOperationNamespace.baseInfo.namespaceName, toDeleteItemId).then( function (result) { toastr.success("删除成功!"); EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: $scope.toOperationNamespace }); }, function (result) { toastr.error(AppUtil.errorMsg(result), "删除失败"); }); } //修改配置 function editItem(namespace, toEditItem) { if (!lockCheck(namespace)) { return; } $scope.item = _.clone(toEditItem); if (namespace.isBranch || namespace.isLinkedNamespace) { var existedItem = false; namespace.items.forEach(function (item) { if (!item.isDeleted && item.item.key == toEditItem.key) { existedItem = true; } }); if (!existedItem) { $scope.item.lineNum = 0; $scope.item.tableViewOperType = 'create'; } else { $scope.item.tableViewOperType = 'update'; } } else { $scope.item.tableViewOperType = 'update'; } $scope.toOperationNamespace = namespace; AppUtil.showModal('#itemModal'); } //新增配置 function createItem(namespace) { if (!lockCheck(namespace)) { return; } $scope.item = { tableViewOperType: 'create' }; $scope.toOperationNamespace = namespace; AppUtil.showModal('#itemModal'); } var selectedClusters = []; $scope.collectSelectedClusters = function (data) { selectedClusters = data; }; function lockCheck(namespace) { if (namespace.lockOwner && $scope.currentUser != namespace.lockOwner) { $scope.lockOwner = namespace.lockOwner; $('#namespaceLockedDialog').modal('show'); return false; } return true; } function closeTip(clusterName) { var hideTip = JSON.parse(localStorage.getItem("hideTip")); if (!hideTip) { hideTip = {}; hideTip[$rootScope.pageContext.appId] = {}; } if (!hideTip[$rootScope.pageContext.appId]) { hideTip[$rootScope.pageContext.appId] = {}; } hideTip[$rootScope.pageContext.appId][clusterName] = true; $rootScope.hideTip = hideTip; localStorage.setItem("hideTip", JSON.stringify(hideTip)); } function showText(text) { $scope.text = text; $('#showTextModal').modal('show'); } function showNoModifyPermissionDialog() { $("#modifyNoPermissionDialog").modal('show'); } var toCreateBranchNamespace = {}; function preCreateBranch(namespace) { toCreateBranchNamespace = namespace; AppUtil.showModal("#createBranchTips"); } function createBranch() { NamespaceBranchService.createBranch($rootScope.pageContext.appId, $rootScope.pageContext.env, $rootScope.pageContext.clusterName, toCreateBranchNamespace.baseInfo.namespaceName) .then(function (result) { toastr.success("创建灰度成功"); EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: toCreateBranchNamespace }); }, function (result) { toastr.error(AppUtil.errorMsg(result), "创建灰度失败"); }) } function preDeleteBranch(branch) { //normal delete branch.branchStatus = 0; $scope.toDeleteBranch = branch; AppUtil.showModal('#deleteBranchDialog'); } function deleteBranch() { NamespaceBranchService.deleteBranch($rootScope.pageContext.appId, $rootScope.pageContext.env, $rootScope.pageContext.clusterName, $scope.toDeleteBranch.baseInfo.namespaceName, $scope.toDeleteBranch.baseInfo.clusterName ) .then(function (result) { toastr.success("删除成功"); EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: $scope.toDeleteBranch.parentNamespace }); }, function (result) { toastr.error(AppUtil.errorMsg(result), "删除分支失败"); }) } EventManager.subscribe(EventManager.EventType.EMERGENCY_PUBLISH, function (context) { AppUtil.showModal("#emergencyPublishAlertDialog"); $scope.emergencyPublishContext = context; }); function emergencyPublish() { if ($scope.emergencyPublishContext.mergeAndPublish) { EventManager.emit(EventManager.EventType.MERGE_AND_PUBLISH_NAMESPACE, { branch: $scope.emergencyPublishContext.namespace, isEmergencyPublish: true }); } else { EventManager.emit(EventManager.EventType.PUBLISH_NAMESPACE, { namespace: $scope.emergencyPublishContext.namespace, isEmergencyPublish: true }); } } EventManager.subscribe(EventManager.EventType.DELETE_NAMESPACE_FAILED, function (context) { $scope.deleteNamespaceContext = context; if (context.reason == 'master_instance') { AppUtil.showModal('#deleteNamespaceDenyForMasterInstanceDialog'); } else if (context.reason == 'branch_instance') { AppUtil.showModal('#deleteNamespaceDenyForBranchInstanceDialog'); } else if (context.reason == 'public_namespace') { var otherAppAssociatedNamespaces = context.otherAppAssociatedNamespaces; var namespaceTips = []; otherAppAssociatedNamespaces.forEach(function (namespace) { var appId = namespace.appId; var clusterName = namespace.clusterName; var url = '/config.html?#/appid=' + appId + '&env=' + $scope.pageContext.env + '&cluster=' + clusterName; namespaceTips.push("AppId = " + appId + ", 集群 = " + clusterName + ", Namespace = " + namespace.namespaceName + ""); }); $scope.deleteNamespaceContext.detailReason = "以下应用已关联此公共Namespace,必须先删除全部已关联的Namespace才能删除公共Namespace。
    " + namespaceTips.join("
    "); AppUtil.showModal('#deleteNamespaceDenyForPublicNamespaceDialog'); } }); new Clipboard('.clipboard'); } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/ReleaseHistoryController.js ================================================ release_history_module.controller("ReleaseHistoryController", ['$scope', '$location', 'AppUtil', 'ReleaseService', 'ConfigService', 'ReleaseHistoryService', releaseHistoryController ]); function releaseHistoryController($scope, $location, AppUtil, ReleaseService, ConfigService, ReleaseHistoryService) { var params = AppUtil.parseParams($location.$$url); $scope.pageContext = { appId: params.appid, env: params.env, clusterName: params.clusterName, namespaceName: params.namespaceName, releaseId: params.releaseId, releaseHistoryId: params.releaseHistoryId }; var PAGE_SIZE = 10; var CONFIG_VIEW_TYPE = { DIFF: 'diff', ALL: 'all' }; $scope.page = 0; $scope.releaseHistories = []; $scope.hasLoadAll = false; $scope.selectedReleaseHistory = 0; $scope.isTextNamespace = false; $scope.showReleaseHistoryDetail = showReleaseHistoryDetail; $scope.switchConfigViewType = switchConfigViewType; $scope.findReleaseHistory = findReleaseHistory; $scope.showText = showText; init(); function init() { findReleaseHistory(); loadNamespace(); } function findReleaseHistory() { if ($scope.hasLoadAll) { return; } ReleaseHistoryService.findReleaseHistoryByNamespace($scope.pageContext.appId, $scope.pageContext.env, $scope.pageContext.clusterName, $scope.pageContext.namespaceName, $scope.page, PAGE_SIZE) .then(function (result) { if ($scope.page == 0) { $(".release-history").removeClass('hidden'); } if (!result || result.length < PAGE_SIZE) { $scope.hasLoadAll = true; } if (result.length == 0) { return; } $scope.releaseHistories = $scope.releaseHistories.concat(result); if ($scope.page == 0) { var defaultToShowReleaseHistory = result[0]; $scope.releaseHistories.forEach(function (history) { if ($scope.pageContext.releaseHistoryId == history.id) { defaultToShowReleaseHistory = history; } else if ($scope.pageContext.releaseId == history.releaseId) { // text namespace doesn't support ALL view if (!$scope.isTextNamespace) { history.viewType = CONFIG_VIEW_TYPE.ALL; } defaultToShowReleaseHistory = history; } }); showReleaseHistoryDetail(defaultToShowReleaseHistory); } $scope.page = $scope.page + 1; }, function (result) { AppUtil.showErrorMsg(result, "加载发布历史信息出错"); }); } function loadNamespace() { ConfigService.load_namespace($scope.pageContext.appId, $scope.pageContext.env, $scope.pageContext.clusterName, $scope.pageContext.namespaceName) .then(function (result) { $scope.isTextNamespace = result.format != "properties"; if ($scope.isTextNamespace) { fixTextNamespaceViewType(); } }) } function showReleaseHistoryDetail(history) { $scope.history = history; $scope.selectedReleaseHistory = history.id; if (!history.viewType) {//default view type history.viewType = CONFIG_VIEW_TYPE.DIFF; getReleaseDiffConfiguration(history); } } function fixTextNamespaceViewType() { $scope.releaseHistories.forEach(function (history) { // text namespace doesn't support ALL view if (history.viewType == CONFIG_VIEW_TYPE.ALL) { switchConfigViewType(history, CONFIG_VIEW_TYPE.DIFF); } }); } function switchConfigViewType(history, viewType) { history.viewType = viewType; if (viewType == CONFIG_VIEW_TYPE.DIFF) { getReleaseDiffConfiguration(history); } } function getReleaseDiffConfiguration(history) { if (!history.changes) { //Set previous release id to master latest release id when branch first gray release. if (history.operation == 2 && history.previousReleaseId == 0) { history.previousReleaseId = history.operationContext.baseReleaseId; } ReleaseService.compare($scope.pageContext.env, history.previousReleaseId, history.releaseId) .then(function (result) { history.changes = result.changes; }) } } function showText(text) { $scope.text = text; AppUtil.showModal("#showTextModal"); } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/config/SyncConfigController.js ================================================ sync_item_module.controller("SyncItemController", ['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil', 'ConfigService', function ($scope, $location, $window, toastr, AppService, AppUtil, ConfigService) { var params = AppUtil.parseParams($location.$$url); $scope.pageContext = { appId: params.appid, env: params.env, clusterName: params.clusterName, namespaceName: params.namespaceName }; var sourceItems = []; $scope.syncBtnDisabled = false; $scope.viewItems = []; $scope.toggleItemsCheckedStatus = toggleItemsCheckedStatus; $scope.diff = diff; $scope.removeItem = removeItem; $scope.syncItems = syncItems; $scope.collectSelectedClusters = collectSelectedClusters; $scope.syncItemNextStep = syncItemNextStep; $scope.backToAppHomePage = backToAppHomePage; $scope.switchSelect = switchSelect; $scope.filter = filter; $scope.resetFilter = resetFilter; $scope.showText = showText; init(); function init() { ////// load items ////// ConfigService.find_items($scope.pageContext.appId, $scope.pageContext.env, $scope.pageContext.clusterName, $scope.pageContext.namespaceName, "lastModifiedTime") .then(function (result) { sourceItems = []; result.forEach(function (item) { if (item.key) { item.checked = false; sourceItems.push(item); } }); $scope.viewItems = sourceItems; $(".apollo-container").removeClass("hidden"); }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载配置出错"); }); } var itemAllSelected = false; function toggleItemsCheckedStatus() { itemAllSelected = !itemAllSelected; $scope.viewItems.forEach(function (item) { item.checked = itemAllSelected; }) } var syncData = { syncToNamespaces: [], syncItems: [] }; function diff() { parseSyncSourceData(); if (syncData.syncItems.length == 0) { toastr.warning("请选择需要同步的配置"); return; } if (syncData.syncToNamespaces.length == 0) { toastr.warning("请选择集群"); return; } $scope.hasDiff = false; ConfigService.diff($scope.pageContext.namespaceName, syncData).then( function (result) { $scope.clusterDiffs = result; $scope.clusterDiffs.forEach(function (clusterDiff) { if (!$scope.hasDiff) { $scope.hasDiff = clusterDiff.diffs.createItems.length + clusterDiff.diffs.updateItems.length > 0; } if (clusterDiff.diffs.updateItems.length > 0) { //赋予同步前的值 ConfigService.find_items(clusterDiff.namespace.appId, clusterDiff.namespace.env, clusterDiff.namespace.clusterName, clusterDiff.namespace.namespaceName) .then(function (result) { var oldItemMap = {}; result.forEach(function (item) { oldItemMap[item.key] = item.value; }); clusterDiff.diffs.updateItems.forEach(function (item) { item.oldValue = oldItemMap[item.key]; }) }); } }); $scope.syncItemNextStep(1); }, function (result) { toastr.error(AppUtil.errorMsg(result)); }); } function removeItem(diff, type, toRemoveItem) { var syncDataResult = [], diffSetResult = [], diffSet; if (type == 'create') { diffSet = diff.createItems; } else { diffSet = diff.updateItems; } diffSet.forEach(function (item) { if (item.key != toRemoveItem.key) { diffSetResult.push(item); } }); if (type == 'create') { diff.createItems = diffSetResult; } else { diff.updateItems = diffSetResult; } syncData.syncItems.forEach(function (item) { if (item.key != toRemoveItem.key) { syncDataResult.push(item); } }); syncData.syncItems = syncDataResult; } function syncItems() { $scope.syncBtnDisabled = true; ConfigService.sync_items($scope.pageContext.appId, $scope.pageContext.namespaceName, syncData).then(function (result) { $scope.syncItemStep += 1; $scope.syncSuccess = true; $scope.syncBtnDisabled = false; }, function (result) { $scope.syncSuccess = false; $scope.syncBtnDisabled = false; toastr.error(AppUtil.errorMsg(result)); }); } var selectedClusters = []; function collectSelectedClusters(data) { selectedClusters = data; } function parseSyncSourceData() { syncData = { syncToNamespaces: [], syncItems: [] }; var namespaceName = $scope.pageContext.namespaceName; selectedClusters.forEach(function (cluster) { if (cluster.checked) { cluster.clusterName = cluster.name; cluster.namespaceName = namespaceName; syncData.syncToNamespaces.push(cluster); } }); $scope.viewItems.forEach(function (item) { if (item.checked) { syncData.syncItems.push(item); } }); return syncData; } ////// flow control /////// $scope.syncItemStep = 1; function syncItemNextStep(offset) { $scope.syncItemStep += offset; } function backToAppHomePage() { $window.location.href = '/config.html?#appid=' + $scope.pageContext.appId; } function switchSelect(o) { o.checked = !o.checked; } function filter() { var beginTime = $scope.filterBeginTime; var endTime = $scope.filterEndTime; var result = []; sourceItems.forEach(function (item) { var updateTime = new Date(item.dataChangeLastModifiedTime); if ((!beginTime || updateTime > beginTime) && (!endTime || updateTime < endTime)) { result.push(item); } }); $scope.viewItems = result; } function resetFilter() { $scope.filterBeginTime = null; $scope.filterEndTime = null; filter(); } function showText(text) { $scope.text = text; AppUtil.showModal('#showTextModal'); } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/open/OpenManageController.js ================================================ open_manage_module.controller('OpenManageController', ['$scope', 'toastr', 'AppUtil', 'OrganizationService', 'ConsumerService', 'PermissionService', OpenManageController]); function OpenManageController($scope, toastr, AppUtil, OrganizationService, ConsumerService, PermissionService) { var $orgWidget = $('#organization'); $scope.consumer = {}; $scope.consumerRole = { type: 'NamespaceRole' }; $scope.submitBtnDisabled = false; $scope.userSelectWidgetId = 'toAssignMasterRoleUser'; $scope.getTokenByAppId = getTokenByAppId; $scope.createConsumer = createConsumer; $scope.assignRoleToConsumer = assignRoleToConsumer; init(); function init() { initOrganization(); initPermission(); } function initOrganization() { OrganizationService.find_organizations().then(function (result) { var organizations = []; result.forEach(function (item) { var org = {}; org.id = item.orgId; org.text = item.orgName + '(' + item.orgId + ')'; org.name = item.orgName; organizations.push(org); }); $orgWidget.select2({ placeholder: '请选择部门', width: '100%', data: organizations }); }, function (result) { toastr.error(AppUtil.errorMsg(result), "load organizations error"); }); } function initPermission() { PermissionService.has_root_permission() .then(function (result) { $scope.isRootUser = result.hasPermission; }) } function getTokenByAppId() { if (!$scope.consumer.appId) { toastr.warning("请输入appId"); return; } ConsumerService.getConsumerTokenByAppId($scope.consumer.appId) .then(function (consumerToken) { if (consumerToken.token) { $scope.consumerToken = consumerToken; $scope.consumerRole.token = consumerToken.token; } else { $scope.consumerToken = {token: 'App(' + $scope.consumer.appId + ')未创建,请先创建'}; } }) } function createConsumer() { $scope.submitBtnDisabled = true; if (!$scope.consumer.appId) { toastr.warning("请输入appId"); return; } var selectedOrg = $orgWidget.select2('data')[0]; if (!selectedOrg.id) { toastr.warning("请选择部门"); return; } $scope.consumer.orgId = selectedOrg.id; $scope.consumer.orgName = selectedOrg.name; // owner var owner = $('.ownerSelector').select2('data')[0]; if (!owner) { toastr.warning("请选择应用负责人"); return; } $scope.consumer.ownerName = owner.id; ConsumerService.createConsumer($scope.consumer) .then(function (consumerToken) { toastr.success("创建成功"); $scope.consumerToken = consumerToken; $scope.consumerRole.token = consumerToken.token; $scope.submitBtnDisabled = false; $scope.consumer = {}; }, function (response) { AppUtil.showErrorMsg(response, "创建失败"); $scope.submitBtnDisabled = false; }) } function assignRoleToConsumer() { ConsumerService.assignRoleToConsumer($scope.consumerRole.token, $scope.consumerRole.type, $scope.consumerRole.appId, $scope.consumerRole.namespaceName) .then(function (consumerRoles) { toastr.success("赋权成功"); }, function (response) { AppUtil.showErrorMsg(response, "赋权失败"); }) } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/controller/role/NamespaceRoleController.js ================================================ role_module.controller('NamespaceRoleController', ['$scope', '$location', '$window', 'toastr', 'AppService', 'UserService', 'AppUtil', 'PermissionService', function ($scope, $location, $window, toastr, AppService, UserService, AppUtil, PermissionService) { var params = AppUtil.parseParams($location.$$url); $scope.pageContext = { appId: params.appid, namespaceName: params.namespaceName }; $scope.modifyRoleSubmitBtnDisabled = false; $scope.ReleaseRoleSubmitBtnDisabled = false; $scope.releaseRoleWidgetId = 'releaseRoleWidgetId'; $scope.modifyRoleWidgetId = 'modifyRoleWidgetId'; PermissionService.has_assign_user_permission($scope.pageContext.appId) .then(function (result) { $scope.hasAssignUserPermission = result.hasPermission; }, function (reslt) { }); PermissionService.get_namespace_role_users($scope.pageContext.appId, $scope.pageContext.namespaceName) .then(function (result) { $scope.rolesAssignedUsers = result; }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载授权用户出错"); }); $scope.assignRoleToUser = function (roleType) { if ('ReleaseNamespace' == roleType) { var user = $('.' + $scope.releaseRoleWidgetId).select2('data')[0]; if (!user) { toastr.warning("请选择用户"); return; } $scope.ReleaseRoleSubmitBtnDisabled = true; var toAssignReleaseNamespaceRoleUser = user.id; PermissionService.assign_release_namespace_role($scope.pageContext.appId, $scope.pageContext.namespaceName, toAssignReleaseNamespaceRoleUser) .then(function (result) { toastr.success("添加成功"); $scope.ReleaseRoleSubmitBtnDisabled = false; $scope.rolesAssignedUsers.releaseRoleUsers.push( {userId: toAssignReleaseNamespaceRoleUser}); $('.' + $scope.releaseRoleWidgetId).select2("val", ""); }, function (result) { $scope.ReleaseRoleSubmitBtnDisabled = false; toastr.error(AppUtil.errorMsg(result), "添加失败"); }); } else { var user = $('.' + $scope.modifyRoleWidgetId).select2('data')[0]; if (!user) { toastr.warning("请选择用户"); return; } $scope.modifyRoleSubmitBtnDisabled = true; var toAssignModifyNamespaceRoleUser = user.id; PermissionService.assign_modify_namespace_role($scope.pageContext.appId, $scope.pageContext.namespaceName, toAssignModifyNamespaceRoleUser) .then(function (result) { toastr.success("添加成功"); $scope.modifyRoleSubmitBtnDisabled = false; $scope.rolesAssignedUsers.modifyRoleUsers.push( {userId: toAssignModifyNamespaceRoleUser}); $('.' + $scope.modifyRoleWidgetId).select2("val", ""); }, function (result) { $scope.modifyRoleSubmitBtnDisabled = false; toastr.error(AppUtil.errorMsg(result), "添加失败"); }); } }; $scope.removeUserRole = function (roleType, user) { if ('ReleaseNamespace' == roleType) { PermissionService.remove_release_namespace_role($scope.pageContext.appId, $scope.pageContext.namespaceName, user) .then(function (result) { toastr.success("删除成功"); removeUserFromList($scope.rolesAssignedUsers.releaseRoleUsers, user); }, function (result) { toastr.error(AppUtil.errorMsg(result), "删除失败"); }); } else { PermissionService.remove_modify_namespace_role($scope.pageContext.appId, $scope.pageContext.namespaceName, user) .then(function (result) { toastr.success("删除成功"); removeUserFromList($scope.rolesAssignedUsers.modifyRoleUsers, user); }, function (result) { toastr.error(AppUtil.errorMsg(result), "删除失败"); }); } }; function removeUserFromList(list, user) { var index = 0; for (var i = 0; i < list.length; i++) { if (list[i].userId == user) { index = i; break; } } list.splice(index, 1); } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/delete-namespace-modal-directive.js ================================================ directive_module.directive('deletenamespacemodal', deleteNamespaceModalDirective); function deleteNamespaceModalDirective($window, $q, toastr, AppUtil, EventManager, PermissionService, UserService, NamespaceService) { return { restrict: 'E', templateUrl: '../../views/component/delete-namespace-modal.html', transclude: true, replace: true, scope: { env: '=' }, link: function (scope) { scope.doDeleteNamespace = doDeleteNamespace; EventManager.subscribe(EventManager.EventType.PRE_DELETE_NAMESPACE, function (context) { var toDeleteNamespace = context.namespace; scope.toDeleteNamespace = toDeleteNamespace; //1. check namespace is not private if (!checkNotPrivateNamespace(toDeleteNamespace)) { return; } //2. check operator has master permission checkPermission(toDeleteNamespace).then(function () { //3. check namespace's master branch has not instances if (!checkMasterInstance(toDeleteNamespace)) { return; } //4. check namespace's gray branch has not instances if (!checkBranchInstance(toDeleteNamespace)) { return; } if (toDeleteNamespace.isLinkedNamespace) { showDeleteNamespaceConfirmDialog(); } else { //5. check public namespace has not associated namespace checkPublicNamespace(toDeleteNamespace).then(function () { showDeleteNamespaceConfirmDialog(); }); } }) }); function checkNotPrivateNamespace(namespace) { if (!namespace.isPublic) { toastr.error("不能删除私有的Namespace", "删除失败"); return false; } return true; } function checkPermission(namespace) { var d = $q.defer(); UserService.load_user().then(function (currentUser) { var isAppMasterUser = false; PermissionService.get_app_role_users(namespace.baseInfo.appId) .then(function (appRoleUsers) { var masterUsers = []; appRoleUsers.masterUsers.forEach(function (user) { masterUsers.push(user.userId); if (currentUser.userId == user.userId) { isAppMasterUser = true; } }); scope.masterUsers = masterUsers; scope.isAppMasterUser = isAppMasterUser; if (!isAppMasterUser) { toastr.error("您没有项目管理员权限,只有管理员才能删除Namespace,请找项目管理员 [" + scope.masterUsers.join(",") + "] 删除Namespace", "删除失败"); d.reject(); } else { d.resolve(); } }); }); return d.promise; } function checkMasterInstance(namespace) { if (namespace.instancesCount > 0) { EventManager.emit(EventManager.EventType.DELETE_NAMESPACE_FAILED, { namespace: namespace, reason: 'master_instance' }); return false; } return true; } function checkBranchInstance(namespace) { if (namespace.hasBranch && namespace.branch.latestReleaseInstances.total > 0) { EventManager.emit(EventManager.EventType.DELETE_NAMESPACE_FAILED, { namespace: namespace, reason: 'branch_instance' }); return false; } return true; } function checkPublicNamespace(namespace) { var d = $q.defer(); var publicAppId = namespace.baseInfo.appId; NamespaceService.getPublicAppNamespaceAllNamespaces(scope.env, namespace.baseInfo.namespaceName, 0, 20) .then(function (associatedNamespaces) { var otherAppAssociatedNamespaces = []; associatedNamespaces.forEach(function (associatedNamespace) { if (associatedNamespace.appId != publicAppId) { otherAppAssociatedNamespaces.push(associatedNamespace); } }); if (otherAppAssociatedNamespaces.length) { EventManager.emit(EventManager.EventType.DELETE_NAMESPACE_FAILED, { namespace: namespace, reason: 'public_namespace', otherAppAssociatedNamespaces: otherAppAssociatedNamespaces }); d.reject(); } else { d.resolve(); } }); return d.promise; } function showDeleteNamespaceConfirmDialog() { AppUtil.showModal('#deleteNamespaceModal'); } function doDeleteNamespace() { var toDeleteNamespace = scope.toDeleteNamespace; NamespaceService.deleteNamespace(toDeleteNamespace.baseInfo.appId, scope.env, toDeleteNamespace.baseInfo.clusterName, toDeleteNamespace.baseInfo.namespaceName) .then(function () { toastr.success("删除成功"); setTimeout(function () { $window.location.reload(); }, 1000); }, function (result) { AppUtil.showErrorMsg(result, "删除失败"); }) } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/diff-directive.js ================================================ directive_module.directive('apollodiff', function ($compile, $window) { return { restrict: 'E', templateUrl: '../../views/component/diff.html', transclude: true, replace: true, scope: { oldStr: '=', newStr: '=', apolloId: '=' }, link: function (scope, element, attrs) { scope.$watch('oldStr', makeDiff); scope.$watch('newStr', makeDiff); function makeDiff() { var displayArea = document.getElementById(scope.apolloId); if (!displayArea){ return; } //clear displayArea.innerHTML = ''; var color = '', span = null, pre = ''; var oldStr = scope.oldStr == undefined ? '' : scope.oldStr; var newStr = scope.newStr == undefined ? '' : scope.newStr; var diff = JsDiff.diffLines(oldStr, newStr), fragment = document.createDocumentFragment(); diff.forEach(function (part) { // green for additions, red for deletions // grey for common parts color = part.added ? 'green' : part.removed ? 'red' : 'grey'; span = document.createElement('span'); span.style.color = color; pre = part.added ? '+' : part.removed ? '-' : ''; span.appendChild(document.createTextNode(pre + part.value)); fragment.appendChild(span); }); displayArea.appendChild(fragment); } } } }); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/directive.js ================================================ /** navbar */ directive_module.directive('apollonav', function ($compile, $window, toastr, AppUtil, AppService, EnvService, UserService, CommonService, PermissionService) { return { restrict: 'E', templateUrl: '../../views/common/nav.html', transclude: true, replace: true, link: function (scope, element, attrs) { CommonService.getPageSetting().then(function (setting) { scope.pageSetting = setting; }); scope.sourceApps = []; scope.copyedApps = []; AppService.find_apps().then(function (result) { result.forEach(function (app) { app.selected = false; scope.sourceApps.push(app); }); scope.copyedApps = angular.copy(scope.sourceApps); }, function (result) { toastr.error(AppUtil.errorMsg(result), "load apps error"); }); scope.searchKey = ''; scope.shouldShowAppList = false; var selectedApp = {}; scope.selectApp = function (app) { select(app); scope.jumpToConfigPage(); }; scope.changeSearchKey = function () { scope.copyedApps = []; var searchKey = scope.searchKey.toLocaleLowerCase(); scope.sourceApps.forEach(function (app) { if (app.name.toLocaleLowerCase().indexOf(searchKey) > -1 || app.appId.toLocaleLowerCase().indexOf(searchKey) > -1) { scope.copyedApps.push(app); } }); scope.shouldShowAppList = true; }; scope.jumpToConfigPage = function () { if (selectedApp.appId) { if ($window.location.href.indexOf("config.html") > -1) { $window.location.hash = "appid=" + selectedApp.appId; $window.location.reload(); } else { $window.location.href = '/config.html?#appid=' + selectedApp.appId; } } }; //up:38 down:40 enter:13 var selectedAppIdx = -1; element.bind("keydown keypress", function (event) { if (event.keyCode == 40) { if (selectedAppIdx < scope.copyedApps.length - 1) { clearAppsSelectedStatus(); scope.copyedApps[++selectedAppIdx].selected = true; } } else if (event.keyCode == 38) { if (selectedAppIdx >= 1) { clearAppsSelectedStatus(); scope.copyedApps[--selectedAppIdx].selected = true; } } else if (event.keyCode == 13) { if (scope.shouldShowAppList && selectedAppIdx > -1) { select(scope.copyedApps[selectedAppIdx]); event.preventDefault(); } else { scope.jumpToConfigPage(); } } //强制刷新 scope.$apply(function () { scope.copiedApps = scope.copiedApps; }); }); $(".search-input").on("click", function (event) { event.stopPropagation(); }); $(document).on('click', function () { scope.$apply(function () { scope.shouldShowAppList = false; }); }); function clearAppsSelectedStatus() { scope.copiedApps.forEach(function (app) { app.selected = false; }) } function select(app) { selectedApp = app; scope.searchKey = app.name; scope.shouldShowAppList = false; clearAppsSelectedStatus(); selectedAppIdx = -1; } UserService.load_user().then(function (result) { scope.userName = result.userId; }, function (result) { }); PermissionService.has_root_permission().then(function(result) { scope.hasRootPermission = result.hasPermission; }) } } }); /** env cluster selector*/ directive_module.directive('apolloclusterselector', function ($compile, $window, AppService, AppUtil, toastr) { return { restrict: 'E', templateUrl: '../../views/component/env-selector.html', transclude: true, replace: true, scope: { appId: '=apolloAppId', defaultAllChecked: '=apolloDefaultAllChecked', select: '=apolloSelect', defaultCheckedEnv: '=apolloDefaultCheckedEnv', defaultCheckedCluster: '=apolloDefaultCheckedCluster', notCheckedEnv: '=apolloNotCheckedEnv', notCheckedCluster: '=apolloNotCheckedCluster' }, link: function (scope, element, attrs) { scope.$watch("defaultCheckedEnv", refreshClusterList); scope.$watch("defaultCheckedCluster", refreshClusterList); refreshClusterList(); function refreshClusterList() { AppService.load_nav_tree(scope.appId).then(function (result) { scope.clusters = []; var envClusterInfo = AppUtil.collectData(result); envClusterInfo.forEach(function (node) { var env = node.env; node.clusters.forEach(function (cluster) { cluster.env = env; //default checked cluster.checked = scope.defaultAllChecked || (cluster.env == scope.defaultCheckedEnv && cluster.name == scope.defaultCheckedCluster); //not checked if (cluster.env == scope.notCheckedEnv && cluster.name == scope.notCheckedCluster) { cluster.checked = false; } scope.clusters.push(cluster); }) }); scope.select(collectSelectedClusters()); }); } scope.envAllSelected = scope.defaultAllChecked; scope.toggleEnvsCheckedStatus = function () { scope.envAllSelected = !scope.envAllSelected; scope.clusters.forEach(function (cluster) { cluster.checked = scope.envAllSelected; }); scope.select(collectSelectedClusters()); }; scope.switchSelect = function (o, $event) { o.checked = !o.checked; $event.stopPropagation(); scope.select(collectSelectedClusters()); }; scope.toggleClusterCheckedStatus = function (cluster) { cluster.checked = !cluster.checked; scope.select(collectSelectedClusters()); }; function collectSelectedClusters() { var selectedClusters = []; scope.clusters.forEach(function (cluster) { if (cluster.checked) { cluster.clusterName = cluster.name; selectedClusters.push(cluster); } }); return selectedClusters; } } } }); /** 必填项*/ directive_module.directive('apollorequiredfield', function ($compile, $window) { return { restrict: 'E', template: '*', transclude: true, replace: true } }); /** 确认框 */ directive_module.directive('apolloconfirmdialog', function ($compile, $window, $sce) { return { restrict: 'E', templateUrl: '../../views/component/confirm-dialog.html', transclude: true, replace: true, scope: { dialogId: '=apolloDialogId', title: '=apolloTitle', detail: '=apolloDetail', showCancelBtn: '=apolloShowCancelBtn', doConfirm: '=apolloConfirm', confirmBtnText: '=?', cancel: '=' }, link: function (scope, element, attrs) { scope.$watch("detail", function () { scope.detailAsHtml = $sce.trustAsHtml(scope.detail); }); if (!scope.confirmBtnText) { scope.confirmBtnText = '确认'; } scope.confirm = function () { if (scope.doConfirm) { scope.doConfirm(); } }; } } }); /** entrance */ directive_module.directive('apolloentrance', function ($compile, $window) { return { restrict: 'E', templateUrl: '../../views/component/entrance.html', transclude: true, replace: true, scope: { imgSrc: '=apolloImgSrc', title: '=apolloTitle', href: '=apolloHref' }, link: function (scope, element, attrs) { } } }); /** entrance */ directive_module.directive('apollouserselector', function ($compile, $window) { return { restrict: 'E', templateUrl: '../../views/component/user-selector.html', transclude: true, replace: true, scope: { id: '=apolloId', disabled: '=' }, link: function (scope, element, attrs) { scope.$watch("id", initSelect2); var select2Options = { ajax: { url: '/users', dataType: 'json', delay: 250, data: function (params) { return { keyword: params.term ? params.term : '', limit: 100 } }, processResults: function (data, params) { var users = []; data.forEach(function (user) { users.push({ id: user.userId, text: user.userId + " | " + user.name }) }); return { results: users } }, cache: true, minimumInputLength: 5 } }; function initSelect2() { $('.' + scope.id).select2(select2Options); } } } }); directive_module.directive('apollomultipleuserselector', function ($compile, $window) { return { restrict: 'E', templateUrl: '../../views/component/multiple-user-selector.html', transclude: true, replace: true, scope: { id: '=apolloId' }, link: function (scope, element, attrs) { scope.$watch("id", initSelect2); var searchUsersAjax = { ajax: { url: '/users', dataType: 'json', delay: 250, data: function (params) { return { keyword: params.term ? params.term : '', limit: 100 } }, processResults: function (data, params) { var users = []; data.forEach(function (user) { users.push({ id: user.userId, text: user.userId + " | " + user.name }) }); return { results: users } }, cache: true, minimumInputLength: 5 } }; function initSelect2() { $('.' + scope.id).select2(searchUsersAjax); } } } }); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/gray-release-rules-modal-directive.js ================================================ directive_module.directive('rulesmodal', rulesModalDirective); function rulesModalDirective(toastr, AppUtil, EventManager, InstanceService) { return { restrict: 'E', templateUrl: '../../views/component/gray-release-rules-modal.html', transclude: true, replace: true, scope: { appId: '=', env: '=', cluster: '=' }, link: function (scope) { scope.completeEditBtnDisable = false; scope.batchAddIPs = batchAddIPs; scope.addRules = addRules; scope.removeRule = removeRule; scope.completeEditItem = completeEditItem; scope.cancelEditItem = cancelEditItem; scope.initSelectIps = initSelectIps; EventManager.subscribe(EventManager.EventType.EDIT_GRAY_RELEASE_RULES, function (context) { var branch = context.branch; scope.branch = branch; if (branch.editingRuleItem.clientIpList && branch.editingRuleItem.clientIpList[0] == '*'){ branch.editingRuleItem.ApplyToAllInstances = true; }else { branch.editingRuleItem.ApplyToAllInstances = false; } $('.rules-ip-selector').select2({ placeholder: "从实例列表中选择", allowClear: true }); AppUtil.showModal('#rulesModal'); }); $('.rules-ip-selector').on('select2:select', function () { addRules(scope.branch); }); function addRules(branch) { var newRules, selector = $('.rules-ip-selector'); newRules = selector.select2('data'); var parsedIPs = []; newRules.forEach(function (rule) { parsedIPs.push(rule.text); }); selector.select2("val", ""); addRuleItemIP(branch, parsedIPs); scope.$apply(); } function batchAddIPs(branch, newIPs) { if (!newIPs) { return; } addRuleItemIP(branch, newIPs.split(',')); } function addRuleItemIP(branch, newIps) { var oldIPs = branch.editingRuleItem.draftIpList; if (newIps && newIps.length > 0) { newIps.forEach(function (IP) { if (!AppUtil.checkIPV4(IP)) { toastr.error("不合法的IP地址:" + IP); } else if (oldIPs.indexOf(IP) < 0) { oldIPs.push(IP); } }) } //remove IP:all oldIPs.forEach(function (IP, index) { if (IP == "*") { oldIPs.splice(index, 1); } }); } function removeRule(ruleItem, IP) { ruleItem.draftIpList.forEach(function (existedRule, index) { if (existedRule == IP) { ruleItem.draftIpList.splice(index, 1); } }) } function completeEditItem(branch) { scope.completeEditBtnDisable = true; if (!branch.editingRuleItem.clientAppId) { toastr.error("灰度的AppId不能为空"); scope.completeEditBtnDisable = false; return; } if (branch.editingRuleItem.isNew && branch.rules && branch.rules.ruleItems) { var errorRuleItem = false; branch.rules.ruleItems.forEach(function (ruleItem) { if (ruleItem.clientAppId == branch.editingRuleItem.clientAppId) { toastr.error("已经存在AppId=" + branch.editingRuleItem.clientAppId + "的规则"); errorRuleItem = true; } }); if (errorRuleItem) { scope.completeEditBtnDisable = false; return; } } if (!branch.editingRuleItem.ApplyToAllInstances) { if (branch.editingRuleItem.draftIpList.length == 0) { toastr.error("IP列表不能为空"); scope.completeEditBtnDisable = false; return; } else { branch.editingRuleItem.clientIpList = branch.editingRuleItem.draftIpList; } } else { branch.editingRuleItem.clientIpList = ['*']; } if (!branch.rules) { branch.rules = { appId: scope.appId, clusterName: scope.cluster, namespaceName: branch.baseInfo.namespaceName, branchName: branch.baseInfo.clusterName }; } if (!branch.rules.ruleItems) { branch.rules.ruleItems = []; } if (branch.editingRuleItem.isNew) { branch.rules.ruleItems.push(branch.editingRuleItem); } branch.editingRuleItem = undefined; scope.toAddIPs = ''; AppUtil.hideModal('#rulesModal'); EventManager.emit(EventManager.EventType.UPDATE_GRAY_RELEASE_RULES, { branch: branch }, branch.baseInfo.namespaceName); scope.completeEditBtnDisable = false; } function cancelEditItem(branch) { branch.editingRuleItem.isEdit = false; branch.editingRuleItem = undefined; scope.toAddIPs = ''; AppUtil.hideModal('#rulesModal'); } $('#rulesModal').on('shown.bs.modal', function (e) { initSelectIps(); }); function initSelectIps() { scope.selectIps = []; if (!scope.branch.parentNamespace.isPublic || scope.branch.parentNamespace.isLinkedNamespace) { scope.branch.editingRuleItem.clientAppId = scope.branch.baseInfo.appId; } if (!scope.branch.editingRuleItem.clientAppId) { return; } InstanceService.findInstancesByNamespace(scope.appId, scope.env, scope.cluster, scope.branch.baseInfo.namespaceName, scope.branch.editingRuleItem.clientAppId, 0, 2000) .then(function (result) { scope.selectIps = result.content; }); } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/item-modal-directive.js ================================================ directive_module.directive('itemmodal', itemModalDirective); function itemModalDirective(toastr, $sce, AppUtil, EventManager, ConfigService) { return { restrict: 'E', templateUrl: '../../views/component/item-modal.html', transclude: true, replace: true, scope: { appId: '=', env: '=', cluster: '=', toOperationNamespace: '=', item: '=' }, link: function (scope) { var TABLE_VIEW_OPER_TYPE = { CREATE: 'create', UPDATE: 'update' }; scope.doItem = doItem; scope.collectSelectedClusters = collectSelectedClusters; scope.showHiddenChars = showHiddenChars; $('#itemModal').on('show.bs.modal', function (e) { scope.showHiddenCharsContext = false; scope.hiddenCharCounter = 0; scope.valueWithHiddenChars = $sce.trustAsHtml(''); }); function doItem() { if (!scope.item.value) { scope.item.value = ""; } if (scope.item.tableViewOperType == TABLE_VIEW_OPER_TYPE.CREATE) { //check key unique var hasRepeatKey = false; scope.toOperationNamespace.items.forEach(function (item) { if (!item.isDeleted && scope.item.key == item.item.key) { toastr.error("key=" + scope.item.key + " 已存在"); hasRepeatKey = true; } }); if (hasRepeatKey) { return; } scope.item.addItemBtnDisabled = true; if (scope.toOperationNamespace.isBranch) { ConfigService.create_item(scope.appId, scope.env, scope.toOperationNamespace.baseInfo.clusterName, scope.toOperationNamespace.baseInfo.namespaceName, scope.item).then( function (result) { toastr.success("添加成功,如需生效请发布"); scope.item.addItemBtnDisabled = false; AppUtil.hideModal('#itemModal'); EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: scope.toOperationNamespace }); }, function (result) { toastr.error(AppUtil.errorMsg(result), "添加失败"); scope.item.addItemBtnDisabled = false; }); } else { if (selectedClusters.length == 0) { toastr.error("请选择集群"); scope.item.addItemBtnDisabled = false; return; } selectedClusters.forEach(function (cluster) { ConfigService.create_item(scope.appId, cluster.env, cluster.name, scope.toOperationNamespace.baseInfo.namespaceName, scope.item).then( function (result) { scope.item.addItemBtnDisabled = false; AppUtil.hideModal('#itemModal'); toastr.success(cluster.env + " , " + scope.item.key, "添加成功,如需生效请发布"); if (cluster.env == scope.env && cluster.name == scope.cluster) { EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: scope.toOperationNamespace }); } }, function (result) { toastr.error(AppUtil.errorMsg(result), "添加失败"); scope.item.addItemBtnDisabled = false; }); }); } } else { if (!scope.item.comment) { scope.item.comment = ""; } ConfigService.update_item(scope.appId, scope.env, scope.toOperationNamespace.baseInfo.clusterName, scope.toOperationNamespace.baseInfo.namespaceName, scope.item).then( function (result) { EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: scope.toOperationNamespace }); AppUtil.hideModal('#itemModal'); toastr.success("更新成功, 如需生效请发布"); }, function (result) { toastr.error(AppUtil.errorMsg(result), "更新失败"); }); } } var selectedClusters = []; function collectSelectedClusters(data) { selectedClusters = data; } function showHiddenChars() { var value = scope.item.value; if (!value) { return; } var hiddenCharCounter = 0, valueWithHiddenChars = value; for (var i = 0; i < valueWithHiddenChars.length; i++) { var c = valueWithHiddenChars[i]; if (isHiddenChar(c)) { valueWithHiddenChars = valueWithHiddenChars.replace(c, viewHiddenChar); hiddenCharCounter++; } } scope.showHiddenCharsContext = true; scope.hiddenCharCounter = hiddenCharCounter; scope.valueWithHiddenChars = $sce.trustAsHtml(valueWithHiddenChars); } function isHiddenChar(c) { return c == '\t' || c == '\n' || c == ' '; } function viewHiddenChar(c) { if (c == '\t') { return '#制表符#'; } else if (c == '\n') { return '#换行符#'; } else if (c == ' ') { return '#空格#'; } } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/merge-and-publish-modal-directive.js ================================================ directive_module.directive('mergeandpublishmodal', mergeAndPublishDirective); function mergeAndPublishDirective(AppUtil, EventManager) { return { restrict: 'E', templateUrl: '../../views/component/merge-and-publish-modal.html', transclude: true, replace: true, scope: { appId: '=', env: '=', cluster: '=' }, link: function (scope) { scope.showReleaseModal = showReleaseModal; EventManager.subscribe(EventManager.EventType.MERGE_AND_PUBLISH_NAMESPACE, function (context) { var branch = context.branch; scope.toReleaseNamespace = branch; scope.toDeleteBranch = branch; scope.isEmergencyPublish = context.isEmergencyPublish ? context.isEmergencyPublish : false; var branchStatusMerge = 2; branch.branchStatus = branchStatusMerge; branch.mergeAndPublish = true; AppUtil.showModal('#mergeAndPublishModal'); }); function showReleaseModal() { EventManager.emit(EventManager.EventType.PUBLISH_NAMESPACE, { namespace: scope.toReleaseNamespace, isEmergencyPublish: scope.isEmergencyPublish }); } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js ================================================ directive_module.directive('apollonspanel', directive); function directive($window, toastr, AppUtil, EventManager, PermissionService, NamespaceLockService, UserService, CommitService, ReleaseService, InstanceService, NamespaceBranchService, ConfigService) { return { restrict: 'E', templateUrl: '../../views/component/namespace-panel.html', transclude: true, replace: true, scope: { namespace: '=', appId: '=', env: '=', cluster: '=', user: '=', lockCheck: '=', createItem: '=', editItem: '=', preDeleteItem: '=', showText: '=', showNoModifyPermissionDialog: '=', preCreateBranch: '=', preDeleteBranch: '=', showMergeAndPublishGrayTips: '=' }, link: function (scope) { //constants var namespace_view_type = { TEXT: 'text', TABLE: 'table', HISTORY: 'history', INSTANCE: 'instance', RULE: 'rule' }; var namespace_instance_view_type = { LATEST_RELEASE: 'latest_release', NOT_LATEST_RELEASE: 'not_latest_release', ALL: 'all' }; var operate_branch_storage_key = 'OperateBranch'; scope.switchView = switchView; scope.toggleItemSearchInput = toggleItemSearchInput; scope.searchItems = searchItems; scope.loadCommitHistory = loadCommitHistory; scope.toggleTextEditStatus = toggleTextEditStatus; scope.goToSyncPage = goToSyncPage; scope.modifyByText = modifyByText; scope.goToParentAppConfigPage = goToParentAppConfigPage; scope.switchInstanceViewType = switchInstanceViewType; scope.switchBranch = switchBranch; scope.loadInstanceInfo = loadInstanceInfo; scope.refreshInstancesInfo = refreshInstancesInfo; scope.deleteRuleItem = deleteRuleItem; scope.rollback = rollback; scope.publish = publish; scope.mergeAndPublish = mergeAndPublish; scope.addRuleItem = addRuleItem; scope.editRuleItem = editRuleItem; scope.deleteNamespace = deleteNamespace; var subscriberId = EventManager.subscribe(EventManager.EventType.UPDATE_GRAY_RELEASE_RULES, function (context) { useRules(context.branch); }, scope.namespace.baseInfo.namespaceName); scope.$on('$destroy', function () { EventManager.unsubscribe(EventManager.EventType.UPDATE_GRAY_RELEASE_RULES, subscriberId, scope.namespace.baseInfo.namespaceName); }); init(); function init() { initNamespace(scope.namespace); initOther(); } function initNamespace(namespace, viewType) { namespace.hasBranch = false; namespace.isBranch = false; namespace.isLinkedNamespace = namespace.isPublic ? namespace.parentAppId != namespace.baseInfo.appId : false; namespace.displayControl = { currentOperateBranch: 'master', showSearchInput: false, show: true }; namespace.viewItems = namespace.items; namespace.isPropertiesFormat = namespace.format == 'properties'; namespace.isTextEditing = false; namespace.instanceViewType = namespace_instance_view_type.LATEST_RELEASE; namespace.latestReleaseInstancesPage = 0; namespace.allInstances = []; namespace.allInstancesPage = 0; namespace.commitChangeBtnDisabled = false; generateNamespaceId(namespace); initNamespaceBranch(namespace); initNamespaceViewName(namespace); initNamespaceLock(namespace); initNamespaceInstancesCount(namespace); initPermission(namespace); initLinkedNamespace(namespace); loadInstanceInfo(namespace); function initNamespaceBranch(namespace) { NamespaceBranchService.findNamespaceBranch(scope.appId, scope.env, namespace.baseInfo.clusterName, namespace.baseInfo.namespaceName) .then(function (result) { if (!result.baseInfo) { return; } //namespace has branch namespace.hasBranch = true; namespace.branchName = result.baseInfo.clusterName; //init branch namespace.branch = result; namespace.branch.isBranch = true; namespace.branch.parentNamespace = namespace; namespace.branch.viewType = namespace_view_type.TABLE; namespace.branch.isPropertiesFormat = namespace.format == 'properties'; namespace.branch.allInstances = [];//master namespace all instances namespace.branch.latestReleaseInstances = []; namespace.branch.latestReleaseInstancesPage = 0; namespace.branch.instanceViewType = namespace_instance_view_type.LATEST_RELEASE; namespace.branch.hasLoadInstances = false; namespace.branch.displayControl = { show: true }; generateNamespaceId(namespace.branch); initBranchItems(namespace.branch); initRules(namespace.branch); loadInstanceInfo(namespace.branch); initNamespaceLock(namespace.branch); initPermission(namespace); initUserOperateBranchScene(namespace); }); function initBranchItems(branch) { branch.masterItems = []; branch.branchItems = []; var masterItemsMap = {}; branch.parentNamespace.items.forEach(function (item) { if (item.item.key) { masterItemsMap[item.item.key] = item; } }); var branchItemsMap = {}; var itemModifiedCnt = 0; branch.items.forEach(function (item) { var key = item.item.key; var masterItem = masterItemsMap[key]; //modify master item and set item's masterReleaseValue if (masterItem) { if (masterItem.isModified && masterItem.oldValue) { item.masterReleaseValue = masterItem.oldValue; } else if (masterItem.item.value) { item.masterReleaseValue = masterItem.item.value; } } else {//delete branch item item.masterReleaseValue = ''; } //delete master item. ignore if (item.isDeleted && masterItem) { if (item.masterReleaseValue != item.oldValue) { itemModifiedCnt++; branch.branchItems.push(item); } } else {//branch's item branchItemsMap[key] = item; if (item.isModified) { itemModifiedCnt++; } branch.branchItems.push(item); } }); branch.itemModifiedCnt = itemModifiedCnt; branch.parentNamespace.items.forEach(function (item) { if (item.item.key) { if (!branchItemsMap[item.item.key]) { branch.masterItems.push(item); } else { item.hasBranchValue = true; } } }) } } function generateNamespaceId(namespace) { namespace.id = Math.random().toString(36).substr(2); } function initPermission(namespace) { PermissionService.has_modify_namespace_permission( scope.appId, namespace.baseInfo.namespaceName) .then(function (result) { //branch has same permission namespace.hasModifyPermission = result.hasPermission; if (namespace.branch) { namespace.branch.hasModifyPermission = result.hasPermission; } }); PermissionService.has_release_namespace_permission( scope.appId, namespace.baseInfo.namespaceName) .then(function (result) { //branch has same permission namespace.hasReleasePermission = result.hasPermission; if (namespace.branch) { namespace.branch.hasReleasePermission = result.hasPermission; } }); } function initLinkedNamespace(namespace) { if (!namespace.isPublic || !namespace.isLinkedNamespace || namespace.format != 'properties') { return; } //load public namespace ConfigService.load_public_namespace_for_associated_namespace(scope.env, scope.appId, scope.cluster, namespace.baseInfo.namespaceName) .then(function (result) { var publicNamespace = result; namespace.publicNamespace = publicNamespace; var linkNamespaceItemKeys = []; namespace.items.forEach(function (item) { var key = item.item.key; linkNamespaceItemKeys.push(key); }); publicNamespace.viewItems = []; publicNamespace.items.forEach(function (item) { var key = item.item.key; if (key) { publicNamespace.viewItems.push(item); } item.covered = linkNamespaceItemKeys.indexOf(key) >= 0; if (item.isModified || item.isDeleted) { publicNamespace.isModified = true; } else if (key) { publicNamespace.hasPublishedItem = true; } }); }); } function initNamespaceViewName(namespace) { //namespace view name hide suffix namespace.viewName = namespace.baseInfo.namespaceName.replace(".xml", "").replace( ".properties", "").replace(".json", "").replace(".yml", "") .replace(".yaml", ""); if (!viewType) { if (namespace.isPropertiesFormat) { switchView(namespace, namespace_view_type.TABLE); } else { switchView(namespace, namespace_view_type.TEXT); } } else if (viewType == namespace_view_type.TABLE) { namespace.viewType = namespace_view_type.TABLE; } } function initNamespaceLock(namespace) { NamespaceLockService.get_namespace_lock(scope.appId, scope.env, namespace.baseInfo.clusterName, namespace.baseInfo.namespaceName) .then(function (result) { namespace.lockOwner = result.lockOwner; namespace.isEmergencyPublishAllowed = result.isEmergencyPublishAllowed; }); } function initUserOperateBranchScene(namespace) { var operateBranchStorage = JSON.parse(localStorage.getItem(operate_branch_storage_key)); var namespaceId = [scope.appId, scope.env, scope.cluster, namespace.baseInfo.namespaceName].join( "+"); if (!operateBranchStorage) { operateBranchStorage = {}; } if (!operateBranchStorage[namespaceId]) { operateBranchStorage[namespaceId] = namespace.branchName; } localStorage.setItem(operate_branch_storage_key, JSON.stringify(operateBranchStorage)); switchBranch(operateBranchStorage[namespaceId]); } } function initNamespaceInstancesCount(namespace) { InstanceService.getInstanceCountByNamespace(scope.appId, scope.env, scope.cluster, namespace.baseInfo.namespaceName) .then(function (result) { namespace.instancesCount = result.num; }) } function initOther() { UserService.load_user().then(function (result) { scope.currentUser = result.userId; }); PermissionService.has_assign_user_permission(scope.appId) .then(function (result) { scope.hasAssignUserPermission = result.hasPermission; }, function (result) { }); } function switchBranch(branchName) { if (branchName != 'master') { scope.namespace.branch.displayControl.show = true; initRules(scope.namespace.branch); } else { scope.namespace.displayControl.show = true; } scope.namespace.displayControl.currentOperateBranch = branchName; //save to local storage var operateBranchStorage = JSON.parse(localStorage.getItem(operate_branch_storage_key)); if (!operateBranchStorage) { return; } var namespaceId = [scope.appId, scope.env, scope.cluster, scope.namespace.baseInfo.namespaceName].join( "+"); operateBranchStorage[namespaceId] = branchName; localStorage.setItem(operate_branch_storage_key, JSON.stringify(operateBranchStorage)); } function switchView(namespace, viewType) { namespace.viewType = viewType; if (namespace_view_type.TEXT == viewType) { namespace.text = parseModel2Text(namespace); } else if (namespace_view_type.TABLE == viewType) { } else if (namespace_view_type.HISTORY == viewType) { loadCommitHistory(namespace); } else if (namespace_view_type.INSTANCE == viewType) { refreshInstancesInfo(namespace); } } function switchInstanceViewType(namespace, type) { namespace.instanceViewType = type; loadInstanceInfo(namespace); } function loadCommitHistory(namespace) { if (!namespace.commits) { namespace.commits = []; namespace.commitPage = 0; } var size = 10; CommitService.find_commits(scope.appId, scope.env, namespace.baseInfo.clusterName, namespace.baseInfo.namespaceName, namespace.commitPage, size) .then(function (result) { if (result.length < size) { namespace.hasLoadAllCommit = true; } for (var i = 0; i < result.length; i++) { //to json result[i].changeSets = JSON.parse(result[i].changeSets); namespace.commits.push(result[i]); } namespace.commitPage += 1; }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载修改历史记录出错"); }); } function loadInstanceInfo(namespace) { var size = 20; if (namespace.isBranch) { size = 2000; } var type = namespace.instanceViewType; if (namespace_instance_view_type.LATEST_RELEASE == type) { if (!namespace.latestRelease) { ReleaseService.findLatestActiveRelease(scope.appId, scope.env, namespace.baseInfo.clusterName, namespace.baseInfo.namespaceName) .then(function (result) { namespace.isLatestReleaseLoaded = true; if (!result) { namespace.latestReleaseInstances = {}; namespace.latestReleaseInstances.total = 0; return; } namespace.latestRelease = result; InstanceService.findInstancesByRelease(scope.env, namespace.latestRelease.id, namespace.latestReleaseInstancesPage, size) .then(function (result) { namespace.latestReleaseInstances = result; namespace.latestReleaseInstancesPage++; }) }); } else { InstanceService.findInstancesByRelease(scope.env, namespace.latestRelease.id, namespace.latestReleaseInstancesPage, size) .then(function (result) { if (result && result.content.length) { namespace.latestReleaseInstancesPage++; result.content.forEach(function (instance) { namespace.latestReleaseInstances.content.push( instance); }) } }) } } else if (namespace_instance_view_type.NOT_LATEST_RELEASE == type) { if (!namespace.latestRelease) { return; } InstanceService.findByReleasesNotIn(scope.appId, scope.env, scope.cluster, namespace.baseInfo.namespaceName, namespace.latestRelease.id) .then(function (result) { if (!result || result.length == 0) { return } var groupedInstances = {}, notLatestReleases = []; result.forEach(function (instance) { var configs = instance.configs; if (configs && configs.length > 0) { configs.forEach(function (instanceConfig) { var release = instanceConfig.release; //filter dirty data if (!release) { return; } if (!groupedInstances[release.id]) { groupedInstances[release.id] = []; notLatestReleases.push(release); } groupedInstances[release.id].push(instance); }) } }); namespace.notLatestReleases = notLatestReleases; namespace.notLatestReleaseInstances = groupedInstances; }) } else { InstanceService.findInstancesByNamespace(scope.appId, scope.env, scope.cluster, namespace.baseInfo.namespaceName, '', namespace.allInstancesPage) .then(function (result) { if (result && result.content.length) { namespace.allInstancesPage++; result.content.forEach(function (instance) { namespace.allInstances.push(instance); }) } }); } } function refreshInstancesInfo(namespace) { namespace.instanceViewType = namespace_instance_view_type.LATEST_RELEASE; namespace.latestReleaseInstancesPage = 0; namespace.latestReleaseInstances = []; namespace.latestRelease = undefined; if (!namespace.isBranch) { namespace.notLatestReleaseNames = []; namespace.notLatestReleaseInstances = {}; namespace.allInstancesPage = 0; namespace.allInstances = []; } initNamespaceInstancesCount(namespace); loadInstanceInfo(namespace); } function initRules(branch) { NamespaceBranchService.findBranchGrayRules(scope.appId, scope.env, scope.cluster, scope.namespace.baseInfo.namespaceName, branch.baseInfo.clusterName) .then(function (result) { if (result.appId) { branch.rules = result; } }, function (result) { toastr.error(AppUtil.errorMsg(result), "加载灰度规则出错"); }); } function addRuleItem(branch) { var newRuleItem = { clientAppId: !branch.parentNamespace.isPublic ? branch.baseInfo.appId : '', clientIpList: [], draftIpList: [], isNew: true }; branch.editingRuleItem = newRuleItem; EventManager.emit(EventManager.EventType.EDIT_GRAY_RELEASE_RULES, { branch: branch }); } function editRuleItem(branch, ruleItem) { ruleItem.isNew = false; ruleItem.draftIpList = _.clone(ruleItem.clientIpList); branch.editingRuleItem = ruleItem; EventManager.emit(EventManager.EventType.EDIT_GRAY_RELEASE_RULES, { branch: branch }); } function deleteRuleItem(branch, ruleItem) { branch.rules.ruleItems.forEach(function (item, index) { if (item.clientAppId == ruleItem.clientAppId) { branch.rules.ruleItems.splice(index, 1); toastr.success("删除成功"); } }); useRules(branch); } function useRules(branch) { NamespaceBranchService.updateBranchGrayRules(scope.appId, scope.env, scope.cluster, scope.namespace.baseInfo.namespaceName, branch.baseInfo.clusterName, branch.rules ) .then(function (result) { toastr.success('灰度规则更新成功'); //show tips if branch has not release configs if (branch.itemModifiedCnt) { AppUtil.showModal("#updateRuleTips"); } setTimeout(function () { refreshInstancesInfo(branch); }, 1500); }, function (result) { AppUtil.showErrorMsg(result, "灰度规则更新失败"); }) } function toggleTextEditStatus(namespace) { if (!scope.lockCheck(namespace)) { return; } namespace.isTextEditing = !namespace.isTextEditing; if (namespace.isTextEditing) {//切换为编辑状态 namespace.commited = false; namespace.backupText = namespace.text; namespace.editText = parseModel2Text(namespace); } else { if (!namespace.commited) {//取消编辑,则复原 namespace.text = namespace.backupText; } } } function goToSyncPage(namespace) { if (!scope.lockCheck(namespace)) { return false; } $window.location.href = "config/sync.html?#/appid=" + scope.appId + "&env=" + scope.env + "&clusterName=" + scope.cluster + "&namespaceName=" + namespace.baseInfo.namespaceName; } function modifyByText(namespace) { var model = { configText: namespace.editText, namespaceId: namespace.baseInfo.id, format: namespace.format }; //prevent repeat submit if (namespace.commitChangeBtnDisabled) { return; } namespace.commitChangeBtnDisabled = true; ConfigService.modify_items(scope.appId, scope.env, scope.cluster, namespace.baseInfo.namespaceName, model).then( function (result) { toastr.success("更新成功, 如需生效请发布"); //refresh all namespace items EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: namespace }); return true; }, function (result) { toastr.error(AppUtil.errorMsg(result), "更新失败"); namespace.commitChangeBtnDisabled = false; return false; } ); namespace.commited = true; toggleTextEditStatus(namespace); } function goToParentAppConfigPage(namespace) { $window.location.href = "/config.html?#/appid=" + namespace.parentAppId; $window.location.reload(); } function parseModel2Text(namespace) { if (namespace.items.length == 0) { namespace.itemCnt = 0; return ""; } //文件模式 if (!namespace.isPropertiesFormat) { return parseNotPropertiesText(namespace); } else { return parsePropertiesText(namespace); } } function parseNotPropertiesText(namespace) { var text = namespace.items[0].item.value; var lineNum = text.split("\n").length; namespace.itemCnt = lineNum; return text; } function parsePropertiesText(namespace) { var result = ""; var itemCnt = 0; namespace.items.forEach(function (item) { //deleted key if (!item.item.dataChangeLastModifiedBy) { return; } if (item.item.key) { //use string \n to display as new line var itemValue = item.item.value.replace(/\n/g, "\\n"); result += item.item.key + " = " + itemValue + "\n"; } else { result += item.item.comment + "\n"; } itemCnt++; }); namespace.itemCnt = itemCnt; return result; } function toggleItemSearchInput(namespace) { namespace.displayControl.showSearchInput = !namespace.displayControl.showSearchInput; } function searchItems(namespace) { var searchKey = namespace.searchKey.toLowerCase(); var items = []; namespace.items.forEach(function (item) { var key = item.item.key; if (key && key.toLowerCase().indexOf(searchKey) >= 0) { items.push(item); } }); namespace.viewItems = items; } //normal release and gray release function publish(namespace) { if (!namespace.hasReleasePermission) { AppUtil.showModal('#releaseNoPermissionDialog'); return; } else if (namespace.lockOwner && scope.user == namespace.lockOwner) { //can not publish if config modified by himself EventManager.emit(EventManager.EventType.PUBLISH_DENY, { namespace: namespace, mergeAndPublish: false }); return; } if (namespace.isBranch) { namespace.mergeAndPublish = false; } EventManager.emit(EventManager.EventType.PUBLISH_NAMESPACE, { namespace: namespace }); } function mergeAndPublish(branch) { var parentNamespace = branch.parentNamespace; if (!parentNamespace.hasReleasePermission) { AppUtil.showModal('#releaseNoPermissionDialog'); } else if (parentNamespace.itemModifiedCnt > 0) { AppUtil.showModal('#mergeAndReleaseDenyDialog'); } else if (branch.lockOwner && scope.user == branch.lockOwner) { EventManager.emit(EventManager.EventType.PUBLISH_DENY, { namespace: branch, mergeAndPublish: true }); } else { EventManager.emit(EventManager.EventType.MERGE_AND_PUBLISH_NAMESPACE, {branch: branch}); } } function rollback(namespace) { EventManager.emit(EventManager.EventType.PRE_ROLLBACK_NAMESPACE, {namespace: namespace}); } function deleteNamespace(namespace) { EventManager.emit(EventManager.EventType.PRE_DELETE_NAMESPACE, {namespace: namespace}); } //theme: https://github.com/ajaxorg/ace-builds/tree/ba3b91e04a5aa559d56ac70964f9054baa0f4caf/src-min scope.aceConfig = { $blockScrolling: Infinity, showPrintMargin: false, theme: 'eclipse', mode: scope.namespace.format === 'yml' ? 'yaml' : scope.namespace.format, onLoad: function (_editor) { _editor.$blockScrolling = Infinity; _editor.setOptions({ fontSize: 13, minLines: 10, maxLines: 20 }) } }; setTimeout(function () { scope.namespace.show = true; }, 70); } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/publish-deny-modal-directive.js ================================================ directive_module.directive('publishdenymodal', publishDenyDirective); function publishDenyDirective(AppUtil, EventManager) { return { restrict: 'E', templateUrl: '../../views/component/publish-deny-modal.html', transclude: true, replace: true, scope: { env: "=" }, link: function (scope) { var MODAL_ID = "#publishDenyModal"; EventManager.subscribe(EventManager.EventType.PUBLISH_DENY, function (context) { scope.toReleaseNamespace = context.namespace; scope.mergeAndPublish = !!context.mergeAndPublish; AppUtil.showModal(MODAL_ID); }); scope.emergencyPublish = emergencyPublish; function emergencyPublish() { AppUtil.hideModal(MODAL_ID); EventManager.emit(EventManager.EventType.EMERGENCY_PUBLISH, { mergeAndPublish: scope.mergeAndPublish, namespace: scope.toReleaseNamespace }); } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/release-modal-directive.js ================================================ directive_module.directive('releasemodal', releaseModalDirective); function releaseModalDirective(toastr, AppUtil, EventManager, ReleaseService, NamespaceBranchService) { return { restrict: 'E', templateUrl: '../../views/component/release-modal.html', transclude: true, replace: true, scope: { appId: '=', env: '=', cluster: '=' }, link: function (scope) { scope.switchReleaseChangeViewType = switchReleaseChangeViewType; scope.release = release; scope.releaseBtnDisabled = false; scope.releaseChangeViewType = 'change'; scope.releaseComment = ''; scope.isEmergencyPublish = false; EventManager.subscribe(EventManager.EventType.PUBLISH_NAMESPACE, function (context) { var namespace = context.namespace; scope.toReleaseNamespace = context.namespace; scope.isEmergencyPublish = !!context.isEmergencyPublish; var date = new Date().Format("yyyyMMddhhmmss"); if (namespace.mergeAndPublish) { namespace.releaseTitle = date + "-gray-release-merge-to-master"; } else if (namespace.isBranch) { namespace.releaseTitle = date + "-gray"; } else { namespace.releaseTitle = date + "-release"; } AppUtil.showModal('#releaseModal'); }); function release() { if (scope.toReleaseNamespace.mergeAndPublish) { mergeAndPublish(); } else if (scope.toReleaseNamespace.isBranch) { grayPublish(); } else { publish(); } } function publish() { scope.releaseBtnDisabled = true; ReleaseService.publish(scope.appId, scope.env, scope.toReleaseNamespace.baseInfo.clusterName, scope.toReleaseNamespace.baseInfo.namespaceName, scope.toReleaseNamespace.releaseTitle, scope.releaseComment, scope.isEmergencyPublish).then( function (result) { AppUtil.hideModal('#releaseModal'); toastr.success("发布成功"); scope.releaseBtnDisabled = false; EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: scope.toReleaseNamespace }) }, function (result) { scope.releaseBtnDisabled = false; toastr.error(AppUtil.errorMsg(result), "发布失败"); } ); } function grayPublish() { scope.releaseBtnDisabled = true; ReleaseService.grayPublish(scope.appId, scope.env, scope.toReleaseNamespace.parentNamespace.baseInfo.clusterName, scope.toReleaseNamespace.baseInfo.namespaceName, scope.toReleaseNamespace.baseInfo.clusterName, scope.toReleaseNamespace.releaseTitle, scope.releaseComment, scope.isEmergencyPublish).then( function (result) { AppUtil.hideModal('#releaseModal'); toastr.success("灰度发布成功"); scope.releaseBtnDisabled = false; //refresh item status scope.toReleaseNamespace.branchItems.forEach(function (item, index) { if (item.isDeleted) { scope.toReleaseNamespace.branchItems.splice(index, 1); } else { item.isModified = false; } }); //reset namespace status scope.toReleaseNamespace.itemModifiedCnt = 0; scope.toReleaseNamespace.lockOwner = undefined; //check rules if (!scope.toReleaseNamespace.rules || !scope.toReleaseNamespace.rules.ruleItems || !scope.toReleaseNamespace.rules.ruleItems.length) { scope.toReleaseNamespace.viewType = 'rule'; AppUtil.showModal('#grayReleaseWithoutRulesTips'); } }, function (result) { scope.releaseBtnDisabled = false; toastr.error(AppUtil.errorMsg(result), "灰度发布失败"); }); } function mergeAndPublish() { NamespaceBranchService.mergeAndReleaseBranch(scope.appId, scope.env, scope.cluster, scope.toReleaseNamespace.baseInfo.namespaceName, scope.toReleaseNamespace.baseInfo.clusterName, scope.toReleaseNamespace.releaseTitle, scope.releaseComment, scope.isEmergencyPublish, scope.toReleaseNamespace.mergeAfterDeleteBranch) .then(function (result) { toastr.success("全量发布成功"); EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace: scope.toReleaseNamespace }) }, function (result) { toastr.error(AppUtil.errorMsg(result), "全量发布失败"); }); AppUtil.hideModal('#releaseModal'); } function switchReleaseChangeViewType(type) { scope.releaseChangeViewType = type; } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/rollback-modal-directive.js ================================================ directive_module.directive('rollbackmodal', rollbackModalDirective); function rollbackModalDirective(AppUtil, EventManager, ReleaseService, toastr) { return { restrict: 'E', templateUrl: '../../views/component/rollback-modal.html', transclude: true, replace: true, scope: { appId: '=', env: '=', cluster: '=' }, link: function (scope) { scope.showRollbackAlertDialog = showRollbackAlertDialog; EventManager.subscribe(EventManager.EventType.PRE_ROLLBACK_NAMESPACE, function (context) { preRollback(context.namespace); }); EventManager.subscribe(EventManager.EventType.ROLLBACK_NAMESPACE, function (context) { rollback(); }); function preRollback(namespace) { scope.toRollbackNamespace = namespace; //load latest two active releases ReleaseService.findActiveReleases(scope.appId, scope.env, scope.cluster, scope.toRollbackNamespace.baseInfo.namespaceName, 0, 2) .then(function (result) { if (result.length <= 1) { toastr.error("没有可以回滚的发布历史"); return; } scope.toRollbackNamespace.firstRelease = result[0]; scope.toRollbackNamespace.secondRelease = result[1]; ReleaseService.compare(scope.env, scope.toRollbackNamespace.firstRelease.id, scope.toRollbackNamespace.secondRelease.id) .then(function (result) { scope.toRollbackNamespace.releaseCompareResult = result.changes; AppUtil.showModal('#rollbackModal'); }) }); } function rollback() { scope.toRollbackNamespace.rollbackBtnDisabled = true; ReleaseService.rollback(scope.env, scope.toRollbackNamespace.firstRelease.id) .then(function (result) { toastr.success("回滚成功"); scope.toRollbackNamespace.rollbackBtnDisabled = false; AppUtil.hideModal('#rollbackModal'); EventManager.emit(EventManager.EventType.REFRESH_NAMESPACE, { namespace:scope.toRollbackNamespace }); }, function (result) { scope.toRollbackNamespace.rollbackBtnDisabled = false; AppUtil.showErrorMsg(result, "回滚失败"); }) } function showRollbackAlertDialog() { AppUtil.hideModal("#rollbackModal"); AppUtil.showModal("#rollbackAlertDialog"); } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/directive/show-text-modal-directive.js ================================================ directive_module.directive('showtextmodal', showTextModalDirective); function showTextModalDirective() { return { restrict: 'E', templateUrl: '../../views/component/show-text-modal.html', transclude: true, replace: true, scope: { text: '=' }, link: function (scope) { scope.$watch('text', init); function init() { scope.jsonObject = undefined; if (isJsonText(scope.text)) { scope.jsonObject = JSON.parse(scope.text); } } function isJsonText(text) { try { JSON.parse(text); } catch (e) { return false; } return true; } } } } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/AppService.js ================================================ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { var app_resource = $resource('/apps/:appId', {}, { find_apps: { method: 'GET', isArray: true, url: '/apps' }, find_app_by_owner: { method: 'GET', isArray: true, url: '/apps/by-owner' }, load_navtree: { method: 'GET', isArray: false, url: '/apps/:appId/navtree' }, load_app: { method: 'GET', isArray: false }, create_app: { method: 'POST', url: '/apps' }, update_app: { method: 'PUT', url: '/apps/:appId' }, create_app_remote: { method: 'POST', url: '/apps/envs/:env' }, find_miss_envs: { method: 'GET', url: '/apps/:appId/miss_envs' } }); return { find_apps: function (appIds) { if (!appIds) { appIds = ''; } var d = $q.defer(); app_resource.find_apps({appIds: appIds}, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, find_app_by_owner: function (owner, page, size) { var d = $q.defer(); app_resource.find_app_by_owner({ owner: owner, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, load_nav_tree: function (appId) { var d = $q.defer(); app_resource.load_navtree({ appId: appId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, create: function (app) { var d = $q.defer(); app_resource.create_app({}, app, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, update: function (app) { var d = $q.defer(); app_resource.update_app({ appId: app.appId }, app, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, create_remote: function (env, app) { var d = $q.defer(); app_resource.create_app_remote({env: env}, app, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, load: function (appId) { var d = $q.defer(); app_resource.load_app({ appId: appId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, find_miss_envs: function (appId) { var d = $q.defer(); app_resource.find_miss_envs({ appId: appId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ClusterService.js ================================================ appService.service('ClusterService', ['$resource', '$q', function ($resource, $q) { var cluster_resource = $resource('', {}, { create_cluster: { method: 'POST', url: 'apps/:appId/envs/:env/clusters' } }); return { create_cluster: function (appId, env, cluster) { var d = $q.defer(); cluster_resource.create_cluster({ appId: appId, env: env }, cluster, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/CommitService.js ================================================ appService.service('CommitService', ['$resource', '$q', function ($resource, $q) { var commit_resource = $resource('', {}, { find_commits: { method: 'GET', isArray: true, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/commits?page=:page' } }); return { find_commits: function (appId, env, clusterName, namespaceName, page, size) { var d = $q.defer(); commit_resource.find_commits({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/CommonService.js ================================================ appService.service('CommonService', ['$resource', '$q', 'AppUtil', function ($resource, $q, AppUtil) { var resource = $resource('', {}, { page_setting: { method: 'GET', isArray: false, url: '/page-settings' } }); return { getPageSetting: function () { return AppUtil.ajax(resource.page_setting, {}); } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ConfigService.js ================================================ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) { var config_source = $resource("", {}, { load_namespace: { method: 'GET', isArray: false, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName' }, load_public_namespace_for_associated_namespace: { method: 'GET', isArray: false, url: '/envs/:env/apps/:appId/clusters/:clusterName/namespaces/:namespaceName/associated-public-namespace' }, load_all_namespaces: { method: 'GET', isArray: true, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces' }, find_items: { method: 'GET', isArray: true, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items' }, modify_items: { method: 'PUT', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items' }, diff: { method: 'POST', url: '/namespaces/:namespaceName/diff', isArray: true }, sync_item: { method: 'PUT', url: '/apps/:appId/namespaces/:namespaceName/items', isArray: false }, create_item: { method: 'POST', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/item' }, update_item: { method: 'PUT', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/item' }, delete_item: { method: 'DELETE', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items/:itemId' } }); return { load_namespace: function (appId, env, clusterName, namespaceName) { var d = $q.defer(); config_source.load_namespace({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, load_public_namespace_for_associated_namespace: function (env, appId, clusterName, namespaceName) { var d = $q.defer(); config_source.load_public_namespace_for_associated_namespace({ env: env, appId: appId, clusterName: clusterName, namespaceName: namespaceName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, load_all_namespaces: function (appId, env, clusterName) { var d = $q.defer(); config_source.load_all_namespaces({ appId: appId, env: env, clusterName: clusterName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, find_items: function (appId, env, clusterName, namespaceName, orderBy) { var d = $q.defer(); config_source.find_items({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, orderBy: orderBy }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, modify_items: function (appId, env, clusterName, namespaceName, model) { var d = $q.defer(); config_source.modify_items({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, model, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, diff: function (namespaceName, sourceData) { var d = $q.defer(); config_source.diff({ namespaceName: namespaceName }, sourceData, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, sync_items: function (appId, namespaceName, sourceData) { var d = $q.defer(); config_source.sync_item({ appId: appId, namespaceName: namespaceName }, sourceData, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, create_item: function (appId, env, clusterName, namespaceName, item) { var d = $q.defer(); config_source.create_item({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, item, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, update_item: function (appId, env, clusterName, namespaceName, item) { var d = $q.defer(); config_source.update_item({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, item, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, delete_item: function (appId, env, clusterName, namespaceName, itemId) { var d = $q.defer(); config_source.delete_item({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, itemId: itemId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ConsumerService.js ================================================ appService.service('ConsumerService', ['$resource', '$q', 'AppUtil', function ($resource, $q, AppUtil) { var resource = $resource('', {}, { create_consumer: { method: 'POST', isArray: false, url: '/consumers' }, get_consumer_token_by_appId: { method: 'GET', isArray: false, url: '/consumers/by-appId' }, assign_role_to_consumer: { method: 'POST', isArray: true, url: '/consumers/:token/assign-role' } }); return { createConsumer: function (consumer) { return AppUtil.ajax(resource.create_consumer, {}, consumer); }, getConsumerTokenByAppId: function (appId) { return AppUtil.ajax(resource.get_consumer_token_by_appId, { appId: appId }); }, assignRoleToConsumer: function (token, type, appId, namespaceName) { return AppUtil.ajax(resource.assign_role_to_consumer, { token: token, type: type }, { appId: appId, namespaceName: namespaceName } ) } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/EnvService.js ================================================ appService.service('EnvService', ['$resource', '$q', function ($resource, $q) { var env_resource = $resource('/envs', {}, { find_all_envs:{ method: 'GET', isArray: true, url:'/envs' } }); return { find_all_envs: function () { var d = $q.defer(); env_resource.find_all_envs({ }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/EventManager.js ================================================ appService.service('EventManager', [function () { /** * subscribe EventType with any object * @type {string} */ var ALL_OBJECT = '*'; var eventRegistry = {}; /** * * @param eventType acquired. event type * @param context optional. event execute context * @param objectId optional. subscribe object id and empty value means subscribe event type with all object */ function emit(eventType, context, objectId) { if (!eventType) { return; } if (!eventRegistry[eventType]) { return; } if (!context) { context = {}; } if (!objectId) { objectId = ALL_OBJECT; } var subscribers = eventRegistry[eventType][objectId]; emitEventToSubscribers(subscribers, context); if (objectId == ALL_OBJECT) { return; } //emit event to subscriber which subscribed all object subscribers = eventRegistry[eventType][ALL_OBJECT]; emitEventToSubscribers(subscribers); } function emitEventToSubscribers(subscribers, context) { if (subscribers) { subscribers.forEach(function (subscriber) { subscriber.callback(context); }) } } /** * * @param eventType acquired. event type * @param callback acquired. callback function when event emitted * @param objectId optional. subscribe object id and empty value means subscribe event type with all object */ function subscribe(eventType, callback, objectId) { if (!eventType || !callback) { return; } if (!objectId) { objectId = ALL_OBJECT; } var subscribedObjects = eventRegistry[eventType]; if (!subscribedObjects) { subscribedObjects = {}; eventRegistry[eventType] = subscribedObjects; } var callbacks = subscribedObjects[objectId]; if (!callbacks) { callbacks = []; subscribedObjects[objectId] = callbacks; } var subscriber = { id: Math.random() * Math.random(), callback: callback }; callbacks.push(subscriber); return subscriber.id; } /** * * @param eventType acquired. event type * @param subscriberId acquired. subscriber id which get from event manager when subscribe * @param objectId optional. subscribe object id and empty value means subscribe event type with all object */ function unsubscribe(eventType, subscriberId, objectId) { if (!eventType || !subscriberId) { return; } if (!objectId) { objectId = ALL_OBJECT; } var subscribers = eventRegistry[eventType] ? eventRegistry[eventType][objectId] : undefined; if (!subscribers) { return; } subscribers.forEach(function (subscriber, index) { if (subscriber.id == subscriberId) { subscribers.splice(index, 1); } }) } return { ALL_OBJECT: ALL_OBJECT, emit: emit, subscribe: subscribe, unsubscribe: unsubscribe, EventType: { REFRESH_NAMESPACE: 'refresh_namespace', PUBLISH_NAMESPACE: 'pre_public_namespace', MERGE_AND_PUBLISH_NAMESPACE: 'merge_and_publish_namespace', PRE_ROLLBACK_NAMESPACE: 'pre_rollback_namespace', ROLLBACK_NAMESPACE: 'rollback_namespace', EDIT_GRAY_RELEASE_RULES: 'edit_gray_release_rules', UPDATE_GRAY_RELEASE_RULES: 'update_gray_release_rules', PUBLISH_DENY: 'publish_deny', EMERGENCY_PUBLISH: 'emergency_publish', PRE_DELETE_NAMESPACE: 'pre_delete_namespace', DELETE_NAMESPACE: 'delete_namespace', DELETE_NAMESPACE_FAILED: 'delete_namespace_failed' } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/FavoriteService.js ================================================ appService.service('FavoriteService', ['$resource', '$q', function ($resource, $q) { var resource = $resource('', {}, { find_favorites: { method: 'GET', url: '/favorites', isArray: true }, add_favorite: { method: 'POST', url: '/favorites' }, delete_favorite: { method: 'DELETE', url: '/favorites/:favoriteId' }, to_top: { method: 'PUT', url: '/favorites/:favoriteId' } }); return { findFavorites: function (userId, appId, page, size) { var d = $q.defer(); resource.find_favorites({ userId: userId, appId: appId, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, addFavorite: function (favorite) { var d = $q.defer(); resource.add_favorite({}, favorite, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, deleteFavorite: function (favoriteId) { var d = $q.defer(); resource.delete_favorite({ favoriteId: favoriteId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, toTop: function (favoriteId) { var d = $q.defer(); resource.to_top({ favoriteId: favoriteId }, {}, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/InstanceService.js ================================================ appService.service('InstanceService', ['$resource', '$q', function ($resource, $q) { var resource = $resource('', {}, { find_instances_by_release: { method: 'GET', url: '/envs/:env/instances/by-release' }, find_instances_by_namespace: { method: 'GET', isArray: false, url: '/envs/:env/instances/by-namespace' }, find_by_releases_not_in: { method: 'GET', isArray: true, url: '/envs/:env/instances/by-namespace-and-releases-not-in' }, get_instance_count_by_namespace: { method: 'GET', isArray: false, url: "envs/:env/instances/by-namespace/count" } }); var instanceService = { findInstancesByRelease: function (env, releaseId, page, size) { if (!size) { size = 20; } var d = $q.defer(); resource.find_instances_by_release({ env: env, releaseId: releaseId, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, findInstancesByNamespace: function (appId, env, clusterName, namespaceName, instanceAppId, page, size) { if (!size) { size = 20; } var d = $q.defer(); var instanceAppIdRequest = instanceAppId; instanceService.lastInstanceAppIdRequest = instanceAppIdRequest; resource.find_instances_by_namespace({ env: env, appId: appId, clusterName: clusterName, namespaceName: namespaceName, instanceAppId: instanceAppId, page: page, size: size }, function (result) { if (instanceAppIdRequest != instanceService.lastInstanceAppIdRequest) { return; } d.resolve(result); }, function (result) { if (instanceAppIdRequest != instanceService.lastInstanceAppIdRequest) { return; } d.reject(result); }); return d.promise; }, findByReleasesNotIn: function (appId, env, clusterName, namespaceName, releaseIds) { var d = $q.defer(); resource.find_by_releases_not_in({ env: env, appId: appId, clusterName: clusterName, namespaceName: namespaceName, releaseIds: releaseIds }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, getInstanceCountByNamespace: function (appId, env, clusterName, namespaceName) { var d = $q.defer(); resource.get_instance_count_by_namespace({ env: env, appId: appId, clusterName: clusterName, namespaceName: namespaceName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } }; return instanceService; }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/NamespaceBranchService.js ================================================ appService.service('NamespaceBranchService', ['$resource', '$q', function ($resource, $q) { var resource = $resource('', {}, { find_namespace_branch: { method: 'GET', isArray: false, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches' }, create_branch: { method: 'POST', isArray: false, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches' }, delete_branch: { method: 'DELETE', isArray: false, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName' }, merge_and_release_branch: { method: 'POST', isArray: false, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/merge' }, find_branch_gray_rules: { method: 'GET', isArray: false, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/rules' }, update_branch_gray_rules: { method: 'PUT', isArray: false, url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/rules' } }); function find_namespace_branch(appId, env, clusterName, namespaceName) { var d = $q.defer(); resource.find_namespace_branch({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function create_branch(appId, env, clusterName, namespaceName) { var d = $q.defer(); resource.create_branch({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, {}, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function delete_branch(appId, env, clusterName, namespaceName, branchName) { var d = $q.defer(); resource.delete_branch({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, branchName: branchName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function merge_and_release_branch(appId, env, clusterName, namespaceName, branchName, title, comment, isEmergencyPublish, deleteBranch) { var d = $q.defer(); resource.merge_and_release_branch({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, branchName: branchName, deleteBranch:deleteBranch }, { releaseTitle: title, releaseComment: comment, isEmergencyPublish: isEmergencyPublish }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function find_branch_gray_rules(appId, env, clusterName, namespaceName, branchName) { var d = $q.defer(); resource.find_branch_gray_rules({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, branchName: branchName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function update_branch_gray_rules(appId, env, clusterName, namespaceName, branchName, newRules) { var d = $q.defer(); resource.update_branch_gray_rules({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, branchName: branchName }, newRules, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } return { findNamespaceBranch: find_namespace_branch, createBranch: create_branch, deleteBranch: delete_branch, mergeAndReleaseBranch: merge_and_release_branch, findBranchGrayRules: find_branch_gray_rules, updateBranchGrayRules: update_branch_gray_rules } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js ================================================ appService.service('NamespaceLockService', ['$resource', '$q', function ($resource, $q) { var resource = $resource('', {}, { get_namespace_lock: { method: 'GET', url: 'apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/lock-info' } }); return { get_namespace_lock: function (appId, env, clusterName, namespaceName) { var d = $q.defer(); resource.get_namespace_lock({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/NamespaceService.js ================================================ appService.service("NamespaceService", ['$resource', '$q', function ($resource, $q) { var namespace_source = $resource("", {}, { find_public_namespaces: { method: 'GET', isArray: true, url: '/appnamespaces/public' }, createNamespace: { method: 'POST', url: '/apps/:appId/namespaces', isArray: false }, createAppNamespace: { method: 'POST', url: '/apps/:appId/appnamespaces', isArray: false }, getNamespacePublishInfo: { method: 'GET', url: '/apps/:appId/namespaces/publish_info' }, deleteNamespace: { method: 'DELETE', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName' }, getPublicAppNamespaceAllNamespaces: { method: 'GET', url: '/envs/:env/appnamespaces/:publicNamespaceName/namespaces', isArray: true } }); function find_public_namespaces() { var d = $q.defer(); namespace_source.find_public_namespaces({}, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function createNamespace(appId, namespaceCreationModel) { var d = $q.defer(); namespace_source.createNamespace({ appId: appId }, namespaceCreationModel, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function createAppNamespace(appId, appnamespace) { var d = $q.defer(); namespace_source.createAppNamespace({ appId: appId }, appnamespace, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function getNamespacePublishInfo(appId) { var d = $q.defer(); namespace_source.getNamespacePublishInfo({ appId: appId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function deleteNamespace(appId, env, clusterName, namespaceName) { var d = $q.defer(); namespace_source.deleteNamespace({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function getPublicAppNamespaceAllNamespaces(env, publicNamespaceName, page, size) { var d = $q.defer(); namespace_source.getPublicAppNamespaceAllNamespaces({ env: env, publicNamespaceName: publicNamespaceName, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } return { find_public_namespaces: find_public_namespaces, createNamespace: createNamespace, createAppNamespace: createAppNamespace, getNamespacePublishInfo: getNamespacePublishInfo, deleteNamespace: deleteNamespace, getPublicAppNamespaceAllNamespaces: getPublicAppNamespaceAllNamespaces } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/OrganizationService.js ================================================ appService.service("OrganizationService", ['$resource', '$q', function ($resource, $q) { var organization_source = $resource("", {}, { find_organizations: { method: 'GET', isArray: true, url: '/organizations' } }); return { find_organizations: function () { var d = $q.defer(); organization_source.find_organizations({}, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/PermissionService.js ================================================ appService.service('PermissionService', ['$resource', '$q', function ($resource, $q) { var permission_resource = $resource('', {}, { has_app_permission: { method: 'GET', url: '/apps/:appId/permissions/:permissionType' }, has_namespace_permission: { method: 'GET', url: '/apps/:appId/namespaces/:namespaceName/permissions/:permissionType' }, has_root_permission:{ method: 'GET', url: '/permissions/root' }, get_namespace_role_users: { method: 'GET', url: '/apps/:appId/namespaces/:namespaceName/role_users' }, assign_namespace_role_to_user: { method: 'POST', url: '/apps/:appId/namespaces/:namespaceName/roles/:roleType' }, remove_namespace_role_from_user: { method: 'DELETE', url: '/apps/:appId/namespaces/:namespaceName/roles/:roleType?user=:user' }, get_app_role_users: { method: 'GET', url: '/apps/:appId/role_users' }, assign_app_role_to_user: { method: 'POST', url: '/apps/:appId/roles/:roleType' }, remove_app_role_from_user: { method: 'DELETE', url: '/apps/:appId/roles/:roleType?user=:user' } }); function hasAppPermission(appId, permissionType) { var d = $q.defer(); permission_resource.has_app_permission({ appId: appId, permissionType: permissionType }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function hasNamespacePermission(appId, namespaceName, permissionType) { var d = $q.defer(); permission_resource.has_namespace_permission({ appId: appId, namespaceName: namespaceName, permissionType: permissionType }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function assignNamespaceRoleToUser(appId, namespaceName, roleType, user) { var d = $q.defer(); permission_resource.assign_namespace_role_to_user({ appId: appId, namespaceName: namespaceName, roleType: roleType }, user, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function removeRoleFromUser(appId, namespaceName, roleType, user) { var d = $q.defer(); permission_resource.remove_namespace_role_from_user({ appId: appId, namespaceName: namespaceName, roleType: roleType, user: user }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } return { has_create_namespace_permission: function (appId) { return hasAppPermission(appId, 'CreateNamespace'); }, has_create_cluster_permission: function (appId) { return hasAppPermission(appId, 'CreateCluster'); }, has_assign_user_permission: function (appId) { return hasAppPermission(appId, 'AssignRole'); }, has_modify_namespace_permission: function (appId, namespaceName) { return hasNamespacePermission(appId, namespaceName, 'ModifyNamespace'); }, has_release_namespace_permission: function (appId, namespaceName) { return hasNamespacePermission(appId, namespaceName, 'ReleaseNamespace'); }, has_root_permission: function () { var d = $q.defer(); permission_resource.has_root_permission({ }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, assign_modify_namespace_role: function (appId, namespaceName, user) { return assignNamespaceRoleToUser(appId, namespaceName, 'ModifyNamespace', user); }, assign_release_namespace_role: function (appId, namespaceName, user) { return assignNamespaceRoleToUser(appId, namespaceName, 'ReleaseNamespace', user); }, remove_modify_namespace_role: function (appId, namespaceName, user) { return removeRoleFromUser(appId, namespaceName, 'ModifyNamespace', user); }, remove_release_namespace_role: function (appId, namespaceName, user) { return removeRoleFromUser(appId, namespaceName, 'ReleaseNamespace', user); }, get_namespace_role_users: function (appId, namespaceName) { var d = $q.defer(); permission_resource.get_namespace_role_users({ appId: appId, namespaceName: namespaceName, }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, get_app_role_users: function (appId) { var d = $q.defer(); permission_resource.get_app_role_users({ appId: appId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, assign_master_role: function (appId, user) { var d = $q.defer(); permission_resource.assign_app_role_to_user({ appId: appId, roleType: 'Master' }, user, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, remove_master_role: function (appId, user) { var d = $q.defer(); permission_resource.remove_app_role_from_user({ appId: appId, roleType: 'Master', user: user }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ReleaseHistoryService.js ================================================ appService.service('ReleaseHistoryService', ['$resource', '$q', function ($resource, $q) { var resource = $resource('', {}, { find_release_history_by_namespace: { method: 'GET', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases/histories', isArray: true } }); function findReleaseHistoryByNamespace(appId, env, clusterName, namespaceName, page, size) { var d = $q.defer(); resource.find_release_history_by_namespace({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } return { findReleaseHistoryByNamespace: findReleaseHistoryByNamespace } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ReleaseService.js ================================================ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q) { var resource = $resource('', {}, { find_all_releases: { method: 'GET', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases/all', isArray: true }, find_active_releases: { method: 'GET', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases/active', isArray: true }, compare: { method: 'GET', url: '/envs/:env/releases/compare' }, release: { method: 'POST', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases' }, gray_release: { method: 'POST', url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/branches/:branchName/releases' }, rollback: { method: 'PUT', url: "envs/:env/releases/:releaseId/rollback" } }); function createRelease(appId, env, clusterName, namespaceName, releaseTitle, comment, isEmergencyPublish) { var d = $q.defer(); resource.release({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName }, { releaseTitle: releaseTitle, releaseComment: comment, isEmergencyPublish: isEmergencyPublish }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function createGrayRelease(appId, env, clusterName, namespaceName, branchName, releaseTitle, comment, isEmergencyPublish) { var d = $q.defer(); resource.gray_release({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, branchName: branchName }, { releaseTitle: releaseTitle, releaseComment: comment, isEmergencyPublish: isEmergencyPublish }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function findAllReleases(appId, env, clusterName, namespaceName, page, size) { var d = $q.defer(); resource.find_all_releases({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function findActiveReleases(appId, env, clusterName, namespaceName, page, size) { var d = $q.defer(); resource.find_active_releases({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, page: page, size: size }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function findLatestActiveRelease(appId, env, clusterName, namespaceName) { var d = $q.defer(); resource.find_active_releases({ appId: appId, env: env, clusterName: clusterName, namespaceName: namespaceName, page: 0, size: 1 }, function (result) { if (result && result.length) { d.resolve(result[0]); } d.resolve(undefined); }, function (result) { d.reject(result); }); return d.promise; } function compare(env, baseReleaseId, toCompareReleaseId) { var d = $q.defer(); resource.compare({ env: env, baseReleaseId: baseReleaseId, toCompareReleaseId: toCompareReleaseId }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } function rollback(env, releaseId) { var d = $q.defer(); resource.rollback({ env: env, releaseId: releaseId }, {}, function (result) { d.resolve(result); }, function (result) { d.reject(result); } ); return d.promise; } return { publish: createRelease, grayPublish: createGrayRelease, findAllRelease: findAllReleases, findActiveReleases: findActiveReleases, findLatestActiveRelease: findLatestActiveRelease, compare: compare, rollback: rollback } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/ServerConfigService.js ================================================ appService.service('ServerConfigService', ['$resource', '$q', function ($resource, $q) { var server_config_resource = $resource('', {}, { create_server_config: { method: 'POST', url: '/server/config' } }); return { create: function (serverConfig) { var d = $q.defer(); server_config_resource.create_server_config({}, serverConfig, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/services/UserService.js ================================================ appService.service('UserService', ['$resource', '$q', function ($resource, $q) { var user_resource = $resource('', {}, { load_user: { method: 'GET', url: '/user' }, find_users: { method: 'GET', url: '/users' }, create_or_update_user: { method: 'POST', url: '/users' } }); return { load_user: function () { var finished = false; var d = $q.defer(); user_resource.load_user({}, function (result) { finished = true; d.resolve(result); }, function (result) { finished = true; d.reject(result); }); return d.promise; }, find_users: function (keyword) { var d = $q.defer(); user_resource.find_users({ keyword: keyword }, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; }, createOrUpdateUser: function (user) { var d = $q.defer(); user_resource.create_or_update_user({}, user, function (result) { d.resolve(result); }, function (result) { d.reject(result); }); return d.promise; } } }]); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/scripts/valdr.js ================================================ app_module.config(appValdr); setting_module.config(appValdr); function appValdr(valdrProvider) { valdrProvider.addConstraints({ 'App': { 'appId': { 'size': { 'max': 32, 'message': 'AppId长度不能多于32个字符' }, 'required': { 'message': 'AppId不能为空' } }, 'appName': { 'size': { 'max': 128, 'message': '应用名称长度不能多于128个字符' }, 'required': { 'message': '应用名称不能为空' } } } }) } cluster_module.config(function (valdrProvider) { valdrProvider.addConstraints({ 'Cluster': { 'clusterName': { 'size': { 'max': 32, 'message': '集群名称长度不能多于32个字符' }, 'required': { 'message': '集群名称不能为空' } } } }) }); namespace_module.config(function (valdrProvider) { valdrProvider.addConstraints({ 'AppNamespace': { 'namespaceName': { 'size': { 'max': 32, 'message': 'Namespace名称长度不能多于32个字符' }, 'required': { 'message': 'Namespace名称不能为空' } }, 'comment': { 'size': { 'max': 64, 'message': '备注长度不能多于64个字符' } } } }) }); application_module.config(function (valdrProvider) { valdrProvider.addConstraints({ 'Item': { 'key': { 'size': { 'max': 128, 'message': 'Key长度不能多于128个字符' }, 'required': { 'message': 'Key不能为空' } }, 'value': { 'required': { 'message': 'value不能为空' } }, 'comment': { 'size': { 'max': 64, 'message': '备注长度不能多于64个字符' } } }, 'Release': { 'releaseName': { 'size': { 'max': 64, 'message': 'Release Name长度不能多于64个字符' }, 'required': { 'message': 'Release Name不能为空' } }, 'comment': { 'size': { 'max': 64, 'message': '备注长度不能多于64个字符' } } } }) }); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/server_config.html ================================================ 应用配置
    应用配置 (维护ServerConfig表数据,如果已存在配置项则会覆盖,否则会创建配置项。配置更新后,一分钟后自动生效)
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/styles/common-style.css ================================================ html, body { height: 100% } body { min-width: 960px; color: #797979; padding: 0 !important; margin: 0 !important; font-size: 13px; background: #f1f2f7; font-family: 'Open Sans', sans-serif; } body.modal-open { overflow: visible; } a { cursor: pointer; } p, td, span { word-wrap: break-word; word-break: break-all; } .modal { overflow-y: scroll } .no-radius { border-radius: 0; } .no-border { border: 0; } .no-margin { margin: 0; } .cursor-pointer { cursor: pointer; } .word-break { word-wrap: break-word; word-break: break-all; } .border { border: solid 1px #c3c3c3; } .padding-top-5 { padding-top: 5px; } .border-top { border-top: 1px solid #ddd; } .bg-info, .bg-primary, .bg-warning, .bg-danger, .bg-success { padding: 10px; } .active { background: #f5f5f5; } .label-default-light { background: #A4A4A4 } .panel-default .panel-heading { color: #797979; } pre { white-space: pre-wrap; /* Since CSS 2.1 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ } .hover:hover { background: #f5f5f5; cursor: pointer } .highlight { background: #ffa; } .hide-border-top { border-top: 0; } .logo { font-size: 25px; } .i-20 { height: 20px; width: 20px; } .i-25-20 { height: 20px; width: 25px; } .i-15 { height: 15px; width: 15px; } .badge { padding: 1px 4px; } .badge-grey { background: #777; color: #fff; } .badge-white { background: #ffffff; color: #6c6c6c; } .modal-dialog { width: 960px; } .apollo-container { min-height: 90%; } .navbar-default { background-color: #ffffff; border: none; } .footer { width: 100%; height: 75px; margin-top: 50px; padding-top: 25px; } /*panel*/ .panel { border: 1px solid #ddd; } table th { text-align: center; } /*首页*/ .site-notice { padding: 5px 0; text-align: center; background-color: #208d4e; } .site-notice { color: #eee; } .site-notice a { color: #ffffff; } .site-notice a:hover { text-underline: none; } .site-notice .selected { color: #000000; } .site-header { position: relative; text-align: center; background-color: #27AE60; color: #fff; margin-bottom: 0; } .site-header .search { border: 2px solid #27AE60; -webkit-box-shadow: none; box-shadow: none; font-size: 16px; padding: 13px 30px; border-radius: 0; height: auto; text-align: center; } .site-header h1 { font-size: 56px; text-shadow: -5px 5px 0 rgba(0, 0, 0, 0.1); } .site-header span { font-size: 14px; } .list-group { margin-top: 20px; } .side-bar { position: absolute; width: 195px; top: 85px; left: 15px; margin-bottom: 25px; background: #f1f2f7; z-index: 2; } .position-absolute { position: absolute; } .position-fix { position: fixed; } .view-mode-1 { margin-left: 235px; padding-right: 15px; } .view-mode-2 { padding: 0 15px; } .side-bar-switch { padding: 10px 10px; margin-right: 30px; } .node-treeview { color: #797979; } .apps .apps-description { color: gray; font-size: 16px; } .app { padding-bottom: 75px; overflow: hidden; } .app td, th { display: table-cell; vertical-align: inherit; } .project-info { width: 100%; } .panel-heading { border-color: #eff2f7; font-size: 16px; font-weight: 300; } .panel-heading .header-namespace { min-width: 415px; } .panel-heading .header-buttons { min-width: 405px; } #treeview .list-group { margin: 0; } #treeview .list-group .list-group-item { border: 0; border-top: 1px solid #eff2f7; } .project-info th { text-align: right; padding: 4px 6px; white-space: nowrap; } .project-info td { border-bottom: 1px dotted gray; padding: 4px 6px; } #config-info { min-height: 500px; } #config-edit { border: 1px solid #ddd; border-radius: 3px; } #config-edit .panel-heading { border-bottom: 1px solid #ddd; } .tocify-header { font-size: 14px; } .tocify-subheader { font-size: 13px; } .config-item-container .panel { border-radius: 0; } .config-item-container .panel-heading b { font-size: 18px; } .config-item-container .form-control[disabled] { background: #ffffff; border: 0; } .config-item-container .second-panel-heading .ns_btn { width: 25px; height: 25px; border-top: solid 1px #ffffff; } .config-item-container .second-panel-heading .nav-tabs .node_active { border-bottom: 3px #1b6d85 solid; } .config-item-container .config-items { height: 500px; overflow: scroll; } .config-item-container .panel-heading button img { width: 12px; height: 12px; } .config-item-container .panel-heading a img { width: 12px; height: 12px; } .config-item-container .panel-heading li img { width: 12px; height: 12px; } .config-item-container .second-panel-heading { height: 45px; } .config-item-container .second-panel-heading a { height: 35px; color: #555; font-size: 13px; margin-bottom: 2px; } .namespace-panel { border-top: 0; border-bottom: 0; } .namespace-panel .namespace-name { font-size: 20px; } .namespace-panel .namespace-label { margin-left: 5px; } .namespace-panel .namespace-attribute-panel { margin-left: 0; color: #fff; border-top: 0; background: #f1f2f7; } .namespace-panel .namespace-attribute-public { background: #31708f; width: 40px; cursor: pointer; } .namespace-panel .second-panel-heading .nav-tabs { border-bottom: 0; } .namespace-panel .namespace-view-table td img { cursor: pointer; width: 23px; height: 23px; } .namespace-panel .namespace-view-table table { table-layout: inherit; } .namespace-panel .namespace-view-table td { word-wrap: break-word; } .namespace-panel .namespace-view-table .glyphicon { cursor: pointer; } .namespace-panel .namespace-view-table .search-input { padding: 15px 0 15px 10px; } .namespace-panel .namespace-view-table .search-input input { width: 350px; } .namespace-panel .no-config-panel { padding: 15px 0; } .namespace-panel .history-view { padding: 10px 20px; } .namespace-panel .instance-view .btn-primary .badge { color: #337ab7; background-color: #fff; } .namespace-panel .instance-view .btn-default .badge { background: #777; color: #fff; } .namespace-panel .rules-manage-view { padding: 45px 20px; } .line { width: 20px; border: 1px solid #ddd; } .editable-table > tbody > tr > td { padding: 4px } .editable-text { padding-left: 4px; padding-top: 4px; padding-bottom: 4px; display: inline-block; } .editable-table tbody > tr > td > .controls { / / width: 100 % } .editable-input { padding-left: 3px; } .editable-input.input-sm { height: 30px; font-size: 14px; padding-top: 4px; padding-bottom: 4px; } .list-group-item .btn-title { color: gray; font-size: 14px; margin: 0; } .list-group-item .icon-project-manage { background: url(../img/manage.png) no-repeat; } .list-group-item .icon-plus-orange { background: url(../img/add.png) no-repeat; } .list-group-item .icon-text { background-size: 20px; background-position: 5% 50%; padding: 5px 0 5px 50px; } /*搜索框*/ ::-webkit-scrollbar { width: 0; height: 0; background: rgba(255, 255, 255, 0); } ::-webkit-scrollbar-thumb:vertical { background: rgba(255, 255, 255, 0); border-radius: 10px; } ::-webkit-scrollbar-thumb:vertical:hover { background: rgba(255, 255, 255, 0); } .app-list { width: 350px; height: 200px; position: absolute; margin-left: 0; cursor: pointer; background: #ffffff; border: 1px solid #ddd; overflow-y: scroll; z-index: 1000; } .app-list .app-item { font-size: medium; padding: 5px 10px; } .app-list .app-item:hover { color: #ffffff; background: #C3C3C3; } .app-list .app-selected { color: #ffffff; background: #c3c3c3; } .item-container { border: solid 1px #f1f2f7; margin-top: 15px; padding: 20px 15px } .item-container .item-info { margin-left: 5px; } .change-type-mark { width: 5px; height: 5px; } .release-history .media-body { padding-left: 20px; } .release-history .panel-body .load-more { margin-top: 20px; } .release-history .media-body textarea { margin-top: 10px; } .release-history .release-history-container { padding: 0; } .release-history .release-history-list { max-height: 750px; padding: 0; border-right: solid 1px #eff2f7; overflow: scroll; } .release-history .release-history-list .media { position: relative; margin: 0; padding: 10px; border-bottom: solid 1px #eff2f7; } .release-history .release-history-list .release-operation { position: absolute; right: 0; top: 0; width: 5px; height: 100%; } .release-history .release-history-list .media .media-left { padding-top: 10px; } .release-history .release-history-list .media .media-body .release-title { padding: 0; } .release-history .release-history-list .emergency-publish { position: absolute; left: 0; top: 0; } .release-history .release-history-list .load-more { height: 45px; background: #f5f5f5; } .release-history .release-operation-normal { background: #316510; } .release-history .release-operation-rollback { background: #997f1c; } .release-history .release-operation-gray { background: #999999; } .release-history .operation-caption-container { position: relative; } .release-history .section-title { padding: 15px 10px 0 10px; } .release-history .operation-caption { position: absolute; top: 45px; width: 75px; height: 18px; color: #fff; font-size: 12px; } .release-history .panel-heading .back-btn { position: absolute; top: 45px; right: 10px; } .release-history .release-info { padding: 0; border: 0; } .release-history .panel-heading { padding: 15px; } .empty-container { padding: 15px; } .valdr-message { display: none; } .valdr-message.ng-dirty.ng-invalid.ng-touched { display: inline; color: #a94442; } .form-group .form-control.ng-invalid.ng-dirty.ng-touched { border-color: #a94442; } .app-not-found { padding-top: 50px; font-size: 18px; } /*index page*/ #app-list h5 { word-wrap: break-word; word-break: break-all; } #app-list .media-body { padding-top: 15px; } #app-list .media { background: #fff; display: table; } #app-list .media-left { width: 1000px; color: #fff; display: table-cell; vertical-align: middle; } #app-list .more-img { width: 30px; height: 30px; } #app-list .app-panel { position: relative; height: 100px; } #app-list .operate-panel { position: absolute; top: 5px; right: 20px; } .create-app-list .media-left { background: #a9d96c; } .create-app-list .create-btn { background: #a9d96c; color: #fff } .create-app-list .create-btn:hover { background: #81AB56; } .create-app-list .create-btn img { width: 26px; height: 26px } .favorites-app-list .media-left { background: #57c8f2; } .favorites-app-list .no-favorites { padding-bottom: 15px; } .visit-app-list .media-left { background: #41cac0; } #rulesModal .rules-ip-selector { width: 500px; height: 50px; } #rulesModal textarea { width: 500px; margin-bottom: 5px; } #rulesModal .rule-edit-panel { padding: 15px 0; } #rulesModal .add-rule { margin-left: 15px; } #rulesModal .select2-container .select2-search__field:not([placeholder='']) { width: auto !important; } .search-onblur { width: 165px; background: #f5f5f5; } .search-focus { width: 165px; background: #fff; } .project-setting .panel-body { padding-top: 35px } .project-setting .panel-body .context { padding-left: 30px; } ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/user-manage.html ================================================ 用户管理
    用户管理
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/ace.js ================================================ (function(){function o(n){var i=e;n&&(e[n]||(e[n]={}),i=e[n]);if(!i.define||!i.define.packaged)t.original=i.define,i.define=t,i.define.packaged=!0;if(!i.require||!i.require.packaged)r.original=i.require,i.require=r,i.require.packaged=!0}var ACE_NAMESPACE="",e=function(){return this}();!e&&typeof window!="undefined"&&(e=window);if(!ACE_NAMESPACE&&typeof requirejs!="undefined")return;var t=function(e,n,r){if(typeof e!="string"){t.original?t.original.apply(this,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(r=n),t.modules[e]||(t.payloads[e]=r,t.modules[e]=null)};t.modules={},t.payloads={};var n=function(e,t,n){if(typeof t=="string"){var i=s(e,t);if(i!=undefined)return n&&n(),i}else if(Object.prototype.toString.call(t)==="[object Array]"){var o=[];for(var u=0,a=t.length;u1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n=0?parseFloat((i.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]):parseFloat((i.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=(window.Controllers||window.controllers)&&window.navigator.product==="Gecko",t.isOldGecko=t.isGecko&&parseInt((i.match(/rv:(\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",t.isWebKit=parseFloat(i.split("WebKit/")[1])||undefined,t.isChrome=parseFloat(i.split(" Chrome/")[1])||undefined,t.isAIR=i.indexOf("AdobeAIR")>=0,t.isIPad=i.indexOf("iPad")>=0,t.isChromeOS=i.indexOf(" CrOS ")>=0,t.isIOS=/iPad|iPhone|iPod/.test(i)&&!window.MSStream,t.isIOS&&(t.isMac=!0)}),define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,n){"use strict";function a(e,t,n){var a=u(t);if(!i.isMac&&s){t.getModifierState&&(t.getModifierState("OS")||t.getModifierState("Win"))&&(a|=8);if(s.altGr){if((3&a)==3)return;s.altGr=0}if(n===18||n===17){var f="location"in t?t.location:t.keyLocation;if(n===17&&f===1)s[n]==1&&(o=t.timeStamp);else if(n===18&&a===3&&f===2){var l=t.timeStamp-o;l<50&&(s.altGr=!0)}}}n in r.MODIFIER_KEYS&&(n=-1),a&8&&n>=91&&n<=93&&(n=-1);if(!a&&n===13){var f="location"in t?t.location:t.keyLocation;if(f===3){e(t,a,-n);if(t.defaultPrevented)return}}if(i.isChromeOS&&a&8){e(t,a,n);if(t.defaultPrevented)return;a&=-9}return!!a||n in r.FUNCTION_KEYS||n in r.PRINTABLE_KEYS?e(t,a,n):!1}function f(){s=Object.create(null)}var r=e("./keys"),i=e("./useragent"),s=null,o=0;t.addListener=function(e,t,n){if(e.addEventListener)return e.addEventListener(t,n,!1);if(e.attachEvent){var r=function(){n.call(e,window.event)};n._wrapper=r,e.attachEvent("on"+t,r)}},t.removeListener=function(e,t,n){if(e.removeEventListener)return e.removeEventListener(t,n,!1);e.detachEvent&&e.detachEvent("on"+t,n._wrapper||n)},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return e.type=="dblclick"?0:e.type=="contextmenu"||i.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},t.capture=function(e,n,r){function i(e){n&&n(e),r&&r(e),t.removeListener(document,"mousemove",n,!0),t.removeListener(document,"mouseup",i,!0),t.removeListener(document,"dragstart",i,!0)}return t.addListener(document,"mousemove",n,!0),t.addListener(document,"mouseup",i,!0),t.addListener(document,"dragstart",i,!0),i},t.addTouchMoveListener=function(e,n){var r,i;t.addListener(e,"touchstart",function(e){var t=e.touches,n=t[0];r=n.clientX,i=n.clientY}),t.addListener(e,"touchmove",function(e){var t=e.touches;if(t.length>1)return;var s=t[0];e.wheelX=r-s.clientX,e.wheelY=i-s.clientY,r=s.clientX,i=s.clientY,n(e)})},t.addMouseWheelListener=function(e,n){"onmousewheel"in e?t.addListener(e,"mousewheel",function(e){var t=8;e.wheelDeltaX!==undefined?(e.wheelX=-e.wheelDeltaX/t,e.wheelY=-e.wheelDeltaY/t):(e.wheelX=0,e.wheelY=-e.wheelDelta/t),n(e)}):"onwheel"in e?t.addListener(e,"wheel",function(e){var t=.35;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=e.deltaX*t||0,e.wheelY=e.deltaY*t||0;break;case e.DOM_DELTA_LINE:case e.DOM_DELTA_PAGE:e.wheelX=(e.deltaX||0)*5,e.wheelY=(e.deltaY||0)*5}n(e)}):t.addListener(e,"DOMMouseScroll",function(e){e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=(e.detail||0)*5,e.wheelY=0):(e.wheelX=0,e.wheelY=(e.detail||0)*5),n(e)})},t.addMultiMouseDownListener=function(e,n,r,s){function c(e){t.getButton(e)!==0?o=0:e.detail>1?(o++,o>4&&(o=1)):o=1;if(i.isIE){var c=Math.abs(e.clientX-u)>5||Math.abs(e.clientY-a)>5;if(!f||c)o=1;f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),o==1&&(u=e.clientX,a=e.clientY)}e._clicks=o,r[s]("mousedown",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}function h(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s]("mousedown",e),r[s](l[o],e)}var o=0,u,a,f,l={2:"dblclick",3:"tripleclick",4:"quadclick"};Array.isArray(e)||(e=[e]),e.forEach(function(e){t.addListener(e,"mousedown",c),i.isOldIE&&t.addListener(e,"dblclick",h)})};var u=!i.isMac||!i.isOpera||"KeyboardEvent"in window?function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)}:function(e){return 0|(e.metaKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.ctrlKey?8:0)};t.getModifierString=function(e){return r.KEY_MODS[u(e)]},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!("KeyboardEvent"in window)){var o=null;r(e,"keydown",function(e){o=e.keyCode}),r(e,"keypress",function(e){return a(n,e,o)})}else{var u=null;r(e,"keydown",function(e){s[e.keyCode]=(s[e.keyCode]||0)+1;var t=a(n,e,e.keyCode);return u=e.defaultPrevented,t}),r(e,"keypress",function(e){u&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),u=null)}),r(e,"keyup",function(e){s[e.keyCode]=null}),s||(f(),r(window,"focus",f))}};if(typeof window=="object"&&window.postMessage&&!i.isOldIE){var l=1;t.nextTick=function(e,n){n=n||window;var r="zero-timeout-message-"+l;t.addListener(n,"message",function i(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,"message",i),e())}),n.postMessage(r,"*")}}t.nextFrame=typeof window=="object"&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),define("ace/lib/lang",["require","exports","module"],function(e,t,n){"use strict";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;nh.length?e=e.substr(9):e.substr(0,4)==h.substr(0,4)?e=e.substr(4,e.length-h.length+1):e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e!=h.charAt(0)&&e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e&&t.onTextInput(e)),p&&(p=!1),L&&(L=!1)},O=function(e){if(m)return;var t=c.value;A(t),T()},M=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||f)return;var i=l||n?"Text":"text/plain";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return M(e,t,!0)}},_=function(e,n){var s=t.getCopyText();if(!s)return r.preventDefault(e);M(e,s)?(i.isIOS&&(d=n,c.value="\n aa"+s+"a a\n",c.setSelectionRange(4,4+s.length),p={value:s}),n?t.onCut():t.onCopy(),i.isIOS||r.preventDefault(e)):(p=!0,c.value=s,c.select(),setTimeout(function(){p=!1,T(),x(),n?t.onCut():t.onCopy()}))},D=function(e){_(e,!0)},P=function(e){_(e,!1)},H=function(e){var n=M(e);typeof n=="string"?(n&&t.onPaste(n,e),i.isIE&&setTimeout(x),r.preventDefault(e)):(c.value="",v=!0)};r.addCommandKeyListener(c,t.onCommandKey.bind(t)),r.addListener(c,"select",C),r.addListener(c,"input",O),r.addListener(c,"cut",D),r.addListener(c,"copy",P),r.addListener(c,"paste",H);var B=function(e){if(m||!t.onCompositionStart||t.$readOnly)return;m={},m.canUndo=t.session.$undoManager,t.onCompositionStart(),setTimeout(j,0),t.on("mousedown",F),m.canUndo&&!t.selection.isEmpty()&&(t.insert(""),t.session.markUndoGroup(),t.selection.clearSelection()),t.session.markUndoGroup()},j=function(){if(!m||!t.onCompositionUpdate||t.$readOnly)return;var e=c.value.replace(/\x01/g,"");if(m.lastValue===e)return;t.onCompositionUpdate(e),m.lastValue&&t.undo(),m.canUndo&&(m.lastValue=e);if(m.lastValue){var n=t.selection.getRange();t.insert(m.lastValue),t.session.markUndoGroup(),m.range=t.selection.getRange(),t.selection.setRange(n),t.selection.clearSelection()}},F=function(e){if(!t.onCompositionEnd||t.$readOnly)return;var n=m;m=!1;var r=setTimeout(function(){r=null;var e=c.value.replace(/\x01/g,"");if(m)return;e==n.lastValue?T():!n.lastValue&&e&&(T(),A(e))});k=function(i){return r&&clearTimeout(r),i=i.replace(/\x01/g,""),i==n.lastValue?"":(n.lastValue&&r&&t.undo(),i)},t.onCompositionEnd(),t.removeListener("mousedown",F),e.type=="compositionend"&&n.range&&t.selection.setRange(n.range);var s=!!i.isChrome&&i.isChrome>=53||!!i.isWebKit&&i.isWebKit>=603;s&&O()},I=o.delayedCall(j,50);r.addListener(c,"compositionstart",B),i.isGecko?r.addListener(c,"text",function(){I.schedule()}):(r.addListener(c,"keyup",function(){I.schedule()}),r.addListener(c,"keydown",function(){I.schedule()})),r.addListener(c,"compositionend",F),this.getElement=function(){return c},this.setReadOnly=function(e){c.readOnly=e},this.onContextMenu=function(e){L=!0,x(t.selection.isEmpty()),t._emit("nativecontextmenu",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,n){g||(g=c.style.cssText),c.style.cssText=(n?"z-index:100000;":"")+"height:"+c.style.height+";"+(i.isIE?"opacity:0.1;":"");var o=t.container.getBoundingClientRect(),u=s.computedStyle(t.container),a=o.top+(parseInt(u.borderTopWidth)||0),f=o.left+(parseInt(o.borderLeftWidth)||0),l=o.bottom-a-c.clientHeight-2,h=function(e){c.style.left=e.clientX-f-2+"px",c.style.top=Math.min(e.clientY-a-2,l)+"px"};h(e);if(e.type!="mousedown")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(q),i.isWin&&r.capture(t.container,h,R)},this.onContextMenuClose=R;var q,U=function(e){t.textInput.onContextMenu(e),R()};r.addListener(c,"mouseup",U),r.addListener(c,"mousedown",function(e){e.preventDefault(),R()}),r.addListener(t.renderer.scroller,"contextmenu",U),r.addListener(c,"contextmenu",U);if(i.isIOS){var z=null,W=!1;e.addEventListener("keydown",function(e){z&&clearTimeout(z),W=!0}),e.addEventListener("keyup",function(e){z=setTimeout(function(){W=!1},100)});var X=function(e){if(document.activeElement!==c)return;if(W)return;if(d)return setTimeout(function(){d=!1},100);var n=c.selectionStart,r=c.selectionEnd;c.setSelectionRange(4,5);if(n==r)switch(n){case 0:t.onCommandKey(null,0,u.up);break;case 1:t.onCommandKey(null,0,u.home);break;case 2:t.onCommandKey(null,a.option,u.left);break;case 4:t.onCommandKey(null,0,u.left);break;case 5:t.onCommandKey(null,0,u.right);break;case 7:t.onCommandKey(null,a.option,u.right);break;case 8:t.onCommandKey(null,0,u.end);break;case 9:t.onCommandKey(null,0,u.down)}else{switch(r){case 6:t.onCommandKey(null,a.shift,u.right);break;case 7:t.onCommandKey(null,a.shift|a.option,u.right);break;case 8:t.onCommandKey(null,a.shift,u.end);break;case 9:t.onCommandKey(null,a.shift,u.down)}switch(n){case 0:t.onCommandKey(null,a.shift,u.up);break;case 1:t.onCommandKey(null,a.shift,u.home);break;case 2:t.onCommandKey(null,a.shift|a.option,u.left);break;case 3:t.onCommandKey(null,a.shift,u.left)}}};document.addEventListener("selectionchange",X),t.on("destroy",function(){document.removeEventListener("selectionchange",X)})}};t.TextInput=c}),define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang","ace/keyboard/textinput_ios"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=e("../lib/dom"),o=e("../lib/lang"),u=i.isChrome<18,a=i.isIE,f=e("./textinput_ios").TextInput,l=function(e,t){function w(e){if(p)return;p=!0;if(T)var t=0,r=e?0:n.value.length-1;else var t=e?2:1,r=2;try{n.setSelectionRange(t,r)}catch(i){}p=!1}function E(){if(p)return;n.value=l,i.isWebKit&&b.schedule()}function F(){clearTimeout(j),j=setTimeout(function(){d&&(n.style.cssText=d,d=""),t.renderer.$keepTextAreaAtCursor==null&&(t.renderer.$keepTextAreaAtCursor=!0,t.renderer.$moveTextAreaToCursor())},0)}if(i.isIOS)return f.call(this,e,t);var n=s.createElement("textarea");n.className="ace_text-input",n.setAttribute("wrap","off"),n.setAttribute("autocorrect","off"),n.setAttribute("autocapitalize","off"),n.setAttribute("spellcheck",!1),n.style.opacity="0",e.insertBefore(n,e.firstChild);var l="\u2028\u2028",c=!1,h=!1,p=!1,d="",v=!0;try{var m=document.activeElement===n}catch(g){}r.addListener(n,"blur",function(e){t.onBlur(e),m=!1}),r.addListener(n,"focus",function(e){m=!0,t.onFocus(e),w()}),this.focus=function(){if(d)return n.focus();var e=n.style.top;n.style.position="fixed",n.style.top="0px",n.focus(),setTimeout(function(){n.style.position="",n.style.top=="0px"&&(n.style.top=e)},0)},this.blur=function(){n.blur()},this.isFocused=function(){return m};var y=o.delayedCall(function(){m&&w(v)}),b=o.delayedCall(function(){p||(n.value=l,m&&w())});i.isWebKit||t.addEventListener("changeSelection",function(){t.selection.isEmpty()!=v&&(v=!v,y.schedule())}),E(),m&&t.onFocus();var S=function(e){return e.selectionStart===0&&e.selectionEnd===e.value.length},x=function(e){c?c=!1:S(n)?(t.selectAll(),w()):T&&w(t.selection.isEmpty())},T=null;this.setInputHandler=function(e){T=e},this.getInputHandler=function(){return T};var N=!1,C=function(e){T&&(e=T(e),T=null),h?(w(),e&&t.onPaste(e),h=!1):e==l.charAt(0)?N?t.execCommand("del",{source:"ace"}):t.execCommand("backspace",{source:"ace"}):(e.substring(0,2)==l?e=e.substr(2):e.charAt(0)==l.charAt(0)?e=e.substr(1):e.charAt(e.length-1)==l.charAt(0)&&(e=e.slice(0,-1)),e.charAt(e.length-1)==l.charAt(0)&&(e=e.slice(0,-1)),e&&t.onTextInput(e)),N&&(N=!1)},k=function(e){if(p)return;var t=n.value;C(t),E()},L=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||u)return;var i=a||n?"Text":"text/plain";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return L(e,t,!0)}},A=function(e,i){var s=t.getCopyText();if(!s)return r.preventDefault(e);L(e,s)?(i?t.onCut():t.onCopy(),r.preventDefault(e)):(c=!0,n.value=s,n.select(),setTimeout(function(){c=!1,E(),w(),i?t.onCut():t.onCopy()}))},O=function(e){A(e,!0)},M=function(e){A(e,!1)},_=function(e){var s=L(e);typeof s=="string"?(s&&t.onPaste(s,e),i.isIE&&setTimeout(w),r.preventDefault(e)):(n.value="",h=!0)};r.addCommandKeyListener(n,t.onCommandKey.bind(t)),r.addListener(n,"select",x),r.addListener(n,"input",k),r.addListener(n,"cut",O),r.addListener(n,"copy",M),r.addListener(n,"paste",_),(!("oncut"in n)||!("oncopy"in n)||!("onpaste"in n))&&r.addListener(e,"keydown",function(e){if(i.isMac&&!e.metaKey||!e.ctrlKey)return;switch(e.keyCode){case 67:M(e);break;case 86:_(e);break;case 88:O(e)}});var D=function(e){if(p||!t.onCompositionStart||t.$readOnly)return;p={},p.canUndo=t.session.$undoManager,t.onCompositionStart(),setTimeout(P,0),t.on("mousedown",H),p.canUndo&&!t.selection.isEmpty()&&(t.insert(""),t.session.markUndoGroup(),t.selection.clearSelection()),t.session.markUndoGroup()},P=function(){if(!p||!t.onCompositionUpdate||t.$readOnly)return;var e=n.value.replace(/\u2028/g,"");if(p.lastValue===e)return;t.onCompositionUpdate(e),p.lastValue&&t.undo(),p.canUndo&&(p.lastValue=e);if(p.lastValue){var r=t.selection.getRange();t.insert(p.lastValue),t.session.markUndoGroup(),p.range=t.selection.getRange(),t.selection.setRange(r),t.selection.clearSelection()}},H=function(e){if(!t.onCompositionEnd||t.$readOnly)return;var r=p;p=!1;var s=setTimeout(function(){s=null;var e=n.value.replace(/\u2028/g,"");if(p)return;e==r.lastValue?E():!r.lastValue&&e&&(E(),C(e))});T=function(n){return s&&clearTimeout(s),n=n.replace(/\u2028/g,""),n==r.lastValue?"":(r.lastValue&&s&&t.undo(),n)},t.onCompositionEnd(),t.removeListener("mousedown",H),e.type=="compositionend"&&r.range&&t.selection.setRange(r.range);var o=!!i.isChrome&&i.isChrome>=53||!!i.isWebKit&&i.isWebKit>=603;o&&k()},B=o.delayedCall(P,50);r.addListener(n,"compositionstart",D),i.isGecko?r.addListener(n,"text",function(){B.schedule()}):(r.addListener(n,"keyup",function(){B.schedule()}),r.addListener(n,"keydown",function(){B.schedule()})),r.addListener(n,"compositionend",H),this.getElement=function(){return n},this.setReadOnly=function(e){n.readOnly=e},this.onContextMenu=function(e){N=!0,w(t.selection.isEmpty()),t._emit("nativecontextmenu",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,o){d||(d=n.style.cssText),n.style.cssText=(o?"z-index:100000;":"")+"height:"+n.style.height+";"+(i.isIE?"opacity:0.1;":"");var u=t.container.getBoundingClientRect(),a=s.computedStyle(t.container),f=u.top+(parseInt(a.borderTopWidth)||0),l=u.left+(parseInt(u.borderLeftWidth)||0),c=u.bottom-f-n.clientHeight-2,h=function(e){n.style.left=e.clientX-l-2+"px",n.style.top=Math.min(e.clientY-f-2,c)+"px"};h(e);if(e.type!="mousedown")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(j),i.isWin&&r.capture(t.container,h,F)},this.onContextMenuClose=F;var j,I=function(e){t.textInput.onContextMenu(e),F()};r.addListener(n,"mouseup",I),r.addListener(n,"mousedown",function(e){e.preventDefault(),F()}),r.addListener(t.renderer.scroller,"contextmenu",I),r.addListener(n,"contextmenu",I)};t.TextInput=l}),define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";function a(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler("mousedown",this.onMouseDown.bind(e)),t.setDefaultHandler("dblclick",this.onDoubleClick.bind(e)),t.setDefaultHandler("tripleclick",this.onTripleClick.bind(e)),t.setDefaultHandler("quadclick",this.onQuadClick.bind(e)),t.setDefaultHandler("mousewheel",this.onMouseWheel.bind(e)),t.setDefaultHandler("touchmove",this.onTouchMove.bind(e));var n=["select","startSelect","selectEnd","selectAllEnd","selectByWordsEnd","selectByLinesEnd","dragWait","dragWaitEnd","focusWait"];n.forEach(function(t){e[t]=this[t]},this),e.selectByLines=this.extendSelectionBy.bind(e,"getLineRange"),e.selectByWords=this.extendSelectionBy.bind(e,"getWordRange")}function f(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}function l(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.column-e.end.column;else if(e.start.row==e.end.row-1&&!e.start.column&&!e.end.column)var n=t.column-4;else var n=2*t.row-e.start.row-e.end.row;return n<0?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var r=e("../lib/dom"),i=e("../lib/event"),s=e("../lib/useragent"),o=0,u=250;(function(){this.onMouseDown=function(e){var t=e.inSelection(),n=e.getDocumentPosition();this.mousedownEvent=e;var r=this.editor,i=e.getButton();if(i!==0){var o=r.getSelectionRange(),u=o.isEmpty();r.$blockScrolling++,(u||i==1)&&r.selection.moveToPosition(n),r.$blockScrolling--,i==2&&(r.textInput.onContextMenu(e.domEvent),s.isMozilla||e.preventDefault());return}this.mousedownEvent.time=Date.now();if(t&&!r.isFocused()){r.focus();if(this.$focusTimout&&!this.$clickSelection&&!r.inMultiSelectMode){this.setState("focusWait"),this.captureMouse(e);return}}return this.captureMouse(e),this.startSelect(n,e.domEvent._clicks>1),e.preventDefault()},this.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var n=this.editor;n.$blockScrolling++,this.mousedownEvent.getShiftKey()?n.selection.selectToPosition(e):t||n.selection.moveToPosition(e),t||this.select(),n.renderer.scroller.setCapture&&n.renderer.scroller.setCapture(),n.setStyle("ace_selecting"),this.setState("select"),n.$blockScrolling--},this.select=function(){var e,t=this.editor,n=t.renderer.screenToTextCoordinates(this.x,this.y);t.$blockScrolling++;if(this.$clickSelection){var r=this.$clickSelection.comparePoint(n);if(r==-1)e=this.$clickSelection.end;else if(r==1)e=this.$clickSelection.start;else{var i=l(this.$clickSelection,n);n=i.cursor,e=i.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(n),t.$blockScrolling--,t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,n=this.editor,r=n.renderer.screenToTextCoordinates(this.x,this.y),i=n.selection[e](r.row,r.column);n.$blockScrolling++;if(this.$clickSelection){var s=this.$clickSelection.comparePoint(i.start),o=this.$clickSelection.comparePoint(i.end);if(s==-1&&o<=0){t=this.$clickSelection.end;if(i.end.row!=r.row||i.end.column!=r.column)r=i.start}else if(o==1&&s>=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=l(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.$blockScrolling--,n.renderer.scrollCursorIntoView()},this.selectEnd=this.selectAllEnd=this.selectByWordsEnd=this.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle("ace_selecting"),this.editor.renderer.scroller.releaseCapture&&this.editor.renderer.scroller.releaseCapture()},this.focusWait=function(){var e=f(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>o||t-this.mousedownEvent.time>this.$focusTimout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);i?(i.isEmpty()&&(i.start.column--,i.end.column++),this.setState("select")):(i=n.selection.getWordRange(t.row,t.column),this.setState("selectByWords")),this.$clickSelection=i,this.select()},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState("selectByLines");var r=n.getSelectionRange();r.isMultiLine()&&r.contains(t.row,t.column)?(this.$clickSelection=n.selection.getLineRange(r.start.row),this.$clickSelection.end=n.selection.getLineRange(r.end.row).end):this.$clickSelection=n.selection.getLineRange(t.row),this.select()},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("selectAll")},this.onMouseWheel=function(e){if(e.getAccelKey())return;e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=this.editor;this.$lastScroll||(this.$lastScroll={t:0,vx:0,vy:0,allowed:0});var n=this.$lastScroll,r=e.domEvent.timeStamp,i=r-n.t,s=e.wheelX/i,o=e.wheelY/i;i=1&&t.renderer.isScrollableBy(e.wheelX*e.speed,0)&&(f=!0),a<=1&&t.renderer.isScrollableBy(0,e.wheelY*e.speed)&&(f=!0);if(f)n.allowed=r;else if(r-n.allowedt.session.documentToScreenRow(l.row,l.column))return c()}if(f==s)return;f=s.text.join("
    "),i.setHtml(f),i.show(),t._signal("showGutterTooltip",i),t.on("mousewheel",c);if(e.$tooltipFollowsMouse)h(u);else{var p=u.domEvent.target,d=p.getBoundingClientRect(),v=i.getElement().style;v.left=d.right+"px",v.top=d.bottom+"px"}}function c(){o&&(o=clearTimeout(o)),f&&(i.hide(),f=null,t._signal("hideGutterTooltip",i),t.removeEventListener("mousewheel",c))}function h(e){i.setPosition(e.x,e.y)}var t=e.editor,n=t.renderer.$gutterLayer,i=new a(t.container);e.editor.setDefaultHandler("guttermousedown",function(r){if(!t.isFocused()||r.getButton()!=0)return;var i=n.getRegion(r);if(i=="foldWidgets")return;var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(r.domEvent.detail==2)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.setState("selectByLines"),e.captureMouse(r),r.preventDefault()});var o,u,f;e.editor.setDefaultHandler("guttermousemove",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(r.hasCssClass(n,"ace_fold-widget"))return c();f&&e.$tooltipFollowsMouse&&h(t),u=t;if(o)return;o=setTimeout(function(){o=null,u&&!e.isMousePressed?l():c()},50)}),s.addListener(t.renderer.$gutter,"mouseout",function(e){u=null;if(!f||o)return;o=setTimeout(function(){o=null,c()},50)}),t.on("changeSession",c)}function a(e){o.call(this,e)}var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/event"),o=e("../tooltip").Tooltip;i.inherits(a,o),function(){this.setPosition=function(e,t){var n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,i=this.getWidth(),s=this.getHeight();e+=15,t+=15,e+i>n&&(e-=e+i-n),t+s>r&&(t-=20+s),o.prototype.setPosition.call(this,e,t)}}.call(a.prototype),t.GutterHandler=u}),define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=t.contains(n.row,n.column)}return this.$inSelection},this.getButton=function(){return r.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=i.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(s.prototype)}),define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";function f(e){function T(e,n){var r=Date.now(),i=!n||e.row!=n.row,s=!n||e.column!=n.column;if(!S||i||s)t.$blockScrolling+=1,t.moveCursorToPosition(e),t.$blockScrolling-=1,S=r,x={x:p,y:d};else{var o=l(x.x,x.y,p,d);o>a?S=null:r-S>=u&&(t.renderer.scrollCursorIntoView(),S=null)}}function N(e,n){var r=Date.now(),i=t.renderer.layerConfig.lineHeight,s=t.renderer.layerConfig.characterWidth,u=t.renderer.scroller.getBoundingClientRect(),a={x:{left:p-u.left,right:u.right-p},y:{top:d-u.top,bottom:u.bottom-d}},f=Math.min(a.x.left,a.x.right),l=Math.min(a.y.top,a.y.bottom),c={row:e.row,column:e.column};f/s<=2&&(c.column+=a.x.left=o&&t.renderer.scrollCursorIntoView(c):E=r:E=null}function C(){var e=g;g=t.renderer.screenToTextCoordinates(p,d),T(g,e),N(g,e)}function k(){m=t.selection.toOrientedRange(),h=t.session.addMarker(m,"ace_selection",t.getSelectionStyle()),t.clearSelection(),t.isFocused()&&t.renderer.$cursorLayer.setBlinking(!1),clearInterval(v),C(),v=setInterval(C,20),y=0,i.addListener(document,"mousemove",O)}function L(){clearInterval(v),t.session.removeMarker(h),h=null,t.$blockScrolling+=1,t.selection.fromOrientedRange(m),t.$blockScrolling-=1,t.isFocused()&&!w&&t.renderer.$cursorLayer.setBlinking(!t.getReadOnly()),m=null,g=null,y=0,E=null,S=null,i.removeListener(document,"mousemove",O)}function O(){A==null&&(A=setTimeout(function(){A!=null&&h&&L()},20))}function M(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return e=="text/plain"||e=="Text"})}function _(e){var t=["copy","copymove","all","uninitialized"],n=["move","copymove","linkmove","all","uninitialized"],r=s.isMac?e.altKey:e.ctrlKey,i="uninitialized";try{i=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o="none";return r&&t.indexOf(i)>=0?o="copy":n.indexOf(i)>=0?o="move":t.indexOf(i)>=0&&(o="copy"),o}var t=e.editor,n=r.createElement("img");n.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",s.isOpera&&(n.style.cssText="width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;");var f=["dragWait","dragWaitEnd","startDrag","dragReadyEnd","onMouseDrag"];f.forEach(function(t){e[t]=this[t]},this),t.addEventListener("mousedown",this.onMouseDown.bind(e));var c=t.container,h,p,d,v,m,g,y=0,b,w,E,S,x;this.onDragStart=function(e){if(this.cancelDrag||!c.draggable){var r=this;return setTimeout(function(){r.startSelect(),r.captureMouse(e)},0),e.preventDefault()}m=t.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=t.getReadOnly()?"copy":"copyMove",s.isOpera&&(t.container.appendChild(n),n.scrollTop=0),i.setDragImage&&i.setDragImage(n,0,0),s.isOpera&&t.container.removeChild(n),i.clearData(),i.setData("Text",t.session.getTextRange()),w=!0,this.setState("drag")},this.onDragEnd=function(e){c.draggable=!1,w=!1,this.setState(null);if(!t.getReadOnly()){var n=e.dataTransfer.dropEffect;!b&&n=="move"&&t.session.remove(t.getSelectionRange()),t.renderer.$cursorLayer.setBlinking(!0)}this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle("")},this.onDragEnter=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||k(),y++,e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragOver=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||(k(),y++),A!==null&&(A=null),e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragLeave=function(e){y--;if(y<=0&&h)return L(),b=null,i.preventDefault(e)},this.onDrop=function(e){if(!g)return;var n=e.dataTransfer;if(w)switch(b){case"move":m.contains(g.row,g.column)?m={start:g,end:g}:m=t.moveText(m,g);break;case"copy":m=t.moveText(m,g,!0)}else{var r=n.getData("Text");m={start:g,end:t.session.insert(g,r)},t.focus(),b=null}return L(),i.preventDefault(e)},i.addListener(c,"dragstart",this.onDragStart.bind(e)),i.addListener(c,"dragend",this.onDragEnd.bind(e)),i.addListener(c,"dragenter",this.onDragEnter.bind(e)),i.addListener(c,"dragover",this.onDragOver.bind(e)),i.addListener(c,"dragleave",this.onDragLeave.bind(e)),i.addListener(c,"drop",this.onDrop.bind(e));var A=null}function l(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}var r=e("../lib/dom"),i=e("../lib/event"),s=e("../lib/useragent"),o=200,u=200,a=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle(""),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle("ace_dragging");var n=s.isWin?"default":"move";e.renderer.setCursorStyle(n),this.setState("dragReady")},this.onMouseDrag=function(e){var t=this.editor.container;if(s.isIE&&this.state=="dragReady"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>3&&t.dragDrop()}if(this.state==="dragWait"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(!this.$dragEnabled)return;this.mousedownEvent=e;var t=this.editor,n=e.inSelection(),r=e.getButton(),i=e.domEvent.detail||1;if(i===1&&r===0&&n){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;"unselectable"in o&&(o.unselectable="on");if(t.getDragDelay()){if(s.isWebKit){this.cancelDrag=!0;var u=t.container;u.draggable=!0}this.setState("dragWait")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}).call(f.prototype),t.DragdropHandler=f}),define("ace/lib/net",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("./dom");t.get=function(e,t){var n=new XMLHttpRequest;n.open("GET",e,!0),n.onreadystatechange=function(){n.readyState===4&&t(n.responseText)},n.send(null)},t.loadScript=function(e,t){var n=r.getDocumentHead(),i=document.createElement("script");i.src=e,n.appendChild(i),i.onload=i.onreadystatechange=function(e,n){if(n||!i.readyState||i.readyState=="loaded"||i.readyState=="complete")i=i.onload=i.onreadystatechange=null,n||t()}},t.qualifyURL=function(e){var t=document.createElement("a");return t.href=e,t.href}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o1&&(i=n[n.length-2]);var o=a[t+"Path"];return o==null?o=a.basePath:r=="/"&&(t=r=""),o&&o.slice(-1)!="/"&&(o+="/"),o+t+r+i+this.get("suffix")},t.setModuleUrl=function(e,t){return a.$moduleUrls[e]=t},t.$loading={},t.loadModule=function(n,r){var i,o;Array.isArray(n)&&(o=n[0],n=n[1]);try{i=e(n)}catch(u){}if(i&&!t.$loading[n])return r&&r(i);t.$loading[n]||(t.$loading[n]=[]),t.$loading[n].push(r);if(t.$loading[n].length>1)return;var a=function(){e([n],function(e){t._emit("load.module",{name:n,module:e});var r=t.$loading[n];t.$loading[n]=null,r.forEach(function(t){t&&t(e)})})};if(!t.get("packaged"))return a();s.loadScript(t.moduleUrl(n,o),a)},t.init=f}),define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop_handler","ace/config"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=e("./default_handlers").DefaultHandlers,o=e("./default_gutter_handler").GutterHandler,u=e("./mouse_event").MouseEvent,a=e("./dragdrop_handler").DragdropHandler,f=e("../config"),l=function(e){var t=this;this.editor=e,new s(this),new o(this),new a(this);var n=function(t){var n=!document.hasFocus||!document.hasFocus()||!e.isFocused()&&document.activeElement==(e.textInput&&e.textInput.getElement());n&&window.focus(),e.focus()},u=e.renderer.getMouseEventTarget();r.addListener(u,"click",this.onMouseEvent.bind(this,"click")),r.addListener(u,"mousemove",this.onMouseMove.bind(this,"mousemove")),r.addMultiMouseDownListener([u,e.renderer.scrollBarV&&e.renderer.scrollBarV.inner,e.renderer.scrollBarH&&e.renderer.scrollBarH.inner,e.textInput&&e.textInput.getElement()].filter(Boolean),[400,300,250],this,"onMouseEvent"),r.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,"mousewheel")),r.addTouchMoveListener(e.container,this.onTouchMove.bind(this,"touchmove"));var f=e.renderer.$gutter;r.addListener(f,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),r.addListener(f,"click",this.onMouseEvent.bind(this,"gutterclick")),r.addListener(f,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),r.addListener(f,"mousemove",this.onMouseEvent.bind(this,"guttermousemove")),r.addListener(u,"mousedown",n),r.addListener(f,"mousedown",n),i.isIE&&e.renderer.scrollBarV&&(r.addListener(e.renderer.scrollBarV.element,"mousedown",n),r.addListener(e.renderer.scrollBarH.element,"mousedown",n)),e.on("mousemove",function(n){if(t.state||t.$dragDelay||!t.$dragEnabled)return;var r=e.renderer.screenToTextCoordinates(n.x,n.y),i=e.session.selection.getRange(),s=e.renderer;!i.isEmpty()&&i.insideStart(r.row,r.column)?s.setCursorStyle("default"):s.setCursorStyle("")})};(function(){this.onMouseEvent=function(e,t){this.editor._emit(e,new u(t,this.editor))},this.onMouseMove=function(e,t){var n=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!n||!n.length)return;this.editor._emit(e,new u(t,this.editor))},this.onMouseWheel=function(e,t){var n=new u(t,this.editor);n.speed=this.$scrollSpeed*2,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.onTouchMove=function(e,t){var n=new u(t,this.editor);n.speed=1,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var n=this.editor.renderer;n.$keepTextAreaAtCursor&&(n.$keepTextAreaAtCursor=null);var s=this,o=function(e){if(!e)return;if(i.isWebKit&&!e.which&&s.releaseMouse)return s.releaseMouse();s.x=e.clientX,s.y=e.clientY,t&&t(e),s.mouseEvent=new u(e,s.editor),s.$mouseMoved=!0},a=function(e){clearInterval(l),f(),s[s.state+"End"]&&s[s.state+"End"](e),s.state="",n.$keepTextAreaAtCursor==null&&(n.$keepTextAreaAtCursor=!0,n.$moveTextAreaToCursor()),s.isMousePressed=!1,s.$onCaptureMouseMove=s.releaseMouse=null,e&&s.onMouseEvent("mouseup",e)},f=function(){s[s.state]&&s[s.state](),s.$mouseMoved=!1};if(i.isOldIE&&e.domEvent.type=="dblclick")return setTimeout(function(){a(e)});s.$onCaptureMouseMove=o,s.releaseMouse=r.capture(this.editor.container,o,a);var l=setInterval(f,20)},this.releaseMouse=null,this.cancelContextMenu=function(){var e=function(t){if(t&&t.domEvent&&t.domEvent.type!="contextmenu")return;this.editor.off("nativecontextmenu",e),t&&t.domEvent&&r.stopEvent(t.domEvent)}.bind(this);setTimeout(e,10),this.editor.on("nativecontextmenu",e)}}).call(l.prototype),f.defineOptions(l.prototype,"mouseHandler",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:i.isMac?150:0},dragEnabled:{initialValue:!0},focusTimout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=l}),define("ace/mouse/fold_handler",["require","exports","module"],function(e,t,n){"use strict";function r(e){e.on("click",function(t){var n=t.getDocumentPosition(),r=e.session,i=r.getFoldAt(n.row,n.column,1);i&&(t.getAccelKey()?r.removeFold(i):r.expandFold(i),t.stop())}),e.on("gutterclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),e.isFocused()||e.focus(),t.stop()}}),e.on("gutterdblclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session,s=i.getParentFoldRangeData(r,!0),o=s.range||s.firstRange;if(o){r=o.start.row;var u=i.getFoldAt(r,i.getLine(r).length,1);u?i.removeFold(u):(i.addFold("...",o),e.renderer.scrollCursorIntoView({row:o.start.row,column:0}))}t.stop()}})}t.FoldHandler=r}),define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,n){"use strict";var r=e("../lib/keys"),i=e("../lib/event"),s=function(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},this.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]==e)return;while(t[t.length-1]&&t[t.length-1]!=this.$defaultHandler)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;typeof e=="function"&&!e.handleKeyboard&&(e.handleKeyboard=e);var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(n){return n.getStatusText&&n.getStatusText(t,e)||""}).filter(Boolean).join(" ")},this.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command=="null"?o=!0:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&s.passEvent!=1&&s.command.passEvent!=1&&i.stopEvent(r);if(o)break}return!o&&e==-1&&(s={command:"insertstring"},o=u.exec("insertstring",this.$editor,t)),o&&this.$editor._signal&&this.$editor._signal("keyboardActivity",s),o},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){this.$callKeyboardHandlers(-1,e)}}).call(s.prototype),t.KeyBinding=s}),define("ace/lib/bidiutil",["require","exports","module"],function(e,t,n){"use strict";function F(e,t,n,r){var i=s?d:p,c=null,h=null,v=null,m=0,g=null,y=null,b=-1,w=null,E=null,T=[];if(!r)for(w=0,r=[];w0)if(g==16){for(w=b;w-1){for(w=b;w=0;C--){if(r[C]!=N)break;t[C]=s}}}function I(e,t,n){if(o=e){u=i+1;while(u=e)u++;for(a=i,l=u-1;a=t.length||(o=n[r-1])!=b&&o!=w||(c=t[r+1])!=b&&c!=w)return E;return u&&(c=w),c==o?c:E;case k:o=r>0?n[r-1]:S;if(o==b&&r+10&&n[r-1]==b)return b;if(u)return E;p=r+1,h=t.length;while(p=1425&&d<=2303||d==64286;o=t[p];if(v&&(o==y||o==T))return y}if(r<1||(o=t[r-1])==S)return E;return n[r-1];case S:return u=!1,f=!0,s;case x:return l=!0,E;case O:case M:case D:case P:case _:u=!1;case H:return E}}function R(e){var t=e.charCodeAt(0),n=t>>8;return n==0?t>191?g:B[t]:n==5?/[\u0591-\u05f4]/.test(e)?y:g:n==6?/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(e)?A:/[\u0660-\u0669\u066b-\u066c]/.test(e)?w:t==1642?L:/[\u06f0-\u06f9]/.test(e)?b:T:n==32&&t<=8287?j[t&255]:n==254?t>=65136?T:E:E}function U(e){return e>="\u064b"&&e<="\u0655"}var r=["\u0621","\u0641"],i=["\u063a","\u064a"],s=0,o=0,u=!1,a=!1,f=!1,l=!1,c=!1,h=!1,p=[[0,3,0,1,0,0,0],[0,3,0,1,2,2,0],[0,3,0,17,2,0,1],[0,3,5,5,4,1,0],[0,3,21,21,4,0,1],[0,3,5,5,4,2,0]],d=[[2,0,1,1,0,1,0],[2,0,1,1,0,2,0],[2,0,2,1,3,2,0],[2,0,2,33,3,1,1]],v=0,m=1,g=0,y=1,b=2,w=3,E=4,S=5,x=6,T=7,N=8,C=9,k=10,L=11,A=12,O=13,M=14,_=15,D=16,P=17,H=18,B=[H,H,H,H,H,H,H,H,H,x,S,x,N,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,S,S,S,x,N,E,E,L,L,L,E,E,E,E,E,k,C,k,C,C,b,b,b,b,b,b,b,b,b,b,C,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,E,E,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,g,E,E,E,E,H,H,H,H,H,H,S,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,C,E,L,L,L,L,E,E,E,E,g,E,E,H,E,E,L,L,b,b,E,g,E,E,E,b,g,E,E,E,E,E],j=[N,N,N,N,N,N,N,N,N,N,N,H,H,H,g,y,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N,S,O,M,_,D,P,C,L,L,L,L,L,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,C,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,N];t.L=g,t.R=y,t.EN=b,t.ON_R=3,t.AN=4,t.R_H=5,t.B=6,t.DOT="\u00b7",t.doBidiReorder=function(e,n,r){if(e.length<2)return{};var i=e.split(""),o=new Array(i.length),u=new Array(i.length),a=[];s=r?m:v,F(i,a,i.length,n);for(var f=0;fT&&n[f]0&&i[f-1]==="\u0644"&&/\u0622|\u0623|\u0625|\u0627/.test(i[f])&&(a[f-1]=a[f]=t.R_H,f++);i[i.length-1]===t.DOT&&(a[i.length-1]=t.B);for(var f=0;f=0&&(e=this.session.$docRowCache[n])}return e},this.getSplitIndex=function(){var e=0,t=this.session.$screenRowCache;if(t.length){var n,r=this.session.$getRowCacheIndex(t,this.currentRow);while(this.currentRow-e>0){n=this.session.$getRowCacheIndex(t,this.currentRow-e-1);if(n!==r)break;r=n,e++}}return e},this.updateRowLine=function(e,t){e===undefined&&(e=this.getDocumentRow()),this.wrapIndent=0,this.isLastRow=e===this.session.getLength()-1,this.line=this.session.getLine(e);if(this.session.$useWrapMode){var n=this.session.$wrapData[e];n&&(t===undefined&&(t=this.getSplitIndex()),t>0&&n.length?(this.wrapIndent=n.indent,this.line=t0?e-1:0,this.bidiMap),n=this.bidiMap.bidiLevels,i=0;e===0&&n[t]%2!==0&&t++;for(var s=0;s=a&&pn+o/2){n+=o;if(i===s.length-1){o=0;break}o=this.charWidths[s[++i]]}return i>0&&s[i-1]%2!==0&&s[i]%2===0?(e0&&s[i-1]%2===0&&s[i]%2!==0?t=1+(e>n?this.bidiMap.logicalFromVisual[i]:this.bidiMap.logicalFromVisual[i-1]):this.isRtlDir&&i===s.length-1&&o===0&&s[i-1]%2===0||!this.isRtlDir&&i===0&&s[i]%2!==0?t=1+this.bidiMap.logicalFromVisual[i]:(i>0&&s[i-1]%2!==0&&o!==0&&i--,t=this.bidiMap.logicalFromVisual[i]),t+this.wrapIndent}}).call(u.prototype),t.BidiHandler=u}),define("ace/range",["require","exports","module"],function(e,t,n){"use strict";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.rowt.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.getRange().isEmpty()&&(this.$isEmpty=!0),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t=="undefined"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e=="number"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t===!0?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.wouldMoveIntoSoftTab=function(e,t,n){var r=e.column,i=e.column+t;return n<0&&(r=e.column-t,i=e.column),this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(r,i).split(" ").length-1==t},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column===0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.wouldMoveIntoSoftTab(e,n,-1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var s=this.session.getFoldAt(e,t,1);if(s){this.moveCursorTo(s.end.row,s.end.column);return}if(i=this.session.nonTokenRe.exec(r))t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t);if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e0&&this.moveCursorWordLeft();return}if(o=this.session.tokenRe.exec(s))t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t,n=0,r,i=/\s/,s=this.session.tokenRe;s.lastIndex=0;if(t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{while((r=e[n])&&i.test(r))n++;if(n<1){s.lastIndex=0;while((r=e[n])&&!s.test(r)){s.lastIndex=0,n++;if(i.test(r)){if(n>2){n--;break}while((r=e[n])&&i.test(r))n++;if(n>2)break}}}}return s.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e0&&/^\s*$/.test(r));t=r.length,/\s+$/.test(r)||(r="")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column),r;t===0&&(e!==0&&(this.session.$bidiHandler.isBidiRow(n.row,this.lead.row)?(r=this.session.$bidiHandler.getPosLeft(n.column),n.column=Math.round(r/this.session.$bidiHandler.charWidths[0])):r=n.column*this.session.$bidiHandler.charWidths[0]),this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var i=this.session.screenToDocumentPosition(n.row+e,n.column,r);e!==0&&t===0&&i.row===this.lead.row&&i.column===this.lead.column&&this.session.lineWidgets&&this.session.lineWidgets[i.row]&&(i.row>0||e>0)&&i.row++,this.moveCursorTo(i.row,i.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0;var i=this.session.getLine(e);/[\uDC00-\uDFFF]/.test(i.charAt(t))&&i.charAt(t-1)&&(this.lead.row==e&&this.lead.column==t+1?t-=1:t+=1),this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e(this);var n=this.getCursor();return o.fromPoints(t,n)}catch(r){return o.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(e.start==undefined){if(this.rangeList){this.toSingleRange(e[0]);for(var t=e.length;t--;){var n=o.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(n.cursor=n.start),this.addRange(n,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(u.prototype),t.Selection=u}),define("ace/tokenizer",["require","exports","module","ace/config"],function(e,t,n){"use strict";var r=e("./config"),i=2e3,s=function(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){var n=this.states[t],r=[],i=0,s=this.matchMappings[t]={defaultToken:"text"},o="g",u=[];for(var a=0;a1?f.onMatch=this.$applyToken:f.onMatch=f.token),c>1&&(/\\\d/.test(f.regex)?l=f.regex.replace(/\\([0-9]+)/g,function(e,t){return"\\"+(parseInt(t,10)+i+1)}):(c=1,l=this.removeCapturingGroups(f.regex)),!f.splitRegex&&typeof f.token!="string"&&u.push(f)),s[i]=a,i+=c,r.push(l),f.onMatch||(f.onMatch=null)}r.length||(s[0]=0,r.push("$")),u.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,o)},this),this.regExps[t]=new RegExp("("+r.join(")|(")+")|($)",o)}};(function(){this.$setMaxTokenCount=function(e){i=e|0},this.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),n=this.token.apply(this,t);if(typeof n=="string")return[{type:n,value:e}];var r=[];for(var i=0,s=n.length;il){var g=e.substring(l,m-v.length);h.type==p?h.value+=g:(h.type&&f.push(h),h={type:p,value:g})}for(var y=0;yi){c>2*e.length&&this.reportError("infinite loop with in ace tokenizer",{startState:t,line:e});while(l1&&n[0]!==r&&n.unshift("#tmp",r),{tokens:f,state:n.length?n:r}},this.reportError=r.reportError}).call(s.prototype),t.Tokenizer=s}),define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../lib/lang"),i=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{defaultToken:"text"}]}};(function(){this.addRules=function(e,t){if(!t){for(var n in e)this.$rules[n]=e[n];return}for(var n in e){var r=e[n];for(var i=0;i=this.$rowTokens.length){this.$row+=1,e||(e=this.$session.getLength());if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n},this.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}},this.getCurrentTokenRange=function(){var e=this.$rowTokens[this.$tokenIndex],t=this.getCurrentTokenColumn();return new r(this.$row,t,this.$row,t+e.value.length)}}).call(i.prototype),t.TokenIterator=i}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f,l={},c={'"':'"',"'":"'"},h=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},p=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},d=function(e){this.add("braces","insertion",function(t,n,r,i,s){var u=r.getCursorPosition(),a=i.doc.getLine(u.row);if(s=="{"){h(r);var l=r.getSelectionRange(),c=i.doc.getTextRange(l);if(c!==""&&c!=="{"&&r.getWrapBehavioursEnabled())return p(l,c,"{","}");if(d.isSaneInsertion(r,i))return/[\]\}\)]/.test(a[u.column])||r.inMultiSelectMode||e&&e.braces?(d.recordAutoInsert(r,i,"}"),{text:"{}",selection:[1,1]}):(d.recordMaybeInsert(r,i,"{"),{text:"{",selection:[1,1]})}else if(s=="}"){h(r);var v=a.substring(u.column,u.column+1);if(v=="}"){var m=i.$findOpeningBracket("}",{column:u.column+1,row:u.row});if(m!==null&&d.isAutoInsertedClosing(u,a,s))return d.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if(s=="\n"||s=="\r\n"){h(r);var g="";d.isMaybeInsertedClosing(u,a)&&(g=o.stringRepeat("}",f.maybeInsertedBrackets),d.clearMaybeInsertedClosing());var v=a.substring(u.column,u.column+1);if(v==="}"){var y=i.findMatchingBracket({row:u.row,column:u.column+1},"}");if(!y)return null;var b=this.$getIndent(i.getLine(y.row))}else{if(!g){d.clearMaybeInsertedClosing();return}var b=this.$getIndent(a)}var w=b+i.getTabString();return{text:"\n"+w+"\n"+b+g,selection:[1,w.length,1,w.length]}}d.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return p(s,o,"(",")");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return p(s,o,"[","]");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){var s=r.$mode.$quotes||c;if(i.length==1&&s[i]){if(this.lineCommentStart&&this.lineCommentStart.indexOf(i)!=-1)return;h(n);var o=i,u=n.getSelectionRange(),a=r.doc.getTextRange(u);if(a!==""&&(a.length!=1||!s[a])&&n.getWrapBehavioursEnabled())return p(u,a,o,o);if(!a){var f=n.getCursorPosition(),l=r.doc.getLine(f.row),d=l.substring(f.column-1,f.column),v=l.substring(f.column,f.column+1),m=r.getTokenAt(f.row,f.column),g=r.getTokenAt(f.row,f.column+1);if(d=="\\"&&m&&/escape/.test(m.type))return null;var y=m&&/string|escape/.test(m.type),b=!g||/string|escape/.test(g.type),w;if(v==o)w=y!==b,w&&/string\.end/.test(g.type)&&(w=!1);else{if(y&&!b)return null;if(y&&b)return null;var E=r.$mode.tokenRe;E.lastIndex=0;var S=E.test(d);E.lastIndex=0;var x=E.test(d);if(S||x)return null;if(v&&!/[\s;,.})\]\\]/.test(v))return null;w=!0}return{text:w?o+o:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};d.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},d.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},d.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},d.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},d.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},d.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},d.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},d.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(d,i),t.CstyleBehaviour=d}),define("ace/unicode",["require","exports","module"],function(e,t,n){"use strict";function r(e){var n=/\w{4}/g;for(var r in e)t.packages[r]=e[r].replace(n,"\\u$&")}t.packages={},r({L:"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",Ll:"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A",Lu:"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A",Lt:"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",Lm:"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F",Lo:"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",M:"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",Mn:"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",Mc:"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC",Me:"0488048906DE20DD-20E020E2-20E4A670-A672",N:"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nd:"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nl:"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",No:"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835",P:"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",Pd:"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D",Ps:"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",Pe:"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",Pi:"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",Pf:"00BB2019201D203A2E032E052E0A2E0D2E1D2E21",Pc:"005F203F20402054FE33FE34FE4D-FE4FFF3F",Po:"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",S:"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",Sm:"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",Sc:"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6",Sk:"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3",So:"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",Z:"002000A01680180E2000-200A20282029202F205F3000",Zs:"002000A01680180E2000-200A202F205F3000",Zl:"2028",Zp:"2029",C:"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",Cc:"0000-001F007F-009F",Cf:"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",Co:"E000-F8FF",Cs:"D800-DFFF",Cn:"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"})}),define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour/cstyle","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"],function(e,t,n){"use strict";var r=e("../tokenizer").Tokenizer,i=e("./text_highlight_rules").TextHighlightRules,s=e("./behaviour/cstyle").CstyleBehaviour,o=e("../unicode"),u=e("../lib/lang"),a=e("../token_iterator").TokenIterator,f=e("../range").Range,l=function(){this.HighlightRules=i};(function(){this.$defaultBehaviour=new s,this.tokenRe=new RegExp("^["+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+"\\$_]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+"\\$_]|\\s])+","g"),this.getTokenizer=function(){return this.$tokenizer||(this.$highlightRules=this.$highlightRules||new this.HighlightRules(this.$highlightRuleConfig),this.$tokenizer=new r(this.$highlightRules.getRules())),this.$tokenizer},this.lineCommentStart="",this.blockComment="",this.toggleCommentLines=function(e,t,n,r){function w(e){for(var t=n;t<=r;t++)e(i.getLine(t),t)}var i=t.doc,s=!0,o=!0,a=Infinity,f=t.getTabSize(),l=!1;if(!this.lineCommentStart){if(!this.blockComment)return!1;var c=this.blockComment.start,h=this.blockComment.end,p=new RegExp("^(\\s*)(?:"+u.escapeRegExp(c)+")"),d=new RegExp("(?:"+u.escapeRegExp(h)+")\\s*$"),v=function(e,t){if(g(e,t))return;if(!s||/\S/.test(e))i.insertInLine({row:t,column:e.length},h),i.insertInLine({row:t,column:a},c)},m=function(e,t){var n;(n=e.match(d))&&i.removeInLine(t,e.length-n[0].length,e.length),(n=e.match(p))&&i.removeInLine(t,n[1].length,n[0].length)},g=function(e,n){if(p.test(e))return!0;var r=t.getTokens(n);for(var i=0;i2?r%f!=f-1:r%f==0}}var E=Infinity;w(function(e,t){var n=e.search(/\S/);n!==-1?(ne.length&&(E=e.length)}),a==Infinity&&(a=E,s=!1,o=!1),l&&a%f!=0&&(a=Math.floor(a/f)*f),w(o?m:v)},this.toggleBlockComment=function(e,t,n,r){var i=this.blockComment;if(!i)return;!i.start&&i[0]&&(i=i[0]);var s=new a(t,r.row,r.column),o=s.getCurrentToken(),u=t.selection,l=t.selection.toOrientedRange(),c,h;if(o&&/comment/.test(o.type)){var p,d;while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.start);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;p=new f(m,g,m,g+i.start.length);break}o=s.stepBackward()}var s=new a(t,r.row,r.column),o=s.getCurrentToken();while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.end);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;d=new f(m,g,m,g+i.end.length);break}o=s.stepForward()}d&&t.remove(d),p&&(t.remove(p),c=p.start.row,h=-i.start.length)}else h=i.start.length,c=n.start.row,t.insert(n.end,i.end),t.insert(n.start,i.start);l.start.row==c&&(l.start.column+=h),l.end.row==c&&(l.end.column+=h),t.selection.fromOrientedRange(l)},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){return e.match(/^\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)e[t]&&(this.$embeds.push(t),this.$modes[t]=new e[t]);var n=["toggleBlockComment","toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction","getCompletions"];for(var t=0;t=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=t.Anchor=function(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n=="undefined"?this.setPosition(t.row,t.column):this.setPosition(t,n)};(function(){function e(e,t,n){var r=n?e.column<=t.column:e.columnthis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal("change",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(""),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action=="insert"?"remove":"insert",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i20){n.running=setTimeout(n.$worker,20);break}}n.currentLine=t,r==-1&&(r=t),s<=r&&n.fireUpdateEvent(s,r)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._signal("update",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},this.$updateOnChange=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.lines[t]=null;else if(e.action=="remove")this.lines.splice(t,n+1,null),this.states.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.lines.splice.apply(this.lines,r),this.states.splice.apply(this.states,r)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1],r=this.tokenizer.getLineTokens(t,n,e);return this.states[e]+""!=r.state+""?(this.states[e]=r.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=r.tokens}}).call(s.prototype),t.BackgroundTokenizer=s}),define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){"use strict";var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+""==e+"")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:"");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i)}}}).call(o.prototype),t.SearchHighlight=o}),define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(e,t,n){"use strict";function i(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e("../range").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.rowthis.endRow)throw new Error("Can't add a fold to this FoldLine as it has no connection");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f0)continue;var a=i(e,o.start);return u===0?t&&a!==0?-s-2:s:a>0||a===0&&!t?s:-s-1}return-s-1},this.add=function(e){var t=!e.isEmpty(),n=this.pointIndex(e.start,t);n<0&&(n=-n-1);var r=this.pointIndex(e.end,t,n);return r<0?r=-r-1:r++,this.ranges.splice(n,r-n,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.apply(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return i(e.start,t.start)});var n=t[0],r;for(var s=1;s=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.rowr)break;l.start.row==r&&l.start.column>=t.column&&(l.start.column!=t.column||!this.$insertRight)&&(l.start.column+=o,l.start.row+=s);if(l.end.row==r&&l.end.column>=t.column){if(l.end.column==t.column&&this.$insertRight)continue;l.end.column==t.column&&o>0&&al.start.column&&l.end.column==u[a+1].start.column&&(l.end.column-=o),l.end.column+=o,l.end.row+=s}}if(s!=0&&a=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i=t){u=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:(o=new s(t,e),o.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u0&&(this.removeFolds(p),p.forEach(function(e){o.addSubFold(e)}));for(var d=0;d0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var n,i;e==null?(n=new r(0,0,this.getLength(),0),t=!0):typeof e=="number"?n=new r(e,0,e,this.getLine(e).length):"row"in e?n=r.fromPoints(e,e):n=e,i=this.getFoldsInRangeList(n);if(t)this.removeFolds(i);else{var s=i;while(s.length)this.expandFolds(s),s=this.getFoldsInRangeList(n)}if(i.length)return i},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var n=this.getFoldLine(e,t);return n?n.end.row:e},this.getRowFoldStart=function(e,t){var n=this.getFoldLine(e,t);return n?n.start.row:e},this.getFoldDisplayLine=function(e,t,n,r,i){r==null&&(r=e.start.row),i==null&&(i=0),t==null&&(t=e.end.row),n==null&&(n=this.getLine(t).length);var s=this.doc,o="";return e.walk(function(e,t,n,u){if(tl)break}while(s&&a.test(s.type));s=i.stepBackward()}else s=i.getCurrentToken();return f.end.row=i.getCurrentTokenRow(),f.end.column=i.getCurrentTokenColumn()+s.value.length-2,f}},this.foldAll=function(e,t,n){n==undefined&&(n=1e5);var r=this.foldWidgets;if(!r)return;t=t||this.getLength(),e=e||0;for(var i=e;i=e){i=s.end.row;try{var o=this.addFold("...",s);o&&(o.collapseChildren=n)}catch(u){}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error("invalid fold style: "+e+"["+Object.keys(this.$foldStyles).join(", ")+"]");if(this.$foldStyle==e)return;this.$foldStyle=e,e=="manual"&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)},this.$setFolding=function(e){if(this.$foldMode==e)return;this.$foldMode=e,this.off("change",this.$updateFoldWidgets),this.off("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets),this._signal("changeAnnotation");if(!e||this.$foldStyle=="manual"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets),this.on("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets)},this.getParentFoldRangeData=function(e,t){var n=this.foldWidgets;if(!n||t&&n[e])return{};var r=e-1,i;while(r>=0){var s=n[r];s==null&&(s=n[r]=this.getFoldWidget(r));if(s=="start"){var o=this.getFoldWidgetRange(r);i||(i=o);if(o&&o.end.row>=e)break}r--}return{range:r!==-1&&o,firstRange:i}},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var n={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},r=this.$toggleFoldWidget(e,n);if(!r){var i=t.target||t.srcElement;i&&/ace_fold-widget/.test(i.className)&&(i.className+=" ace_invalid")}},this.$toggleFoldWidget=function(e,t){if(!this.getFoldWidget)return;var n=this.getFoldWidget(e),r=this.getLine(e),i=n==="end"?-1:1,s=this.getFoldAt(e,i===-1?0:r.length,i);if(s)return t.children||t.all?this.removeFold(s):this.expandFold(s),s;var o=this.getFoldWidgetRange(e,!0);if(o&&!o.isMultiLine()){s=this.getFoldAt(o.start.row,o.start.column,1);if(s&&o.isEqual(s.range))return this.removeFold(s),s}if(t.siblings){var u=this.getParentFoldRangeData(e);if(u.range)var a=u.range.start.row+1,f=u.range.end.row;this.foldAll(a,f,t.all?1e4:0)}else t.children?(f=o?o.end.row:this.getLength(),this.foldAll(e+1,f,t.all?1e4:0)):o&&(t.all&&(o.collapseChildren=1e4),this.addFold("...",o));return o},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var n=this.$toggleFoldWidget(t,{});if(n)return;var r=this.getParentFoldRangeData(t,!0);n=r.range||r.firstRange;if(n){t=n.start.row;var i=this.getFoldAt(t,this.getLine(t).length,1);i?this.removeFold(i):this.addFold("...",n)}},this.updateFoldWidgets=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.foldWidgets[t]=null;else if(e.action=="remove")this.foldWidgets.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,r)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e("../range").Range,i=e("./fold_line").FoldLine,s=e("./fold").Fold,o=e("../token_iterator").TokenIterator;t.Folding=u}),define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,n){"use strict";function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n=="")return null;var r=n.match(/([\(\[\{])|([\)\]\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\(\[\{])|([\)\]\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\(\[\{])|([\)\]\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("rparen",".paren").replace(/\b(?:end)\b/,"(?:start|begin|end)")+")+"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("lparen",".paren").replace(/\b(?:start|begin)\b/,"(?:start|begin|end)")+")+"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(a=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}r.implement(this,u),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$docRowCache.length,n=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>n&&(this.$docRowCache.splice(n,t),this.$screenRowCache.splice(n,t))},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:"fold",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:"doc",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:"aceupdate",args:[t.$deltas,t],merge:t.mergeUndoDeltas}),t.mergeUndoDeltas=!1,t.$deltas=[]},this.$informUndoManager=i.delayedCall(this.$syncInformUndoManager)}},this.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?i.stringRepeat(" ",this.getTabSize()):" "},this.setUseSoftTabs=function(e){this.setOption("useSoftTabs",e)},this.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},this.setTabSize=function(e){this.setOption("tabSize",e)},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},this.setNavigateWithinSoftTabs=function(e){this.setOption("navigateWithinSoftTabs",e)},this.getNavigateWithinSoftTabs=function(){return this.$navigateWithinSoftTabs},this.$overwrite=!1,this.setOverwrite=function(e){this.setOption("overwrite",e)},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._signal("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._signal("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\s+$/.test(n.slice(t-1,t+1)))var i=/\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(oe&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:Infinity,u=t.length;for(var a=0;ao){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=e.length-1;r!=-1;r--){var i=e[r];i.group=="doc"?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=0;re.end.column&&(s.start.column+=u),s.end.row==e.end.row&&s.end.column>e.end.column&&(s.end.column+=u)),o&&s.start.row>=e.end.row&&(s.start.row+=o,s.end.row+=o)}s.end=this.insert(s.start,r);if(i.length){var a=e.start,f=s.start,o=f.row-a.row,u=f.column-a.column;this.addFolds(i.map(function(e){return e=e.clone(),e.start.row==a.row&&(e.start.column+=u),e.end.row==a.row&&(e.end.column+=u),e.start.row+=o,e.end.row+=o,e}))}return s},this.indentRows=function(e,t,n){n=n.replace(/\t/g,this.getTabString());for(var r=e;r<=t;r++)this.doc.insertInLine({row:r,column:0},n)},this.outdentRows=function(e){var t=e.collapseRows(),n=new l(0,0,0,0),r=this.getTabSize();for(var i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;o0){var r=this.getRowFoldEnd(t+n);if(r>this.doc.getLength()-1)return 0;var i=r-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var i=t-e+1}var s=new l(e,0,t,Number.MAX_VALUE),o=this.getFoldsInRange(s).map(function(e){return e=e.clone(),e.start.row+=i,e.end.row+=i,e}),u=n==0?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+i,u),o.length&&this.addFolds(o),i},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){if(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$bidiHandler.markAsDirty(),this.$useWrapMode&&this._signal("changeWrapMode")},this.adjustWrapLimit=function(e,t){var n=this.$wrapLimitRange;n.max<0&&(n={min:t,max:t});var r=this.$constrainWrapLimit(e,n.min,n.max);return r!=this.$wrapLimit&&r>1?(this.$wrapLimit=r,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e,t,n){return t&&(e=Math.max(t,e)),n&&(e=Math.min(n,e)),e},this.getWrapLimit=function(){return this.$wrapLimit},this.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n=e.action,r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=null;this.$updating=!0;if(u!=0)if(n==="remove"){this[t?"$wrapData":"$rowLengthCache"].splice(s,u);var f=this.$foldData;a=this.getFoldsInRange(e),this.removeFolds(a);var l=this.getFoldLine(i.row),c=0;if(l){l.addRemoveChars(i.row,i.column,r.column-i.column),l.shiftRow(-u);var h=this.getFoldLine(s);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c=i.row&&l.shiftRow(-u)}o=s}else{var p=Array(u);p.unshift(s,0);var d=t?this.$wrapData:this.$rowLengthCache;d.splice.apply(d,p);var f=this.$foldData,l=this.getFoldLine(s),c=0;if(l){var v=l.range.compareInside(r.row,r.column);v==0?(l=l.split(r.row,r.column),l&&(l.shiftRow(u),l.addRemoveChars(o,0,i.column-r.column))):v==-1&&(l.addRemoveChars(s,0,i.column-r.column),l.shiftRow(u)),c=f.indexOf(l)+1}for(c;c=s&&l.shiftRow(u)}}else{u=Math.abs(e.start.column-e.end.column),n==="remove"&&(a=this.getFoldsInRange(e),this.removeFolds(a),u=-u);var l=this.getFoldLine(s);l&&l.addRemoveChars(s,r.column,u)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),this.$updating=!1,t?this.$updateWrapData(s,o):this.$updateRowLengthCache(s,o),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var r=this.doc.getAllLines(),i=this.getTabSize(),o=this.$wrapData,u=this.$wrapLimit,a,f,l=e;t=Math.min(t,r.length-1);while(l<=t)f=this.getFoldLine(l,f),f?(a=[],f.walk(function(e,t,i,o){var u;if(e!=null){u=this.$getDisplayTokens(e,a.length),u[0]=n;for(var f=1;fr-b){var w=f+r-b;if(e[w-1]>=c&&e[w]>=c){y(w);continue}if(e[w]==n||e[w]==s){for(w;w!=f-1;w--)if(e[w]==n)break;if(w>f){y(w);continue}w=f+r;for(w;w>2)),f-1);while(w>E&&e[w]E&&e[w]E&&e[w]==a)w--}else while(w>E&&e[w]E){y(++w);continue}w=f+r,e[w]==t&&w--,y(w-b)}return o},this.$getDisplayTokens=function(n,r){var i=[],s;r=r||0;for(var o=0;o39&&u<48||u>57&&u<64?i.push(a):u>=4352&&m(u)?i.push(e,t):i.push(e)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i=4352&&m(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.lineWidgets=null,this.getRowLength=function(e){if(this.lineWidgets)var t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;else t=0;return!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.getRowLineCount=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),n=this.$wrapData[t.row];return n.length&&n[0]=0)var u=f[l],i=this.$docRowCache[l],h=e>f[c-1];else var h=!c;var p=this.getLength()-1,d=this.getNextFoldLine(i),v=d?d.start.row:Infinity;while(u<=e){a=this.getRowLength(i);if(u+a>e||i>=p)break;u+=a,i++,i>v&&(i=d.end.row+1,d=this.getNextFoldLine(i,d),v=d?d.start.row:Infinity),h&&(this.$docRowCache.push(i),this.$screenRowCache.push(u))}if(d&&d.start.row<=i)r=this.getFoldDisplayLine(d),i=d.start.row;else{if(u+a<=e||i>p)return{row:p,column:this.getLine(p).length};r=this.getLine(i),d=null}var m=0,g=Math.floor(e-u);if(this.$useWrapMode){var y=this.$wrapData[i];y&&(o=y[g],g>0&&y.length&&(m=y.indent,s=y[g-1]||y[y.length-1],r=r.substring(s)))}return n!==undefined&&this.$bidiHandler.isBidiRow(u+g,i,g)&&(t=this.$bidiHandler.offsetToCol(n)),s+=this.$getStringScreenWidth(r,t-m)[1],this.$useWrapMode&&s>=o&&(s=o-1),d?d.idxToPosition(s):{row:i,column:s}},this.documentToScreenPosition=function(e,t){if(typeof t=="undefined")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d="";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);var v=0;if(this.$useWrapMode){var m=this.$wrapData[i];if(m){var g=0;while(d.length>=m[g])r++,g++;d=d.substring(m[g-1]||0,d.length),v=g>0?m.indent:0}}return{row:r,column:v+this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;ro&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}}return this.lineWidgets&&(e+=this.$getWidgetScreenLength()),e},this.$setFontMetrics=function(e){if(!this.$enableVarChar)return;this.$getStringScreenWidth=function(t,n,r){if(n===0)return[0,0];n||(n=Infinity),r=r||0;var i,s;for(s=0;sn)break}return[r,s]}},this.destroy=function(){this.bgTokenizer&&(this.bgTokenizer.setDocument(null),this.bgTokenizer=null),this.$stopWorker()},this.isFullWidth=m}.call(d.prototype),e("./edit_session/folding").Folding.call(d.prototype),e("./edit_session/bracket_match").BracketMatch.call(d.prototype),o.defineOptions(d.prototype,"session",{wrap:{set:function(e){!e||e=="off"?e=!1:e=="free"?e=!0:e=="printMargin"?e=-1:typeof e=="string"&&(e=parseInt(e,10)||!1);if(this.$wrap==e)return;this.$wrap=e;if(!e)this.setUseWrapMode(!1);else{var t=typeof e=="number"?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}},get:function(){return this.getUseWrapMode()?this.$wrap==-1?"printMargin":this.getWrapLimitRange().min?this.$wrap:"free":"off"},handlesSet:!0},wrapMethod:{set:function(e){e=e=="auto"?this.$mode.type!="text":e!="text",e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$modified=!0,this.$resetRowCache(0),this.$updateWrapData(0,this.getLength()-1)))},initialValue:"auto"},indentedSoftWrap:{initialValue:!0},firstLineNumber:{set:function(){this._signal("changeBreakpoint")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal("changeTabSize")},initialValue:4,handlesSet:!0},navigateWithinSoftTabs:{initialValue:!1},overwrite:{set:function(e){this._signal("changeOverwrite")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId}}}),t.EditSession=d}),define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){"use strict";function u(e,t){function n(e){return/\w/.test(e)||t.regExp?"\\b":""}return n(e[0])+e+n(e[e.length-1])}var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(){this.$options={}};(function(){this.set=function(e){return i.mixin(this.$options,e),this},this.getOptions=function(){return r.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$options,n=this.$matchIterator(e,t);if(!n)return!1;var r=null;return n.forEach(function(e,n,i,o){return r=new s(e,n,i,o),n==o&&t.start&&t.start.start&&t.skipCurrent!=0&&r.isEqual(t.start)?(r=null,!1):!0}),r},this.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var n=t.range,i=n?e.getLines(n.start.row,n.end.row):e.doc.getAllLines(),o=[],u=t.re;if(t.$isMultiLine){var a=u.length,f=i.length-a,l;e:for(var c=u.offset||0;c<=f;c++){for(var h=0;hv)continue;o.push(l=new s(c,v,c+a-1,m)),a>2&&(c=c+a-2)}}else for(var g=0;gE&&o[h].end.row==n.end.row)h--;o=o.slice(g,h+1);for(g=0,h=o.length;g=u;n--)if(c(n,Number.MAX_VALUE,e))return;if(t.wrap==0)return;for(n=a,u=o.row;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return};else var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n+=1;n<=a;n++)if(c(n,0,e))return;if(t.wrap==0)return;for(n=u,a=o.row;n<=a;n++)if(c(n,0,e))return};if(t.$isMultiLine)var l=n.length,c=function(t,i,s){var o=r?t-l+1:t;if(o<0)return;var u=e.getLine(o),a=u.search(n[0]);if(!r&&ai)return;if(s(o,a,o+l-1,c))return!0};else if(r)var c=function(t,r,i){var s=e.getLine(t),o=[],u,a=0;n.lastIndex=0;while(u=n.exec(s)){var f=u[0].length;a=u.index;if(!f){if(a>=s.length)break;n.lastIndex=a+=1}if(u.index+f>r)break;o.push(u.index,f)}for(var l=o.length-1;l>=0;l-=2){var c=o[l-1],f=o[l];if(i(t,c,t,c+f))return!0}};else var c=function(t,r,i){var s=e.getLine(t),o,u=r;n.lastIndex=r;while(o=n.exec(s)){var a=o[0].length;u=o.index;if(i(t,u,t,u+a))return!0;if(!a){n.lastIndex=u+=1;if(u>=s.length)return!1}}};return{forEach:f}}}).call(o.prototype),t.Search=o}),define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,n){"use strict";function o(e,t){this.platform=t||(i.isMac?"mac":"win"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=!0}function u(e,t){o.call(this,e,t),this.$singleCommand=!1}var r=e("../lib/keys"),i=e("../lib/useragent"),s=r.KEY_MODS;u.prototype=o.prototype,function(){function e(e){return typeof e=="object"&&e.bindKey&&e.bindKey.position||(e.isDefault?-100:0)}this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e,t){var n=e&&(typeof e=="string"?e:e.name);e=this.commands[n],t||delete this.commands[n];var r=this.commandKeyBinding;for(var i in r){var s=r[i];if(s==e)delete r[i];else if(Array.isArray(s)){var o=s.indexOf(e);o!=-1&&(s.splice(o,1),s.length==1&&(r[i]=s[0]))}}},this.bindKey=function(e,t,n){typeof e=="object"&&e&&(n==undefined&&(n=e.position),e=e[this.platform]);if(!e)return;if(typeof t=="function")return this.addCommand({exec:t,bindKey:e,name:t.name||e});e.split("|").forEach(function(e){var r="";if(e.indexOf(" ")!=-1){var i=e.split(/\s+/);e=i.pop(),i.forEach(function(e){var t=this.parseKeys(e),n=s[t.hashId]+t.key;r+=(r?" ":"")+n,this._addCommandToBinding(r,"chainKeys")},this),r+=" "}var o=this.parseKeys(e),u=s[o.hashId]+o.key;this._addCommandToBinding(r+u,t,n)},this)},this._addCommandToBinding=function(t,n,r){var i=this.commandKeyBinding,s;if(!n)delete i[t];else if(!i[t]||this.$singleCommand)i[t]=n;else{Array.isArray(i[t])?(s=i[t].indexOf(n))!=-1&&i[t].splice(s,1):i[t]=[i[t]],typeof r!="number"&&(r=e(n));var o=i[t];for(s=0;sr)break}o.splice(s,0,n)}},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(!n)return;if(typeof n=="string")return this.bindKey(n,t);typeof n=="function"&&(n={exec:n});if(typeof n!="object")return;n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]=="shift")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)return typeof console!="undefined"&&console.error("invalid modifier "+t[o]+" in "+e),!1;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=s[t]+n;return this.commandKeyBinding[r]},this.handleKeyboard=function(e,t,n,r){if(r<0)return;var i=s[t]+n,o=this.commandKeyBinding[i];e.$keyChain&&(e.$keyChain+=" "+i,o=this.commandKeyBinding[e.$keyChain]||o);if(o)if(o=="chainKeys"||o[o.length-1]=="chainKeys")return e.$keyChain=e.$keyChain||i,{command:"null"};if(e.$keyChain)if(!!t&&t!=4||n.length!=1){if(t==-1||r>0)e.$keyChain=""}else e.$keyChain=e.$keyChain.slice(0,-i.length-1);return{command:o}},this.getStatusText=function(e,t){return t.$keyChain||""}}.call(o.prototype),t.HashHandler=o,t.MultiHashHandler=u}),define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../keyboard/hash_handler").MultiHashHandler,s=e("../lib/event_emitter").EventEmitter,o=function(e,t){i.call(this,t,e),this.byName=this.commands,this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){if(Array.isArray(e)){for(var r=e.length;r--;)if(this.exec(e[r],t,n))return!0;return!1}typeof e=="string"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;if(e.isAvailable&&!e.isAvailable(t))return!1;var i={editor:t,command:e,args:n};return i.returnValue=this._emit("exec",i),this._signal("afterExec",i),i.returnValue===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t=="string"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!="string"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"],function(e,t,n){"use strict";function o(e,t){return{win:e,mac:t}}var r=e("../lib/lang"),i=e("../config"),s=e("../range").Range;t.commands=[{name:"showSettingsMenu",bindKey:o("Ctrl-,","Command-,"),exec:function(e){i.loadModule("ace/ext/settings_menu",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:"goToNextError",bindKey:o("Alt-E","F4"),exec:function(e){i.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,1)})},scrollIntoView:"animate",readOnly:!0},{name:"goToPreviousError",bindKey:o("Alt-Shift-E","Shift-F4"),exec:function(e){i.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:"animate",readOnly:!0},{name:"selectall",bindKey:o("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:o(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:o("Ctrl-L","Command-L"),exec:function(e){var t=parseInt(prompt("Enter line number:"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:o("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"unfold",bindKey:o("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleFoldWidget",bindKey:o("F2","F2"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleParentFoldWidget",bindKey:o("Alt-F2","Alt-F2"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"foldall",bindKey:o(null,"Ctrl-Command-Option-0"),exec:function(e){e.session.foldAll()},scrollIntoView:"center",readOnly:!0},{name:"foldOther",bindKey:o("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:"center",readOnly:!0},{name:"unfoldall",bindKey:o("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},scrollIntoView:"center",readOnly:!0},{name:"findnext",bindKey:o("Ctrl-K","Command-G"),exec:function(e){e.findNext()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"findprevious",bindKey:o("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"selectOrFindNext",bindKey:o("Alt-K","Ctrl-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:"selectOrFindPrevious",bindKey:o("Alt-Shift-K","Ctrl-Shift-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:"find",bindKey:o("Ctrl-F","Command-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e)})},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:o("Ctrl-Shift-Home","Command-Shift-Home|Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotostart",bindKey:o("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectup",bindKey:o("Shift-Up","Shift-Up|Ctrl-Shift-P"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golineup",bindKey:o("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttoend",bindKey:o("Ctrl-Shift-End","Command-Shift-End|Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotoend",bindKey:o("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectdown",bindKey:o("Shift-Down","Shift-Down|Ctrl-Shift-N"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golinedown",bindKey:o("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordleft",bindKey:o("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordleft",bindKey:o("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolinestart",bindKey:o("Alt-Shift-Left","Command-Shift-Left|Ctrl-Shift-A"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolinestart",bindKey:o("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectleft",bindKey:o("Shift-Left","Shift-Left|Ctrl-Shift-B"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoleft",bindKey:o("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordright",bindKey:o("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordright",bindKey:o("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolineend",bindKey:o("Alt-Shift-Right","Command-Shift-Right|Shift-End|Ctrl-Shift-E"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolineend",bindKey:o("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectright",bindKey:o("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoright",bindKey:o("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:o(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:o("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:o(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:o("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:o("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"togglerecording",bindKey:o("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:o("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:o("Ctrl-P","Ctrl-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"selecttomatching",bindKey:o("Ctrl-Shift-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"expandToMatching",bindKey:o("Ctrl-Shift-M","Ctrl-Shift-M"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"passKeysToBrowser",bindKey:o(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:"copy",exec:function(e){},readOnly:!0},{name:"cut",exec:function(e){var t=e.getSelectionRange();e._emit("cut",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"paste",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:"cursor"},{name:"removeline",bindKey:o("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},scrollIntoView:"cursor",multiSelectAction:"forEachLine"},{name:"duplicateSelection",bindKey:o("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"sortlines",bindKey:o("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},scrollIntoView:"selection",multiSelectAction:"forEachLine"},{name:"togglecomment",bindKey:o("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"toggleBlockComment",bindKey:o("Ctrl-Shift-/","Command-Shift-/"),exec:function(e){e.toggleBlockComment()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"modifyNumberUp",bindKey:o("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:o("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"replace",bindKey:o("Ctrl-H","Command-Option-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e,!0)})}},{name:"undo",bindKey:o("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:o("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:o("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()},scrollIntoView:"cursor"},{name:"movelinesup",bindKey:o("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()},scrollIntoView:"cursor"},{name:"copylinesdown",bindKey:o("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()},scrollIntoView:"cursor"},{name:"movelinesdown",bindKey:o("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()},scrollIntoView:"cursor"},{name:"del",bindKey:o("Delete","Delete|Ctrl-D|Shift-Delete"),exec:function(e){e.remove("right")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"backspace",bindKey:o("Shift-Backspace|Backspace","Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"cut_or_delete",bindKey:o("Shift-Delete",null),exec:function(e){if(!e.selection.isEmpty())return!1;e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestart",bindKey:o("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineend",bindKey:o("Alt-Delete","Ctrl-K|Command-Delete"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestarthard",bindKey:o("Ctrl-Shift-Backspace",null),exec:function(e){var t=e.selection.getRange();t.start.column=0,e.session.remove(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineendhard",bindKey:o("Ctrl-Shift-Delete",null),exec:function(e){var t=e.selection.getRange();t.end.column=Number.MAX_VALUE,e.session.remove(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordleft",bindKey:o("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordright",bindKey:o("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"outdent",bindKey:o("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"indent",bindKey:o("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"blockoutdent",bindKey:o("Ctrl-[","Ctrl-["),exec:function(e){e.blockOutdent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"blockindent",bindKey:o("Ctrl-]","Ctrl-]"),exec:function(e){e.blockIndent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"splitline",bindKey:o(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"transposeletters",bindKey:o("Alt-Shift-X","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:"cursor"},{name:"touppercase",bindKey:o("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"tolowercase",bindKey:o("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"expandtoline",bindKey:o("Ctrl-Shift-L","Command-Shift-L"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"joinlines",bindKey:o(null,null),exec:function(e){var t=e.selection.isBackwards(),n=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),i=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(n.row).length,u=e.session.doc.getTextRange(e.selection.getRange()),a=u.replace(/\n\s*/," ").length,f=e.session.doc.getLine(n.row);for(var l=n.row+1;l<=i.row+1;l++){var c=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(l)));c.length!==0&&(c=" "+c),f+=c}i.row+10?(e.selection.moveCursorTo(n.row,n.column),e.selection.selectTo(n.row,n.column+a)):(o=e.session.doc.getLine(n.row).length>o?o+1:o,e.selection.moveCursorTo(n.row,o))},multiSelectAction:"forEach",readOnly:!0},{name:"invertSelection",bindKey:o(null,null),exec:function(e){var t=e.session.doc.getLength()-1,n=e.session.doc.getLine(t).length,r=e.selection.rangeList.ranges,i=[];r.length<1&&(r=[e.selection.getRange()]);for(var o=0;o0&&this.$blockScrolling--;var n=t&&t.scrollIntoView;if(n){switch(n){case"center-animate":n="animate";case"center":this.renderer.scrollCursorIntoView(null,.5);break;case"animate":case"cursor":this.renderer.scrollCursorIntoView();break;case"selectionPart":var r=this.selection.getRange(),i=this.renderer.layerConfig;(r.start.row>=i.lastRow||r.end.row<=i.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead);break;default:}n=="animate"&&this.renderer.animateScrolling(this.curOp.scrollTop)}this.prevOp=this.curOp,this.curOp=null}},this.$mergeableCommands=["backspace","del","insertstring"],this.$historyTracker=function(e){if(!this.$mergeUndoDeltas)return;var t=this.prevOp,n=this.$mergeableCommands,r=t.command&&e.command.name==t.command.name;if(e.command.name=="insertstring"){var i=e.args;this.mergeNextCommand===undefined&&(this.mergeNextCommand=!0),r=r&&this.mergeNextCommand&&(!/\s/.test(i)||/\s/.test(t.args)),this.mergeNextCommand=!0}else r=r&&n.indexOf(e.command.name)!==-1;this.$mergeUndoDeltas!="always"&&Date.now()-this.sequenceStartTime>2e3&&(r=!1),r?this.session.mergeUndoDeltas=!0:n.indexOf(e.command.name)!==-1&&(this.sequenceStartTime=Date.now())},this.setKeyboardHandler=function(e,t){if(e&&typeof e=="string"){this.$keybindingId=e;var n=this;g.loadModule(["keybinding",e],function(r){n.$keybindingId==e&&n.keyBinding.setKeyboardHandler(r&&r.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.off("change",this.$onDocumentChange),this.session.off("changeMode",this.$onChangeMode),this.session.off("tokenizerUpdate",this.$onTokenizerUpdate),this.session.off("changeTabSize",this.$onChangeTabSize),this.session.off("changeWrapLimit",this.$onChangeWrapLimit),this.session.off("changeWrapMode",this.$onChangeWrapMode),this.session.off("changeFold",this.$onChangeFold),this.session.off("changeFrontMarker",this.$onChangeFrontMarker),this.session.off("changeBackMarker",this.$onChangeBackMarker),this.session.off("changeBreakpoint",this.$onChangeBreakpoint),this.session.off("changeAnnotation",this.$onChangeAnnotation),this.session.off("changeOverwrite",this.$onCursorChange),this.session.off("changeScrollTop",this.$onScrollTopChange),this.session.off("changeScrollLeft",this.$onScrollLeftChange);var n=this.session.getSelection();n.off("changeCursor",this.$onCursorChange),n.off("changeSelection",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.on("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.on("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.on("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.on("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.on("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.on("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.on("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.on("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal("changeSession",{session:e,oldSession:t}),this.curOp=null,t&&t._signal("changeEditor",{oldEditor:this}),e&&e._signal("changeEditor",{editor:this}),e&&e.bgTokenizer&&e.bgTokenizer.scheduleStart()},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e,t){this.renderer.setTheme(e,t)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.getFontSize=function(){return this.getOption("fontSize")||i.computedStyle(this.container,"fontSize")},this.setFontSize=function(e){this.setOption("fontSize",e)},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=t.findMatchingBracket(e.getCursorPosition());if(n)var r=new p(n.row,n.column,n.row,n.column+1);else if(t.$mode.getMatching)var r=t.$mode.getMatching(e.session);r&&(t.$bracketHighlight=t.addMarker(r,"ace_bracket","text"))},50)},this.$highlightTags=function(){if(this.$highlightTagPending)return;var e=this;this.$highlightTagPending=!0,setTimeout(function(){e.$highlightTagPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=e.getCursorPosition(),r=new y(e.session,n.row,n.column),i=r.getCurrentToken();if(!i||!/\b(?:tag-open|tag-name)/.test(i.type)){t.removeMarker(t.$tagHighlight),t.$tagHighlight=null;return}if(i.type.indexOf("tag-open")!=-1){i=r.stepForward();if(!i)return}var s=i.value,o=0,u=r.stepBackward();if(u.value=="<"){do u=i,i=r.stepForward(),i&&i.value===s&&i.type.indexOf("tag-name")!==-1&&(u.value==="<"?o++:u.value==="=0)}else{do i=u,u=r.stepBackward(),i&&i.value===s&&i.type.indexOf("tag-name")!==-1&&(u.value==="<"?o++:u.value==="1)&&(t=!1)}if(e.$highlightLineMarker&&!t)e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null;else if(!e.$highlightLineMarker&&t){var n=new p(t.row,t.column,t.row,Infinity);n.id=e.addMarker(n,"ace_active-line","screenLine"),e.$highlightLineMarker=n}else t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e.$highlightLineMarker.start.column=t.column,e._signal("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,"ace_selection",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._signal("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column-1,r=t.end.column+1,i=e.getLine(t.start.row),s=i.length,o=i.substring(Math.max(n,0),Math.min(r,s));if(n>=0&&/^[\w\d]/.test(o)||r<=s&&/[\w\d]$/.test(o))return;o=i.substring(t.start.column,t.end.column);if(!/^[\w\d]+$/.test(o))return;var u=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:o});return u},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(e){this.renderer.updateText(),this._emit("changeMode",e)},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},this.getCopyText=function(){var e=this.getSelectedText();return this._signal("copy",e),e},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(e,t){var n={text:e,event:t};this.commands.exec("paste",this,n)},this.$handlePaste=function(e){typeof e=="string"&&(e={text:e}),this._signal("paste",e);var t=e.text;if(!this.inMultiSelectMode||this.inVirtualSelectionMode)this.insert(t);else{var n=t.split(/\r\n|\r|\n/),r=this.selection.rangeList.ranges;if(n.length>r.length||n.length<2||!n[1])return this.commands.exec("insertstring",this,t);for(var i=r.length;i--;){var s=r[i];s.isEmpty()||this.session.remove(s),this.session.insert(s.start,n[i])}}},this.execCommand=function(e,t){return this.commands.exec(e,this,t)},this.insert=function(e,t){var n=this.session,r=n.getMode(),i=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var s=r.transformAction(n.getState(i.row),"insertion",this,n,e);s&&(e!==s.text&&(this.session.mergeUndoDeltas=!1,this.$mergeNextCommand=!1),e=s.text)}e==" "&&(e=this.session.getTabString());if(!this.selection.isEmpty()){var o=this.getSelectionRange();i=this.session.remove(o),this.clearSelection()}else if(this.session.getOverwrite()&&e.indexOf("\n")==-1){var o=new p.fromPoints(i,i);o.end.column+=e.length,this.session.remove(o)}if(e=="\n"||e=="\r\n"){var u=n.getLine(i.row);if(i.column>u.search(/\S|$/)){var a=u.substr(i.column).search(/\S|$/);n.doc.removeInLine(i.row,i.column,i.column+a)}}this.clearSelection();var f=i.column,l=n.getState(i.row),u=n.getLine(i.row),c=r.checkOutdent(l,u,e),h=n.insert(i,e);s&&s.selection&&(s.selection.length==2?this.selection.setSelectionRange(new p(i.row,f+s.selection[0],i.row,f+s.selection[1])):this.selection.setSelectionRange(new p(i.row+s.selection[0],s.selection[1],i.row+s.selection[2],s.selection[3])));if(n.getDocument().isNewLine(e)){var d=r.getNextLineIndent(l,u.slice(0,i.column),n.getTabString());n.insert({row:i.row+1,column:0},d)}c&&r.autoOutdent(l,n,i.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption("scrollSpeed",e)},this.getScrollSpeed=function(){return this.getOption("scrollSpeed")},this.setDragDelay=function(e){this.setOption("dragDelay",e)},this.getDragDelay=function(){return this.getOption("dragDelay")},this.setSelectionStyle=function(e){this.setOption("selectionStyle",e)},this.getSelectionStyle=function(){return this.getOption("selectionStyle")},this.setHighlightActiveLine=function(e){this.setOption("highlightActiveLine",e)},this.getHighlightActiveLine=function(){return this.getOption("highlightActiveLine")},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.setHighlightSelectedWord=function(e){this.setOption("highlightSelectedWord",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption("readOnly",e)},this.getReadOnly=function(){return this.getOption("readOnly")},this.setBehavioursEnabled=function(e){this.setOption("behavioursEnabled",e)},this.getBehavioursEnabled=function(){return this.getOption("behavioursEnabled")},this.setWrapBehavioursEnabled=function(e){this.setOption("wrapBehavioursEnabled",e)},this.getWrapBehavioursEnabled=function(){return this.getOption("wrapBehavioursEnabled")},this.setShowFoldWidgets=function(e){this.setOption("showFoldWidgets",e)},this.getShowFoldWidgets=function(){return this.getOption("showFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.remove=function(e){this.selection.isEmpty()&&(e=="left"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,"deletion",this,n,t);if(t.end.column===0){var s=n.getTextRange(t);if(s[s.length-1]=="\n"){var o=n.getLine(t.end.row);/^\s+$/.test(o)&&(t.end.column=o.length)}}i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;tt.toLowerCase()?1:0});var i=new p(0,0,0,0);for(var r=e.first;r<=e.last;r++){var s=t.getLine(r);i.start.row=r,i.end.row=r,i.end.column=s.length,t.replace(i,n[r-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),n=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,n,e)},this.getNumberAt=function(e,t){var n=/[\-]?[0-9]+(?:\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new p(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(".")>=0?s.start+s.value.indexOf(".")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&np+1)break;p=d.last}l--,u=this.session.$moveLines(h,p,t?0:e),t&&e==-1&&(c=l+1);while(c<=l)o[c].moveBy(u,0),c++;t||(u=0),a+=u}i.fromOrientedRange(i.ranges[0]),i.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},this.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},this.onCompositionStart=function(e){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t===!1&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e,t){var n=this.getCursorPosition(),r=new y(this.session,n.row,n.column),i=r.getCurrentToken(),s=i||r.stepForward();if(!s)return;var o,u=!1,a={},f=n.column-s.start,l,c={")":"(","(":"(","]":"[","[":"[","{":"{","}":"{"};do{if(s.value.match(/[{}()\[\]]/g))for(;f=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),this.$blockScrolling-=1,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e=="string"||e instanceof RegExp?t.needle=e:typeof e=="object"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal("destroy",this),this.session&&this.session.destroy()},this.setAutoScrollEditorIntoView=function(e){if(!e)return;var t,n=this,r=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement("div"));var i=this.$scrollAnchor;i.style.cssText="position:absolute",this.container.insertBefore(i,this.container.firstChild);var s=this.on("changeSelection",function(){r=!0}),o=this.renderer.on("beforeRender",function(){r&&(t=n.renderer.container.getBoundingClientRect())}),u=this.renderer.on("afterRender",function(){if(r&&t&&(n.isFocused()||n.searchBox&&n.searchBox.isFocused())){var e=n.renderer,s=e.$cursorLayer.$pixelPos,o=e.layerConfig,u=s.top-o.offset;s.top>=0&&u+t.top<0?r=!0:s.topwindow.innerHeight?r=!1:r=null,r!=null&&(i.style.top=u+"px",i.style.left=s.left+"px",i.style.height=o.lineHeight+"px",i.scrollIntoView(r)),r=t=null}});this.setAutoScrollEditorIntoView=function(e){if(e)return;delete this.setAutoScrollEditorIntoView,this.off("changeSelection",s),this.renderer.off("afterRender",u),this.renderer.off("beforeRender",o)}},this.$resetCursorStyle=function(){var e=this.$cursorStyle||"ace",t=this.renderer.$cursorLayer;if(!t)return;t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&e!="wide",i.setCssClass(t.element,"ace_slim-cursors",/slim/.test(e))}}.call(b.prototype),g.defineOptions(b.prototype,"editor",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal("changeSelectionStyle",{data:e})},initialValue:"line"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.$resetCursorStyle()},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:["ace","slim","smooth","wide"],initialValue:"ace"},mergeUndoDeltas:{values:[!1,!0,"always"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},keyboardHandler:{set:function(e){this.setKeyboardHandler(e)},get:function(){return this.keybindingId},handlesSet:!0},hScrollBarAlwaysVisible:"renderer",vScrollBarAlwaysVisible:"renderer",highlightGutterLine:"renderer",animatedScroll:"renderer",showInvisibles:"renderer",showPrintMargin:"renderer",printMarginColumn:"renderer",printMargin:"renderer",fadeFoldWidgets:"renderer",showFoldWidgets:"renderer",showLineNumbers:"renderer",showGutter:"renderer",displayIndentGuides:"renderer",fontSize:"renderer",fontFamily:"renderer",maxLines:"renderer",minLines:"renderer",scrollPastEnd:"renderer",fixedWidthGutter:"renderer",theme:"renderer",scrollSpeed:"$mouseHandler",dragDelay:"$mouseHandler",dragEnabled:"$mouseHandler",focusTimout:"$mouseHandler",tooltipFollowsMouse:"$mouseHandler",firstLineNumber:"session",overwrite:"session",newLineMode:"session",useWorker:"session",useSoftTabs:"session",tabSize:"session",wrap:"session",indentedSoftWrap:"session",foldStyle:"session",mode:"session"}),t.Editor=b}),define("ace/undomanager",["require","exports","module"],function(e,t,n){"use strict";var r=function(){this.reset()};(function(){function e(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines.length==1?null:e.lines,text:e.lines.length==1?e.lines[0]:null}}function t(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines||[e.text]}}function n(e,t){var n=new Array(e.length);for(var r=0;r0},this.hasRedo=function(){return this.$redoStack.length>0},this.markClean=function(){this.dirtyCounter=0},this.isClean=function(){return this.dirtyCounter===0},this.$serializeDeltas=function(t){return n(t,e)},this.$deserializeDeltas=function(e){return n(e,t)}}).call(r.prototype),t.UndoManager=r}),define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/lang"),o=e("../lib/event_emitter").EventEmitter,u=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_gutter-layer",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this),this.$cells=[]};(function(){i.implement(this,o),this.setSession=function(e){this.session&&this.session.removeEventListener("change",this.$updateAnnotations),this.session=e,e&&e.on("change",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.addGutterDecoration"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.removeGutterDecoration"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];for(var t=0;to&&(v=s.end.row+1,s=t.getNextFoldLine(v,s),o=s?s.start.row:Infinity);if(v>i){while(this.$cells.length>d+1)p=this.$cells.pop(),this.element.removeChild(p.element);break}p=this.$cells[++d],p||(p={element:null,textNode:null,foldWidget:null},p.element=r.createElement("div"),p.textNode=document.createTextNode(""),p.element.appendChild(p.textNode),this.element.appendChild(p.element),this.$cells[d]=p);var m="ace_gutter-cell ";a[v]&&(m+=a[v]),f[v]&&(m+=f[v]),this.$annotations[v]&&(m+=this.$annotations[v].className),p.element.className!=m&&(p.element.className=m);var g=t.getRowLength(v)*e.lineHeight+"px";g!=p.element.style.height&&(p.element.style.height=g);if(u){var y=u[v];y==null&&(y=u[v]=t.getFoldWidget(v))}if(y){p.foldWidget||(p.foldWidget=r.createElement("span"),p.element.appendChild(p.foldWidget));var m="ace_fold-widget ace_"+y;y=="start"&&v==o&&vn.right-t.right)return"foldWidgets"}}).call(u.prototype),t.Gutter=u}),define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../range").Range,i=e("../lib/dom"),s=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){function e(e,t,n,r){return(e?1:0)|(t?2:0)|(n?4:0)|(r?8:0)}this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){if(!e)return;this.config=e;var t=[];for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var i=r.range.clipRows(e.firstRow,e.lastRow);if(i.isEmpty())continue;i=i.toScreenRange(this.session);if(r.renderer){var s=this.$getTop(i.start.row,e),o=this.$padding+(this.session.$bidiHandler.isBidiRow(i.start.row)?this.session.$bidiHandler.getPosLeft(i.start.column):i.start.column*e.characterWidth);r.renderer(t,i,o,s,e)}else r.type=="fullLine"?this.drawFullLineMarker(t,i,r.clazz,e):r.type=="screenLine"?this.drawScreenLineMarker(t,i,r.clazz,e):i.isMultiLine()?r.type=="text"?this.drawTextMarker(t,i,r.clazz,e):this.drawMultiLineMarker(t,i,r.clazz,e):this.session.$bidiHandler.isBidiRow(i.start.row)?this.drawBidiSingleLineMarker(t,i,r.clazz+" ace_start"+" ace_br15",e):this.drawSingleLineMarker(t,i,r.clazz+" ace_start"+" ace_br15",e)}this.element.innerHTML=t.join("")},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(t,n,i,s,o){var u=this.session,a=n.start.row,f=n.end.row,l=a,c=0,h=0,p=u.getScreenLastRowColumn(l),d=null,v=new r(l,n.start.column,l,h);for(;l<=f;l++)v.start.row=v.end.row=l,v.start.column=l==a?n.start.column:u.getRowWrapIndent(l),v.end.column=p,c=h,h=p,p=l+1p,l==f),this.session.$bidiHandler.isBidiRow(l)?this.drawBidiSingleLineMarker(t,v,d,s,l==f?0:1,o):this.drawSingleLineMarker(t,v,d,s,l==f?0:1,o)},this.drawMultiLineMarker=function(e,t,n,r,i){var s=this.$padding,o,u,a;i=i||"";if(this.session.$bidiHandler.isBidiRow(t.start.row)){var f=t.clone();f.end.row=f.start.row,f.end.column=this.session.getLine(f.start.row).length,this.drawBidiSingleLineMarker(e,f,n+" ace_br1 ace_start",r,null,i)}else o=r.lineHeight,u=this.$getTop(t.start.row,r),a=s+t.start.column*r.characterWidth,e.push("
    ");if(this.session.$bidiHandler.isBidiRow(t.end.row)){var f=t.clone();f.start.row=f.end.row,f.start.column=0,this.drawBidiSingleLineMarker(e,f,n+" ace_br12",r,null,i)}else{var l=t.end.column*r.characterWidth;o=r.lineHeight,u=this.$getTop(t.end.row,r),e.push("
    ")}o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<=0)return;u=this.$getTop(t.start.row+1,r);var c=(t.start.column?1:0)|(t.end.column?0:8);e.push("
    ")},this.drawSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=(t.end.column+(i||0)-t.start.column)*r.characterWidth,a=this.$getTop(t.start.row,r),f=this.$padding+t.start.column*r.characterWidth;e.push("
    ")},this.drawBidiSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=this.$getTop(t.start.row,r),a=this.$padding,f=this.session.$bidiHandler.getSelections(t.start.column,t.end.column);f.forEach(function(t){e.push("
    ")})},this.drawFullLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;t.start.row!=t.end.row&&(o+=this.$getTop(t.end.row,r)-s),e.push("
    ")},this.drawScreenLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;e.push("
    ")}}).call(s.prototype),t.Marker=s}),define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/useragent"),u=e("../lib/event_emitter").EventEmitter,a=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this)};(function(){r.implement(this,u),this.EOF_CHAR="\u00b6",this.EOL_CHAR_LF="\u00ac",this.EOL_CHAR_CRLF="\u00a4",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR="\u2014",this.SPACE_CHAR="\u00b7",this.$padding=0,this.$updateEolChar=function(){var e=this.session.doc.getNewLineCharacter()=="\n"?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=e)return this.EOL_CHAR=e,!0},this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on("changeCharacterSize",function(e){this._signal("changeCharacterSize",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,e&&this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n"+s.stringRepeat(this.TAB_CHAR,n)+""):t.push(s.stringRepeat(" ",n));if(this.displayIndentGuides){this.$indentGuideRe=/\s\S| \t|\t |\s$/;var r="ace_indent-guide",i="",o="";if(this.showInvisibles){r+=" ace_invisible",i=" ace_invisible_space",o=" ace_invisible_tab";var u=s.stringRepeat(this.SPACE_CHAR,this.tabSize),a=s.stringRepeat(this.TAB_CHAR,this.tabSize)}else var u=s.stringRepeat(" ",this.tabSize),a=u;this.$tabStrings[" "]=""+u+"",this.$tabStrings[" "]=""+a+""}},this.updateLines=function(e,t,n){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;var r=Math.max(t,e.firstRow),i=Math.min(n,e.lastRow),s=this.element.childNodes,o=0;for(var u=e.firstRow;uf&&(u=a.end.row+1,a=this.session.getNextFoldLine(u,a),f=a?a.start.row:Infinity);if(u>i)break;var l=s[o++];if(l){var c=[];this.$renderLine(c,u,!this.$useLineGroups(),u==f?a:!1),l.style.height=e.lineHeight*this.session.getRowLength(u)+"px",l.innerHTML=c.join("")}u++}},this.scrollLines=function(e){var t=this.config;this.config=e;if(!t||t.lastRow0;r--)n.removeChild(n.firstChild);if(t.lastRow>e.lastRow)for(var r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);r>0;r--)n.removeChild(n.lastChild);if(e.firstRowt.lastRow){var i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);n.appendChild(i)}},this.$renderLinesFragment=function(e,t,n){var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=i.createElement("div"),f=[];this.$renderLine(f,s,!1,s==u?o:!1),a.innerHTML=f.join("");if(this.$useLineGroups())a.className="ace_line_group",r.appendChild(a),a.style.height=e.lineHeight*this.session.getRowLength(s)+"px";else while(a.firstChild)r.appendChild(a.firstChild);s++}return r},this.update=function(e){this.config=e;var t=[],n=e.firstRow,r=e.lastRow,i=n,s=this.session.getNextFoldLine(i),o=s?s.start.row:Infinity;for(;;){i>o&&(i=s.end.row+1,s=this.session.getNextFoldLine(i,s),o=s?s.start.row:Infinity);if(i>r)break;this.$useLineGroups()&&t.push("
    "),this.$renderLine(t,i,!1,i==o?s:!1),this.$useLineGroups()&&t.push("
    "),i++}this.element.innerHTML=t.join("")},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var i=this,o=/\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,u=function(e,n,r,o,u){if(n)return i.showInvisibles?""+s.stringRepeat(i.SPACE_CHAR,e.length)+"":e;if(e=="&")return"&";if(e=="<")return"<";if(e==">")return">";if(e==" "){var a=i.session.getScreenTabSize(t+o);return t+=a-1,i.$tabStrings[a]}if(e=="\u3000"){var f=i.showInvisibles?"ace_cjk ace_invisible ace_invisible_space":"ace_cjk",l=i.showInvisibles?i.SPACE_CHAR:"";return t+=1,""+l+""}return r?""+i.SPACE_CHAR+"":(t+=1,""+e+"")},a=r.replace(o,u);if(!this.$textToken[n.type]){var f="ace_"+n.type.replace(/\./g," ace_"),l="";n.type=="fold"&&(l=" style='width:"+n.value.length*this.config.characterWidth+"px;' "),e.push("",a,"")}else e.push(a);return t+r.length},this.renderIndentGuide=function(e,t,n){var r=t.search(this.$indentGuideRe);return r<=0||r>=n?t:t[0]==" "?(r-=r%this.tabSize,e.push(s.stringRepeat(this.$tabStrings[" "],r/this.tabSize)),t.substr(r)):t[0]==" "?(e.push(s.stringRepeat(this.$tabStrings[" "],r)),t.substr(r)):t},this.$renderWrappedLine=function(e,t,n,r){var i=0,o=0,u=n[0],a=0;for(var f=0;f=u)a=this.$renderToken(e,a,l,c.substring(0,u-i)),c=c.substring(u-i),i=u,r||e.push("","
    "),e.push(s.stringRepeat("\u00a0",n.indent)),o++,a=0,u=n[o]||Number.MAX_VALUE;c.length!=0&&(i+=c.length,a=this.$renderToken(e,a,l,c))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;s");if(i.length){var s=this.session.getRowSplitData(t);s&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)}this.showInvisibles&&(r&&(t=r.end.row),e.push("",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"")),n||e.push("
    ")},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.lengthn-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(sn?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:"fold",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../lib/dom"),i,s=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),i===undefined&&(i=!("opacity"in this.element.style)),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors"),this.$updateCursors=(i?this.$updateVisibility:this.$updateOpacity).bind(this)};(function(){this.$updateVisibility=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.visibility=e?"":"hidden"},this.$updateOpacity=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.opacity=e?"":"0"},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&!i&&(this.smoothBlinking=e,r.setCssClass(this.element,"ace_smooth-blinking",e),this.$updateCursors(!0),this.$updateCursors=this.$updateOpacity.bind(this),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){var e=this.$updateCursors;clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking"),e(!0);if(!this.isBlinking||!this.blinkInterval||!this.isVisible)return;this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+(this.session.$bidiHandler.isBidiRow(n.row,e.row)?this.session.$bidiHandler.getPosLeft(n.column):n.column*this.config.characterWidth),i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,r=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=0,i=t.length;ne.height+e.offset||s.top<0)&&n>1)continue;var o=(this.cursors[r++]||this.addCursor()).style;this.drawCursor?this.drawCursor(o,s,e,t[n],this.session):(o.left=s.left+"px",o.top=s.top+"px",o.width=e.characterWidth+"px",o.height=e.lineHeight+"px")}while(this.cursors.length>r)this.removeCursor();var u=this.session.getOverwrite();this.$setOverwrite(u),this.$pixelPos=s,this.restartTimer()},this.drawCursor=null,this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(s.prototype),t.Cursor=s}),define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/event_emitter").EventEmitter,u=32768,a=function(e){this.element=i.createElement("div"),this.element.className="ace_scrollbar ace_scrollbar"+this.classSuffix,this.inner=i.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,s.addListener(this.element,"scroll",this.onScroll.bind(this)),s.addListener(this.element,"mousedown",s.preventDefault)};(function(){r.implement(this,o),this.setVisible=function(e){this.element.style.display=e?"":"none",this.isVisible=e,this.coeff=1}}).call(a.prototype);var f=function(e,t){a.call(this,e),this.scrollTop=0,this.scrollHeight=0,t.$scrollbarWidth=this.width=i.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+"px",this.$minWidth=0};r.inherits(f,a),function(){this.classSuffix="-v",this.onScroll=function(){if(!this.skipEvent){this.scrollTop=this.element.scrollTop;if(this.coeff!=1){var e=this.element.clientHeight/this.scrollHeight;this.scrollTop=this.scrollTop*(1-e)/(this.coeff-e)}this._emit("scroll",{data:this.scrollTop})}this.skipEvent=!1},this.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=this.setScrollHeight=function(e){this.scrollHeight=e,e>u?(this.coeff=u/e,e=u):this.coeff!=1&&(this.coeff=1),this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=e,this.element.scrollTop=e*this.coeff)}}.call(f.prototype);var l=function(e,t){a.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+"px"};r.inherits(l,a),function(){this.classSuffix="-h",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit("scroll",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+"px"},this.setInnerWidth=function(e){this.inner.style.width=e+"px"},this.setScrollWidth=function(e){this.inner.style.width=e+"px"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(l.prototype),t.ScrollBar=f,t.ScrollBarV=f,t.ScrollBarH=l,t.VScrollBar=f,t.HScrollBar=l}),define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,n){"use strict";var r=e("./lib/event"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){this.changes=this.changes|e;if(!this.pending&&this.changes){this.pending=!0;var t=this;r.nextFrame(function(){t.pending=!1;var e;while(e=t.changes)t.changes=0,t.onRender(e)},this.window)}}}).call(i.prototype),t.RenderLoop=i}),define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/useragent"),u=e("../lib/event_emitter").EventEmitter,a=0,f=t.FontMetrics=function(e){this.el=i.createElement("div"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=i.createElement("div"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=i.createElement("div"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),a||this.$testFractionalRect(),this.$measureNode.innerHTML=s.stringRepeat("X",a),this.$characterSize={width:0,height:0},this.checkForSizeChanges()};(function(){r.implement(this,u),this.$characterSize={width:0,height:0},this.$testFractionalRect=function(){var e=i.createElement("div");this.$setMeasureNodeStyles(e.style),e.style.width="0.2px",document.documentElement.appendChild(e);var t=e.getBoundingClientRect().width;t>0&&t<1?a=50:a=100,e.parentNode.removeChild(e)},this.$setMeasureNodeStyles=function(e,t){e.width=e.height="auto",e.left=e.top="0px",e.visibility="hidden",e.position="absolute",e.whiteSpace="pre",o.isIE<8?e["font-family"]="inherit":e.font="inherit",e.overflow=t?"hidden":"visible"},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},this.$measureSizes=function(){if(a===50){var e=null;try{e=this.$measureNode.getBoundingClientRect()}catch(t){e={width:0,height:0}}var n={height:e.height,width:e.width/a}}else var n={height:this.$measureNode.clientHeight,width:this.$measureNode.clientWidth/a};return n.width===0||n.height===0?null:n},this.$measureCharWidth=function(e){this.$main.innerHTML=s.stringRepeat(e,a);var t=this.$main.getBoundingClientRect();return t.width/a},this.getCharacterWidth=function(e){var t=this.charSizes[e];return t===undefined&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)}}).call(f.prototype)}),define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./config"),o=e("./lib/useragent"),u=e("./layer/gutter").Gutter,a=e("./layer/marker").Marker,f=e("./layer/text").Text,l=e("./layer/cursor").Cursor,c=e("./scrollbar").HScrollBar,h=e("./scrollbar").VScrollBar,p=e("./renderloop").RenderLoop,d=e("./layer/font_metrics").FontMetrics,v=e("./lib/event_emitter").EventEmitter,m='.ace_editor {position: relative;overflow: hidden;font: 12px/normal \'Monaco\', \'Menlo\', \'Ubuntu Mono\', \'Consolas\', \'source-code-pro\', monospace;direction: ltr;text-align: left;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;background-color: inherit;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;cursor: text;}.ace_content {position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;min-width: 100%;}.ace_dragging .ace_scroller:before{position: absolute;top: 0;left: 0;right: 0;bottom: 0;content: \'\';background: rgba(250, 250, 250, 0.01);z-index: 1000;}.ace_dragging.ace_dark .ace_scroller:before{background: rgba(0, 0, 0, 0.01);}.ace_selecting, .ace_selecting * {cursor: text !important;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC");}.ace_scrollbar {position: absolute;right: 0;bottom: 0;z-index: 6;}.ace_scrollbar-inner {position: absolute;cursor: text;left: 0;top: 0;}.ace_scrollbar-v{overflow-x: hidden;overflow-y: scroll;top: 0;}.ace_scrollbar-h {overflow-x: scroll;overflow-y: hidden;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;padding: 0 1px;margin: 0 -1px;text-indent: -1em;-ms-user-select: text;-moz-user-select: text;-webkit-user-select: text;user-select: text;white-space: pre!important;}.ace_text-input.ace_composition {background: inherit;color: inherit;z-index: 1000;opacity: 1;text-indent: 0;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;word-wrap: normal;white-space: pre;height: 100%;width: 100%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;}.ace_text-layer {font: inherit !important;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;border-left: 2px solid;transform: translatez(0);}.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_slim-cursors .ace_cursor {border-left-width: 1px;}.ace_overwrite-cursors .ace_cursor {border-left-width: 0;border-bottom: 1px solid;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {-webkit-transition: opacity 0.18s;transition: opacity 0.18s;}.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_line .ace_fold {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC");}.ace_tooltip {background-color: #FFF;background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;max-width: 100%;padding: 3px 4px;position: fixed;z-index: 999999;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: default;white-space: pre;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;pointer-events: none;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: none;width: 11px;vertical-align: top;background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;cursor: pointer;}.ace_folding-enabled .ace_fold-widget {display: inline-block; }.ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==");}.ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}.ace_dark .ace_fold-widget {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC");}.ace_dark .ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-webkit-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-webkit-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}.ace_error-marker {background-color: rgba(255, 0, 0,0.2);position: absolute;z-index: 9;}.ace_highlight-marker {background-color: rgba(255, 255, 0,0.2);position: absolute;z-index: 8;}.ace_br1 {border-top-left-radius : 3px;}.ace_br2 {border-top-right-radius : 3px;}.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}.ace_br4 {border-bottom-right-radius: 3px;}.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}.ace_br8 {border-bottom-left-radius : 3px;}.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_text-input-ios {position: absolute !important;top: -100000px !important;left: -100000px !important;}';i.importCssString(m,"ace_editor.css");var g=function(e,t){var n=this;this.container=e||i.createElement("div"),this.$keepTextAreaAtCursor=!o.isOldIE,i.addCssClass(this.container,"ace_editor"),this.setTheme(t),this.$gutter=i.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.$gutter.setAttribute("aria-hidden",!0),this.scroller=i.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=i.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new u(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new a(this.content);var r=this.$textLayer=new f(this.content);this.canvas=r.element,this.$markerFront=new a(this.content),this.$cursorLayer=new l(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new h(this.container,this),this.scrollBarH=new c(this.container,this),this.scrollBarV.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollTop(e.data-n.scrollMargin.top)}),this.scrollBarH.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollLeft(e.data-n.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new d(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener("changeCharacterSize",function(e){n.updateCharacterSize(),n.onResize(!0,n.gutterWidth,n.$size.width,n.$size.height),n._signal("changeCharacterSize",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$loop=new p(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),s.resetOptions(this),s._emit("renderer",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off("changeNewLineMode",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e);if(!e)return;this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on("changeNewLineMode",this.onChangeNewLineMode)},this.updateLines=function(e,t,n){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow)return;this.$loop.schedule(this.CHANGE_LINES)},this.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar(),this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR)},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.$changes=0,this.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},this.onResize=function(e,t,n,r){if(this.resizing>2)return;this.resizing>0?this.resizing++:this.resizing=e?1:0;var i=this.container;r||(r=i.clientHeight||i.scrollHeight),n||(n=i.clientWidth||i.scrollWidth);var s=this.$updateCachedSize(e,t,n,r);if(!this.$size.scrollerHeight||!n&&!r)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(s|this.$changes,!0):this.$loop.schedule(s|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null},this.$updateCachedSize=function(e,t,n,r){r-=this.$extraHeight||0;var i=0,s=this.$size,o={width:s.width,height:s.height,scrollerHeight:s.scrollerHeight,scrollerWidth:s.scrollerWidth};r&&(e||s.height!=r)&&(s.height=r,i|=this.CHANGE_SIZE,s.scrollerHeight=s.height,this.$horizScroll&&(s.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+"px",i|=this.CHANGE_SCROLL);if(n&&(e||s.width!=n)){i|=this.CHANGE_SIZE,s.width=n,t==null&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,this.scrollBarH.element.style.left=this.scroller.style.left=t+"px",s.scrollerWidth=Math.max(0,n-t-this.scrollBarV.getWidth()),this.scrollBarH.element.style.right=this.scroller.style.right=this.scrollBarV.getWidth()+"px",this.scroller.style.bottom=this.scrollBarH.getHeight()+"px";if(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)i|=this.CHANGE_FULL}return s.$dirty=!n||!r,i&&this._signal("resize",o),i},this.onGutterResize=function(){var e=this.$showGutter?this.$gutter.offsetWidth:0;e!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,e,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):(this.$computeLayerConfig(),this.$loop.schedule(this.CHANGE_MARKER))},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},this.setAnimatedScroll=function(e){this.setOption("animatedScroll",e)},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.setOption("showInvisibles",e),this.session.$bidiHandler.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.getOption("showInvisibles")},this.getDisplayIndentGuides=function(){return this.getOption("displayIndentGuides")},this.setDisplayIndentGuides=function(e){this.setOption("displayIndentGuides",e)},this.setShowPrintMargin=function(e){this.setOption("showPrintMargin",e)},this.getShowPrintMargin=function(){return this.getOption("showPrintMargin")},this.setPrintMarginColumn=function(e){this.setOption("printMarginColumn",e)},this.getPrintMarginColumn=function(){return this.getOption("printMarginColumn")},this.getShowGutter=function(){return this.getOption("showGutter")},this.setShowGutter=function(e){return this.setOption("showGutter",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.$updateGutterLineHighlight=function(){var e=this.$cursorLayer.$pixelPos,t=this.layerConfig.lineHeight;if(this.session.getUseWrapMode()){var n=this.session.selection.getCursor();n.column=0,e=this.$cursorLayer.getPixelPosition(n,!0),t*=this.session.getRowLength(n.row)}this.$gutterLineHighlight.style.top=e.top-this.layerConfig.offset+"px",this.$gutterLineHighlight.style.height=t+"px"},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=i.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",t.visibility=this.$showPrintMargin?"visible":"hidden",this.session&&this.session.$wrap==-1&&this.adjustWrapLimit()},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.scroller},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,n=this.$cursorLayer.$pixelPos.left;t-=e.offset;var r=this.textarea.style,i=this.lineHeight;if(t<0||t>e.height-i){r.top=r.left="0";return}var s=this.characterWidth;if(this.$composition){var o=this.textarea.value.replace(/^\x01+/,"");s*=this.session.$getStringScreenWidth(o)[0]+2,i+=2}n-=this.scrollLeft,n>this.$size.scrollerWidth-s&&(n=this.$size.scrollerWidth-s),n+=this.gutterWidth,r.height=i+"px",r.width=s+"px",r.left=Math.min(n,this.$size.scrollerWidth-s)+"px",r.top=Math.min(t,this.$size.height-i)+"px"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=this.layerConfig,t=e.lastRow,n=this.session.documentToScreenRow(t,0)*e.lineHeight;return n-this.session.getScrollTop()>e.height-e.lineHeight?t-1:t},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,n,r){var i=this.scrollMargin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,i.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-i.top),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption("hScrollBarAlwaysVisible",e)},this.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption("vScrollBarAlwaysVisible",e)},this.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,t){this.$changes&&(e|=this.$changes,this.$changes=0);if(!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t){this.$changes|=e;return}if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal("beforeRender"),this.session&&this.session.$bidiHandler&&this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics);var n=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){e|=this.$computeLayerConfig();if(n.firstRow!=this.layerConfig.firstRow&&n.firstRowScreen==this.layerConfig.firstRowScreen){var r=this.scrollTop+(n.firstRow-this.layerConfig.firstRow)*this.lineHeight;r>0&&(this.scrollTop=r,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig())}n=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),this.$gutterLayer.element.style.marginTop=-n.offset+"px",this.content.style.marginTop=-n.offset+"px",this.content.style.width=n.width+2*this.$padding+"px",this.content.style.height=n.minHeight+"px"}e&this.CHANGE_H_SCROLL&&(this.content.style.marginLeft=-this.scrollLeft+"px",this.scroller.className=this.scrollLeft<=0?"ace_scroller":"ace_scroller ace_scroll-left");if(e&this.CHANGE_FULL){this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this._signal("afterRender");return}if(e&this.CHANGE_SCROLL){e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(n):this.$textLayer.scrollLines(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this.$moveTextAreaToCursor(),this._signal("afterRender");return}e&this.CHANGE_TEXT?(this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(n):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.$showGutter&&this.$gutterLayer.update(n),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(n),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(n),this._signal("afterRender")},this.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,n=Math.min(t,Math.max((this.$minLines||1)*this.lineHeight,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(n+=this.scrollBarH.getHeight()),this.$maxPixelHeight&&n>this.$maxPixelHeight&&(n=this.$maxPixelHeight);var r=e>t;if(n!=this.desiredHeight||this.$size.height!=this.desiredHeight||r!=this.$vScroll){r!=this.$vScroll&&(this.$vScroll=r,this.scrollBarV.setVisible(r));var i=this.container.clientWidth;this.container.style.height=n+"px",this.$updateCachedSize(!0,this.$gutterWidth,i,n),this.desiredHeight=n,this._signal("autosize")}},this.$computeLayerConfig=function(){var e=this.session,t=this.$size,n=t.height<=2*this.lineHeight,r=this.session.getScreenLength(),i=r*this.lineHeight,s=this.$getLongestLine(),o=!n&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-s-2*this.$padding<0),u=this.$horizScroll!==o;u&&(this.$horizScroll=o,this.scrollBarH.setVisible(o));var a=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var f=this.scrollTop%this.lineHeight,l=t.scrollerHeight+this.lineHeight,c=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;i+=c;var h=this.scrollMargin;this.session.setScrollTop(Math.max(-h.top,Math.min(this.scrollTop,i-t.scrollerHeight+h.bottom))),this.session.setScrollLeft(Math.max(-h.left,Math.min(this.scrollLeft,s+2*this.$padding-t.scrollerWidth+h.right)));var p=!n&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-i+c<0||this.scrollTop>h.top),d=a!==p;d&&(this.$vScroll=p,this.scrollBarV.setVisible(p));var v=Math.ceil(l/this.lineHeight)-1,m=Math.max(0,Math.round((this.scrollTop-f)/this.lineHeight)),g=m+v,y,b,w=this.lineHeight;m=e.screenToDocumentRow(m,0);var E=e.getFoldLine(m);E&&(m=E.start.row),y=e.documentToScreenRow(m,0),b=e.getRowLength(m)*w,g=Math.min(e.screenToDocumentRow(g,0),e.getLength()-1),l=t.scrollerHeight+e.getRowLength(g)*w+b,f=this.scrollTop-y*w;var S=0;this.layerConfig.width!=s&&(S=this.CHANGE_H_SCROLL);if(u||d)S=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal("scrollbarVisibilityChanged"),d&&(s=this.$getLongestLine());return this.layerConfig={width:s,padding:this.$padding,firstRow:m,firstRowScreen:y,lastRow:g,lineHeight:w,characterWidth:this.characterWidth,minHeight:l,maxHeight:i,offset:f,gutterOffset:w?Math.max(0,Math.ceil((f+t.height-t.scrollerHeight)/w)):0,height:this.$size.scrollerHeight},S},this.$updateLines=function(){if(!this.$changedLines)return;var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(ts?(t&&a+o>s+this.lineHeight&&(s-=t*this.$size.scrollerHeight),s===0&&(s=-this.scrollMargin.top),this.session.setScrollTop(s)):a+this.$size.scrollerHeight-ui?(i=1-this.scrollMargin.top)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom)return!0;if(e<0&&this.session.getScrollLeft()>=1-this.scrollMargin.left)return!0;if(e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right)return!0},this.pixelToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=e+this.scrollLeft-n.left-this.$padding,i=r/this.characterWidth,s=Math.floor((t+this.scrollTop-n.top)/this.lineHeight),o=Math.round(i);return{row:s,column:o,side:i-o>0?1:-1,offsetX:r}},this.screenToTextCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=e+this.scrollLeft-n.left-this.$padding,i=Math.round(r/this.characterWidth),s=(t+this.scrollTop-n.top)/this.lineHeight;return this.session.screenToDocumentPosition(s,Math.max(i,0),r)},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+(this.session.$bidiHandler.isBidiRow(r.row,e)?this.session.$bidiHandler.getPosLeft(r.column):Math.round(r.column*this.characterWidth)),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){i.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;i.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this.setTheme=function(e,t){function o(r){if(n.$themeId!=e)return t&&t();if(!r||!r.cssClass)throw new Error("couldn't load module "+e+" or it didn't call define");i.importCssString(r.cssText,r.cssClass,n.container.ownerDocument),n.theme&&i.removeCssClass(n.container,n.theme.cssClass);var s="padding"in r?r.padding:"padding"in(n.theme||{})?4:n.$padding;n.$padding&&s!=n.$padding&&n.setPadding(s),n.$theme=r.cssClass,n.theme=r,i.addCssClass(n.container,r.cssClass),i.setCssClass(n.container,"ace_dark",r.isDark),n.$size&&(n.$size.width=0,n.$updateSizeAsync()),n._dispatchEvent("themeLoaded",{theme:r}),t&&t()}var n=this;this.$themeId=e,n._dispatchEvent("themeChange",{theme:e});if(!e||typeof e=="string"){var r=e||this.$options.theme.initialValue;s.loadModule(["theme",r],o)}else o(e)},this.getTheme=function(){return this.$themeId},this.setStyle=function(e,t){i.setCssClass(this.container,e,t!==!1)},this.unsetStyle=function(e){i.removeCssClass(this.container,e)},this.setCursorStyle=function(e){this.scroller.style.cursor!=e&&(this.scroller.style.cursor=e)},this.setMouseCursor=function(e){this.scroller.style.cursor=e},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(g.prototype),s.defineOptions(g.prototype,"renderer",{animatedScroll:{initialValue:!1},showInvisibles:{set:function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(e){typeof e=="number"&&(this.$printMarginColumn=e),this.$showPrintMargin=!!e,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(e){this.$gutter.style.display=e?"block":"none",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},fadeFoldWidgets:{set:function(e){i.setCssClass(this.$gutter,"ace_fade-fold-widgets",e)},initialValue:!1},showFoldWidgets:{set:function(e){this.$gutterLayer.setShowFoldWidgets(e)},initialValue:!0},showLineNumbers:{set:function(e){this.$gutterLayer.setShowLineNumbers(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightGutterLine:{set:function(e){if(!this.$gutterLineHighlight){this.$gutterLineHighlight=i.createElement("div"),this.$gutterLineHighlight.className="ace_gutter-active-line",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=e?"":"none",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},initialValue:!1,value:!0},hScrollBarAlwaysVisible:{set:function(e){(!this.$hScrollBarAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(e){(!this.$vScrollBarAlwaysVisible||!this.$vScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(e){typeof e=="number"&&(e+="px"),this.container.style.fontSize=e,this.updateFontSize()},initialValue:12},fontFamily:{set:function(e){this.container.style.fontFamily=e,this.updateFontSize()}},maxLines:{set:function(e){this.updateFull()}},minLines:{set:function(e){this.updateFull()}},maxPixelHeight:{set:function(e){this.updateFull()},initialValue:0},scrollPastEnd:{set:function(e){e=+e||0;if(this.$scrollPastEnd==e)return;this.$scrollPastEnd=e,this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(e){this.$gutterLayer.$fixedWidth=!!e,this.$loop.schedule(this.CHANGE_GUTTER)}},theme:{set:function(e){this.setTheme(e)},get:function(){return this.$themeId||this.theme},initialValue:"./theme/textmate",handlesSet:!0}}),t.VirtualRenderer=g}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"],function(e,t,n){"use strict";function u(e){var t="importScripts('"+i.qualifyURL(e)+"');";try{return new Blob([t],{type:"application/javascript"})}catch(n){var r=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,s=new r;return s.append(t),s.getBlob("application/javascript")}}function a(e){var t=u(e),n=window.URL||window.webkitURL,r=n.createObjectURL(t);return new Worker(r)}var r=e("../lib/oop"),i=e("../lib/net"),s=e("../lib/event_emitter").EventEmitter,o=e("../config"),f=function(t,n,r,i,s){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl);if(o.get("packaged")||!e.toUrl)i=i||o.moduleUrl(n,"worker");else{var u=this.$normalizePath;i=i||u(e.toUrl("ace/worker/worker.js",null,"_"));var f={};t.forEach(function(t){f[t]=u(e.toUrl(t,null,"_").replace(/(\.js)?(\?.*)?$/,""))})}this.$worker=a(i),s&&this.send("importScripts",s),this.$worker.postMessage({init:!0,tlns:f,module:n,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){r.implement(this,s),this.onMessage=function(e){var t=e.data;switch(t.type){case"event":this._signal(t.name,{data:t.data});break;case"call":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id]);break;case"error":this.reportError(t.data);break;case"log":window.console&&console.log&&console.log.apply(console,t.data)}},this.reportError=function(e){window.console&&console.error&&console.error(e)},this.$normalizePath=function(e){return i.qualifyURL(e)},this.terminate=function(){this._signal("terminate",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker=null,this.$doc&&this.$doc.off("change",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){console.error(n.stack)}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call("setValue",[e.getValue()]),e.on("change",this.changeListener)},this.changeListener=function(e){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),e.action=="insert"?this.deltaQueue.push(e.start,e.lines):this.deltaQueue.push(e.start,e.end)},this.$sendDeltaQueue=function(){var e=this.deltaQueue;if(!e)return;this.deltaQueue=null,e.length>50&&e.length>this.$doc.getLength()>>1?this.call("setValue",[this.$doc.getValue()]):this.emit("change",{data:e})}}).call(f.prototype);var l=function(e,t,n){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var r=null,i=!1,u=Object.create(s),a=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){a.messageBuffer.push(e),r&&(i?setTimeout(f):f())},this.setEmitSync=function(e){i=e};var f=function(){var e=a.messageBuffer.shift();e.command?r[e.command].apply(r,e.args):e.event&&u._signal(e.event,e.data)};u.postMessage=function(e){a.onMessage({data:e})},u.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},u.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},o.loadModule(["worker",t],function(e){r=new e[n](u);while(a.messageBuffer.length)f()})};l.prototype=f.prototype,t.UIWorkerClient=l,t.WorkerClient=f,t.createWorker=a}),define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,n){"use strict";var r=e("./range").Range,i=e("./lib/event_emitter").EventEmitter,s=e("./lib/oop"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session;this.selectionBefore=n.selection.toJSON(),n.selection.inMultiSelectMode&&n.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var i=this.pos;i.$insertRight=!0,i.detach(),i.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);r.$insertRight=!0,r.detach(),e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1)})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e=this.pos.column&&t.start.column<=this.pos.column+this.length+1,s=t.start.column-this.pos.column;this.updateAnchors(e),i&&(this.length+=n);if(i&&!this.session.$fromUndo)if(e.action==="insert")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.insertMergedLines(a,e.lines)}else if(e.action==="remove")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.remove(new r(a.row,a.column,a.row,a.column-n))}this.$updating=!1,this.updateMarkers()},this.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},this.updateMarkers=function(){if(this.$updating)return;var e=this,t=this.session,n=function(n,i){t.removeMarker(n.markerId),n.markerId=t.addMarker(new r(n.row,n.column,n.row,n.column+e.length),i,null,!1)};n(this.pos,this.mainClass);for(var i=this.others.length;i--;)n(this.others[i],this.othersClass)},this.onCursorChange=function(e){if(this.$updating||!this.session)return;var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))},this.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},this.cancel=function(){if(this.$undoStackDepth===-1)return;var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth;for(var n=0;n1&&!this.inMultiSelectMode&&(this._signal("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal("addRange",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._signal("removeRange",{ranges:e}),this.rangeCount===0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.selectionLead),s=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column0)g--;if(g>0){var y=0;while(r[y].isEmpty())y++}for(var b=g;b>=y;b--)r[b].isEmpty()&&r.splice(b,1)}return r}}.call(s.prototype);var d=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit("changeSelection")},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;if(!t.multiSelectAction){var r=t.exec(n,e.args||{});n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()}else t.multiSelectAction=="forEach"?r=n.forEachSelection(t,e.args):t.multiSelectAction=="forEachLine"?r=n.forEachSelection(t,e.args,!0):t.multiSelectAction=="single"?(n.exitMultiSelectMode(),r=t.exec(n,e.args||{})):r=t.multiSelectAction(n,e.args||{});return r},this.forEachSelection=function(e,t,n){if(this.inVirtualSelectionMode)return;var r=n&&n.keepOrder,i=n==1||n&&n.$byLines,o=this.session,u=this.selection,a=u.rangeList,f=(r?u:a).ranges,l;if(!f.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var c=u._eventRegistry;u._eventRegistry={};var h=new s(o);this.inVirtualSelectionMode=!0;for(var p=f.length;p--;){if(i)while(p>0&&f[p].start.row==f[p-1].end.row)p--;h.fromOrientedRange(f[p]),h.index=p,this.selection=o.selection=h;var d=e.exec?e.exec(this,t||{}):e(this,t||{});!l&&d!==undefined&&(l=d),h.toOrientedRange(f[p])}h.detach(),this.selection=o.selection=u,this.inVirtualSelectionMode=!1,u._eventRegistry=c,u.mergeOverlappingRanges();var v=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),v&&v.from==v.to&&this.renderer.animateScrolling(v.from),l},this.exitMultiSelectMode=function(){if(!this.inMultiSelectMode||this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e="";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var t=this.multiSelect.rangeList.ranges,n=[];for(var r=0;r0);u<0&&(u=0),f>=c&&(f=c-1)}var p=this.session.removeFullLines(u,f);p=this.$reAlignText(p,l),this.session.insert({row:u,column:0},p.join("\n")+"\n"),l||(o.start.column=0,o.end.column=p[p.length-1].length),this.selection.setRange(o)}else{s.forEach(function(e){t.substractPoint(e.cursor)});var d=0,v=Infinity,m=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\S/g);return i==-1&&(i=0),n.column>d&&(d=n.column),io?e.insert(r,a.stringRepeat(" ",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=d,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e,t){function u(e){return a.stringRepeat(" ",e)}function f(e){return e[2]?u(i)+e[2]+u(s-e[2].length+o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function l(e){return e[2]?u(i+s-e[2].length)+e[2]+u(o," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function c(e){return e[2]?u(i)+e[2]+u(o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var n=!0,r=!0,i,s,o;return e.map(function(e){var t=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return t?i==null?(i=t[1].length,s=t[2].length,o=t[3].length,t):(i+s+o!=t[1].length+t[2].length+t[3].length&&(r=!1),i!=t[1].length&&(n=!1),i>t[1].length&&(i=t[1].length),st[3].length&&(o=t[3].length),t):[e]}).map(t?f:n?r?l:f:c)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var n=e.oldSession;n&&(n.multiSelect.off("addRange",this.$onAddRange),n.multiSelect.off("removeRange",this.$onRemoveRange),n.multiSelect.off("multiSelect",this.$onMultiSelect),n.multiSelect.off("singleSelect",this.$onSingleSelect),n.multiSelect.lead.off("change",this.$checkMultiselectChange),n.multiSelect.anchor.off("change",this.$checkMultiselectChange)),t&&(t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),t.multiSelect.lead.on("change",this.$checkMultiselectChange),t.multiSelect.anchor.on("change",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m,e("./config").defineOptions(d.prototype,"editor",{enableMultiselect:{set:function(e){m(this),e?(this.on("changeSession",this.$multiselectOnSessionChange),this.on("mousedown",o)):(this.off("changeSession",this.$multiselectOnSessionChange),this.off("mousedown",o))},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../../range").Range,i=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?"start":t=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(r)?"end":""},this.getFoldWidgetRange=function(e,t,n){return null},this.indentationBlock=function(e,t,n){var i=/\S/,s=e.getLine(t),o=s.search(i);if(o==-1)return;var u=n||s.length,a=e.getLength(),f=t,l=t;while(++tf){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=e.getFoldWidget(u.row)),a=="start"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}),define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}),define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"],function(e,t,n){"use strict";function o(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on("change",this.updateOnChange),this.session.on("changeFold",this.updateOnFold),this.session.on("changeEditor",this.$onChangeEditor)}var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./range").Range;(function(){this.getRowLength=function(e){var t;return this.lineWidgets?t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:t=0,!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},this.$onChangeEditor=function(e){this.attach(e.editor)},this.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach();if(this.editor==e)return;this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on("beforeRender",this.measureWidgets),e.renderer.on("afterRender",this.renderWidgets))},this.detach=function(e){var t=this.editor;if(!t)return;this.editor=null,t.widgetManager=null,t.renderer.off("beforeRender",this.measureWidgets),t.renderer.off("afterRender",this.renderWidgets);var n=this.session.lineWidgets;n&&n.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})},this.updateOnFold=function(e,t){var n=t.lineWidgets;if(!n||!e.action)return;var r=e.data,i=r.start.row,s=r.end.row,o=e.action=="add";for(var u=i+1;u0&&!r[i])i--;this.firstRow=n.firstRow,this.lastRow=n.lastRow,t.$cursorLayer.config=n;for(var o=i;o<=s;o++){var u=r[o];if(!u||!u.el)continue;if(u.hidden){u.el.style.top=-100-(u.pixelHeight||0)+"px";continue}u._inDocument||(u._inDocument=!0,t.container.appendChild(u.el));var a=t.$cursorLayer.getPixelPosition({row:o,column:0},!0).top;u.coverLine||(a+=n.lineHeight*this.session.getRowLineCount(u.row)),u.el.style.top=a-n.offset+"px";var f=u.coverGutter?0:t.gutterWidth;u.fixedWidth||(f-=t.scrollLeft),u.el.style.left=f+"px",u.fullWidth&&u.screenWidth&&(u.el.style.minWidth=n.width+2*n.padding+"px"),u.fixedWidth?u.el.style.right=t.scrollBar.getWidth()+"px":u.el.style.right=""}}}).call(o.prototype),t.LineWidgets=o}),define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"],function(e,t,n){"use strict";function o(e,t,n){var r=0,i=e.length-1;while(r<=i){var s=r+i>>1,o=n(t,e[s]);if(o>0)r=s+1;else{if(!(o<0))return s;i=s-1}}return-(r+1)}function u(e,t,n){var r=e.getAnnotations().sort(s.comparePoints);if(!r.length)return;var i=o(r,{row:t,column:-1},s.comparePoints);i<0&&(i=-i-1),i>=r.length?i=n>0?0:r.length-1:i===0&&n<0&&(i=r.length-1);var u=r[i];if(!u||!n)return;if(u.row===t){do u=r[i+=n];while(u&&u.row===t);if(!u)return r.slice()}var a=[];t=u.row;do a[n<0?"unshift":"push"](u),u=r[i+=n];while(u&&u.row==t);return a.length&&a}var r=e("../line_widgets").LineWidgets,i=e("../lib/dom"),s=e("../range").Range;t.showErrorMarker=function(e,t){var n=e.session;n.widgetManager||(n.widgetManager=new r(n),n.widgetManager.attach(e));var s=e.getCursorPosition(),o=s.row,a=n.widgetManager.getWidgetsAtRow(o).filter(function(e){return e.type=="errorMarker"})[0];a?a.destroy():o-=t;var f=u(n,o,t),l;if(f){var c=f[0];s.column=(c.pos&&typeof c.column!="number"?c.pos.sc:c.column)||0,s.row=c.row,l=e.renderer.$gutterLayer.$annotations[s.row]}else{if(a)return;l={text:["Looks good!"],className:"ace_ok"}}e.session.unfold(s.row),e.selection.moveToPosition(s);var h={row:s.row,fixedWidth:!0,coverGutter:!0,el:i.createElement("div"),type:"errorMarker"},p=h.el.appendChild(i.createElement("div")),d=h.el.appendChild(i.createElement("div"));d.className="error_widget_arrow "+l.className;var v=e.renderer.$cursorLayer.getPixelPosition(s).left;d.style.left=v+e.renderer.gutterWidth-5+"px",h.el.className="error_widget_wrapper",p.className="error_widget "+l.className,p.innerHTML=l.text.join("
    "),p.appendChild(i.createElement("div"));var m=function(e,t,n){if(t===0&&(n==="esc"||n==="return"))return h.destroy(),{command:"null"}};h.destroy=function(){if(e.$mouseHandler.isMousePressed)return;e.keyBinding.removeKeyboardHandler(m),n.widgetManager.removeLineWidget(h),e.off("changeSelection",h.destroy),e.off("changeSession",h.destroy),e.off("mouseup",h.destroy),e.off("change",h.destroy)},e.keyBinding.addKeyboardHandler(m),e.on("changeSelection",h.destroy),e.on("changeSession",h.destroy),e.on("mouseup",h.destroy),e.on("change",h.destroy),e.session.widgetManager.addLineWidget(h),h.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:h.el.offsetHeight})},i.importCssString(" .error_widget_wrapper { background: inherit; color: inherit; border:none } .error_widget { border-top: solid 2px; border-bottom: solid 2px; margin: 5px 0; padding: 10px 40px; white-space: pre-wrap; } .error_widget.ace_error, .error_widget_arrow.ace_error{ border-color: #ff5a5a } .error_widget.ace_warning, .error_widget_arrow.ace_warning{ border-color: #F1D817 } .error_widget.ace_info, .error_widget_arrow.ace_info{ border-color: #5a5a5a } .error_widget.ace_ok, .error_widget_arrow.ace_ok{ border-color: #5aaa5a } .error_widget_arrow { position: absolute; border: solid 5px; border-top-color: transparent!important; border-right-color: transparent!important; border-left-color: transparent!important; top: -5px; }","")}),define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"],function(e,t,n){"use strict";e("./lib/fixoldbrowsers");var r=e("./lib/dom"),i=e("./lib/event"),s=e("./editor").Editor,o=e("./edit_session").EditSession,u=e("./undomanager").UndoManager,a=e("./virtual_renderer").VirtualRenderer;e("./worker/worker_client"),e("./keyboard/hash_handler"),e("./placeholder"),e("./multi_select"),e("./mode/folding/fold_mode"),e("./theme/textmate"),e("./ext/error_marker"),t.config=e("./config"),t.require=e,typeof define=="function"&&(t.define=define),t.edit=function(e){if(typeof e=="string"){var n=e;e=document.getElementById(n);if(!e)throw new Error("ace.edit can't find div #"+n)}if(e&&e.env&&e.env.editor instanceof s)return e.env.editor;var o="";if(e&&/input|textarea/i.test(e.tagName)){var u=e;o=u.value,e=r.createElement("pre"),u.parentNode.replaceChild(e,u)}else e&&(o=r.getInnerText(e),e.innerHTML="");var f=t.createEditSession(o),l=new s(new a(e));l.setSession(f);var c={document:f,editor:l,onResize:l.resize.bind(l,null)};return u&&(c.textarea=u),i.addListener(window,"resize",c.onResize),l.on("destroy",function(){i.removeListener(window,"resize",c.onResize),c.editor.container.env=null}),l.container.env=l.env=c,l},t.createEditSession=function(e,t){var n=new o(e,t);return n.setUndoManager(new u),n},t.EditSession=o,t.UndoManager=u,t.version="1.2.9"}); (function() { window.require(["ace/ace"], function(a) { if (a) { a.config.init(true); a.define = window.define; } if (!window.ace) window.ace = a; for (var key in a) if (a.hasOwnProperty(key)) window.ace[key] = a[key]; }); })(); ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-json.js ================================================ define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"text",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"comment",regex:"\\/\\/.*$"},{token:"comment.start",regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'"|$',next:"start"},{defaultToken:"string"}],comment:[{token:"comment.end",regex:"\\*\\/",next:"start"},{defaultToken:"comment"}]}};r.inherits(s,i),t.JsonHighlightRules=s}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);if(this.singleLineBlockCommentRe.test(r)&&!this.startRegionRe.test(r)&&!this.tripleStarBlockCommentRe.test(r))return"";var i=this._getFoldWidgetBase(e,t,n);return!i&&this.startRegionRe.test(r)?"start":i},this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n);if(this.startRegionRe.test(i))return this.getCommentRegionBlock(e,i,n);var s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)},this.getCommentRegionBlock=function(e,t,n){var r=t.search(/\s*$/),s=e.getLength(),o=n,u=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,a=1;while(++no)return new i(o,r,l,t.length)}}.call(o.prototype)}),define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./json_highlight_rules").JsonHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./behaviour/cstyle").CstyleBehaviour,a=e("./folding/cstyle").FoldMode,f=e("../worker/worker_client").WorkerClient,l=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new u,this.foldingRules=new a};r.inherits(l,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/json_worker","JsonWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/json"}.call(l.prototype),t.Mode=l}) ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-properties.js ================================================ define("ace/mode/properties_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e=/\\u[0-9a-fA-F]{4}|\\/;this.$rules={start:[{token:"comment",regex:/[!#].*$/},{token:"keyword",regex:/[=:]$/},{token:"keyword",regex:/[=:]/,next:"value"},{token:"constant.language.escape",regex:e},{defaultToken:"variable"}],value:[{regex:/\\$/,token:"string",next:"value"},{regex:/$/,token:"string",next:"start"},{token:"constant.language.escape",regex:e},{defaultToken:"string"}]}};r.inherits(s,i),t.PropertiesHighlightRules=s}),define("ace/mode/properties",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/properties_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./properties_highlight_rules").PropertiesHighlightRules,o=function(){this.HighlightRules=s,this.$behaviour=this.$defaultBehaviour};r.inherits(o,i),function(){this.$id="ace/mode/properties"}.call(o.prototype),t.Mode=o}) ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-xml.js ================================================ define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(e){var t="[_:a-zA-Z\u00c0-\uffff][-_:.a-zA-Z0-9\u00c0-\uffff]*";this.$rules={start:[{token:"string.cdata.xml",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:["punctuation.instruction.xml","keyword.instruction.xml"],regex:"(<\\?)("+t+")",next:"processing_instruction"},{token:"comment.start.xml",regex:"<\\!--",next:"comment"},{token:["xml-pe.doctype.xml","xml-pe.doctype.xml"],regex:"(<\\!)(DOCTYPE)(?=[\\s])",next:"doctype",caseInsensitive:!0},{include:"tag"},{token:"text.end-tag-open.xml",regex:"",next:"start"}],doctype:[{include:"whitespace"},{include:"string"},{token:"xml-pe.doctype.xml",regex:">",next:"start"},{token:"xml-pe.xml",regex:"[-_a-zA-Z0-9:]+"},{token:"punctuation.int-subset",regex:"\\[",push:"int_subset"}],int_subset:[{token:"text.xml",regex:"\\s+"},{token:"punctuation.int-subset.xml",regex:"]",next:"pop"},{token:["punctuation.markup-decl.xml","keyword.markup-decl.xml"],regex:"(<\\!)("+t+")",push:[{token:"text",regex:"\\s+"},{token:"punctuation.markup-decl.xml",regex:">",next:"pop"},{include:"string"}]}],cdata:[{token:"string.cdata.xml",regex:"\\]\\]>",next:"start"},{token:"text.xml",regex:"\\s+"},{token:"text.xml",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment.end.xml",regex:"-->",next:"start"},{defaultToken:"comment.xml"}],reference:[{token:"constant.language.escape.reference.xml",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"}],attr_reference:[{token:"constant.language.escape.reference.attribute-value.xml",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"}],tag:[{token:["meta.tag.punctuation.tag-open.xml","meta.tag.punctuation.end-tag-open.xml","meta.tag.tag-name.xml"],regex:"(?:(<)|(",next:"start"}]}],tag_whitespace:[{token:"text.tag-whitespace.xml",regex:"\\s+"}],whitespace:[{token:"text.whitespace.xml",regex:"\\s+"}],string:[{token:"string.xml",regex:"'",push:[{token:"string.xml",regex:"'",next:"pop"},{defaultToken:"string.xml"}]},{token:"string.xml",regex:'"',push:[{token:"string.xml",regex:'"',next:"pop"},{defaultToken:"string.xml"}]}],attributes:[{token:"entity.other.attribute-name.xml",regex:t},{token:"keyword.operator.attribute-equals.xml",regex:"="},{include:"tag_whitespace"},{include:"attribute_value"}],attribute_value:[{token:"string.attribute-value.xml",regex:"'",push:[{token:"string.attribute-value.xml",regex:"'",next:"pop"},{include:"attr_reference"},{defaultToken:"string.attribute-value.xml"}]},{token:"string.attribute-value.xml",regex:'"',push:[{token:"string.attribute-value.xml",regex:'"',next:"pop"},{include:"attr_reference"},{defaultToken:"string.attribute-value.xml"}]}]},this.constructor===s&&this.normalizeRules()};(function(){this.embedTagRules=function(e,t,n){this.$rules.tag.unshift({token:["meta.tag.punctuation.tag-open.xml","meta.tag."+n+".tag-name.xml"],regex:"(<)("+n+"(?=\\s|>|$))",next:[{include:"attributes"},{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",next:t+"start"}]}),this.$rules[n+"-end"]=[{include:"attributes"},{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",next:"start",onMatch:function(e,t,n){return n.splice(0),this.token}}],this.embedRules(e,t,[{token:["meta.tag.punctuation.end-tag-open.xml","meta.tag."+n+".tag-name.xml"],regex:"(|$))",next:n+"-end"},{token:"string.cdata.xml",regex:"<\\!\\[CDATA\\["},{token:"string.cdata.xml",regex:"\\]\\]>"}])}}).call(i.prototype),r.inherits(s,i),t.XmlHighlightRules=s}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";function u(e,t){return e.type.lastIndexOf(t+".xml")>-1}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),a=function(){this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var o=i,a=r.doc.getTextRange(n.getSelectionRange());if(a!==""&&a!=="'"&&a!='"'&&n.getWrapBehavioursEnabled())return{text:o+a+o,selection:!1};var f=n.getCursorPosition(),l=r.doc.getLine(f.row),c=l.substring(f.column,f.column+1),h=new s(r,f.row,f.column),p=h.getCurrentToken();if(c==o&&(u(p,"attribute-value")||u(p,"string")))return{text:"",selection:[1,1]};p||(p=h.stepBackward());if(!p)return;while(u(p,"tag-whitespace")||u(p,"whitespace"))p=h.stepBackward();var d=!c||c.match(/\s/);if(u(p,"attribute-equals")&&(d||c==">")||u(p,"decl-attribute-equals")&&(d||c=="?"))return{text:o+o,selection:[1,1]}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}}),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var o=n.getSelectionRange().start,a=new s(r,o.row,o.column),f=a.getCurrentToken()||a.stepBackward();if(!f||!(u(f,"tag-name")||u(f,"tag-whitespace")||u(f,"attribute-name")||u(f,"attribute-equals")||u(f,"attribute-value")))return;if(u(f,"reference.attribute-value"))return;if(u(f,"attribute-value")){var l=f.value.charAt(0);if(l=='"'||l=="'"){var c=f.value.charAt(f.value.length-1),h=a.getCurrentTokenColumn()+f.value.length;if(h>o.column||h==o.column&&l!=c)return}}while(!u(f,"tag-name")){f=a.stepBackward();if(f.value=="<"){f=a.stepForward();break}}var p=a.getCurrentTokenRow(),d=a.getCurrentTokenColumn();if(u(a.stepBackward(),"end-tag-open"))return;var v=f.value;p==o.row&&(v=v.substring(0,o.column-d));if(this.voidElements.hasOwnProperty(v.toLowerCase()))return;return{text:">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var o=n.getCursorPosition(),u=r.getLine(o.row),a=new s(r,o.row,o.column),f=a.getCurrentToken();if(f&&f.type.indexOf("tag-close")!==-1){if(f.value=="/>")return;while(f&&f.type.indexOf("tag-name")===-1)f=a.stepBackward();if(!f)return;var l=f.value,c=a.getCurrentTokenRow();f=a.stepBackward();if(!f||f.type.indexOf("end-tag")!==-1)return;if(this.voidElements&&!this.voidElements[l]){var h=r.getTokenAt(o.row,o.column+1),u=r.getLine(c),p=this.$getIndent(u),d=p+r.getTabString();return h&&h.value==="-1}var r=e("../../lib/oop"),i=e("../../lib/lang"),s=e("../../range").Range,o=e("./fold_mode").FoldMode,u=e("../../token_iterator").TokenIterator,a=t.FoldMode=function(e,t){o.call(this),this.voidElements=e||{},this.optionalEndTags=r.mixin({},this.voidElements),t&&r.mixin(this.optionalEndTags,t)};r.inherits(a,o);var f=function(){this.tagName="",this.closing=!1,this.selfClosing=!1,this.start={row:0,column:0},this.end={row:0,column:0}};(function(){this.getFoldWidget=function(e,t,n){var r=this._getFirstTagInLine(e,n);return r?r.closing||!r.tagName&&r.selfClosing?t=="markbeginend"?"end":"":!r.tagName||r.selfClosing||this.voidElements.hasOwnProperty(r.tagName.toLowerCase())?"":this._findEndTagInLine(e,n,r.tagName,r.end.column)?"":"start":this.getCommentFoldWidget(e,n)},this.getCommentFoldWidget=function(e,t){return/comment/.test(e.getState(t))&&/";break}}return r}if(l(s,"tag-close"))return r.selfClosing=s.value=="/>",r;r.start.column+=s.value.length}return null},this._findEndTagInLine=function(e,t,n,r){var i=e.getTokens(t),s=0;for(var o=0;o",n.end.row=e.getCurrentTokenRow(),n.end.column=e.getCurrentTokenColumn()+t.value.length,e.stepForward(),n;while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n=new f;do{if(l(t,"tag-open"))return n.closing=l(t,"end-tag-open"),n.start.row=e.getCurrentTokenRow(),n.start.column=e.getCurrentTokenColumn(),e.stepBackward(),n;l(t,"tag-name")?n.tagName=t.value:l(t,"tag-close")&&(n.selfClosing=t.value=="/>",n.end.row=e.getCurrentTokenRow(),n.end.column=e.getCurrentTokenColumn()+t.value.length)}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.optionalEndTags.hasOwnProperty(n.tagName)){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r)return this.getCommentFoldWidget(e,n)&&e.getCommentFoldRange(n,e.getLine(n).length);var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.start.column),l={row:n,column:r.start.column+r.tagName.length+2};r.start.row==r.end.row&&(l.column=r.end.column);while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.end.column),c={row:n,column:r.start.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,a.start.row==a.end.row&&a.start.column"},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/xml_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("error",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/xml"}.call(l.prototype),t.Mode=l}) ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/vendor/ui-ace/mode-yaml.js ================================================ define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"list.markup",regex:/^(?:-{3}|\.{3})\s*(?=#|$)/},{token:"list.markup",regex:/^\s*[\-?](?:$|\s)/},{token:"constant",regex:"!![\\w//]+"},{token:"constant.language",regex:"[&\\*][a-zA-Z0-9-_]+"},{token:["meta.tag","keyword"],regex:/^(\s*\w.*?)(:(?=\s|$))/},{token:["meta.tag","keyword"],regex:/(\w+?)(\s*:(?=\s|$))/},{token:"keyword.operator",regex:"<<\\w*:\\w*"},{token:"keyword.operator",regex:"-\\s*(?=[{])"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:/[|>][-+\d\s]*$/,onMatch:function(e,t,n,r){var i=/^\s*/.exec(r)[0];return n.length<1?n.push(this.next):n[0]="mlString",n.length<2?n.push(i.length):n[1]=i.length,this.token},next:"mlString"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:/(\b|[+\-\.])[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)(?=[^\d-\w]|$)/},{token:"constant.numeric",regex:/[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/},{token:"constant.language.boolean",regex:"\\b(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:/[^\s,:\[\]\{\}]+/}],mlString:[{token:"indent",regex:/^\s*$/},{token:"indent",regex:/^\s*/,onMatch:function(e,t,n){var r=n[1];return r>=e.length?(this.next="start",n.splice(0)):this.next="mlString",this.token},next:"mlString"},{token:"string",regex:".+"}]},this.normalizeRules()};r.inherits(s,i),t.YamlHighlightRules=s}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.row=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;othis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal("change",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(""),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action=="insert"?"remove":"insert",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n="0"&&i<="9")t+=i,a();if(i==="."){t+=".";while(a()&&i>="0"&&i<="9")t+=i}if(i==="e"||i==="E"){t+=i,a();if(i==="-"||i==="+")t+=i,a();while(i>="0"&&i<="9")t+=i,a()}e=+t;if(!isNaN(e))return e;u("Bad number")},l=function(){var e,t,n="",r;if(i==='"')while(a()){if(i==='"')return a(),n;if(i==="\\"){a();if(i==="u"){r=0;for(t=0;t<4;t+=1){e=parseInt(a(),16);if(!isFinite(e))break;r=r*16+e}n+=String.fromCharCode(r)}else{if(typeof s[i]!="string")break;n+=s[i]}}else n+=i}u("Bad string")},c=function(){while(i&&i<=" ")a()},h=function(){switch(i){case"t":return a("t"),a("r"),a("u"),a("e"),!0;case"f":return a("f"),a("a"),a("l"),a("s"),a("e"),!1;case"n":return a("n"),a("u"),a("l"),a("l"),null}u("Unexpected '"+i+"'")},p,d=function(){var e=[];if(i==="["){a("["),c();if(i==="]")return a("]"),e;while(i){e.push(p()),c();if(i==="]")return a("]"),e;a(","),c()}}u("Bad array")},v=function(){var e,t={};if(i==="{"){a("{"),c();if(i==="}")return a("}"),t;while(i){e=l(),c(),a(":"),Object.hasOwnProperty.call(t,e)&&u('Duplicate key "'+e+'"'),t[e]=p(),c();if(i==="}")return a("}"),t;a(","),c()}}u("Bad object")};return p=function(){c();switch(i){case"{":return v();case"[":return d();case'"':return l();case"-":return f();default:return i>="0"&&i<="9"?f():h()}},function(e,t){var n;return o=e,r=0,i=" ",n=p(),c(),i&&u("Syntax error"),typeof t=="function"?function s(e,n){var r,i,o=e[n];if(o&&typeof o=="object")for(r in o)Object.hasOwnProperty.call(o,r)&&(i=s(o,r),i!==undefined?o[r]=i:delete o[r]);return t.call(e,n,o)}({"":n},""):n}}),define("ace/mode/json_worker",["require","exports","module","ace/lib/oop","ace/worker/mirror","ace/mode/json/json_parse"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../worker/mirror").Mirror,s=e("./json/json_parse"),o=t.JsonWorker=function(e){i.call(this,e),this.setTimeout(200)};r.inherits(o,i),function(){this.onUpdate=function(){var e=this.doc.getValue(),t=[];try{e&&s(e)}catch(n){var r=this.doc.indexToPosition(n.at-1);t.push({row:r.row,column:r.column,text:n.message,type:"error"})}this.sender.emit("annotate",t)}}.call(o.prototype)}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.row=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;othis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal("change",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(""),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action=="insert"?"remove":"insert",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i65535){e-=65536;var t=55296+(e>>10),n=56320+(e&1023);return String.fromCharCode(t,n)}return String.fromCharCode(e)}function o(e){var t=e.slice(1,-1);return t in n?n[t]:t.charAt(0)==="#"?s(parseInt(t.substr(1).replace("x","0x"))):(i.error("entity not found:"+e),e)}function u(t){var n=e.substring(v,t).replace(/&#?\w+;/g,o);h&&a(v),r.characters(n,0,t-v),v=t}function a(t,n){while(t>=l&&(n=c.exec(e)))f=n.index,l=f+n[0].length,h.lineNumber++;h.columnNumber=t-f+1}var f=0,l=0,c=/.+(?:\r\n?|\n)|.*$/g,h=r.locator,p=[{currentNSMap:t}],d={},v=0;for(;;){var E=e.indexOf("<",v);if(E<0){if(!e.substr(v).match(/^\s*$/)){var N=r.document,C=N.createTextNode(e.substr(v));N.appendChild(C),r.currentElement=C}return}E>v&&u(E);switch(e.charAt(E+1)){case"/":var k=e.indexOf(">",E+3),L=e.substring(E+2,k),A;if(!(p.length>1)){i.fatalError("end tag name not found for: "+L);break}A=p.pop();var O=A.localNSMap;A.tagName!=L&&i.fatalError("end tag name: "+L+" does not match the current start tagName: "+A.tagName),r.endElement(A.uri,A.localName,L);if(O)for(var M in O)r.endPrefixMapping(M);k++;break;case"?":h&&a(E),k=x(e,E,r);break;case"!":h&&a(E),k=S(e,E,r,i);break;default:try{h&&a(E);var _=new T,k=g(e,E,_,o,i),D=_.length;if(D&&h){var P=m(h,{});for(var E=0;E0))throw new Error("attribute value no end '"+g+"' match");d=e.slice(t,v).replace(/&#?\w+;/g,r),n.add(s,d,t-1),m=c}else{if(m!=l)throw new Error('attribute value must after "="');d=e.slice(t,v).replace(/&#?\w+;/g,r),n.add(s,d,t),i.warning('attribute "'+s+'" missed start quot('+g+")!!"),t=v+1,m=c}break;case"/":switch(m){case o:n.setTagName(e.slice(t,v));case c:case h:case p:m=p,n.closed=!0;case l:case u:case a:break;default:throw new Error("attribute invalid close char('/')")}break;case"":i.error("unexpected end of input");case">":switch(m){case o:n.setTagName(e.slice(t,v));case c:case h:case p:break;case l:case u:d=e.slice(t,v),d.slice(-1)==="/"&&(n.closed=!0,d=d.slice(0,-1));case a:m===a&&(d=s),m==l?(i.warning('attribute "'+d+'" missed quot(")!!'),n.add(s,d.replace(/&#?\w+;/g,r),t)):(i.warning('attribute "'+d+'" missed value!! "'+d+'" instead!!'),n.add(d,d,t));break;case f:throw new Error("attribute value missed!!")}return v;case"\u0080":g=" ";default:if(g<=" ")switch(m){case o:n.setTagName(e.slice(t,v)),m=h;break;case u:s=e.slice(t,v),m=a;break;case l:var d=e.slice(t,v).replace(/&#?\w+;/g,r);i.warning('attribute "'+d+'" missed quot(")!!'),n.add(s,d,t);case c:m=h}else switch(m){case a:i.warning('attribute "'+s+'" missed value!! "'+s+'" instead!!'),n.add(s,s,t),t=v,m=u;break;case c:i.warning('attribute space is required"'+s+'"!!');case h:m=u,t=v;break;case f:m=l,t=v;break;case p:throw new Error("elements closed character '/' and '>' must be connected to")}}v++}}function y(e,t,n){var r=e.tagName,i=null,s=n[n.length-1].currentNSMap,o=e.length;while(o--){var u=e[o],a=u.qName,f=u.value,l=a.indexOf(":");if(l>0)var c=u.prefix=a.slice(0,l),h=a.slice(l+1),p=c==="xmlns"&&h;else h=a,c=null,p=a==="xmlns"&&"";u.localName=h,p!==!1&&(i==null&&(i={},E(s,s={})),s[p]=i[p]=f,u.uri="http://www.w3.org/2000/xmlns/",t.startPrefixMapping(p,f))}var o=e.length;while(o--){u=e[o];var c=u.prefix;c&&(c==="xml"&&(u.uri="http://www.w3.org/XML/1998/namespace"),c!=="xmlns"&&(u.uri=s[c]))}var l=r.indexOf(":");l>0?(c=e.prefix=r.slice(0,l),h=e.localName=r.slice(l+1)):(c=null,h=e.localName=r);var d=e.uri=s[c||""];t.startElement(d,h,r,e);if(e.closed){t.endElement(d,h,r);if(i)for(c in i)t.endPrefixMapping(c)}else e.currentNSMap=s,e.localNSMap=i,n.push(e)}function b(e,t,n,r,i){if(/^(?:script|textarea)$/i.test(n)){var s=e.indexOf("",t),o=e.substring(t+1,s);if(/[&<]/.test(o))return/^script$/i.test(n)?(i.characters(o,0,o.length),s):(o=o.replace(/&#?\w+;/g,r),i.characters(o,0,o.length),s)}return t+1}function w(e,t,n,r){var i=r[n];return i==null&&(i=r[n]=e.lastIndexOf("")),i",t+4);return s>t?(n.comment(e,t+4,s-t-4),s+3):(r.error("Unclosed comment"),-1)}return-1;default:if(e.substr(t+3,6)=="CDATA["){var s=e.indexOf("]]>",t+9);return n.startCDATA(),n.characters(e,t+9,s-t-9),n.endCDATA(),s+3}var o=C(e,t),u=o.length;if(u>1&&/!doctype/i.test(o[0][0])){var a=o[1][0],f=u>3&&/^public$/i.test(o[2][0])&&o[3][0],l=u>4&&o[4][0],c=o[u-1];return n.startDTD(a,f&&f.replace(/^(['"])(.*?)\1$/,"$2"),l&&l.replace(/^(['"])(.*?)\1$/,"$2")),n.endDTD(),c.index+c[0].length}}return-1}function x(e,t,n){var r=e.indexOf("?>",t);if(r){var i=e.substring(t,r).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);if(i){var s=i[0].length;return n.processingInstruction(i[1],i[2]),r+2}return-1}return-1}function T(e){}function N(e,t){return e.__proto__=t,e}function C(e,t){var n,r=[],i=/'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;i.lastIndex=t,i.exec(e);while(n=i.exec(e)){r.push(n);if(n[1])return r}}var r=/[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/,i=new RegExp("[\\-\\.0-9"+r.source.slice(1,-1)+"\u00b7\u0300-\u036f\\ux203F-\u2040]"),s=new RegExp("^"+r.source+i.source+"*(?::"+r.source+i.source+"*)?$"),o=0,u=1,a=2,f=3,l=4,c=5,h=6,p=7;return d.prototype={parse:function(e,t,n){var r=this.domBuilder;r.startDocument(),E(t,t={}),v(e,t,n,r,this.errorHandler),r.endDocument()}},T.prototype={setTagName:function(e){if(!s.test(e))throw new Error("invalid tagName:"+e);this.tagName=e},add:function(e,t,n){if(!s.test(e))throw new Error("invalid attribute:"+e);this[this.length++]={qName:e,value:t,offset:n}},length:0,getLocalName:function(e){return this[e].localName},getOffset:function(e){return this[e].offset},getQName:function(e){return this[e].qName},getURI:function(e){return this[e].uri},getValue:function(e){return this[e].value}},N({},N.prototype)instanceof N||(N=function(e,t){function n(){}n.prototype=t,n=new n;for(t in e)n[t]=e[t];return n}),d}),define("ace/mode/xml/dom",["require","exports","module"],function(e,t,n){function r(e,t){for(var n in e)t[n]=e[n]}function i(e,t){var n=e.prototype;if(Object.create){var i=Object.create(t.prototype);n.__proto__=i}if(!(n instanceof t)){function s(){}s.prototype=t.prototype,s=new s,r(n,s),e.prototype=n=s}n.constructor!=e&&(typeof e!="function"&&console.error("unknow Class:"+e),n.constructor=e)}function B(e,t){if(t instanceof Error)var n=t;else n=this,Error.call(this,w[e]),this.message=w[e],Error.captureStackTrace&&Error.captureStackTrace(this,B);return n.code=e,t&&(this.message=this.message+": "+t),n}function j(){}function F(e,t){this._node=e,this._refresh=t,I(this)}function I(e){var t=e._node._inc||e._node.ownerDocument._inc;if(e._inc!=t){var n=e._refresh(e._node);gt(e,"length",n.length),r(n,e),e._inc=t}}function q(){}function R(e,t){var n=e.length;while(n--)if(e[n]===t)return n}function U(e,t,n,r){r?t[R(t,r)]=n:t[t.length++]=n;if(e){n.ownerElement=e;var i=e.ownerDocument;i&&(r&&Q(i,e,r),K(i,e,n))}}function z(e,t,n){var r=R(t,n);if(!(r>=0))throw B(L,new Error);var i=t.length-1;while(r"&&">"||e=="&"&&"&"||e=='"'&&"""||"&#"+e.charCodeAt()+";"}function $(e,t){if(t(e))return!0;if(e=e.firstChild)do if($(e,t))return!0;while(e=e.nextSibling)}function J(){}function K(e,t,n){e&&e._inc++;var r=n.namespaceURI;r=="http://www.w3.org/2000/xmlns/"&&(t._nsMap[n.prefix?n.localName:""]=n.value)}function Q(e,t,n,r){e&&e._inc++;var i=n.namespaceURI;i=="http://www.w3.org/2000/xmlns/"&&delete t._nsMap[n.prefix?n.localName:""]}function G(e,t,n){if(e&&e._inc){e._inc++;var r=t.childNodes;if(n)r[r.length++]=n;else{var i=t.firstChild,s=0;while(i)r[s++]=i,i=i.nextSibling;r.length=s}}}function Y(e,t){var n=t.previousSibling,r=t.nextSibling;return n?n.nextSibling=r:e.firstChild=r,r?r.previousSibling=n:e.lastChild=n,G(e.ownerDocument,e),t}function Z(e,t,n){var r=t.parentNode;r&&r.removeChild(t);if(t.nodeType===g){var i=t.firstChild;if(i==null)return t;var s=t.lastChild}else i=s=t;var o=n?n.previousSibling:e.lastChild;i.previousSibling=o,s.nextSibling=n,o?o.nextSibling=i:e.firstChild=i,n==null?e.lastChild=s:n.previousSibling=s;do i.parentNode=e;while(i!==s&&(i=i.nextSibling));return G(e.ownerDocument||e,e),t.nodeType==g&&(t.firstChild=t.lastChild=null),t}function et(e,t){var n=t.parentNode;if(n){var r=e.lastChild;n.removeChild(t);var r=e.lastChild}var r=e.lastChild;return t.parentNode=e,t.previousSibling=r,t.nextSibling=null,r?r.nextSibling=t:e.firstChild=t,e.lastChild=t,G(e.ownerDocument,e,t),t}function tt(){this._nsMap={}}function nt(){}function rt(){}function it(){}function st(){}function ot(){}function ut(){}function at(){}function ft(){}function lt(){}function ct(){}function ht(){}function pt(){}function dt(e,t){switch(e.nodeType){case u:var n=e.attributes,r=n.length,i=e.firstChild,o=e.tagName,h=s===e.namespaceURI;t.push("<",o);for(var y=0;y");if(h&&/^script$/i.test(o))i&&t.push(i.data);else while(i)dt(i,t),i=i.nextSibling;t.push("")}else t.push("/>");return;case v:case g:var i=e.firstChild;while(i)dt(i,t),i=i.nextSibling;return;case a:return t.push(" ",e.name,'="',e.value.replace(/[<&"]/g,V),'"');case f:return t.push(e.data.replace(/[<&]/g,V));case l:return t.push("");case d:return t.push("");case m:var b=e.publicId,w=e.systemId;t.push("');else if(w&&w!=".")t.push(' SYSTEM "',w,'">');else{var E=e.internalSubset;E&&t.push(" [",E,"]"),t.push(">")}return;case p:return t.push("");case c:return t.push("&",e.nodeName,";");default:t.push("??",e.nodeName)}}function vt(e,t,n){var r;switch(t.nodeType){case u:r=t.cloneNode(!1),r.ownerDocument=e;case g:break;case a:n=!0}r||(r=t.cloneNode(!1)),r.ownerDocument=e,r.parentNode=null;if(n){var i=t.firstChild;while(i)r.appendChild(vt(e,i,n)),i=i.nextSibling}return r}function mt(e,t,n){var r=new t.constructor;for(var i in t){var s=t[i];typeof s!="object"&&s!=r[i]&&(r[i]=s)}t.childNodes&&(r.childNodes=new j),r.ownerDocument=e;switch(r.nodeType){case u:var o=t.attributes,f=r.attributes=new q,l=o.length;f._ownerElement=r;for(var c=0;c0},lookupPrefix:function(e){var t=this;while(t){var n=t._nsMap;if(n)for(var r in n)if(n[r]==e)return r;t=t.nodeType==2?t.ownerDocument:t.parentNode}return null},lookupNamespaceURI:function(e){var t=this;while(t){var n=t._nsMap;if(n&&e in n)return n[e];t=t.nodeType==2?t.ownerDocument:t.parentNode}return null},isDefaultNamespace:function(e){var t=this.lookupPrefix(e);return t==null}},r(o,X),r(o,X.prototype),J.prototype={nodeName:"#document",nodeType:v,doctype:null,documentElement:null,_inc:1,insertBefore:function(e,t){if(e.nodeType==g){var n=e.firstChild;while(n){var r=n.nextSibling;this.insertBefore(n,t),n=r}return e}return this.documentElement==null&&e.nodeType==1&&(this.documentElement=e),Z(this,e,t),e.ownerDocument=this,e},removeChild:function(e){return this.documentElement==e&&(this.documentElement=null),Y(this,e)},importNode:function(e,t){return vt(this,e,t)},getElementById:function(e){var t=null;return $(this.documentElement,function(n){if(n.nodeType==1&&n.getAttribute("id")==e)return t=n,!0}),t},createElement:function(e){var t=new tt;t.ownerDocument=this,t.nodeName=e,t.tagName=e,t.childNodes=new j;var n=t.attributes=new q;return n._ownerElement=t,t},createDocumentFragment:function(){var e=new ct;return e.ownerDocument=this,e.childNodes=new j,e},createTextNode:function(e){var t=new it;return t.ownerDocument=this,t.appendData(e),t},createComment:function(e){var t=new st;return t.ownerDocument=this,t.appendData(e),t},createCDATASection:function(e){var t=new ot;return t.ownerDocument=this,t.appendData(e),t},createProcessingInstruction:function(e,t){var n=new ht;return n.ownerDocument=this,n.tagName=n.target=e,n.nodeValue=n.data=t,n},createAttribute:function(e){var t=new nt;return t.ownerDocument=this,t.name=e,t.nodeName=e,t.localName=e,t.specified=!0,t},createEntityReference:function(e){var t=new lt;return t.ownerDocument=this,t.nodeName=e,t},createElementNS:function(e,t){var n=new tt,r=t.split(":"),i=n.attributes=new q;return n.childNodes=new j,n.ownerDocument=this,n.nodeName=t,n.tagName=t,n.namespaceURI=e,r.length==2?(n.prefix=r[0],n.localName=r[1]):n.localName=t,i._ownerElement=n,n},createAttributeNS:function(e,t){var n=new nt,r=t.split(":");return n.ownerDocument=this,n.nodeName=t,n.name=t,n.namespaceURI=e,n.specified=!0,r.length==2?(n.prefix=r[0],n.localName=r[1]):n.localName=t,n}},i(J,X),tt.prototype={nodeType:u,hasAttribute:function(e){return this.getAttributeNode(e)!=null},getAttribute:function(e){var t=this.getAttributeNode(e);return t&&t.value||""},getAttributeNode:function(e){return this.attributes.getNamedItem(e)},setAttribute:function(e,t){var n=this.ownerDocument.createAttribute(e);n.value=n.nodeValue=""+t,this.setAttributeNode(n)},removeAttribute:function(e){var t=this.getAttributeNode(e);t&&this.removeAttributeNode(t)},appendChild:function(e){return e.nodeType===g?this.insertBefore(e,null):et(this,e)},setAttributeNode:function(e){return this.attributes.setNamedItem(e)},setAttributeNodeNS:function(e){return this.attributes.setNamedItemNS(e)},removeAttributeNode:function(e){return this.attributes.removeNamedItem(e.nodeName)},removeAttributeNS:function(e,t){var n=this.getAttributeNodeNS(e,t);n&&this.removeAttributeNode(n)},hasAttributeNS:function(e,t){return this.getAttributeNodeNS(e,t)!=null},getAttributeNS:function(e,t){var n=this.getAttributeNodeNS(e,t);return n&&n.value||""},setAttributeNS:function(e,t,n){var r=this.ownerDocument.createAttributeNS(e,t);r.value=r.nodeValue=""+n,this.setAttributeNode(r)},getAttributeNodeNS:function(e,t){return this.attributes.getNamedItemNS(e,t)},getElementsByTagName:function(e){return new F(this,function(t){var n=[];return $(t,function(r){r!==t&&r.nodeType==u&&(e==="*"||r.tagName==e)&&n.push(r)}),n})},getElementsByTagNameNS:function(e,t){return new F(this,function(n){var r=[];return $(n,function(i){i!==n&&i.nodeType===u&&(e==="*"||i.namespaceURI===e)&&(t==="*"||i.localName==t)&&r.push(i)}),r})}},J.prototype.getElementsByTagName=tt.prototype.getElementsByTagName,J.prototype.getElementsByTagNameNS=tt.prototype.getElementsByTagNameNS,i(tt,X),nt.prototype.nodeType=a,i(nt,X),rt.prototype={data:"",substringData:function(e,t){return this.data.substring(e,e+t)},appendData:function(e){e=this.data+e,this.nodeValue=this.data=e,this.length=e.length},insertData:function(e,t){this.replaceData(e,0,t)},appendChild:function(e){throw new Error(w[3])},deleteData:function(e,t){this.replaceData(e,t,"")},replaceData:function(e,t,n){var r=this.data.substring(0,e),i=this.data.substring(e+t);n=r+n+i,this.nodeValue=this.data=n,this.length=n.length}},i(rt,X),it.prototype={nodeName:"#text",nodeType:f,splitText:function(e){var t=this.data,n=t.substring(e);t=t.substring(0,e),this.data=this.nodeValue=t,this.length=t.length;var r=this.ownerDocument.createTextNode(n);return this.parentNode&&this.parentNode.insertBefore(r,this.nextSibling),r}},i(it,rt),st.prototype={nodeName:"#comment",nodeType:d},i(st,rt),ot.prototype={nodeName:"#cdata-section",nodeType:l},i(ot,rt),ut.prototype.nodeType=m,i(ut,X),at.prototype.nodeType=y,i(at,X),ft.prototype.nodeType=h,i(ft,X),lt.prototype.nodeType=c,i(lt,X),ct.prototype.nodeName="#document-fragment",ct.prototype.nodeType=g,i(ct,X),ht.prototype.nodeType=p,i(ht,X),pt.prototype.serializeToString=function(e){var t=[];return dt(e,t),t.join("")},X.prototype.toString=function(){return pt.prototype.serializeToString(this)};try{if(Object.defineProperty){Object.defineProperty(F.prototype,"length",{get:function(){return I(this),this.$$length}}),Object.defineProperty(X.prototype,"textContent",{get:function(){return yt(this)},set:function(e){switch(this.nodeType){case 1:case 11:while(this.firstChild)this.removeChild(this.firstChild);(e||String(e))&&this.appendChild(this.ownerDocument.createTextNode(e));break;default:this.data=e,this.value=value,this.nodeValue=e}}});function yt(e){switch(e.nodeType){case 1:case 11:var t=[];e=e.firstChild;while(e)e.nodeType!==7&&e.nodeType!==8&&t.push(yt(e)),e=e.nextSibling;return t.join("");default:return e.nodeValue}}gt=function(e,t,n){e["$$"+t]=n}}}catch(bt){}return W}),define("ace/mode/xml/dom-parser",["require","exports","module","ace/mode/xml/sax","ace/mode/xml/dom"],function(e,t,n){"use strict";function s(e){this.options=e||{locator:{}}}function o(e,t,n){function s(t){var s=e[t];if(!s)if(i)s=e.length==2?function(n){e(t,n)}:e;else{var o=arguments.length;while(--o)if(s=e[arguments[o]])break}r[t]=s&&function(e){s(e+f(n),e,n)}||function(){}}if(!e){if(t instanceof u)return t;e=t}var r={},i=e instanceof Function;return n=n||{},s("warning","warn"),s("error","warn","warning"),s("fatalError","warn","warning","error"),r}function u(){this.cdata=!1}function a(e,t){t.lineNumber=e.lineNumber,t.columnNumber=e.columnNumber}function f(e){if(e)return"\n@"+(e.systemId||"")+"#[line:"+e.lineNumber+",col:"+e.columnNumber+"]"}function l(e,t,n){return typeof e=="string"?e.substr(t,n):e.length>=t+n||t?new java.lang.String(e,t,n)+"":e}function c(e,t){e.currentElement?e.currentElement.appendChild(t):e.document.appendChild(t)}var r=e("./sax"),i=e("./dom");return s.prototype.parseFromString=function(e,t){var n=this.options,i=new r,s=n.domBuilder||new u,a=n.errorHandler,f=n.locator,l=n.xmlns||{},c={lt:"<",gt:">",amp:"&",quot:'"',apos:"'"};return f&&s.setDocumentLocator(f),i.errorHandler=o(a,s,f),i.domBuilder=n.domBuilder||s,/\/x?html?$/.test(t)&&(c.nbsp="\u00a0",c.copy="\u00a9",l[""]="http://www.w3.org/1999/xhtml"),e?i.parse(e,l,c):i.errorHandler.error("invalid document source"),s.document},u.prototype={startDocument:function(){this.document=(new i).createDocument(null,null,null),this.locator&&(this.document.documentURI=this.locator.systemId)},startElement:function(e,t,n,r){var i=this.document,s=i.createElementNS(e,n||t),o=r.length;c(this,s),this.currentElement=s,this.locator&&a(this.locator,s);for(var u=0;u0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/confirm-dialog.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/delete-namespace-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/diff.html ================================================
    
    
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/entrance.html ================================================

    {{title}}

    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/env-selector.html ================================================
    环境 集群
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/gray-release-rules-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/item-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/merge-and-publish-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/multiple-user-selector.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel-branch-tab.html ================================================
    灰度的配置
    发布状态 Key  主版本的值 灰度的值 备注 最后修改人 最后修改时间 操作
    未发布 已发布
    主版本的配置
    发布状态 Key  Value 备注 最后修改人 最后修改时间 操作
    未发布 已发布
    Tips: 您没有权限编辑灰度规则, 具有namespace修改权或者发布权的人员才可以编辑灰度规则. 如需要编辑灰度规则,请找项目管理员申请权限.
    灰度的AppId 灰度的IP列表 操作
    ALL
    App ID Cluster Name Data Center IP 配置获取时间
    {{instance.configs && instance.configs.length ? (instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
    无实例信息

    Type Key Old Value New Value Comment
    新增
    更新
    删除

    无更改历史
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel-header.html ================================================
    私有 公共 关联
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel-master-tab.html ================================================
    有修改 当前修改者:{{namespace.lockOwner}}
       
    Tips: 此namespace从来没有发布过,Apollo客户端将获取不到配置并记录404日志信息,请及时发布。
    发布状态 Key  Value 备注 最后修改人 最后修改时间 操作
    未发布 已发布
    覆盖的配置
    发布状态 Key  Value 备注 最后修改人 最后修改时间 操作
    未发布 已发布
    无覆盖的配置
    Key  Value 备注 最后修改人 最后修改时间 操作
    无发布的配置
    Key  已发布的值 未发布的值 备注 最后修改时间 操作
    无公共的配置
    公共的配置
    当前公共namespace的所有者 {{namespace.parentAppId}} 没有关联此namespace,请联系{{namespace.parentAppId}}的所有者在{{namespace.parentAppId}}项目里关联此namespace

    Type Key Old Value New Value Comment
    新增
    更新
    删除

    无更改历史
    实例说明:只展示最近一天访问过Apollo的实例
    App ID Cluster Name Data Center IP 配置获取时间
    {{instance.configs && instance.configs.length ? (instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
    无实例信息
    App ID Cluster Name Data Center IP 配置获取时间
    {{instance.configs && instance.configs.length ? (instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
    无实例信息
    App ID Cluster Name Data Center IP
    无实例信息
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/namespace-panel.html ================================================
    ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/publish-deny-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/release-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/rollback-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/show-text-modal.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/resources/static/views/component/user-selector.html ================================================ ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/scripts/shutdown.sh ================================================ #!/bin/bash SERVICE_NAME=apollo-portal if [[ -z "$JAVA_HOME" && -d /usr/java/latest/ ]]; then export JAVA_HOME=/usr/java/latest/ fi cd `dirname $0`/.. if [[ ! -f $SERVICE_NAME".jar" && -d current ]]; then cd current fi if [[ -f $SERVICE_NAME".jar" ]]; then chmod a+x $SERVICE_NAME".jar" ./$SERVICE_NAME".jar" stop fi ================================================ FILE: open-config-center/apollo/apollo-portal/src/main/scripts/startup.sh ================================================ #!/bin/bash SERVICE_NAME=apollo-portal ## Adjust log dir if necessary LOG_DIR=/opt/logs/100003173 ## Adjust server port if necessary SERVER_PORT=8080 ## Adjust memory settings if necessary #export JAVA_OPTS="-Xms2560m -Xmx2560m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=1536m -XX:MaxNewSize=1536m -XX:SurvivorRatio=8" ## Only uncomment the following when you are using server jvm #export JAVA_OPTS="$JAVA_OPTS -server -XX:-ReduceInitialCardMarks" ########### The following is the same for configservice, adminservice, portal ########### export JAVA_OPTS="$JAVA_OPTS -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom" export JAVA_OPTS="$JAVA_OPTS -Dserver.port=$SERVER_PORT -Dlogging.file=$LOG_DIR/$SERVICE_NAME.log -Xloggc:$LOG_DIR/heap_trace.txt -XX:HeapDumpPath=$LOG_DIR/HeapDumpOnOutOfMemoryError/" PATH_TO_JAR=$SERVICE_NAME".jar" SERVER_URL="http://localhost:$SERVER_PORT" function checkPidAlive { for i in `ls -t $SERVICE_NAME*.pid 2>/dev/null` do read pid < $i result=$(ps -p "$pid") if [ "$?" -eq 0 ]; then return 0 else printf "\npid - $pid just quit unexpectedly, please check logs under $LOG_DIR and /tmp for more information!\n" exit 1; fi done printf "\nNo pid file found, startup may failed. Please check logs under $LOG_DIR and /tmp for more information!\n" exit 1; } if [ "$(uname)" == "Darwin" ]; then windows="0" elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then windows="0" elif [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then windows="1" else windows="0" fi # for Windows if [ "$windows" == "1" ] && [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then tmp_java_home=`cygpath -sw "$JAVA_HOME"` export JAVA_HOME=`cygpath -u $tmp_java_home` echo "Windows new JAVA_HOME is: $JAVA_HOME" fi cd `dirname $0`/.. for i in `ls $SERVICE_NAME-*.jar 2>/dev/null` do if [[ ! $i == *"-sources.jar" ]] then PATH_TO_JAR=$i break fi done if [[ ! -f PATH_TO_JAR && -d current ]]; then cd current for i in `ls $SERVICE_NAME-*.jar 2>/dev/null` do if [[ ! $i == *"-sources.jar" ]] then PATH_TO_JAR=$i break fi done fi if [[ -f $SERVICE_NAME".jar" ]]; then rm -rf $SERVICE_NAME".jar" fi printf "$(date) ==== Starting ==== \n" ln $PATH_TO_JAR $SERVICE_NAME".jar" chmod a+x $SERVICE_NAME".jar" ./$SERVICE_NAME".jar" start rc=$?; if [[ $rc != 0 ]]; then echo "$(date) Failed to start $SERVICE_NAME.jar, return code: $rc" exit $rc; fi declare -i counter=0 declare -i max_counter=48 # 48*5=240s declare -i total_time=0 printf "Waiting for server startup" until [[ (( counter -ge max_counter )) || "$(curl -X GET --silent --connect-timeout 1 --max-time 2 --head $SERVER_URL | grep "Coyote")" != "" ]]; do printf "." counter+=1 sleep 5 checkPidAlive done total_time=counter*5 if [[ (( counter -ge max_counter )) ]]; then printf "\n$(date) Server failed to start in $total_time seconds!\n" exit 1; fi printf "\n$(date) Server started in $total_time seconds!\n" exit 0; ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/application.properties ================================================ spring.datasource.url = jdbc:h2:mem:~/apolloportaldb;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy spring.jpa.properties.hibernate.show_sql=true spring.h2.console.enabled = true spring.h2.console.settings.web-allow-others=true ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/application.yml ================================================ server: port: 8070 spring: application: name: apollo-portal logging: level: org.springframework.cloud: 'DEBUG' file: /opt/logs/100003173/apollo-portal.log apollo: portal: envs: local endpoints: health: sensitive: false management: security: enabled: false health: status: order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/logback-test.xml ================================================ utf-8 [%p] %c - %m%n ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/appnamespaceservice/init-appnamespace.sql ================================================ INSERT INTO `appnamespace` (`Id`, `Name`, `AppId`, `Format`, `IsPublic`, `Comment`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_CreatedTime`, `DataChange_LastModifiedBy`, `DataChange_LastTime`) VALUES (139, 'FX.old.xml', '100003173', 'properties', 1, '', 0, 'zhanglea', '2016-07-11 10:00:58', 'zhanglea', '2016-07-11 10:00:58'), (140, 'SCC.song0711-03', 'song0711-01', 'properties', 1, '', 0, 'song_s', '2016-07-11 10:04:09', 'song_s', '2016-07-11 10:04:09'), (141, 'SCC.song0711-04', 'song0711-01', 'properties', 1, '', 0, 'song_s', '2016-07-11 10:06:29', 'song_s', '2016-07-11 10:06:29'), (142, 'application', 'song0711-02', 'properties', 1, 'default app namespace', 0, 'song_s', '2016-07-11 11:18:24', 'song_s', '2016-07-11 11:18:24'), (143, 'TFF.song0711-02', 'song0711-02', 'properties', 0, '', 0, 'song_s', '2016-07-11 11:15:11', 'song_s', '2016-07-11 11:15:11'), (144, 'datasourcexml', '100003173', 'xml', 1, '', 0, 'apollo', '2016-07-11 12:08:29', 'apollo', '2016-07-11 12:08:29'), (145, 'datasource.xml', '100003173', 'xml', 0, '', 0, 'apollo', '2016-07-11 12:09:30', 'apollo', '2016-07-11 12:09:30'); INSERT INTO `app` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES ('1000', 'apollo-portal', 'FX', '框架', 'song_s', 'song_s@ctrip.com', 0, 'song_s', 'song_s'); ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/cleanup.sql ================================================ delete from Permission; delete from Role; delete from RolePermission; delete from UserRole; delete from AppNamespace; DELETE FROM Favorite; DELETE FROM ServerConfig; DELETE FROM App; ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/favorites/favorites.sql ================================================ INSERT INTO `favorite` (`Id`, `UserId`, `AppId`, `Position`, `IsDeleted`, `DataChange_CreatedBy`, `DataChange_CreatedTime`, `DataChange_LastModifiedBy`, `DataChange_LastTime`) VALUES (18, 'apollo', 'test0621-03', 10000, 0, 'apollo', '2016-10-10 17:45:30', 'apollo', '2016-10-10 17:45:30'), (19, 'apollo', '100003173', 9999, 0, 'apollo', '2016-10-10 17:45:42', 'apollo', '2016-10-10 17:51:12'), (20, 'apollo', 'test0621-01', 10000, 00000000, 'apollo', '2016-10-10 17:50:57', 'apollo', '2016-10-10 17:50:57'), (21, 'apollo', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:03', 'apollo', '2016-10-10 17:55:03'), (22, 'apollo2', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:21', 'apollo', '2016-10-10 17:55:21'), (23, 'apollo3', 'test0621-04', 10000, 00000000, 'apollo', '2016-10-10 17:55:21', 'apollo', '2016-10-10 17:55:21'); ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-consumerroles.sql ================================================ INSERT INTO `consumerrole` (`Id`, `ConsumerId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (890, 1, 990, 'someOperator', 'someOperator'); INSERT INTO `consumerrole` (`Id`, `ConsumerId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (891, 2, 990, 'someOperator', 'someOperator'); ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-permissions.sql ================================================ INSERT INTO `permission` (`Id`, `PermissionType`, `TargetId`) VALUES (990, 'somePermissionType', 'someTargetId'); INSERT INTO `permission` (`Id`, `PermissionType`, `TargetId`) VALUES (991, 'anotherPermissionType', 'anotherTargetId'); ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-rolepermissions.sql ================================================ INSERT INTO `rolepermission` (`Id`, `RoleId`, `PermissionId`) VALUES (990, 990, 990); INSERT INTO `rolepermission` (`Id`, `RoleId`, `PermissionId`) VALUES (991, 990, 991); ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-roles.sql ================================================ INSERT INTO `role` (`Id`, `RoleName`) VALUES (990, 'someRoleName'); INSERT INTO `role` (`Id`, `RoleName`) VALUES (991, 'anotherRoleName'); ================================================ FILE: open-config-center/apollo/apollo-portal/src/test/resources/sql/permission/insert-test-userroles.sql ================================================ INSERT INTO `userrole` (`Id`, `UserId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (990, 'someUser', 990, 'someOperator', 'someOperator'); INSERT INTO `userrole` (`Id`, `UserId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES (991, 'anotherUser', 990, 'someOperator', 'someOperator'); ================================================ FILE: open-config-center/apollo/pom.xml ================================================ 4.0.0 com.open.capacity open-config-center 0.0.1-SNAPSHOT com.ctrip.framework.apollo apollo pom 0.10.0-SNAPSHOT 1.8 UTF-8 1.3.8.RELEASE 1.2.3.RELEASE 3.6.0 2.19.1 3.0.1 3.0.2 2.5.2 2.8.2 apollo-core apollo-client apollo-common apollo-biz apollo-configservice apollo-adminservice apollo-portal com.ctrip.framework.apollo apollo-core ${project.version} com.ctrip.framework.apollo apollo-common ${project.version} com.ctrip.framework.apollo apollo-biz ${project.version} com.ctrip.framework.apollo apollo-buildtools ${project.version} com.ctrip.framework.apollo apollo-configservice ${project.version} com.ctrip.framework.apollo apollo-adminservice ${project.version} com.ctrip.framework.apollo apollo-portal ${project.version} com.dianping.cat cat-client 2.2.3 com.ctrip.platform ctrip-dal-client 1.0.2 logback-core ch.qos.logback logback-classic ch.qos.logback commons-logging commons-logging xmlpull xmlpull org.bouncycastle bcprov-jdk16 javax.persistence persistence-api com.ctrip.framework.clogging clogging-agent 3.5.2 logback-core ch.qos.logback logback-classic ch.qos.logback commons-logging commons-logging com.ctrip.credis credis 2.4.11 com.ctrip.framework vi 0.9.1 com.ctrip.framework.apollo-sso apollo-sso-ctrip 1.1.0 asm asm com.ctrip.framework.apollo-ctrip-service apollo-email-service 1.0.0 javax.servlet javax.servlet-api commons-logging commons-logging commons-beanutils commons-beanutils-core org.slf4j slf4j-api 1.7.21 com.google.guava guava 19.0 com.google.code.gson gson 2.8.0 mysql mysql-connector-java 5.1.39 com.google.inject guice 4.1.0 com.h2database h2 1.4.191 io.spring.platform platform-bom 2.0.8.RELEASE pom import org.springframework.cloud spring-cloud-netflix 1.2.3.RELEASE pom import com.ctrip.3rdparty.tomcat.embed tomcat-embed-core 8.0.37 org.apache.tomcat.embed tomcat-embed-logging-juli org.springframework.boot spring-boot-starter-test test org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} ${java.version} ${java.version} ${project.build.sourceEncoding} org.springframework.boot spring-boot-maven-plugin 1.3.5.RELEASE repackage org.codehaus.mojo versions-maven-plugin 2.2 org.apache.maven.plugins maven-compiler-plugin src/main/resources true **/*.yml **/*.yaml **/*.properties **/*.xml src/main/resources false **/*.yml **/*.yaml **/*.properties **/*.xml ctrip-dev ctrip org.springframework.boot spring-boot-starter-web ${spring-boot.version} org.apache.tomcat.embed tomcat-embed-logging-juli org.apache.tomcat.embed tomcat-embed-core org.springframework.cloud spring-cloud-starter-eureka ${spring-cloud.version} stax stax-api javax.xml.stream stax-api org.springframework.security spring-security-crypto xmlpull xmlpull io.netty netty-codec-http io.netty netty-buffer io.netty netty-common io.netty netty-transport-native-epoll io.netty netty-transport commons-beanutils commons-beanutils-core aopalliance aopalliance com.ctrip.3rdparty.tomcat.embed tomcat-embed-core org.springframework.boot spring-boot-starter-web ${spring-boot.version} org.apache.tomcat.embed tomcat-embed-logging-juli org.apache.tomcat.embed tomcat-embed-core org.springframework.cloud spring-cloud-starter-eureka ${spring-cloud.version} stax stax-api javax.xml.stream stax-api org.springframework.security spring-security-crypto xmlpull xmlpull io.netty netty-codec-http io.netty netty-buffer io.netty netty-common io.netty netty-transport-native-epoll io.netty netty-transport commons-beanutils commons-beanutils-core aopalliance aopalliance com.dianping.cat cat-client com.ctrip.3rdparty.tomcat.embed tomcat-embed-core com.ctrip.framework.clogging clogging-agent com.ctrip.platform ctrip-dal-client ================================================ FILE: open-config-center/apollo/scripts/build.bat ================================================ @echo off rem apollo config db info set apollo_config_db_url="jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8" set apollo_config_db_username="root" set apollo_config_db_password="" rem apollo portal db info set apollo_portal_db_url="jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8" set apollo_portal_db_username="root" set apollo_portal_db_password="" rem meta server url, different environments should have different meta server addresses set dev_meta="http://localhost:8080" set fat_meta="http://someIp:8080" set uat_meta="http://anotherIp:8080" set pro_meta="http://yetAnotherIp:8080" set META_SERVERS_OPTS=-Ddev_meta=%dev_meta% -Dfat_meta=%fat_meta% -Duat_meta=%uat_meta% -Dpro_meta=%pro_meta% rem =============== Please do not modify the following content =============== rem go to script directory cd "%~dp0" cd .. rem package config-service and admin-service echo "==== starting to build config-service and admin-service ====" call mvn clean package -DskipTests -pl apollo-configservice,apollo-adminservice -am -Dapollo_profile=github -Dspring_datasource_url=%apollo_config_db_url% -Dspring_datasource_username=%apollo_config_db_username% -Dspring_datasource_password=%apollo_config_db_password% echo "==== building config-service and admin-service finished ====" echo "==== starting to build portal ====" call mvn clean package -DskipTests -pl apollo-portal -am -Dapollo_profile=github,auth -Dspring_datasource_url=%apollo_portal_db_url% -Dspring_datasource_username=%apollo_portal_db_username% -Dspring_datasource_password=%apollo_portal_db_password% %META_SERVERS_OPTS% echo "==== building portal finished ====" echo "==== starting to build client ====" call mvn clean install -DskipTests -pl apollo-client -am %META_SERVERS_OPTS% echo "==== building client finished ====" pause ================================================ FILE: open-config-center/apollo/scripts/build.sh ================================================ #!/bin/sh # apollo config db info apollo_config_db_url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 apollo_config_db_username=root apollo_config_db_password= # apollo portal db info apollo_portal_db_url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8 apollo_portal_db_username=root apollo_portal_db_password= # meta server url, different environments should have different meta server addresses dev_meta=http://localhost:8080 fat_meta=http://someIp:8080 uat_meta=http://anotherIp:8080 pro_meta=http://yetAnotherIp:8080 META_SERVERS_OPTS="-Ddev_meta=$dev_meta -Dfat_meta=$fat_meta -Duat_meta=$uat_meta -Dpro_meta=$pro_meta" # =============== Please do not modify the following content =============== # # go to script directory cd "${0%/*}" cd .. # package config-service and admin-service echo "==== starting to build config-service and admin-service ====" mvn clean package -DskipTests -pl apollo-configservice,apollo-adminservice -am -Dapollo_profile=github -Dspring_datasource_url=$apollo_config_db_url -Dspring_datasource_username=$apollo_config_db_username -Dspring_datasource_password=$apollo_config_db_password echo "==== building config-service and admin-service finished ====" echo "==== starting to build portal ====" mvn clean package -DskipTests -pl apollo-portal -am -Dapollo_profile=github,auth -Dspring_datasource_url=$apollo_portal_db_url -Dspring_datasource_username=$apollo_portal_db_username -Dspring_datasource_password=$apollo_portal_db_password $META_SERVERS_OPTS echo "==== building portal finished ====" echo "==== starting to build client ====" mvn clean install -DskipTests -pl apollo-client -am $META_SERVERS_OPTS echo "==== building client finished ====" ================================================ FILE: open-config-center/apollo/scripts/docker-quick-start/docker-compose.yml ================================================ version: '2' services: apollo-quick-start: image: nobodyiam/apollo-quick-start container_name: apollo-quick-start depends_on: - apollo-db ports: - "8080:8080" - "8070:8070" links: - apollo-db apollo-db: image: mysql:5.7 container_name: apollo-db environment: TZ: Asia/Shanghai MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' depends_on: - apollo-dbdata ports: - "13306:3306" volumes: - ./sql:/docker-entrypoint-initdb.d volumes_from: - apollo-dbdata apollo-dbdata: image: alpine:latest container_name: apollo-dbdata volumes: - /var/lib/mysql ================================================ FILE: open-config-center/apollo/scripts/docker-quick-start/sql/apolloconfigdb.sql ================================================ /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; # Create Database # ------------------------------------------------------------ CREATE DATABASE IF NOT EXISTS ApolloConfigDB DEFAULT CHARACTER SET = utf8mb4; Use ApolloConfigDB; # Dump of table app # ------------------------------------------------------------ DROP TABLE IF EXISTS `App`; CREATE TABLE `App` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名', `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id', `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字', `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName', `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Name` (`Name`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表'; # Dump of table appnamespace # ------------------------------------------------------------ DROP TABLE IF EXISTS `AppNamespace`; CREATE TABLE `AppNamespace` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字,注意,需要全局唯一', `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id', `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型', `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共', `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_AppId` (`AppId`), KEY `Name_AppId` (`Name`,`AppId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义'; # Dump of table audit # ------------------------------------------------------------ DROP TABLE IF EXISTS `Audit`; CREATE TABLE `Audit` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `EntityName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '表名', `EntityId` int(10) unsigned DEFAULT NULL COMMENT '记录ID', `OpName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '操作类型', `Comment` varchar(500) DEFAULT NULL COMMENT '备注', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日志审计表'; # Dump of table cluster # ------------------------------------------------------------ DROP TABLE IF EXISTS `Cluster`; CREATE TABLE `Cluster` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Name` varchar(32) NOT NULL DEFAULT '' COMMENT '集群名字', `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'App id', `ParentClusterId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父cluster', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_AppId_Name` (`AppId`,`Name`), KEY `IX_ParentClusterId` (`ParentClusterId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群'; # Dump of table commit # ------------------------------------------------------------ DROP TABLE IF EXISTS `Commit`; CREATE TABLE `Commit` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `ChangeSets` longtext NOT NULL COMMENT '修改变更集', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName', `Comment` varchar(500) DEFAULT NULL COMMENT '备注', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `AppId` (`AppId`(191)), KEY `ClusterName` (`ClusterName`(191)), KEY `NamespaceName` (`NamespaceName`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='commit 历史表'; # Dump of table grayreleaserule # ------------------------------------------------------------ DROP TABLE IF EXISTS `GrayReleaseRule`; CREATE TABLE `GrayReleaseRule` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name', `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name', `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'branch name', `Rules` varchar(16000) DEFAULT '[]' COMMENT '灰度规则', `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '灰度对应的release', `BranchStatus` tinyint(2) DEFAULT '1' COMMENT '灰度分支状态: 0:删除分支,1:正在使用的规则 2:全量发布', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='灰度规则表'; # Dump of table instance # ------------------------------------------------------------ DROP TABLE IF EXISTS `Instance`; CREATE TABLE `Instance` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `DataCenter` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'Data Center Name', `Ip` varchar(32) NOT NULL DEFAULT '' COMMENT 'instance ip', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), UNIQUE KEY `IX_UNIQUE_KEY` (`AppId`,`ClusterName`,`Ip`,`DataCenter`), KEY `IX_IP` (`Ip`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='使用配置的应用实例'; # Dump of table instanceconfig # ------------------------------------------------------------ DROP TABLE IF EXISTS `InstanceConfig`; CREATE TABLE `InstanceConfig` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `InstanceId` int(11) unsigned DEFAULT NULL COMMENT 'Instance Id', `ConfigAppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config App Id', `ConfigClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Cluster Name', `ConfigNamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Namespace Name', `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key', `ReleaseDeliveryTime` timestamp NULL DEFAULT NULL COMMENT '配置获取时间', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), UNIQUE KEY `IX_UNIQUE_KEY` (`InstanceId`,`ConfigAppId`,`ConfigNamespaceName`), KEY `IX_ReleaseKey` (`ReleaseKey`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Valid_Namespace` (`ConfigAppId`,`ConfigClusterName`,`ConfigNamespaceName`,`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用实例的配置信息'; # Dump of table item # ------------------------------------------------------------ DROP TABLE IF EXISTS `Item`; CREATE TABLE `Item` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId', `Key` varchar(128) NOT NULL DEFAULT 'default' COMMENT '配置项Key', `Value` longtext NOT NULL COMMENT '配置项值', `Comment` varchar(1024) DEFAULT '' COMMENT '注释', `LineNum` int(10) unsigned DEFAULT '0' COMMENT '行号', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_GroupId` (`NamespaceId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置项目'; # Dump of table namespace # ------------------------------------------------------------ DROP TABLE IF EXISTS `Namespace`; CREATE TABLE `Namespace` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name', `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId_ClusterName_NamespaceName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_NamespaceName` (`NamespaceName`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='命名空间'; # Dump of table namespacelock # ------------------------------------------------------------ DROP TABLE IF EXISTS `NamespaceLock`; CREATE TABLE `NamespaceLock` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT 'default' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', `IsDeleted` bit(1) DEFAULT b'0' COMMENT '软删除', PRIMARY KEY (`Id`), UNIQUE KEY `IX_NamespaceId` (`NamespaceId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='namespace的编辑锁'; # Dump of table release # ------------------------------------------------------------ DROP TABLE IF EXISTS `Release`; CREATE TABLE `Release` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key', `Name` varchar(64) NOT NULL DEFAULT 'default' COMMENT '发布名字', `Comment` varchar(256) DEFAULT NULL COMMENT '发布说明', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName', `Configurations` longtext NOT NULL COMMENT '发布配置', `IsAbandoned` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否废弃', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId_ClusterName_GroupName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_ReleaseKey` (`ReleaseKey`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布'; # Dump of table releasehistory # ------------------------------------------------------------ DROP TABLE IF EXISTS `ReleaseHistory`; CREATE TABLE `ReleaseHistory` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'namespaceName', `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT '发布分支名', `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联的Release Id', `PreviousReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '前一次发布的ReleaseId', `Operation` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '发布类型,0: 普通发布,1: 回滚,2: 灰度发布,3: 灰度规则更新,4: 灰度合并回主分支发布,5: 主分支发布灰度自动发布,6: 主分支回滚灰度自动发布,7: 放弃灰度', `OperationContext` longtext NOT NULL COMMENT '发布上下文信息', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`,`BranchName`), KEY `IX_ReleaseId` (`ReleaseId`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布历史'; # Dump of table releasemessage # ------------------------------------------------------------ DROP TABLE IF EXISTS `ReleaseMessage`; CREATE TABLE `ReleaseMessage` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Message` varchar(1024) NOT NULL DEFAULT '' COMMENT '发布的消息内容', `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Message` (`Message`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布消息'; # Dump of table serverconfig # ------------------------------------------------------------ DROP TABLE IF EXISTS `ServerConfig`; CREATE TABLE `ServerConfig` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key', `Cluster` varchar(32) NOT NULL DEFAULT 'default' COMMENT '配置对应的集群,default为不针对特定的集群', `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值', `Comment` varchar(1024) DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_Key` (`Key`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置'; # Config # ------------------------------------------------------------ INSERT INTO `ServerConfig` (`Key`, `Cluster`, `Value`, `Comment`) VALUES ('eureka.service.url', 'default', 'http://localhost:8080/eureka/', 'Eureka服务Url,多个service以英文逗号分隔'), ('namespace.lock.switch', 'default', 'false', '一次发布只能有一个人修改开关'), ('item.value.length.limit', 'default', '20000', 'item value最大长度限制'), ('config-service.cache.enabled', 'default', 'false', 'ConfigService是否开启缓存,开启后能提高性能,但是会增大内存消耗!'), ('item.key.length.limit', 'default', '128', 'item key 最大长度限制'); # Sample Data # ------------------------------------------------------------ INSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`) VALUES ('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com'); INSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`) VALUES ('application', 'SampleApp', 'properties', 0, 'default app namespace'); INSERT INTO `Cluster` (`Name`, `AppId`) VALUES ('default', 'SampleApp'); INSERT INTO `Namespace` (`Id`, `AppId`, `ClusterName`, `NamespaceName`) VALUES (1, 'SampleApp', 'default', 'application'); INSERT INTO `Item` (`NamespaceId`, `Key`, `Value`, `Comment`, `LineNum`) VALUES (1, 'timeout', '100', 'sample timeout配置', 1); INSERT INTO `Release` (`ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`) VALUES ('20161009155425-d3a0749c6e20bc15', '20161009155424-release', 'Sample发布', 'SampleApp', 'default', 'application', '{\"timeout\":\"100\"}'); INSERT INTO `ReleaseHistory` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `ReleaseId`, `PreviousReleaseId`, `Operation`, `OperationContext`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`) VALUES ('SampleApp', 'default', 'application', 'default', 1, 0, 0, '{}', 'apollo', 'apollo'); /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; ================================================ FILE: open-config-center/apollo/scripts/docker-quick-start/sql/apolloportaldb.sql ================================================ /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; # Create Database # ------------------------------------------------------------ CREATE DATABASE IF NOT EXISTS ApolloPortalDB DEFAULT CHARACTER SET = utf8mb4; Use ApolloPortalDB; # Dump of table app # ------------------------------------------------------------ DROP TABLE IF EXISTS `App`; CREATE TABLE `App` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名', `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id', `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字', `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName', `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Name` (`Name`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表'; # Dump of table appnamespace # ------------------------------------------------------------ DROP TABLE IF EXISTS `AppNamespace`; CREATE TABLE `AppNamespace` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字,注意,需要全局唯一', `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id', `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型', `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共', `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_AppId` (`AppId`), KEY `Name_AppId` (`Name`,`AppId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义'; # Dump of table consumer # ------------------------------------------------------------ DROP TABLE IF EXISTS `Consumer`; CREATE TABLE `Consumer` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名', `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id', `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字', `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName', `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放API消费者'; # Dump of table consumeraudit # ------------------------------------------------------------ DROP TABLE IF EXISTS `ConsumerAudit`; CREATE TABLE `ConsumerAudit` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id', `Uri` varchar(1024) NOT NULL DEFAULT '' COMMENT '访问的Uri', `Method` varchar(16) NOT NULL DEFAULT '' COMMENT '访问的Method', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_ConsumerId` (`ConsumerId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer审计表'; # Dump of table consumerrole # ------------------------------------------------------------ DROP TABLE IF EXISTS `ConsumerRole`; CREATE TABLE `ConsumerRole` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id', `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_RoleId` (`RoleId`), KEY `IX_ConsumerId_RoleId` (`ConsumerId`,`RoleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer和role的绑定表'; # Dump of table consumertoken # ------------------------------------------------------------ DROP TABLE IF EXISTS `ConsumerToken`; CREATE TABLE `ConsumerToken` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'ConsumerId', `Token` varchar(128) NOT NULL DEFAULT '' COMMENT 'token', `Expires` datetime NOT NULL DEFAULT '2099-01-01 00:00:00' COMMENT 'token失效时间', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), UNIQUE KEY `IX_Token` (`Token`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer token表'; # Dump of table favorite # ------------------------------------------------------------ DROP TABLE IF EXISTS `Favorite`; CREATE TABLE `Favorite` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `UserId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '收藏的用户', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Position` int(32) NOT NULL DEFAULT '10000' COMMENT '收藏顺序', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `IX_UserId` (`UserId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COMMENT='应用收藏表'; # Dump of table permission # ------------------------------------------------------------ DROP TABLE IF EXISTS `Permission`; CREATE TABLE `Permission` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `PermissionType` varchar(32) NOT NULL DEFAULT '' COMMENT '权限类型', `TargetId` varchar(256) NOT NULL DEFAULT '' COMMENT '权限对象类型', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_TargetId_PermissionType` (`TargetId`(191),`PermissionType`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='permission表'; # Dump of table role # ------------------------------------------------------------ DROP TABLE IF EXISTS `Role`; CREATE TABLE `Role` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `RoleName` varchar(256) NOT NULL DEFAULT '' COMMENT 'Role name', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_RoleName` (`RoleName`(191)), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表'; # Dump of table rolepermission # ------------------------------------------------------------ DROP TABLE IF EXISTS `RolePermission`; CREATE TABLE `RolePermission` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id', `PermissionId` int(10) unsigned DEFAULT NULL COMMENT 'Permission Id', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_RoleId` (`RoleId`), KEY `IX_PermissionId` (`PermissionId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色和权限的绑定表'; # Dump of table serverconfig # ------------------------------------------------------------ DROP TABLE IF EXISTS `ServerConfig`; CREATE TABLE `ServerConfig` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key', `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值', `Comment` varchar(1024) DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_Key` (`Key`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置'; # Dump of table userrole # ------------------------------------------------------------ DROP TABLE IF EXISTS `UserRole`; CREATE TABLE `UserRole` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `UserId` varchar(128) DEFAULT '' COMMENT '用户身份标识', `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_RoleId` (`RoleId`), KEY `IX_UserId_RoleId` (`UserId`,`RoleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和role的绑定表'; # Dump of table Users # ------------------------------------------------------------ DROP TABLE IF EXISTS `Users`; CREATE TABLE `Users` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Username` varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户名', `Password` varchar(64) NOT NULL DEFAULT 'default' COMMENT '密码', `Email` varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱地址', `Enabled` tinyint(4) DEFAULT NULL COMMENT '是否有效', PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; # Dump of table Authorities # ------------------------------------------------------------ DROP TABLE IF EXISTS `Authorities`; CREATE TABLE `Authorities` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Username` varchar(50) NOT NULL, `Authority` varchar(50) NOT NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # Config # ------------------------------------------------------------ INSERT INTO `ServerConfig` (`Key`, `Value`, `Comment`) VALUES ('apollo.portal.envs', 'dev', '可支持的环境列表'), ('organizations', '[{\"orgId\":\"TEST1\",\"orgName\":\"样例部门1\"},{\"orgId\":\"TEST2\",\"orgName\":\"样例部门2\"}]', '部门列表'), ('superAdmin', 'apollo', 'Portal超级管理员'), ('api.readTimeout', '10000', 'http接口read timeout'), ('consumer.token.salt', 'someSalt', 'consumer token salt'), ('admin.createPrivateNamespace.switch', 'false', '是否允许项目管理员创建私有namespace'); INSERT INTO `Users` (`Username`, `Password`, `Email`, `Enabled`) VALUES ('apollo', '$2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS', 'apollo@acme.com', 1); INSERT INTO `Authorities` (`Username`, `Authority`) VALUES ('apollo', 'ROLE_user'); # Sample Data # ------------------------------------------------------------ INSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`) VALUES ('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com'); INSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`) VALUES ('application', 'SampleApp', 'properties', 0, 'default app namespace'); INSERT INTO `Permission` (`Id`, `PermissionType`, `TargetId`) VALUES (1, 'CreateCluster', 'SampleApp'), (2, 'CreateNamespace', 'SampleApp'), (3, 'AssignRole', 'SampleApp'), (4, 'ModifyNamespace', 'SampleApp+application'), (5, 'ReleaseNamespace', 'SampleApp+application'); INSERT INTO `Role` (`Id`, `RoleName`) VALUES (1, 'Master+SampleApp'), (2, 'ModifyNamespace+SampleApp+application'), (3, 'ReleaseNamespace+SampleApp+application'); INSERT INTO `RolePermission` (`RoleId`, `PermissionId`) VALUES (1, 1), (1, 2), (1, 3), (2, 4), (3, 5); INSERT INTO `UserRole` (`UserId`, `RoleId`) VALUES ('apollo', 1), ('apollo', 2), ('apollo', 3); /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; ================================================ FILE: open-config-center/apollo/scripts/sql/apolloconfigdb.sql ================================================ # Create Database # ------------------------------------------------------------ CREATE DATABASE IF NOT EXISTS ApolloConfigDB DEFAULT CHARACTER SET = utf8mb4; Use ApolloConfigDB; # Host: 47.94.252.160 (Version 5.7.22) # Date: 2018-06-26 20:02:25 # Generator: MySQL-Front 5.4 (Build 4.153) - http://www.mysqlfront.de/ /*!40101 SET NAMES utf8 */; # # Structure for table "app" # DROP TABLE IF EXISTS `app`; CREATE TABLE `app` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名', `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id', `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字', `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName', `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Name` (`Name`(191)) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用表'; # # Data for table "app" # INSERT INTO `app` VALUES (1,'SampleApp','Sample App','TEST1','样例部门1','apollo','apollo@acme.com',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'zuulservice','zuulservice-dev','TEST1','样例部门1','apollo','apollo@acme.com',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'); # # Structure for table "appnamespace" # DROP TABLE IF EXISTS `appnamespace`; CREATE TABLE `appnamespace` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字,注意,需要全局唯一', `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id', `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型', `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共', `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_AppId` (`AppId`), KEY `Name_AppId` (`Name`,`AppId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义'; # # Data for table "appnamespace" # INSERT INTO `appnamespace` VALUES (1,'application','SampleApp','properties',b'0','default app namespace',b'0','','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'application','zuulservice','properties',b'0','default app namespace',b'0','apollo','2018-04-04 00:09:43','apollo','2018-04-04 00:09:43'); # # Structure for table "audit" # DROP TABLE IF EXISTS `audit`; CREATE TABLE `audit` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `EntityName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '表名', `EntityId` int(10) unsigned DEFAULT NULL COMMENT '记录ID', `OpName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '操作类型', `Comment` varchar(500) DEFAULT NULL COMMENT '备注', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COMMENT='日志审计表'; # # Data for table "audit" # INSERT INTO `audit` VALUES (1,'App',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(2,'AppNamespace',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(3,'Cluster',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(4,'Namespace',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:09:43',NULL,'2018-04-04 00:09:43'),(5,'Item',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(6,'Item',3,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(7,'Item',4,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(8,'Item',5,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(9,'Item',6,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(10,'Item',7,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(11,'Item',8,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(12,'Item',9,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(13,'Item',10,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(14,'Item',11,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(15,'Item',12,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(16,'Item',13,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(17,'Item',14,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(18,'Item',15,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(19,'Item',16,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(20,'Item',17,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(21,'Item',18,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(22,'Item',19,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(23,'Item',20,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(24,'Item',21,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(25,'Item',22,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(26,'Item',23,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(27,'Item',24,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(28,'Item',25,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(29,'Item',26,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(30,'Item',27,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(31,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 00:11:27',NULL,'2018-04-04 00:11:27'),(32,'Item',8,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(33,'Item',16,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(34,'Item',20,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(35,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(36,'Item',26,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(37,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 00:12:13',NULL,'2018-04-04 00:12:13'),(38,'Release',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:12:29',NULL,'2018-04-04 00:12:29'),(39,'ReleaseHistory',2,'INSERT',NULL,b'0','apollo','2018-04-04 00:12:29',NULL,'2018-04-04 00:12:29'),(40,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 00:22:18',NULL,'2018-04-04 00:22:18'),(41,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 00:22:19',NULL,'2018-04-04 00:22:19'),(42,'Release',3,'INSERT',NULL,b'0','apollo','2018-04-04 00:22:21',NULL,'2018-04-04 00:22:21'),(43,'ReleaseHistory',3,'INSERT',NULL,b'0','apollo','2018-04-04 00:22:21',NULL,'2018-04-04 00:22:21'),(44,'Item',28,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(45,'Item',29,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(46,'Item',30,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(47,'Item',31,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(48,'Item',32,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(49,'Item',33,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(50,'Item',34,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(51,'Item',35,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(52,'Item',36,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(53,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(54,'Item',13,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(55,'Item',18,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(56,'Item',11,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(57,'Item',12,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(58,'Item',19,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(59,'Item',23,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:46',NULL,'2018-04-04 00:55:46'),(60,'Item',24,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(61,'Item',14,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(62,'Item',15,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(63,'Item',17,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(64,'Item',7,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(65,'Item',9,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(66,'Item',10,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(67,'Item',20,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(68,'Item',22,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(69,'Item',25,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(70,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(71,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(72,'Item',8,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(73,'Item',27,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(74,'Item',5,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(75,'Item',16,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(76,'Item',2,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(77,'Item',26,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(78,'ItemSet',NULL,'DELETE',NULL,b'0','apollo','2018-04-04 00:55:47',NULL,'2018-04-04 00:55:47'),(79,'Release',4,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:50',NULL,'2018-04-04 00:55:50'),(80,'ReleaseHistory',4,'INSERT',NULL,b'0','apollo','2018-04-04 00:55:50',NULL,'2018-04-04 00:55:50'),(81,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-03 19:25:16',NULL,'2018-04-03 19:25:16'),(82,'Release',5,'INSERT',NULL,b'0','apollo','2018-04-03 19:25:22',NULL,'2018-04-03 19:25:22'),(83,'ReleaseHistory',5,'INSERT',NULL,b'0','apollo','2018-04-03 19:25:22',NULL,'2018-04-03 19:25:22'),(84,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 17:53:27',NULL,'2018-04-04 17:53:27'),(85,'Release',6,'INSERT',NULL,b'0','apollo','2018-04-04 17:53:31',NULL,'2018-04-04 17:53:31'),(86,'ReleaseHistory',6,'INSERT',NULL,b'0','apollo','2018-04-04 17:53:31',NULL,'2018-04-04 17:53:31'),(87,'Item',37,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(88,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(89,'Item',21,'UPDATE',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(90,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-04-04 17:56:31',NULL,'2018-04-04 17:56:31'),(91,'Release',7,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:35',NULL,'2018-04-04 17:56:35'),(92,'ReleaseHistory',7,'INSERT',NULL,b'0','apollo','2018-04-04 17:56:35',NULL,'2018-04-04 17:56:35'),(93,'Item',37,'DELETE',NULL,b'0','apollo','2018-04-04 19:38:49',NULL,'2018-04-04 19:38:49'),(94,'Release',8,'INSERT',NULL,b'0','apollo','2018-04-04 19:39:15',NULL,'2018-04-04 19:39:15'),(95,'ReleaseHistory',8,'INSERT',NULL,b'0','apollo','2018-04-04 19:39:15',NULL,'2018-04-04 19:39:15'),(96,'Item',38,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:46',NULL,'2018-04-04 19:41:46'),(97,'ItemSet',NULL,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:46',NULL,'2018-04-04 19:41:46'),(98,'Release',9,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:50',NULL,'2018-04-04 19:41:50'),(99,'ReleaseHistory',9,'INSERT',NULL,b'0','apollo','2018-04-04 19:41:50',NULL,'2018-04-04 19:41:50'),(100,'Item',24,'UPDATE',NULL,b'0','apollo','2018-06-26 19:59:13',NULL,'2018-06-26 19:59:13'),(101,'ItemSet',NULL,'UPDATE',NULL,b'0','apollo','2018-06-26 19:59:14',NULL,'2018-06-26 19:59:14'),(102,'Release',10,'INSERT',NULL,b'0','apollo','2018-06-26 19:59:20',NULL,'2018-06-26 19:59:20'),(103,'ReleaseHistory',10,'INSERT',NULL,b'0','apollo','2018-06-26 19:59:20',NULL,'2018-06-26 19:59:20'),(104,'Item',21,'UPDATE',NULL,b'0','apollo','2018-06-26 20:00:37',NULL,'2018-06-26 20:00:37'),(105,'Release',11,'INSERT',NULL,b'0','apollo','2018-06-26 20:00:42',NULL,'2018-06-26 20:00:42'),(106,'ReleaseHistory',11,'INSERT',NULL,b'0','apollo','2018-06-26 20:00:42',NULL,'2018-06-26 20:00:42'); # # Structure for table "cluster" # DROP TABLE IF EXISTS `cluster`; CREATE TABLE `cluster` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Name` varchar(32) NOT NULL DEFAULT '' COMMENT '集群名字', `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'App id', `ParentClusterId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父cluster', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_AppId_Name` (`AppId`,`Name`), KEY `IX_ParentClusterId` (`ParentClusterId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='集群'; # # Data for table "cluster" # INSERT INTO `cluster` VALUES (1,'default','SampleApp',0,b'0','','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'default','zuulservice',0,b'0','apollo','2018-04-04 00:09:43','apollo','2018-04-04 00:09:43'); # # Structure for table "commit" # DROP TABLE IF EXISTS `commit`; CREATE TABLE `commit` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `ChangeSets` longtext NOT NULL COMMENT '修改变更集', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName', `Comment` varchar(500) DEFAULT NULL COMMENT '备注', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `AppId` (`AppId`(191)), KEY `ClusterName` (`ClusterName`(191)), KEY `NamespaceName` (`NamespaceName`(191)) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='commit 历史表'; # # Data for table "commit" # INSERT INTO `commit` VALUES (1,'{\"createItems\":[{\"namespaceId\":2,\"key\":\"zuul.routes.test165.path\",\"value\":\"/test165/**\",\"comment\":\"\",\"lineNum\":1,\"id\":2,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"ribbon.ConnectTimeout\",\"value\":\"10000\",\"comment\":\"\",\"lineNum\":2,\"id\":3,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"ribbon.OkToRetryOnAllOperations\",\"value\":\"true\",\"comment\":\"\",\"lineNum\":3,\"id\":4,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test166.path\",\"value\":\"/test166/**\",\"comment\":\"\",\"lineNum\":4,\"id\":5,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"ribbon.MaxAutoRetriesNextServer\",\"value\":\"2\",\"comment\":\"\",\"lineNum\":5,\"id\":6,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.host.connect-timeout-millis\",\"value\":\"10000\",\"comment\":\"\",\"lineNum\":6,\"id\":7,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test164.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":7,\"id\":8,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.host.maxTotalConnections\",\"value\":\"1024\",\"comment\":\"\",\"lineNum\":8,\"id\":9,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.host.maxPerRouteConnections\",\"value\":\"512\",\"comment\":\"\",\"lineNum\":9,\"id\":10,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"management.security.enabled\",\"value\":\"false\",\"comment\":\"\",\"lineNum\":10,\"id\":11,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"spring.application.name\",\"value\":\"sop-api-gateway\",\"comment\":\"\",\"lineNum\":11,\"id\":12,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"ribbon.MaxAutoRetries\",\"value\":\"1\",\"comment\":\"\",\"lineNum\":12,\"id\":13,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.semaphore.max-semaphores\",\"value\":\"1024\",\"comment\":\"\",\"lineNum\":13,\"id\":14,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.host.socket-timeout-millis\",\"value\":\"10000\",\"comment\":\"\",\"lineNum\":14,\"id\":15,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test166.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":15,\"id\":16,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:26\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.ignored-services\",\"value\":\"\\\"*\\\"\",\"comment\":\"\",\"lineNum\":16,\"id\":17,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"ribbon.ReadTimeout\",\"value\":\"10000\",\"comment\":\"\",\"lineNum\":17,\"id\":18,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\",\"value\":\"10000\",\"comment\":\"\",\"lineNum\":18,\"id\":19,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test163.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":19,\"id\":20,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http\\\\://130.75.131.236\\\\:1111/eureka/\",\"comment\":\"\",\"lineNum\":20,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test163.path\",\"value\":\"/test163/**\",\"comment\":\"\",\"lineNum\":21,\"id\":22,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"hystrix.command.default.execution.timeout.enabled\",\"value\":\"true\",\"comment\":\"\",\"lineNum\":22,\"id\":23,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"server.port\",\"value\":\"9000\",\"comment\":\"\",\"lineNum\":23,\"id\":24,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"eureka.instance.prefer-ip-address\",\"value\":\"true\",\"comment\":\"\",\"lineNum\":24,\"id\":25,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test165.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":25,\"id\":26,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test164.path\",\"value\":\"/test164/**\",\"comment\":\"\",\"lineNum\":26,\"id\":27,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"}],\"updateItems\":[],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(2,'{\"createItems\":[],\"updateItems\":[{\"oldItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test164.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":7,\"id\":8,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},\"newItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test164.url\",\"value\":\"http://www.163.com\",\"comment\":\"\",\"lineNum\":7,\"id\":8,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:12:13\"}},{\"oldItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test166.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":15,\"id\":16,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},\"newItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test166.url\",\"value\":\"http://www.163.com\",\"comment\":\"\",\"lineNum\":15,\"id\":16,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:12:13\"}},{\"oldItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test163.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":19,\"id\":20,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},\"newItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test163.url\",\"value\":\"http://www.163.com\",\"comment\":\"\",\"lineNum\":19,\"id\":20,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:12:13\"}},{\"oldItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http\\\\://130.75.131.236\\\\:1111/eureka/\",\"comment\":\"\",\"lineNum\":20,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},\"newItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236\\\\:1111/eureka/\",\"comment\":\"\",\"lineNum\":20,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:12:13\"}},{\"oldItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test165.url\",\"value\":\"http\\\\://www.163.com\",\"comment\":\"\",\"lineNum\":25,\"id\":26,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:11:27\"},\"newItem\":{\"namespaceId\":2,\"key\":\"zuul.routes.test165.url\",\"value\":\"http://www.163.com\",\"comment\":\"\",\"lineNum\":25,\"id\":26,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:12:13\"}}],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:12:13','apollo','2018-04-04 00:12:13'),(3,'{\"createItems\":[],\"updateItems\":[{\"oldItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236\\\\:1111/eureka/\",\"comment\":\"\",\"lineNum\":20,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:12:13\"},\"newItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236:1111/eureka/\",\"comment\":\"\",\"lineNum\":20,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:22:18\"}}],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:22:19','apollo','2018-04-04 00:22:19'),(4,'{\"createItems\":[],\"updateItems\":[{\"oldItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236:1111/eureka/\",\"comment\":\"\",\"lineNum\":20,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:22:19\"},\"newItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236:1111/eureka\",\"comment\":\"\",\"lineNum\":29,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:46\"}}],\"deleteItems\":[{\"namespaceId\":2,\"key\":\"zuul.routes.test164.url\",\"value\":\"http://www.163.com\",\"comment\":\"\",\"lineNum\":7,\"id\":8,\"isDeleted\":true,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:46\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test164.path\",\"value\":\"/test164/**\",\"comment\":\"\",\"lineNum\":26,\"id\":27,\"isDeleted\":true,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:46\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test166.path\",\"value\":\"/test166/**\",\"comment\":\"\",\"lineNum\":4,\"id\":5,\"isDeleted\":true,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:46\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test166.url\",\"value\":\"http://www.163.com\",\"comment\":\"\",\"lineNum\":15,\"id\":16,\"isDeleted\":true,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:46\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test165.path\",\"value\":\"/test165/**\",\"comment\":\"\",\"lineNum\":1,\"id\":2,\"isDeleted\":true,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:46\"},{\"namespaceId\":2,\"key\":\"zuul.routes.test165.url\",\"value\":\"http://www.163.com\",\"comment\":\"\",\"lineNum\":25,\"id\":26,\"isDeleted\":true,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:46\"}]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 00:55:47','apollo','2018-04-04 00:55:47'),(5,'{\"createItems\":[],\"updateItems\":[{\"oldItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236:1111/eureka\",\"comment\":\"\",\"lineNum\":29,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:47\"},\"newItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://192.168.3.151:1111/eureka\",\"comment\":\"\",\"lineNum\":29,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-03 19:25:16\"}}],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-03 19:25:16','apollo','2018-04-03 19:25:16'),(6,'{\"createItems\":[],\"updateItems\":[{\"oldItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://192.168.3.151:1111/eureka\",\"comment\":\"\",\"lineNum\":29,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-03 19:25:16\"},\"newItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236:1111/eureka\",\"comment\":\"\",\"lineNum\":29,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 17:53:26\"}}],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 17:53:27','apollo','2018-04-04 17:53:27'),(7,'{\"createItems\":[{\"namespaceId\":2,\"key\":\"eureka.client.register-with-eureka\",\"value\":\"false\",\"comment\":\"\",\"lineNum\":29,\"id\":37,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 17:56:31\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 17:56:31\"}],\"updateItems\":[],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 17:56:31','apollo','2018-04-04 17:56:31'),(8,'{\"createItems\":[],\"updateItems\":[],\"deleteItems\":[{\"namespaceId\":2,\"key\":\"eureka.client.register-with-eureka\",\"value\":\"false\",\"comment\":\"\",\"lineNum\":29,\"id\":37,\"isDeleted\":true,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 17:56:31\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 19:38:49\"}]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 19:38:49','apollo','2018-04-04 19:38:49'),(9,'{\"createItems\":[{\"namespaceId\":2,\"key\":\"eureka.instance.instance-id\",\"value\":\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\",\"comment\":\"\",\"lineNum\":29,\"id\":38,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 19:41:46\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 19:41:46\"}],\"updateItems\":[],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-04-04 19:41:46','apollo','2018-04-04 19:41:46'),(10,'{\"createItems\":[],\"updateItems\":[{\"oldItem\":{\"namespaceId\":2,\"key\":\"server.port\",\"value\":\"9999\",\"comment\":\"\",\"lineNum\":15,\"id\":24,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 00:55:47\"},\"newItem\":{\"namespaceId\":2,\"key\":\"server.port\",\"value\":\"9000\",\"comment\":\"\",\"lineNum\":15,\"id\":24,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-06-26 19:59:13\"}}],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-06-26 19:59:14','apollo','2018-06-26 19:59:14'),(11,'{\"createItems\":[],\"updateItems\":[{\"oldItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://130.75.131.236:1111/eureka\",\"comment\":\"\",\"lineNum\":30,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-04-04 17:56:31\"},\"newItem\":{\"namespaceId\":2,\"key\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://127.0.0.1:1111/eureka\",\"comment\":\"\",\"lineNum\":30,\"id\":21,\"isDeleted\":false,\"dataChangeCreatedBy\":\"apollo\",\"dataChangeCreatedTime\":\"2018-04-04 00:11:27\",\"dataChangeLastModifiedBy\":\"apollo\",\"dataChangeLastModifiedTime\":\"2018-06-26 20:00:37\"}}],\"deleteItems\":[]}','zuulservice','default','application',NULL,b'0','apollo','2018-06-26 20:00:37','apollo','2018-06-26 20:00:37'); # # Structure for table "grayreleaserule" # DROP TABLE IF EXISTS `grayreleaserule`; CREATE TABLE `grayreleaserule` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name', `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name', `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'branch name', `Rules` varchar(16000) DEFAULT '[]' COMMENT '灰度规则', `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '灰度对应的release', `BranchStatus` tinyint(2) DEFAULT '1' COMMENT '灰度分支状态: 0:删除分支,1:正在使用的规则 2:全量发布', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='灰度规则表'; # # Data for table "grayreleaserule" # # # Structure for table "instance" # DROP TABLE IF EXISTS `instance`; CREATE TABLE `instance` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `DataCenter` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'Data Center Name', `Ip` varchar(32) NOT NULL DEFAULT '' COMMENT 'instance ip', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), UNIQUE KEY `IX_UNIQUE_KEY` (`AppId`,`ClusterName`,`Ip`,`DataCenter`), KEY `IX_IP` (`Ip`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='使用配置的应用实例'; # # Data for table "instance" # INSERT INTO `instance` VALUES (1,'zuulservice','default','','192.168.249.1','2018-04-04 00:21:12','2018-04-04 00:21:12'),(2,'zuulservice','default','','192.168.3.151','2018-04-03 19:28:09','2018-04-03 19:28:09'),(3,'zuulservice','default','','130.75.131.236','2018-04-04 19:34:26','2018-04-04 19:34:26'); # # Structure for table "instanceconfig" # DROP TABLE IF EXISTS `instanceconfig`; CREATE TABLE `instanceconfig` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `InstanceId` int(11) unsigned DEFAULT NULL COMMENT 'Instance Id', `ConfigAppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config App Id', `ConfigClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Cluster Name', `ConfigNamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Namespace Name', `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key', `ReleaseDeliveryTime` timestamp NULL DEFAULT NULL COMMENT '配置获取时间', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), UNIQUE KEY `IX_UNIQUE_KEY` (`InstanceId`,`ConfigAppId`,`ConfigNamespaceName`), KEY `IX_ReleaseKey` (`ReleaseKey`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Valid_Namespace` (`ConfigAppId`,`ConfigClusterName`,`ConfigNamespaceName`,`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='应用实例的配置信息'; # # Data for table "instanceconfig" # INSERT INTO `instanceconfig` VALUES (1,1,'zuulservice','default','application','20180626200041-7231d6ad3e03c09a','2018-06-26 20:00:42','2018-04-04 00:21:11','2018-06-26 20:00:43'),(2,2,'zuulservice','default','application','20180403192522-723164972d4b5883','2018-04-03 19:28:08','2018-04-03 19:28:08','2018-04-03 19:28:08'),(3,3,'zuulservice','default','application','20180404194149-723164972d357e8a','2018-04-04 19:41:50','2018-04-04 19:34:26','2018-04-04 19:41:51'); # # Structure for table "item" # DROP TABLE IF EXISTS `item`; CREATE TABLE `item` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId', `Key` varchar(128) NOT NULL DEFAULT 'default' COMMENT '配置项Key', `Value` longtext NOT NULL COMMENT '配置项值', `Comment` varchar(1024) DEFAULT '' COMMENT '注释', `LineNum` int(10) unsigned DEFAULT '0' COMMENT '行号', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_GroupId` (`NamespaceId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8mb4 COMMENT='配置项目'; # # Data for table "item" # INSERT INTO `item` VALUES (1,1,'timeout','100','sample timeout配置',1,b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,2,'zuul.routes.test165.path','/test165/**','',1,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(3,2,'ribbon.ConnectTimeout','10000','',2,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(4,2,'ribbon.OkToRetryOnAllOperations','true','',3,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(5,2,'zuul.routes.test166.path','/test166/**','',4,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(6,2,'ribbon.MaxAutoRetriesNextServer','2','',5,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:11:27'),(7,2,'zuul.host.connect-timeout-millis','10000','',22,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(8,2,'zuul.routes.test164.url','http://www.163.com','',7,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(9,2,'zuul.host.maxTotalConnections','1024','',23,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(10,2,'zuul.host.maxPerRouteConnections','512','',24,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(11,2,'management.security.enabled','false','',6,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(12,2,'spring.application.name','sop-api-gateway','',8,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(13,2,'ribbon.MaxAutoRetries','1','',1,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(14,2,'zuul.semaphore.max-semaphores','1024','',19,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(15,2,'zuul.host.socket-timeout-millis','10000','',20,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(16,2,'zuul.routes.test166.url','http://www.163.com','',15,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(17,2,'zuul.ignored-services','\"*\"','',21,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(18,2,'ribbon.ReadTimeout','10000','',4,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(19,2,'hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds','10000','',10,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(20,2,'zuul.routes.test163.url','http://www.163.com','',25,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(21,2,'eureka.client.serviceUrl.defaultZone','http://127.0.0.1:1111/eureka','',30,b'0','apollo','2018-04-04 00:11:27','apollo','2018-06-26 20:00:37'),(22,2,'zuul.routes.test163.path','/test163/**','',26,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(23,2,'hystrix.command.default.execution.timeout.enabled','true','',11,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(24,2,'server.port','9000','',15,b'0','apollo','2018-04-04 00:11:27','apollo','2018-06-26 19:59:14'),(25,2,'eureka.instance.prefer-ip-address','true','',28,b'0','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(26,2,'zuul.routes.test165.url','http://www.163.com','',25,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(27,2,'zuul.routes.test164.path','/test164/**','',26,b'1','apollo','2018-04-04 00:11:27','apollo','2018-04-04 00:55:47'),(28,2,'','','',7,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(29,2,'','','',9,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(30,2,'','','',12,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(31,2,'','','',13,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(32,2,'','','',14,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(33,2,'','','',16,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(34,2,'','','',17,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(35,2,'','','',18,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(36,2,'','','',27,b'0','apollo','2018-04-04 00:55:46','apollo','2018-04-04 00:55:46'),(37,2,'eureka.client.register-with-eureka','false','',29,b'1','apollo','2018-04-04 17:56:31','apollo','2018-04-04 19:38:49'),(38,2,'eureka.instance.instance-id','${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}','',29,b'0','apollo','2018-04-04 19:41:46','apollo','2018-04-04 19:41:46'); # # Structure for table "namespace" # DROP TABLE IF EXISTS `namespace`; CREATE TABLE `namespace` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name', `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId_ClusterName_NamespaceName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_NamespaceName` (`NamespaceName`(191)) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='命名空间'; # # Data for table "namespace" # INSERT INTO `namespace` VALUES (1,'SampleApp','default','application',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'zuulservice','default','application',b'0','apollo','2018-04-04 00:09:43','apollo','2018-04-04 00:09:43'); # # Structure for table "namespacelock" # DROP TABLE IF EXISTS `namespacelock`; CREATE TABLE `namespacelock` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT 'default' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', `IsDeleted` bit(1) DEFAULT b'0' COMMENT '软删除', PRIMARY KEY (`Id`), UNIQUE KEY `IX_NamespaceId` (`NamespaceId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='namespace的编辑锁'; # # Data for table "namespacelock" # # # Structure for table "release" # DROP TABLE IF EXISTS `release`; CREATE TABLE `release` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key', `Name` varchar(64) NOT NULL DEFAULT 'default' COMMENT '发布名字', `Comment` varchar(256) DEFAULT NULL COMMENT '发布说明', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName', `Configurations` longtext NOT NULL COMMENT '发布配置', `IsAbandoned` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否废弃', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId_ClusterName_GroupName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_ReleaseKey` (`ReleaseKey`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='发布'; # # Data for table "release" # INSERT INTO `release` VALUES (1,'20161009155425-d3a0749c6e20bc15','20161009155424-release','Sample发布','SampleApp','default','application','{\"timeout\":\"100\"}',b'0',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(2,'20180404001228-7231d1afd3efc760','20180403161355-release','','zuulservice','default','application','{\"zuul.routes.test164.url\":\"http://www.163.com\",\"zuul.routes.test164.path\":\"/test164/**\",\"zuul.host.maxPerRouteConnections\":\"512\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236\\\\:1111/eureka/\",\"zuul.routes.test166.path\":\"/test166/**\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\",\"ribbon.MaxAutoRetries\":\"1\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.routes.test166.url\":\"http://www.163.com\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.routes.test165.path\":\"/test165/**\",\"zuul.routes.test165.url\":\"http://www.163.com\",\"zuul.semaphore.max-semaphores\":\"1024\"}',b'0',b'0','apollo','2018-04-04 00:12:29','apollo','2018-04-04 00:12:29'),(3,'20180404002220-7231d1afd3efc761','20180403162348-release','','zuulservice','default','application','{\"zuul.routes.test164.url\":\"http://www.163.com\",\"zuul.routes.test164.path\":\"/test164/**\",\"zuul.host.maxPerRouteConnections\":\"512\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236:1111/eureka/\",\"zuul.routes.test166.path\":\"/test166/**\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\",\"ribbon.MaxAutoRetries\":\"1\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.routes.test166.url\":\"http://www.163.com\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.routes.test165.path\":\"/test165/**\",\"zuul.routes.test165.url\":\"http://www.163.com\",\"zuul.semaphore.max-semaphores\":\"1024\"}',b'0',b'0','apollo','2018-04-04 00:22:20','apollo','2018-04-04 00:22:20'),(4,'20180404005550-7231d1afd3efc762','20180403165718-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-04-04 00:55:50','apollo','2018-04-04 00:55:50'),(5,'20180403192522-723164972d4b5883','20180403192755-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://192.168.3.151:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-04-03 19:25:22','apollo','2018-04-03 19:25:22'),(6,'20180404175330-723164972d189c81','20180404095329-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-04-04 17:53:30','apollo','2018-04-04 17:53:30'),(7,'20180404175634-723164972d189c82','20180404095633-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"eureka.client.register-with-eureka\":\"false\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-04-04 17:56:35','apollo','2018-04-04 17:56:35'),(8,'20180404193915-723164972d357e89','20180404113911-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-04-04 19:39:15','apollo','2018-04-04 19:39:15'),(9,'20180404194149-723164972d357e8a','20180404114148-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"eureka.instance.instance-id\":\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9999\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-04-04 19:41:50','apollo','2018-04-04 19:41:50'),(10,'20180626195919-7231d6ad3e03c099','20180626195916-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"eureka.instance.instance-id\":\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9000\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://130.75.131.236:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-06-26 19:59:20','apollo','2018-06-26 19:59:20'),(11,'20180626200041-7231d6ad3e03c09a','20180626200039-release','','zuulservice','default','application','{\"ribbon.MaxAutoRetries\":\"1\",\"eureka.instance.instance-id\":\"${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}\",\"spring.application.name\":\"sop-api-gateway\",\"ribbon.ConnectTimeout\":\"10000\",\"hystrix.command.default.execution.timeout.enabled\":\"true\",\"zuul.host.connect-timeout-millis\":\"10000\",\"ribbon.OkToRetryOnAllOperations\":\"true\",\"zuul.host.maxPerRouteConnections\":\"512\",\"eureka.instance.prefer-ip-address\":\"true\",\"zuul.host.socket-timeout-millis\":\"10000\",\"zuul.ignored-services\":\"\\\"*\\\"\",\"ribbon.ReadTimeout\":\"10000\",\"zuul.routes.test163.url\":\"http://www.163.com\",\"zuul.host.maxTotalConnections\":\"1024\",\"management.security.enabled\":\"false\",\"server.port\":\"9000\",\"zuul.semaphore.max-semaphores\":\"1024\",\"zuul.routes.test163.path\":\"/test163/**\",\"ribbon.MaxAutoRetriesNextServer\":\"2\",\"eureka.client.serviceUrl.defaultZone\":\"http://127.0.0.1:1111/eureka\",\"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds\":\"10000\"}',b'0',b'0','apollo','2018-06-26 20:00:41','apollo','2018-06-26 20:00:41'); # # Structure for table "releasehistory" # DROP TABLE IF EXISTS `releasehistory`; CREATE TABLE `releasehistory` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID', `ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName', `NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'namespaceName', `BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT '发布分支名', `ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联的Release Id', `PreviousReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '前一次发布的ReleaseId', `Operation` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '发布类型,0: 普通发布,1: 回滚,2: 灰度发布,3: 灰度规则更新,4: 灰度合并回主分支发布,5: 主分支发布灰度自动发布,6: 主分支回滚灰度自动发布,7: 放弃灰度', `OperationContext` longtext NOT NULL COMMENT '发布上下文信息', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`,`BranchName`), KEY `IX_ReleaseId` (`ReleaseId`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT='发布历史'; # # Data for table "releasehistory" # INSERT INTO `releasehistory` VALUES (1,'SampleApp','default','application','default',1,0,0,'{}',b'0','apollo','2018-04-03 23:19:15','apollo','2018-04-03 23:19:15'),(2,'zuulservice','default','application','default',2,0,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-04 00:12:29','apollo','2018-04-04 00:12:29'),(3,'zuulservice','default','application','default',3,2,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-04 00:22:21','apollo','2018-04-04 00:22:21'),(4,'zuulservice','default','application','default',4,3,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-04 00:55:50','apollo','2018-04-04 00:55:50'),(5,'zuulservice','default','application','default',5,4,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-03 19:25:22','apollo','2018-04-03 19:25:22'),(6,'zuulservice','default','application','default',6,5,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-04 17:53:31','apollo','2018-04-04 17:53:31'),(7,'zuulservice','default','application','default',7,6,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-04 17:56:35','apollo','2018-04-04 17:56:35'),(8,'zuulservice','default','application','default',8,7,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-04 19:39:15','apollo','2018-04-04 19:39:15'),(9,'zuulservice','default','application','default',9,8,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-04-04 19:41:50','apollo','2018-04-04 19:41:50'),(10,'zuulservice','default','application','default',10,9,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-06-26 19:59:20','apollo','2018-06-26 19:59:20'),(11,'zuulservice','default','application','default',11,10,0,'{\"isEmergencyPublish\":false}',b'0','apollo','2018-06-26 20:00:42','apollo','2018-06-26 20:00:42'); # # Structure for table "releasemessage" # DROP TABLE IF EXISTS `releasemessage`; CREATE TABLE `releasemessage` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Message` varchar(1024) NOT NULL DEFAULT '' COMMENT '发布的消息内容', `DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Message` (`Message`(191)) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='发布消息'; # # Data for table "releasemessage" # INSERT INTO `releasemessage` VALUES (10,'zuulservice+default+application','2018-06-26 20:00:42'); # # Structure for table "serverconfig" # DROP TABLE IF EXISTS `serverconfig`; CREATE TABLE `serverconfig` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key', `Cluster` varchar(32) NOT NULL DEFAULT 'default' COMMENT '配置对应的集群,default为不针对特定的集群', `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值', `Comment` varchar(1024) DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_Key` (`Key`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置'; # # Data for table "serverconfig" # INSERT INTO `serverconfig` VALUES (1,'eureka.service.url','default','http://134.224.240.170:1111/eureka/','Eureka服务Url,多个service以英文逗号分隔 http://130.75.131.236:1111/eureka/ http://192.168.3.151:1111/eureka/',b'0','default','2018-04-03 23:19:15','','2018-06-26 11:52:52'),(2,'namespace.lock.switch','default','false','一次发布只能有一个人修改开关',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(3,'item.value.length.limit','default','20000','item value最大长度限制',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(4,'config-service.cache.enabled','default','false','ConfigService是否开启缓存,开启后能提高性能,但是会增大内存消耗!',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'),(5,'item.key.length.limit','default','128','item key 最大长度限制',b'0','default','2018-04-03 23:19:15','','2018-04-03 23:19:15'); ================================================ FILE: open-config-center/apollo/scripts/sql/apolloportaldb.sql ================================================ # Create Database # ------------------------------------------------------------ CREATE DATABASE IF NOT EXISTS ApolloPortalDB DEFAULT CHARACTER SET = utf8mb4; Use ApolloPortalDB; # Host: 47.94.252.160 (Version 5.7.22) # Date: 2018-06-26 20:03:34 # Generator: MySQL-Front 5.4 (Build 4.153) - http://www.mysqlfront.de/ /*!40101 SET NAMES utf8 */; # # Structure for table "app" # DROP TABLE IF EXISTS `app`; CREATE TABLE `app` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名', `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id', `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字', `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName', `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_Name` (`Name`(191)) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用表'; # # Data for table "app" # INSERT INTO `app` VALUES (1,'SampleApp','Sample App','TEST1','样例部门1','apollo','apollo@acme.com',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'zuulservice','zuulservice-dev','TEST1','样例部门1','apollo','apollo@acme.com',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'); # # Structure for table "appnamespace" # DROP TABLE IF EXISTS `appnamespace`; CREATE TABLE `appnamespace` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字,注意,需要全局唯一', `AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id', `Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型', `IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共', `Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_AppId` (`AppId`), KEY `Name_AppId` (`Name`,`AppId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义'; # # Data for table "appnamespace" # INSERT INTO `appnamespace` VALUES (1,'application','SampleApp','properties',b'0','default app namespace',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'application','zuulservice','properties',b'0','default app namespace',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'); # # Structure for table "authorities" # DROP TABLE IF EXISTS `authorities`; CREATE TABLE `authorities` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Username` varchar(50) NOT NULL, `Authority` varchar(50) NOT NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; # # Data for table "authorities" # INSERT INTO `authorities` VALUES (1,'apollo','ROLE_user'); # # Structure for table "consumer" # DROP TABLE IF EXISTS `consumer`; CREATE TABLE `consumer` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名', `OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id', `OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字', `OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName', `OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放API消费者'; # # Data for table "consumer" # # # Structure for table "consumeraudit" # DROP TABLE IF EXISTS `consumeraudit`; CREATE TABLE `consumeraudit` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id', `Uri` varchar(1024) NOT NULL DEFAULT '' COMMENT '访问的Uri', `Method` varchar(16) NOT NULL DEFAULT '' COMMENT '访问的Method', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_ConsumerId` (`ConsumerId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer审计表'; # # Data for table "consumeraudit" # # # Structure for table "consumerrole" # DROP TABLE IF EXISTS `consumerrole`; CREATE TABLE `consumerrole` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id', `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_RoleId` (`RoleId`), KEY `IX_ConsumerId_RoleId` (`ConsumerId`,`RoleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer和role的绑定表'; # # Data for table "consumerrole" # # # Structure for table "consumertoken" # DROP TABLE IF EXISTS `consumertoken`; CREATE TABLE `consumertoken` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'ConsumerId', `Token` varchar(128) NOT NULL DEFAULT '' COMMENT 'token', `Expires` datetime NOT NULL DEFAULT '2099-01-01 00:00:00' COMMENT 'token失效时间', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), UNIQUE KEY `IX_Token` (`Token`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer token表'; # # Data for table "consumertoken" # # # Structure for table "favorite" # DROP TABLE IF EXISTS `favorite`; CREATE TABLE `favorite` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `UserId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '收藏的用户', `AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID', `Position` int(32) NOT NULL DEFAULT '10000' COMMENT '收藏顺序', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `AppId` (`AppId`(191)), KEY `IX_UserId` (`UserId`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用收藏表'; # # Data for table "favorite" # # # Structure for table "permission" # DROP TABLE IF EXISTS `permission`; CREATE TABLE `permission` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `PermissionType` varchar(32) NOT NULL DEFAULT '' COMMENT '权限类型', `TargetId` varchar(256) NOT NULL DEFAULT '' COMMENT '权限对象类型', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_TargetId_PermissionType` (`TargetId`(191),`PermissionType`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='permission表'; # # Data for table "permission" # INSERT INTO `permission` VALUES (1,'CreateCluster','SampleApp',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'CreateNamespace','SampleApp',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'AssignRole','SampleApp',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'ModifyNamespace','SampleApp+application',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(5,'ReleaseNamespace','SampleApp+application',b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(6,'CreateCluster','zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(7,'CreateNamespace','zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(8,'AssignRole','zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(9,'ModifyNamespace','zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(10,'ReleaseNamespace','zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'); # # Structure for table "role" # DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `RoleName` varchar(256) NOT NULL DEFAULT '' COMMENT 'Role name', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_RoleName` (`RoleName`(191)), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='角色表'; # # Data for table "role" # INSERT INTO `role` VALUES (1,'Master+SampleApp',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'ModifyNamespace+SampleApp+application',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'ReleaseNamespace+SampleApp+application',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'Master+zuulservice',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(5,'ModifyNamespace+zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(6,'ReleaseNamespace+zuulservice+application',b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'); # # Structure for table "rolepermission" # DROP TABLE IF EXISTS `rolepermission`; CREATE TABLE `rolepermission` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id', `PermissionId` int(10) unsigned DEFAULT NULL COMMENT 'Permission Id', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_RoleId` (`RoleId`), KEY `IX_PermissionId` (`PermissionId`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='角色和权限的绑定表'; # # Data for table "rolepermission" # INSERT INTO `rolepermission` VALUES (1,1,1,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,1,2,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,1,3,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,2,4,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(5,3,5,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(6,4,6,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(7,4,7,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(8,4,8,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(9,5,9,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(10,6,10,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'); # # Structure for table "serverconfig" # DROP TABLE IF EXISTS `serverconfig`; CREATE TABLE `serverconfig` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key', `Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值', `Comment` varchar(1024) DEFAULT '' COMMENT '注释', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_Key` (`Key`), KEY `DataChange_LastTime` (`DataChange_LastTime`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置'; # # Data for table "serverconfig" # INSERT INTO `serverconfig` VALUES (1,'apollo.portal.envs','dev','可支持的环境列表',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'organizations','[{\"orgId\":\"TEST1\",\"orgName\":\"样例部门1\"},{\"orgId\":\"TEST2\",\"orgName\":\"样例部门2\"}]','部门列表',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'superAdmin','apollo','Portal超级管理员',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'api.readTimeout','10000','http接口read timeout',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(5,'consumer.token.salt','someSalt','consumer token salt',b'0','default','2018-04-03 23:21:10','','2018-04-03 23:21:10'); # # Structure for table "userrole" # DROP TABLE IF EXISTS `userrole`; CREATE TABLE `userrole` ( `Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `UserId` varchar(128) DEFAULT '' COMMENT '用户身份标识', `RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id', `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal', `DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀', `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀', `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间', PRIMARY KEY (`Id`), KEY `IX_DataChange_LastTime` (`DataChange_LastTime`), KEY `IX_RoleId` (`RoleId`), KEY `IX_UserId_RoleId` (`UserId`,`RoleId`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='用户和role的绑定表'; # # Data for table "userrole" # INSERT INTO `userrole` VALUES (1,'apollo',1,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(2,'apollo',2,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(3,'apollo',3,b'0','','2018-04-03 23:21:10','','2018-04-03 23:21:10'),(4,'apollo',4,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(5,'apollo',5,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'),(6,'apollo',6,b'0','apollo','2018-04-04 00:09:41','apollo','2018-04-04 00:09:41'); # # Structure for table "users" # DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id', `Username` varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户名', `Password` varchar(64) NOT NULL DEFAULT 'default' COMMENT '密码', `Email` varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱地址', `Enabled` tinyint(4) DEFAULT NULL COMMENT '是否有效', PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; # # Data for table "users" # INSERT INTO `users` VALUES (1,'apollo','$2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS','apollo@acme.com',1); ================================================ FILE: open-config-center/apollo-gateway/pom.xml ================================================ 4.0.0 com.open.capacity open-config-center 0.0.1-SNAPSHOT apollo-gateway 阿波罗整合网关 org.springframework.cloud spring-cloud-starter-eureka com.ctrip.framework.apollo apollo-client 0.10.0-SNAPSHOT org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-actuator true org.springframework.cloud spring-cloud-starter-zuul org.apache.maven.plugins maven-jar-plugin false org.springframework.boot spring-boot-maven-plugin repackage apollo-zuul ================================================ FILE: open-config-center/apollo-gateway/src/main/java/com/open/capacity/ApiGateWayApp.java ================================================ package com.open.capacity; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.PropertySource; import org.springframework.web.bind.annotation.RestController; import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月7日 下午4:44:46 * 类说明 */ @RestController @EnableZuulProxy @EnableDiscoveryClient @SpringBootApplication public class ApiGateWayApp { public static void main(String[] args) { SpringApplication.run(ApiGateWayApp.class, args); } } ================================================ FILE: open-config-center/apollo-gateway/src/main/java/com/open/capacity/config/ZuulConfig.java ================================================ package com.open.capacity.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年2月23日 下午10:29:25 * 类说明 */ @Configuration @EnableApolloConfig public class ZuulConfig { @Bean(name="zuul.CONFIGURATION_PROPERTIES") @RefreshScope @ConfigurationProperties("zuul") @Primary public ZuulProperties zuulProperties() { return new ZuulProperties(); } } ================================================ FILE: open-config-center/apollo-gateway/src/main/java/com/open/capacity/config/ZuulConfigRreshConfig.java ================================================ package com.open.capacity.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.context.scope.refresh.RefreshScope; import org.springframework.stereotype.Component; import com.ctrip.framework.apollo.core.dto.ApolloConfig; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月7日 下午10:56:13 * 类说明 */ @Component public class ZuulConfigRreshConfig { @Autowired private ZuulConfig zuulConfig ; @Autowired private RefreshScope refreshScope ; @ApolloConfigChangeListener public void onChange(ConfigChangeEvent changEvent){ refreshScope.refresh("zuul.CONFIGURATION_PROPERTIES") ; } } ================================================ FILE: open-config-center/apollo-gateway/src/main/resources/META-INF/app.properties ================================================ # test app.id=zuulservice ================================================ FILE: open-config-center/apollo-gateway/src/main/resources/bootstrap.yml ================================================ management: security: enabled: false ================================================ FILE: open-config-center/pom.xml ================================================ 4.0.0 com.open.capacity open-capacity-platform 0.0.1-SNAPSHOT open-config-center pom apollo apollo-gateway ================================================ FILE: open-db-core/pom.xml ================================================ 4.0.0 com.open.capacity open-capacity-platform 0.0.1-SNAPSHOT open-db-core org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-cache com.github.ulisesbocchio jasypt-spring-boot-starter 1.8 org.springframework.boot spring-boot-starter-jdbc mysql mysql-connector-java com.alibaba druid 1.0.31 com.oracle ojdbc6 11.2.0.3 org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.0 com.alibaba fastjson 1.2.32 commons-lang commons-lang commons-collections commons-collections commons-beanutils commons-beanutils org.springframework.boot spring-boot-starter-aop org.springframework.boot spring-boot-maven-plugin ${project.name} ================================================ FILE: open-db-core/src/main/java/com/open/capacity/db/config/DruidConfig.java ================================================ package com.open.capacity.db.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年04月23日 下午20:01:06 类说明 * */ @Configuration @ConditionalOnProperty(name = {"spring.datasource.enable.dynamic"}, matchIfMissing = true) public class DruidConfig { // 将druid纳入监控步骤如下 // 1通过springboot配置文件注入datasource中 @Bean @ConfigurationProperties(prefix = "spring.datasource") @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = false) public DataSource druidDataSource() { return DataSourceBuilder.create().type(DruidDataSource.class).build(); } // 2.StatViewServlet注入到spring中 // Druid内置提供了一个StatViewServlet用于展示Druid的统计信息。 // 这个StatViewServlet的用途包括: // 提供监控信息展示的html页面 // 提供监控信息的JSON API // 注意:使用StatViewServlet,建议使用druid 0.2.6以上版本。 // 注入第三方没有注解的servlet @Bean @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = false) public ServletRegistrationBean druidServlet() { // 主要实现WEB监控的配置处理 ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*"); // 现在要进行druid监控的配置处理操作 servletRegistrationBean.addInitParameter("allow", "127.0.0.1,130.75.131.208,134.224.249.39,134.224.249.33"); // 白名单 servletRegistrationBean.addInitParameter("deny", "192.168.28.200"); // 黑名单 servletRegistrationBean.addInitParameter("loginUsername", "owen"); // 用户名 servletRegistrationBean.addInitParameter("loginPassword", "1q2w3e4r"); // 密码 servletRegistrationBean.addInitParameter("resetEnable", "false"); // 是否可以重置数据源 return servletRegistrationBean; } // 3.对请求进行过滤 // WebStatFilter注入到spring容器中 // 注入第三方没有注解的过滤器 @Bean @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = false) public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new WebStatFilter()); filterRegistrationBean.addUrlPatterns("/*"); // 所有请求进行监控处理 filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*"); return filterRegistrationBean; } } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/db/config/dynamic/annotation/DataSource.java ================================================ package com.open.capacity.db.config.dynamic.annotation; import java.lang.annotation.*; /** * 数据源选择 * * @author owen * @create 2017年7月2日 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { String name(); } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/db/config/dynamic/aop/DataSourceAspect.java ================================================ package com.open.capacity.db.config.dynamic.aop; import com.open.capacity.db.config.dynamic.annotation.DataSource; import com.open.capacity.db.config.dynamic.config.util.DataSourceHolder; import com.open.capacity.db.config.dynamic.config.util.DataSourceKey; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; /** * 切换数据源Advice */ @Aspect @Order(-1) // 保证该AOP在@Transactional之前执行 public class DataSourceAspect { private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class); @Before("@annotation(ds)") public void changeDataSource(JoinPoint point, DataSource ds) throws Throwable { String dsId = ds.name(); try { DataSourceKey dataSourceKey = DataSourceKey.valueOf(dsId); logger.debug("Use DataSource : {}", ds.name(), point.getSignature()); DataSourceHolder.setDataSourceKey(dataSourceKey); } catch (Exception e) { logger.error("数据源[{}]不存在,使用默认数据源 > {}", ds.name(), point.getSignature()); } } @After("@annotation(ds)") public void restoreDataSource(JoinPoint point, DataSource ds) { logger.debug("Revert DataSource : ", ds.name(), point.getSignature()); DataSourceHolder.clearDataSourceKey(); } } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/DynamicDataSourceConfig.java ================================================ package com.open.capacity.db.config.dynamic.config; import com.alibaba.druid.filter.Filter; import com.alibaba.druid.filter.stat.StatFilter; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallFilter; import com.open.capacity.db.config.dynamic.config.util.DataSourceKey; import com.open.capacity.db.config.dynamic.config.util.DynamicDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.util.ArrayList; import java.util.List; /** * 定义数据源 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年04月23日 下午20:01:06 类说明 */ @Configuration @PropertySource("classpath:jdbc.test.properties") @ConditionalOnProperty(name = {"spring.datasource.enable.dynamic"}, matchIfMissing = false, havingValue = "true") public class DynamicDataSourceConfig { private Logger logger = LoggerFactory.getLogger(DynamicDataSourceConfig.class); // crm库 @Value("${spring.datasource.primary.url:#{null}}") private String primaryDbUrl; @Value("${spring.datasource.primary.username: #{null}}") private String primaryUsername; @Value("${spring.datasource.primary.password:#{null}}") private String primaryPassword; // bill库 @Value("${spring.datasource.secondary.url:#{null}}") private String secondaryDbUrl; @Value("${spring.datasource.secondary.username: #{null}}") private String secondaryUsername; @Value("${spring.datasource.secondary.password:#{null}}") private String secondaryPassword; // 公共配置 @Value("${spring.datasource.driverClassName:#{null}}") private String driverClassName; @Value("${spring.datasource.initialSize:#{null}}") private Integer initialSize; @Value("${spring.datasource.minIdle:#{null}}") private Integer minIdle; @Value("${spring.datasource.maxActive:#{null}}") private Integer maxActive; @Value("${spring.datasource.maxWait:#{null}}") private Integer maxWait; @Value("${spring.datasource.timeBetweenEvictionRunsMillis:#{null}}") private Integer timeBetweenEvictionRunsMillis; @Value("${spring.datasource.minEvictableIdleTimeMillis:#{null}}") private Integer minEvictableIdleTimeMillis; @Value("${spring.datasource.validationQuery:#{null}}") private String validationQuery; @Value("${spring.datasource.testWhileIdle:#{null}}") private Boolean testWhileIdle; @Value("${spring.datasource.testOnBorrow:#{null}}") private Boolean testOnBorrow; @Value("${spring.datasource.testOnReturn:#{null}}") private Boolean testOnReturn; @Value("${spring.datasource.poolPreparedStatements:#{null}}") private Boolean poolPreparedStatements; @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize:#{null}}") private Integer maxPoolPreparedStatementPerConnectionSize; @Value("${spring.datasource.filters:#{null}}") private String filters; @Value("{spring.datasource.connectionProperties:#{null}}") private String connectionProperties; // 不需要纳入spring容器 public DataSource crmDataSource() { DruidDataSource crmDataSource = new DruidDataSource(); crmDataSource.setUrl(this.primaryDbUrl); crmDataSource.setUsername(this.primaryUsername);// 用户名 crmDataSource.setPassword(this.primaryPassword);// 密码 crmDataSource.setDriverClassName(driverClassName); this.setCommons(crmDataSource); return crmDataSource; } // 不需要纳入spring容器 public DataSource billDataSource() { DruidDataSource billDataSource = new DruidDataSource(); billDataSource.setUrl(secondaryDbUrl); billDataSource.setUsername(secondaryUsername);// 用户名 billDataSource.setPassword(secondaryPassword);// 密码 billDataSource.setDriverClassName(driverClassName); this.setCommons(billDataSource); return billDataSource; } @Bean // 只需要纳入动态数据源到spring容器 @Primary public DataSource dataSource() { DynamicDataSource dataSource = new DynamicDataSource(); DataSource crmDataSource = this.crmDataSource(); DataSource billDataSource = this.billDataSource(); dataSource.addDataSource(DataSourceKey.crm, crmDataSource); dataSource.addDataSource(DataSourceKey.bill, billDataSource); dataSource.setDefaultTargetDataSource(crmDataSource); return dataSource; } @Bean public StatFilter statFilter() { StatFilter statFilter = new StatFilter(); statFilter.setLogSlowSql(true); statFilter.setMergeSql(true); statFilter.setSlowSqlMillis(1000); return statFilter; } @Bean public WallFilter wallFilter() { WallFilter wallFilter = new WallFilter(); // 允许执行多条SQL WallConfig config = new WallConfig(); config.setMultiStatementAllow(true); wallFilter.setConfig(config); return wallFilter; } @Bean public ServletRegistrationBean druidServlet() { ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(); servletRegistrationBean.setServlet(new StatViewServlet()); servletRegistrationBean.addUrlMappings("/druid/*"); return servletRegistrationBean; } @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { return new NamedParameterJdbcTemplate(dataSource); } private void setCommons(DruidDataSource dataSource) { // configuration if (initialSize != null) { dataSource.setInitialSize(initialSize); } if (minIdle != null) { dataSource.setMinIdle(minIdle); } if (maxActive != null) { dataSource.setMaxActive(maxActive); } if (maxWait != null) { dataSource.setMaxWait(maxWait); } if (timeBetweenEvictionRunsMillis != null) { dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); } if (minEvictableIdleTimeMillis != null) { dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); } if (validationQuery != null) { dataSource.setValidationQuery(validationQuery); } if (testWhileIdle != null) { dataSource.setTestWhileIdle(testWhileIdle); } if (testOnBorrow != null) { dataSource.setTestOnBorrow(testOnBorrow); } if (testOnReturn != null) { dataSource.setTestOnReturn(testOnReturn); } if (poolPreparedStatements != null) { dataSource.setPoolPreparedStatements(poolPreparedStatements); } if (maxPoolPreparedStatementPerConnectionSize != null) { dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); } if (connectionProperties != null) { dataSource.setConnectionProperties(connectionProperties); } List filters = new ArrayList<>(); filters.add(statFilter()); filters.add(wallFilter()); dataSource.setProxyFilters(filters); } @Bean // 将数据源纳入spring事物管理 @Primary public DataSourceTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public PlatformTransactionManager annotationDrivenTransactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/util/DataSourceHolder.java ================================================ package com.open.capacity.db.config.dynamic.config.util; /** * 用于数据源切换 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年04月23日 下午20:01:06 类说明 */ public class DataSourceHolder { private static final ThreadLocal dataSourceKey = new ThreadLocal<>(); public static DataSourceKey getDataSourceKey() { return dataSourceKey.get(); } public static void setDataSourceKey(DataSourceKey type) { dataSourceKey.set(type); } public static void clearDataSourceKey() { dataSourceKey.remove(); } } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/util/DataSourceKey.java ================================================ package com.open.capacity.db.config.dynamic.config.util; /** * 数据源定义 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年04月23日 下午20:01:06 类说明 */ public enum DataSourceKey { crm, bill } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/db/config/dynamic/config/util/DynamicDataSource.java ================================================ package com.open.capacity.db.config.dynamic.config.util; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年04月23日 下午20:01:06 类说明 类说明 */ public class DynamicDataSource extends AbstractRoutingDataSource { private Map datasources; public DynamicDataSource() { datasources = new HashMap<>(); super.setTargetDataSources(datasources); } public void addDataSource(DataSourceKey key, T data) { datasources.put(key, data); } @Override protected Object determineCurrentLookupKey() { return DataSourceHolder.getDataSourceKey(); } } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/redis/config/RedisConfig.java ================================================ package com.open.capacity.redis.config; import com.open.capacity.redis.config.util.RedisObjectSerializer; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年04月23日 下午20:01:06 类说明 */ @Configuration public class RedisConfig { @Primary @Bean("redisTemplate") // 没有此属性就不会装配bean 如果是单个redis 将此注解注释掉 @ConditionalOnProperty(name = "spring.redis.cluster.nodes", matchIfMissing = false) public RedisTemplate getRedisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(factory); RedisSerializer stringSerializer = new StringRedisSerializer(); // RedisSerializer redisObjectSerializer = new RedisObjectSerializer(); RedisSerializer redisObjectSerializer = new RedisObjectSerializer(); redisTemplate.setKeySerializer(stringSerializer); // key的序列化类型 redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setValueSerializer(redisObjectSerializer); // value的序列化类型 redisTemplate.afterPropertiesSet(); redisTemplate.opsForValue().set("hello", "wolrd"); return redisTemplate; } @Primary @Bean("redisTemplate") @ConditionalOnProperty(name = "spring.redis.host", matchIfMissing = true) public RedisTemplate getSingleRedisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(factory); redisTemplate.setKeySerializer(new StringRedisSerializer()); // key的序列化类型 redisTemplate.setValueSerializer(new RedisObjectSerializer()); // value的序列化类型 redisTemplate.afterPropertiesSet(); return redisTemplate; } } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/redis/config/util/FastJson2JsonRedisSerializer.java ================================================ package com.open.capacity.redis.config.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import java.nio.charset.Charset; /** * * @author 作者 owen E-mail: 624191343@qq.com * * @version 创建时间:2017年04月23日 下午20:01:06 类说明 类说明 */ public class FastJson2JsonRedisSerializer implements RedisSerializer { public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private Class clazz; public FastJson2JsonRedisSerializer(Class clazz) { super(); this.clazz = clazz; } public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length <= 0) { return null; } String str = new String(bytes, DEFAULT_CHARSET); return (T) JSON.parseObject(str, clazz); } } ================================================ FILE: open-db-core/src/main/java/com/open/capacity/redis/config/util/RedisObjectSerializer.java ================================================ package com.open.capacity.redis.config.util; import org.springframework.core.convert.converter.Converter; import org.springframework.core.serializer.support.DeserializingConverter; import org.springframework.core.serializer.support.SerializingConverter; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年04月23日 下午20:01:06 类说明 * 类说明 */ // 此时定义的序列化操作表示可以序列化所有类的对象,当然,这个对象所在的类一定要实现序列化接口 public class RedisObjectSerializer implements RedisSerializer { private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; // 做一个空数组,不是null // 为了方便进行对象与字节数组的转换,所以应该首先准备出两个转换器 private Converter serializingConverter = new SerializingConverter(); private Converter deserializingConverter = new DeserializingConverter(); @Override public byte[] serialize(Object obj) throws SerializationException { if (obj == null) { // 这个时候没有要序列化的对象出现,所以返回的字节数组应该就是一个空数组 return EMPTY_BYTE_ARRAY; } return this.serializingConverter.convert(obj); // 将对象变为字节数组 } @Override public Object deserialize(byte[] data) throws SerializationException { if (data == null || data.length == 0) { // 此时没有对象的内容信息 return null; } return this.deserializingConverter.convert(data); } } ================================================ FILE: open-db-core/src/main/java/mybatis.cfg.xml ================================================ ================================================ FILE: open-db-core/src/main/resources/jdbc.bcv.properties ================================================ ################################common param############################################## spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driverClassName=oracle.jdbc.OracleDriver #spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 spring.datasource.maxWait=60000 spring.datasource.timeBetweenEvictionRunsMillis=60000 spring.datasource.minEvictableIdleTimeMillis=300000 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false spring.datasource.poolPreparedStatements=true spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.filters=stat,wall,log4j spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 ################################crm############################################## spring.datasource.primary.driver-class-name=oracle.jdbc.OracleDriver spring.datasource.primary.url=jdbc:oracle:thin:@192.168.1.11:2268:jxcrm spring.datasource.primary.username=111111111 spring.datasource.primary.password=111111111 ################################bill############################################## spring.datasource.secondary.driver-class-name=oracle.jdbc.OracleDriver spring.datasource.secondary.url=jdbc:oracle:thin:@192.168.1.11:3361:jxbill spring.datasource.secondary.username=111111111 spring.datasource.secondary.password=111111111 #spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver #spring.datasource.secondary.url=jdbc:mysql://localhost:3306/myspringcloud?useSSL=false #spring.datasource.secondary.username=root #spring.datasource.secondary.password=123456 ================================================ FILE: open-eureka-center/README.md ================================================ # 服务注册中心 ## 什么是服务治理 服务治理可以说是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务实例的自动化注册与发现。 ## 为什么需要服务治理模块 在最初构建微服务系统的时候可能服务并不多,我们可以通过做一些静态配置来完成服务调用 ![](https://i.imgur.com/ASRyYWJ.png) 此时看着一切都还正常。 随着项目逐渐接近尾声,维护人员需要维护的服务越来越多,越来越复杂,最终形成大量的配置文件,维护将会变得越来越困难。此时,微服务应用实例自动化管理框架变得至关重要。 ## 服务治理框架需要完成什么任务 ● 服务注册:在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。 ![](https://i.imgur.com/lFXx64x.png) ● 服务发现:我们的所有服务都已经注册到注册中心,并且在注册中心是按照服务名分类,并且由注册中心维护者服务的具体位置。所以调用方需要调用某个服务时,需要先和注册中心咨询,注册中心会返回被调用方服务的所有具体位置,调用方在根据某种轮询策略选择一个具体位置进行服务调用。 ![](https://i.imgur.com/tvnjhZD.png) ## Netflix Eureka   Spring Cloud Eureka,使用Netflix Eureka来实现服务注册与发现,它既包含了服务端组件,也包含了客户端组件。 ## Eureka服务端   Eureka服务端,我们也称为服务注册中心,他同其他服务注册中心一样,支持高可用配置。它依托于强一致性提供良好的服务实例可用性,可以应对多种不同的故障场景。   如果Eureka以集群方式部署,当集群中有分片出现故障时,那么Eureka就转入自我保护模式。它允许在分片故障期间继续提供服务的发现和注册,当故障分片恢复运行时,集群中的其他分片会把它们的状态再次同步回来。 ## Eureka客户端   Eureka客户端,主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式,嵌入在客户端应用程序的代码中,在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时,他也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态。 ## 服务端与客户端的关系 ![](https://i.imgur.com/oPDCh7u.png) ## 搭建服务注册中心 1.创建Spring Boot工程,命名为open-eureka-center,并在pom中加入必要依赖,如下图: ![](https://i.imgur.com/pFbNOUi.jpg) 2.通过@EnableEurekaServer注解启动一个服务注册中心提供给其他应用进行对话。在Spring boot应用中添加这个注解就能开启此功能。 ![](https://i.imgur.com/MlKBKTX.png) 在默认情况下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,只需在application.properties中增加如下配置: spring.application.name=open-eureka-server server.port=1111 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://127.0.0.1:1111/eureka ● spring.application.name是服务名称,会在服务注册中心中看到这个属性的值,也是服务间调用时使用的名字。 ● server.port是该服务启动时所使用的端口号。 ● eureka.client.register-with-eureka因为该应用为注册中心,所以设置为false,代表不向服务注册中心注册自己。 ● eureka.client.fetch-registry因为服务注册中心的职责就是维护服务服务实例,它并不需要去检索服务,所以设置为false。 完成上面的配置,在浏览器中输入http://127.0.0.1:1111/,如图: ![](https://i.imgur.com/IC0omfS.jpg) 此时的Instances currently registered with Eureka栏是空的,因为还没有服务注册到注册中心。 ## 注册服务提供者(Eureka客户端) 1.创建eureka客户端工程 ![](https://i.imgur.com/PhjRZIj.png) 2.修改HelloController类 在日志中打印服务的相关内容: @RestController public class HelloController{ private final Logger logger = Logger.getLogger(getClass()); @Autowired private DiscoveryClient client; @RequestMapping(value="/hello",method = RequestMethod.GET) public String index() { ServiceInstance instance = client.getLocalServiceInstance(); logger.info("/hello , host:"+ instance.getHost() + ", service_id:" + instance.getServiceId()); return "hello world"; } } 3.修改application.properties文件: spring.application.name=open-eureka-client eureka.client.serviceUrl.defaultZone=http://127.0.0.1:1111/eureka/ ● eureka.client.serviceUrl.defaultZone属性指定服务注册中心的地址。 4.分别启动服务注册中心和open-eureka-client服务。结果如下图: ![](https://i.imgur.com/lVxUsmu.jpg) 通过访问http://127.0.0.1:7760/client/hello,直接向该服务发起请求 ## 什么叫高可用 高可用一般指服务的冗余,一个服务挂了,可以自动切换到另一个服务上,不会影响到客户体验。 高可用注册中心 在微服务架构这样的分布式环境中,我们需要充分考虑发生故障的情况,所以在生产环境中必须对各个组件进行高可用部署,对于微服务如此,对于服务中心也一样。 Eureka Server的设计一开始就考虑了高可用问题,在Eureka的服务治理设计中,所有节点既是服务提供方,也是服务消费方,服务注册中心也不例外。在前一篇随笔中用到过这样的配置: eureka.client.register-with-eureka=false eureka.client.fetch-registry=false 现在回顾一下上面提到的这两个属性的作用: ● eureka.client.register-with-eureka=false设置为不将自己注册到服务注册中心(默认是true) ● eureka.client.fetch-registry=false设置为不检索服务(默认是true,在单节点服务注册中心的情况下,服务注册中心并不需要检索自己的服务) Eureka server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的效果。 ![](https://i.imgur.com/pphn4Gw.png) ## 常见问题 ![](https://i.imgur.com/fUC3dXN.png) ## eureka restful api 查看eureka的状态 http://127.0.0.1:7768/eureka/status 查看有多少服务 http://127.0.0.1:7778/eureka/apps 查看某个服务多少实例 http://127.0.0.1:7768/eureka/apps?name=OPEN-EUREKA-CLIENT 查看某个实例的状态 http://127.0.0.1:7768/eureka/apps/OPEN-EUREKA-CLIENT/open-eureka-client:192.168.45.1:7778 暂停微服务 http://127.0.0.1:7768/pause 查看某个实例的状态 http://127.0.0.1:7768/resume ================================================ FILE: open-eureka-center/open-eureka-client/pom.xml ================================================ 4.0.0 com.open.capacity open-eureka-center 0.0.1-SNAPSHOT open-eureka-client gitgeek org.springframework.cloud spring-cloud-starter-eureka org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web com.fasterxml.jackson.dataformat jackson-dataformat-xml io.swagger swagger-core 1.5.8 io.springfox springfox-swagger2 2.4.0 io.springfox springfox-swagger-ui 2.4.0 com.github.xiaoymin swagger-bootstrap-ui 1.6 org.springframework.boot spring-boot-maven-plugin 1.3.3.RELEASE repackage com.spotify docker-maven-plugin 0.4.13 ${docker.image.prefix}/${project.artifactId} src/main/docker / ${project.build.directory} ${project.build.finalName}.jar eureka-client ================================================ FILE: open-eureka-center/open-eureka-client/src/main/docker/Dockerfile ================================================ FROM frolvlad/alpine-oraclejdk8 VOLUME /tmp ADD eureka-client.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] ================================================ FILE: open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/EurekaClientApplication.java ================================================ package com.open.capacity; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月28日 下午21:52:43 * 类说明 * 服务提供商 eureka的客户端程序 */ @EnableEurekaClient @EnableDiscoveryClient @SpringBootApplication public class EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } /** * 使用ribbon负载均衡器,用于服务提供商的负载均衡 * * @return */ @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } } ================================================ FILE: open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/config/SwaggerConfig.java ================================================ package com.open.capacity.config; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.stereotype.Component; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; import springfox.documentation.builders.ParameterBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.Parameter; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.ArrayList; import java.util.List; @Component @Configuration @EnableSwagger2 public class SwaggerConfig extends WebMvcConfigurerAdapter { @Bean public Docket api() { ParameterBuilder tokenPar = new ParameterBuilder(); List pars = new ArrayList<>(); tokenPar.name("Authorization").description("令牌"). modelRef(new ModelRef("string")). parameterType("header").required(false).build(); pars.add(tokenPar.build()); return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.open.capacity")) .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build().globalOperationParameters(pars); } @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setViewClass(JstlView.class); resolver.setPrefix("/"); resolver.setSuffix(".html"); return resolver; } @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("messages"); return messageSource; } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } } ================================================ FILE: open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/controller/EurekaController.java ================================================ package com.open.capacity.controller; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.io.StringWriter; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月28日 下午21:52:43 */ @Controller @RequestMapping("/eureka/") public class EurekaController { private static final Logger LOGGER = LoggerFactory.getLogger(EurekaController.class); @Autowired private DiscoveryClient discoveryClient; private static String getoperate(String url, int post2get, String... str) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(10 * 1000) .setConnectTimeout(10 * 1000).setSocketTimeout(10 * 1000).build(); if (post2get == 1) { HttpGet po = new HttpGet(url); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString.toString(); } if (post2get == 3) { HttpPost po = new HttpPost(url); po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0])); po.setConfig(requestConfig); String queryCase = "name=admin&password=admin&remember=0"; StringEntity reqEntity = new StringEntity(queryCase); reqEntity.setContentType("application/x-www-form-urlencoded"); po.setEntity(reqEntity); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } if (post2get == 4) { HttpGet po = new HttpGet(url); po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0] + ";DISCONF=" + str[1])); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } if (post2get == 5) { HttpPut po = new HttpPut(url); po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0] + ";DISCONF=" + str[1])); po.setConfig(requestConfig); String text = "fileContent=" + str[2]; StringEntity reqEntity = new StringEntity(text); reqEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); po.setEntity(reqEntity); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } if (post2get == 6) { HttpPost po = new HttpPost(url); po.setConfig(requestConfig); StringEntity reqEntity = new StringEntity(str[0]); reqEntity.setContentType("application/json;charset=utf-8"); po.setEntity(reqEntity); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } else { HttpPost po = new HttpPost(url); if (str != null && str.length > 0) { po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0])); } StringEntity reqEntity = new StringEntity(""); reqEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); po.setEntity(reqEntity); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return "{}"; } private static String getinfo(String url) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000) .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build(); HttpGet po = new HttpGet(url); if (url.indexOf("apps") > 0) { po.setHeader("Accept", "application/json"); } po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); if (url.indexOf("apps") > 0) { LOGGER.info(bodyAsString.toString()); return bodyAsString; } ObjectMapper objectMapper = new ObjectMapper(); XmlMapper xmlMapper = new XmlMapper(); StringWriter w = new StringWriter(); JsonParser jp; try { jp = xmlMapper.getFactory().createParser(bodyAsString); JsonGenerator jg = objectMapper.getFactory().createGenerator(w); while (jp.nextToken() != null) { jg.copyCurrentEvent(jp); } jp.close(); jg.close(); } catch (Exception e) { e.printStackTrace(); } LOGGER.info(w.toString()); return w.toString(); // logger.info("RestContr "+bodyAsString); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return "{}"; } private static String getinfo_put(String url) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000) .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build(); HttpPut po = new HttpPut(url); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); // LOGGER.info(w.toString()); return "{}"; // logger.info("RestContr "+bodyAsString); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return "{}"; } private static String getinfo_del(String url) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50000) .setConnectTimeout(50000).setSocketTimeout(50000).build(); HttpDelete po = new HttpDelete(url); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); return "{}"; } catch (Exception e) { e.printStackTrace(); } return "{}"; } @ResponseBody @RequestMapping(value = "status", method = RequestMethod.GET) public String status() { String url = "http://127.0.0.1:1111/eureka/status"; return getinfo(url); } @ResponseBody @RequestMapping(value = "apps", method = RequestMethod.GET) public String apps() { String url = "http://127.0.0.1:1111/eureka/apps"; return getinfo(url); } @ResponseBody @RequestMapping(value = "list", method = RequestMethod.GET) public Map list() { List list = discoveryClient.getServices(); Map res = new HashMap<>(); for (Iterator it = list.iterator(); it.hasNext(); ) { String serviceName = it.next(); List instances = discoveryClient.getInstances(serviceName); for (Iterator its = instances.iterator(); its.hasNext(); ) { ServiceInstance instance = its.next(); res.putAll(instance.getMetadata()); } } return res; } @ResponseBody @RequestMapping(value = "appsmd", method = RequestMethod.POST) public String appsmd(@RequestParam(value = "name", required = false) String str) { String url = "http://127.0.0.1:1111/eureka/apps/" + str; return getinfo(url); } @ResponseBody @RequestMapping(value = {"appsmddel"}, method = RequestMethod.POST) public String appsmddel(@RequestParam(value = "name", required = false) String str) { String url = "http://127.0.0.1:1111/metadata/apps/" + str; return getinfo_del(url); } @ResponseBody @RequestMapping(value = "operate", method = RequestMethod.POST) public String operate(@RequestBody HashMap inmap) { LOGGER.info(inmap.toString()); String op = ""; int post2get = 0; if (inmap.get("operate").equals("1")) {// 暂停 op = "pause"; } if (inmap.get("operate").equals("2")) {// 挂起 op = "pause"; } if (inmap.get("operate").equals("3")) {// 恢复 op = "resume"; } if (inmap.get("operate").equals("4")) {// 刷新 op = "refresh"; } if (inmap.get("operate").equals("5")) {// 主机性能指标 op = "metrics"; post2get = 1; } String url = "http://" + inmap.get("ip") + ":" + inmap.get("port") + "/" + op; return getoperate(url, post2get, "", ""); } } ================================================ FILE: open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/controller/EurekaManageController.java ================================================ package com.open.capacity.controller; import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.InstanceInfo.InstanceStatus; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月28日 下午21:52:43 * 类说明 */ @RestController public class EurekaManageController { //手工启停标识 public static boolean upOrDown = true; @Resource private ApplicationInfoManager applicationInfoManager; @RequestMapping(value = "/resume", method = RequestMethod.POST) public void up() { applicationInfoManager.getInfo().setStatus(InstanceStatus.UP); upOrDown = true; } @RequestMapping(value = "/pause", method = RequestMethod.POST) public void down() { applicationInfoManager.getInfo().setStatus(InstanceStatus.DOWN); upOrDown = false; } } ================================================ FILE: open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/controller/HelloController.java ================================================ package com.open.capacity.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月28日 下午21:52:43 * 类说明 */ @RestController public class HelloController { @Resource private RestTemplate restTemplate; @GetMapping("/hello") public String hello(HttpServletRequest request) { return "hello: " + request.getHeader("Authorization"); } @GetMapping("/route") public String hello1() { String resp = this.restTemplate.getForObject("http://open-eureka-client/client/hello", String.class); return resp; } } ================================================ FILE: open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/health/EurekaClientHealthIndicator.java ================================================ package com.open.capacity.health; import com.open.capacity.controller.EurekaManageController; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.Status; import org.springframework.stereotype.Component; @Component public class EurekaClientHealthIndicator implements HealthIndicator { public Health health() { if (EurekaManageController.upOrDown) { return new Health.Builder(Status.UP).withDetail("details", "").withDetail("status", Status.UP).build(); } else { return new Health.Builder(Status.DOWN).withDetail("details", "").withDetail("status", Status.DOWN).build(); } } } ================================================ FILE: open-eureka-center/open-eureka-client/src/main/java/com/open/capacity/health/EurekaHealthCheckHandler.java ================================================ package com.open.capacity.health; import com.netflix.appinfo.HealthCheckHandler; import com.netflix.appinfo.InstanceInfo.InstanceStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.health.Status; import org.springframework.stereotype.Component; @Component public class EurekaHealthCheckHandler implements HealthCheckHandler { @Autowired private EurekaClientHealthIndicator halthIndicator; public InstanceStatus getStatus(InstanceStatus currentStatus) { Status status = halthIndicator.health().getStatus(); if (status.equals(Status.UP)) { return InstanceStatus.UP; } else { return InstanceStatus.DOWN; } } } ================================================ FILE: open-eureka-center/open-eureka-client/src/main/resources/application.yml ================================================ server: port: 7768 tomcat: uri-encoding: UTF-8 management: security: enabled: false spring: application: name: open-eureka-client http: encoding: charset: utf8 force: true enabled: true docker: ipAddress: 47.94.252.160 eureka: client: healthcheck: enabled: true instance-info-replication-interval-seconds: 10 serviceUrl: defaultZone: http://127.0.0.1:1111/eureka #http://130.75.131.241:8761/eureka,http://130.75.131.248:8762/eureka #http://134.224.249.33:1111/eureka/ 正式库 #http://134.224.249.33:1111/eureka/ 测试库 #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} # instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 5 #每隔几秒告诉eureka服务器我还存活,用于心跳检测 lease-expiration-duration-in-seconds: 15 #如果心跳检测一直没有发送,10秒后会从eureka服务器中将此服务剔除 #注册实例文档 status-page-url: http://${spring.cloud.client.ipAddress}:${server.port}/doc.html # ${server.port}为该服务的端口号 # status-page-url: http://${docker.ipAddress}:${server.port}/client/doc.html # ${server.port}为该服务的端口号 logging: level: root: INFO org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE com.neusoft: DEBUG com.netflix: DEBUG #用于心跳检测输出的日志 ================================================ FILE: open-eureka-center/open-eureka-client/src/main/resources/logback.xml ================================================ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n ../logs/eureka-server-error.%d{yyyy-MM-dd}.%i.log 100MB 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n 100MB ERROR ACCEPT DENY ../logs/eureka-server-info.%d{yyyy-MM-dd}.%i.log 100MB 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n INFO ACCEPT DENY ================================================ FILE: open-eureka-center/open-eureka-server/pom.xml ================================================  4.0.0 com.open.capacity open-eureka-center 0.0.1-SNAPSHOT open-eureka-server gitgeek org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-eureka-server org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-maven-plugin repackage com.spotify docker-maven-plugin 0.4.13 ${docker.image.prefix}/${project.artifactId} src/main/docker / ${project.build.directory} ${project.build.finalName}.jar eureka-server ================================================ FILE: open-eureka-center/open-eureka-server/src/main/docker/Dockerfile ================================================ FROM frolvlad/alpine-oraclejdk8 VOLUME /tmp ADD eureka-server.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] ================================================ FILE: open-eureka-center/open-eureka-server/src/main/java/com/open/capacity/EurekaServerApp.java ================================================ package com.open.capacity; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import org.springframework.context.ConfigurableApplicationContext; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月28日 下午22:50:29 * 类说明 * eureka高可用三台机器 */ @EnableEurekaServer //@EnableEurekaClient @SpringBootApplication public class EurekaServerApp { public static void main(String[] args) { // 1本地启动采用此方法加载profiles文件 // ConfigurableApplicationContext context = new SpringApplicationBuilder(UnieapEurekaServerApplication.class). // profiles("slave3").run(args); // 2服务器采用此方法 java -jar --spring.profiles.active=slave3; // SpringApplication.run(DreiEurekaServerApp.class, args); ConfigurableApplicationContext context = new SpringApplicationBuilder(EurekaServerApp.class). profiles("slave0").run(args); } } ================================================ FILE: open-eureka-center/open-eureka-server/src/main/java/com/open/capacity/controller/EurekaController.java ================================================ package com.open.capacity.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2017年11月28日 下午22:50:29 * 类说明 */ @RestController public class EurekaController { @GetMapping("/hello") public String hello() { return "hello"; } } ================================================ FILE: open-eureka-center/open-eureka-server/src/main/java/com/open/capacity/listener/EurekaInstanceCanceledListener.java ================================================ package com.open.capacity.listener; import com.netflix.discovery.shared.Applications; import com.netflix.eureka.EurekaServerContextHolder; import com.netflix.eureka.registry.PeerAwareInstanceRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Configuration; /** * 用于监听eureka服务停机通知 * Created by ace on 2017/7/8. */ @Configuration public class EurekaInstanceCanceledListener implements ApplicationListener { private Logger log = LoggerFactory.getLogger(EurekaInstanceCanceledListener.class); @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { // 服务挂掉事件 if (applicationEvent instanceof EurekaInstanceCanceledEvent) { EurekaInstanceCanceledEvent event = (EurekaInstanceCanceledEvent) applicationEvent; // 获取当前Eureka实例中的节点信息 PeerAwareInstanceRegistry registry = EurekaServerContextHolder.getInstance().getServerContext().getRegistry(); Applications applications = registry.getApplications(); // 遍历获取已注册节点中与当前失效节点ID一致的节点信息 applications.getRegisteredApplications().forEach((registeredApplication) -> { registeredApplication.getInstances().forEach((instance) -> { if (instance.getInstanceId().equals(event.getServerId())) { log.debug("服务:" + instance.getAppName() + " 挂啦。。。"); // // TODO: 2017/9/3 扩展消息提醒 邮件、手机短信、微信等 } }); }); } if (applicationEvent instanceof EurekaInstanceRegisteredEvent) { EurekaInstanceRegisteredEvent event = (EurekaInstanceRegisteredEvent) applicationEvent; log.debug("服务:" + event.getInstanceInfo().getAppName() + " 注册成功啦。。。"); } if (applicationEvent instanceof EurekaInstanceRenewedEvent) { EurekaInstanceRenewedEvent event = (EurekaInstanceRenewedEvent) applicationEvent; log.debug("心跳检测服务:" + event.getInstanceInfo().getAppName() + "。。"); } if (applicationEvent instanceof EurekaRegistryAvailableEvent) { log.debug("服务 Aualiable。。"); } } } ================================================ FILE: open-eureka-center/open-eureka-server/src/main/resources/application.yml ================================================ server: port: 1111 spring: application: name: open-eureka-server profiles: slave0 management: security: enabled: false eureka: server: shouldUseReadOnlyResponseCache: true #eureka是CAP理论种基于AP策略,为了保证强一致性关闭此切换CP 默认不关闭 false关闭 enable-self-preservation: false #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务 eviction-interval-timer-in-ms: 60000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除# response-cache-update-interval-ms: 3000 ##eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上默认30s response-cache-auto-expiration-in-seconds: 180 ##eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。 client: register-with-eureka: false #false:不作为一个客户端注册到注册中心 fetch-registry: false #为true时,可以启动,但报异常:Cannot execute request on any known server instance-info-replication-interval-seconds: 10 service-url: defaultZone: http://127.0.0.1:1111/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 30 ## 续约更新时间间隔(默认30秒) lease-expiration-duration-in-seconds: 90 # 续约到期时间(默认90秒) ribbon: ServerListRefreshInterval: 1000 logging: level: # root: INFO com.open: INFO org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE --- server: port: 1111 spring: application: name: open-eureka-server profiles: slave1 management: security: enabled: false eureka: server: enable-self-preservation: true #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务 eviction-interval-timer-in-ms: 15000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除# client: register-with-eureka: true #false:不作为一个客户端注册到注册中心 fetch-registry: true #为true时,可以启动,但报异常:Cannot execute request on any known server serviceUrl: defaultZone: http://127.0.0.1:1111/eureka,http://127.0.0.1:1112/eureka,http://127.0.0.1:1113/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 30 ## 续约更新时间间隔(默认30秒) lease-expiration-duration-in-seconds: 90 # 续约到期时间(默认90秒) logging: level: root: INFO com.drei: DEBUG org.springframework.web: INFO org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE --- server: port: 1112 spring: application: name: open-eureka-server profiles: slave2 management: security: enabled: false eureka: server: enable-self-preservation: true #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务 eviction-interval-timer-in-ms: 15000 #5秒将客户端剔除的服务在服务注册列表中剔除 client: register-with-eureka: true #false:不作为一个客户端注册到注册中心 fetch-registry: true #为true时,可以启动,但报异常:Cannot execute request on any known server serviceUrl: defaultZone: http://127.0.0.1:1111/eureka,http://127.0.0.1:1112/eureka,http://127.0.0.1:1113/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 30 ## 续约更新时间间隔(默认30秒) lease-expiration-duration-in-seconds: 90 # 续约到期时间(默认90秒) logging: level: root: INFO com.drei: DEBUG org.springframework.web: INFO org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE --- server: port: 1113 spring: application: name: open-eureka-server profiles: slave3 management: security: enabled: false eureka: server: enable-self-preservation: true #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务 eviction-interval-timer-in-ms: 15000 #5秒将客户端剔除的服务在服务注册列表中剔除 client: register-with-eureka: true #false:不作为一个客户端注册到注册中心 fetch-registry: true #为true时,可以启动,但报异常:Cannot execute request on any known server serviceUrl: defaultZone: http://127.0.0.1:1111/eureka,http://127.0.0.1:1112/eureka,http://127.0.0.1:1113/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 30 ## 续约更新时间间隔(默认30秒) lease-expiration-duration-in-seconds: 90 # 续约到期时间(默认90秒) logging: level: root: INFO com.drei: DEBUG org.springframework.web: INFO org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE ================================================ FILE: open-eureka-center/open-eureka-server/src/main/resources/templates/.keep ================================================ ================================================ FILE: open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/.keep ================================================ ================================================ FILE: open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/header.ftl ================================================ <#import "/spring.ftl" as spring /> ================================================ FILE: open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/lastn.ftl ================================================ <#import "/spring.ftl" as spring /> 注册中心-事件 <#include "header.ftl">
    <#include "navbar.ftl">
    <#if lastNCanceled?has_content> <#list lastNCanceled as entry> <#else>
    租约时间戳
    ${entry.date?datetime}${entry.id}
    没有可用的资源
    <#if lastNRegistered?has_content> <#list lastNRegistered as entry> <#else>
    租约时间戳
    ${entry.date?datetime}${entry.id}
    没有可用的资源
    ================================================ FILE: open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/navbar.ftl ================================================

    系统状态

    <#if amazonInfo??>
    服务注册和发现 AMI: ${amiId!}
    空间 ${availabilityZone!}
    示例Id ${instanceId!}
    环境 ${environment!}
    数据中心 ${datacenter!}
    当前时间 ${currentTime}
    运行 ${upTime}
    启用租约到期时间 ${registry.leaseExpirationEnabled?c}
    续订阈值 ${registry.numOfRenewsPerMinThreshold}
    续订 (最后一分钟) ${registry.numOfRenewsInLastMin}
    <#if isBelowRenewThresold> <#if !registry.selfPreservationModeEnabled>

    续订小于阈值。自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。

    <#else>

    紧急!注册中心可能不正确地验证身份, 当他们没有的情况下。续订小于阈值, 因此实例不会过期, 只是为了安全起见。

    <#elseif !registry.selfPreservationModeEnabled>

    自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。

    服务副本

    ================================================ FILE: open-eureka-center/open-eureka-server/src/main/resources/templates/eureka/status.ftl ================================================ <#import "/spring.ftl" as spring /> 服务注册和发现 <#include "header.ftl">
    <#include "navbar.ftl">

    当前注册的服务实例

    <#if apps?has_content> <#list apps as app> <#else>
    应用申请可用性区域状态
    ${app.name} <#list app.amiCounts as amiCount> ${amiCount.key} (${amiCount.value})<#if amiCount_has_next>, <#list app.zoneCounts as zoneCount> ${zoneCount.key} (${zoneCount.value})<#if zoneCount_has_next>, <#list app.instanceInfos as instanceInfo> <#if instanceInfo.isNotUp> ${instanceInfo.status} (${instanceInfo.instances?size}) - <#if instanceInfo.isNotUp> <#list instanceInfo.instances as instance> <#if instance.isHref> ${instance.id} <#else> ${instance.id} <#if instance_has_next>,
    没有可用的实例

    一般信息

    <#list statusInfo.generalStats?keys as stat> <#list statusInfo.applicationStats?keys as stat>
    名称
    ${stat}${statusInfo.generalStats[stat]!""}
    ${stat}${statusInfo.applicationStats[stat]!""}

    示例信息

    <#list instanceInfo?keys as key>
    名称
    ${key}${instanceInfo[key]!""}
    ================================================ FILE: open-eureka-center/pom.xml ================================================ 4.0.0 com.open.capacity open-capacity-platform 0.0.1-SNAPSHOT open-eureka-center pom open-eureka-client open-eureka-server ================================================ FILE: open-layui-web/.gitignore ================================================ /bin/ ================================================ FILE: open-layui-web/pom.xml ================================================ 4.0.0 com.open.capacity open-capacity-platform 0.0.1-SNAPSHOT open-layui-web 1.8 2.8.0 23.0 1.2.46 3.17 0.9.0 1.8 1.8 UTF-8 5.22.0 gitgeek 3.0.9.RELEASE 2.2.2 com.open.capacity open-db-core org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-aop org.springframework.boot spring-boot-starter-actuator com.google.guava guava ${google.guava} org.apache.commons commons-lang3 com.fasterxml.jackson.core jackson-databind com.fasterxml.jackson.core jackson-annotations commons-codec commons-codec com.alibaba fastjson ${fastjson.version} org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-oauth2 log4j log4j 1.2.17 io.springfox springfox-bean-validators ${swagger.version} io.springfox springfox-swagger2 ${swagger.version} io.springfox springfox-swagger-ui ${swagger.version} org.springframework.boot spring-boot-starter-mail org.quartz-scheduler quartz org.springframework spring-context-support org.apache.poi poi ${poi.version} io.jsonwebtoken jjwt ${jwt.version} com.fasterxml.jackson.dataformat jackson-dataformat-xml org.activiti activiti-engine ${activiti.version} org.mybatis mybatis org.activiti activiti-spring ${activiti.version} org.activiti activiti-modeler ${activiti.version} org.activiti activiti-diagram-rest ${activiti.version} org.projectlombok lombok 1.16.10 provided org.springframework.boot spring-boot-starter-thymeleaf net.sourceforge.nekohtml nekohtml 1.9.22 src/main/resources **/*.properties **/*.yml **/*.xml **/*.tld **/*.p12 **/*.conf **/*.txt **/*.wsdl **/*.xsd **/*.ftl **/*.json false src/main/java **/*.properties **/*.xml **/*.tld false src/main/view **/*.* false org.springframework.boot spring-boot-maven-plugin repackage com.spotify docker-maven-plugin 0.4.13 ${docker.image.prefix}/${project.artifactId} src/main/docker / ${project.build.directory} ${project.build.finalName}.jar open-layui-web ================================================ FILE: open-layui-web/src/main/docker/Dockerfile ================================================ FROM frolvlad/alpine-oraclejdk8 VOLUME /tmp ADD open-layui-web.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/SecurityApplication.java ================================================ package com.open.capacity; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * 启动类 * * @author owen 624191343@qq.com */ @SpringBootApplication public class SecurityApplication { public static void main(String[] args) { SpringApplication.run(SecurityApplication.class, args); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/config/ActPropertiesConfig.java ================================================ package com.open.capacity.activiti.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:23] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Configuration @PropertySource("classpath:activiti.properties") public class ActPropertiesConfig { @Value("${modelId}") private String modelId; public String getModelId() { return modelId; } public void setModelId(String modelId) { this.modelId = modelId; } @Bean public ActPropertiesConfig getActPropertiesConfig() { return new ActPropertiesConfig(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/config/ActivitiConfig.java ================================================ package com.open.capacity.activiti.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.activiti.engine.*; import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.activiti.spring.ProcessEngineFactoryBean; import org.activiti.spring.SpringProcessEngineConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:21] * @Description: [ activiti工作流配置 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Configuration public class ActivitiConfig { /** * spring 集成 activiti */ @Bean public ProcessEngineConfiguration processEngineConfiguration(DataSource dataSource, PlatformTransactionManager transactionManager) { SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration(); processEngineConfiguration.setDataSource(dataSource); //表不存在创建表 processEngineConfiguration.setDatabaseSchemaUpdate("true"); //指定数据库 processEngineConfiguration.setDatabaseType("mysql"); processEngineConfiguration.setTransactionManager(transactionManager); //历史变量 processEngineConfiguration.setHistory("full"); //指定字体 processEngineConfiguration.setActivityFontName("宋体"); processEngineConfiguration.setAnnotationFontName("宋体"); processEngineConfiguration.setLabelFontName("宋体"); return processEngineConfiguration; } //流程引擎,与spring整合使用factoryBean @Bean public ProcessEngineFactoryBean processEngine(ProcessEngineConfiguration processEngineConfiguration) { ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean(); processEngineFactoryBean.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration); return processEngineFactoryBean; } @Bean public RepositoryService repositoryService(ProcessEngine processEngine) { return processEngine.getRepositoryService(); } @Bean public RuntimeService runtimeService(ProcessEngine processEngine) { return processEngine.getRuntimeService(); } @Bean public TaskService taskService(ProcessEngine processEngine) { return processEngine.getTaskService(); } @Bean public HistoryService historyService(ProcessEngine processEngine) { return processEngine.getHistoryService(); } @Bean public FormService formService(ProcessEngine processEngine) { return processEngine.getFormService(); } @Bean public IdentityService identityService(ProcessEngine processEngine) { return processEngine.getIdentityService(); } @Bean public ManagementService managementService(ProcessEngine processEngine) { return processEngine.getManagementService(); } @Bean public DynamicBpmnService dynamicBpmnService(ProcessEngine processEngine) { return processEngine.getDynamicBpmnService(); } @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/controller/ActivitiController.java ================================================ package com.open.capacity.activiti.controller; import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.open.capacity.activiti.config.ActPropertiesConfig; import com.open.capacity.activiti.entity.ActAssignee; import com.open.capacity.activiti.entity.ActModel; import com.open.capacity.activiti.entity.ProcessDefinition; import com.open.capacity.activiti.service.ActAssigneeService; import com.open.capacity.activiti.util.Checkbox; import com.open.capacity.activiti.util.JsonUtil; import com.open.capacity.activiti.util.ResultType; import com.open.capacity.security.dao.RoleDao; import com.open.capacity.security.model.Role; import io.swagger.annotations.ApiOperation; import org.activiti.bpmn.converter.BpmnXMLConverter; import org.activiti.bpmn.model.BpmnModel; import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.editor.language.json.converter.BpmnJsonConverter; import org.activiti.engine.IdentityService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.impl.RepositoryServiceImpl; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.Model; import org.activiti.engine.repository.ModelQuery; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.io.FileInputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:06] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Controller @RequestMapping(value = "/activiti") public class ActivitiController { @Autowired RepositoryService repositoryService; @Autowired RuntimeService runtimeService; @Autowired IdentityService identityService; @Autowired ActAssigneeService actAssigneeService; @Autowired ActPropertiesConfig actPropertiesConfig; @Autowired ObjectMapper objectMapper; @Autowired private RoleDao roleDao; /** * 部署列表 */ @GetMapping(value = "/showAct") @ApiOperation(value = "列表") @ResponseBody public String showAct(org.springframework.ui.Model model, ProcessDefinition definition, String page, String limit) { ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); List processDefinitionList = null; if (definition != null) { if (!StringUtils.isEmpty(definition.getDeploymentId())) { processDefinitionQuery.deploymentId(definition.getDeploymentId()); } if (!StringUtils.isEmpty(definition.getName())) { processDefinitionQuery.processDefinitionNameLike("%" + definition.getName() + "%"); } } processDefinitionList = processDefinitionQuery.listPage(Integer.valueOf(limit) * (Integer.valueOf(page) - 1), Integer.valueOf(limit)); long count = repositoryService.createDeploymentQuery().count(); List list = new ArrayList<>(); processDefinitionList.forEach(processDefinition -> list.add(new ProcessDefinition(processDefinition))); ResultType resultType = new ResultType(count, list); return JSON.toJSONString(resultType); } public List getActivityList(String deploymentId) { org.activiti.engine.repository.ProcessDefinition processDefinition = repositoryService .createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) .getDeployedProcessDefinition(processDefinition.getId()); return processDefinitionEntity.getActivities(); } /** * 删除流程定义 级联 删除 流程节点绑定信息 * * @param model * @param id * @return */ @PostMapping("delDeploy") @ResponseBody public JsonUtil delDeploy(org.springframework.ui.Model model, String id) { JsonUtil j = new JsonUtil(); try { List activityList = getActivityList(id); for (ActivityImpl activity : activityList) { String nodeId = activity.getId(); if (StringUtils.isEmpty(nodeId) || "start".equals(nodeId) || "end".equals(nodeId)) { continue; } /**接触节点和代办关联*/ actAssigneeService.deleteByNodeId(nodeId); } repositoryService.deleteDeployment(id, true); j.setMsg("删除成功"); } catch (Exception e) { j.setMsg("删除失败"); j.setFlag(false); } return j; } /** * 模型列表 */ @GetMapping(value = "showAm") @ResponseBody public String showModel(org.springframework.ui.Model model, ActModel actModel, String page, String limit) { ModelQuery modelQuery = repositoryService.createModelQuery(); if (actModel != null) { if (!StringUtils.isEmpty(actModel.getKey())) { modelQuery.modelKey(actModel.getKey()); } if (!StringUtils.isEmpty(actModel.getName())) { modelQuery.modelNameLike("%" + actModel.getName() + "%"); } } List models = modelQuery .listPage(Integer.valueOf(limit) * (Integer.valueOf(page) - 1), Integer.valueOf(limit)); long count = repositoryService.createModelQuery().count(); List list = new ArrayList<>(); models.forEach(mo -> list.add(new ActModel(mo))); ResultType resultType = new ResultType(count, list); return JSON.toJSONString(resultType); } /** * 发布流程 */ @PostMapping(value = "open") @ResponseBody public JsonUtil open(String id) { String msg = "发布成功"; JsonUtil j = new JsonUtil(); try { Model modelData = repositoryService.getModel(id); byte[] bytes = repositoryService.getModelEditorSource(modelData.getId()); if (bytes == null) { return JsonUtil.error("模型为空"); } JsonNode modelNode = null; modelNode = new ObjectMapper().readTree(bytes); BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode); if (model.getProcesses().size() == 0) { return JsonUtil.error("数据不符合要求"); } byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model); //发布流程 String processName = modelData.getName() + ".bpmn20.xml"; String convertToXML = new String(bpmnBytes); System.out.println(convertToXML); Deployment deployment = repositoryService.createDeployment() .name(modelData.getName()) .addString(processName, new String(bpmnBytes, "UTF-8")) .deploy(); modelData.setDeploymentId(deployment.getId()); repositoryService.saveModel(modelData); } catch (Exception e) { msg = "发布数失败"; j.setFlag(false); } j.setMsg(msg); return j; } @PostMapping("delModel") @ResponseBody public JsonUtil delModel(org.springframework.ui.Model model, String id) { FileInputStream inputStream = null; String modelId = actPropertiesConfig.getModelId(); if (id.equals(modelId)) { return JsonUtil.error("演示禁止删除"); } JsonUtil j = new JsonUtil(); try { repositoryService.deleteModel(id); j.setMsg("删除成功"); } catch (Exception e) { j.setMsg("删除失败"); j.setFlag(false); e.printStackTrace(); } return j; } @GetMapping("actUpdate/{id}") public String actUpdate(@PathVariable String id, String token) { return "redirect:/pages/activiti/modeler.html?modelId=" + id + "&token=" + token; } /** * 方法此有所参考 感谢我参考原作者:liuruijie */ @GetMapping(value = "goActiviti") public String goActiviti(String token) throws UnsupportedEncodingException { Model model = repositoryService.newModel(); String name = "新建流程"; String description = ""; int revision = 1; String key = "processKey"; ObjectNode modelNode = objectMapper.createObjectNode(); modelNode.put(ModelDataJsonConstants.MODEL_NAME, name); modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description); modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision); model.setName(name); model.setKey(key); model.setMetaInfo(modelNode.toString()); repositoryService.saveModel(model); String id = model.getId(); //完善ModelEditorSource ObjectNode editorNode = objectMapper.createObjectNode(); editorNode.put("id", "canvas"); editorNode.put("resourceId", "canvas"); ObjectNode stencilSetNode = objectMapper.createObjectNode(); stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#"); editorNode.put("stencilset", stencilSetNode); repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8")); return "redirect:/pages/activiti/modeler.html?modelId=" + id; } /** * 根据流程部署id获取节点并且传到前端 * * @param deploymentId 部署id * @param model * @return */ @GetMapping("goAssignee/{id}") public String goAssignee(@PathVariable("id") String deploymentId, String token, org.springframework.ui.Model model) { /**根据流程实例id查询出所有流程节点*/ List activityList = getActivityList(deploymentId); /**角色和节点关系封装成list*/ Map params = new HashMap<>(); List list = roleDao.list(params, null, null); List checkboxes = new ArrayList<>(); Checkbox checkbox = null; Map map = null; List> mapList = new ArrayList<>(); List assigneeList = null; List checkboxList = null; for (ActivityImpl activiti : activityList) { map = new HashMap<>(); String name = (String) activiti.getProperty("name"); if (StringUtils.isEmpty(name) || "start".equals(name) || "end".equals(name)) { continue; } //节点id 、name、节点目前关联的角色 封装成进map String nodeId = activiti.getId(); assigneeList = actAssigneeService.selectListByPage(new ActAssignee(nodeId)); List strings = new ArrayList<>(); assigneeList.forEach(actAssignee1 -> strings.add(actAssignee1.getRoleId())); map.put("id", nodeId); map.put("name", name); checkboxList = new ArrayList<>(); for (Role role : list) { checkbox = new Checkbox(); checkbox.setId(role.getId().toString()); checkbox.setName(role.getName()); if (strings.contains(role.getId().toString())) { checkbox.setCheck(true); } checkboxList.add(checkbox); } map.put("boxJson", checkboxList); mapList.add(map); } model.addAttribute("actList", mapList); return "activiti/deploy/act-node"; } /** * 节点更新配置办理者(人/组) * * @param request * @return */ @PostMapping("goAssignee/updateNode") @ResponseBody public JsonUtil updateNode(HttpServletRequest request) { JsonUtil j = new JsonUtil(); Map map = request.getParameterMap(); List assigneeList = new ArrayList<>(); ActAssignee assignee = null; for (Map.Entry entry : map.entrySet()) { assignee = new ActAssignee(); int sub = entry.getKey().lastIndexOf("_"); String nodeId = entry.getKey().substring(0, sub); nodeId = nodeId.substring(nodeId.lastIndexOf("_") + 1, nodeId.length()); String nodeName = entry.getKey().substring(entry.getKey().lastIndexOf("_") + 1, entry.getKey().length()); //更新进list assignee.setAssigneeType(3); assignee.setRoleId(entry.getValue()[0]); assignee.setSid(nodeId); assignee.setActivtiName(nodeName); //先清除 actAssigneeService.deleteByNodeId(nodeId); assigneeList.add(assignee); } //后添加 在map循环里添加 多角色会导致添加了的再次被删除 so 要拿出来 for (ActAssignee actAssignee : assigneeList) { actAssigneeService.insertSelective(actAssignee); } j.setMsg("更新成功"); return j; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/entity/ActAssignee.java ================================================ package com.open.capacity.activiti.entity; import java.io.Serializable; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:17] * @Description: [ 任务节点和代理人、候选人、候选组的绑定实体 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ public class ActAssignee implements Serializable { private static final long serialVersionUID = 1L; private String id; private String sid; private String assignee; private String roleId; private Integer assigneeType; private String activtiName; public ActAssignee() { } public ActAssignee(String sid) { this.sid = sid; } public String getId() { return id; } public void setId(String id) { this.id = id == null ? null : id.trim(); } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid == null ? null : sid.trim(); } public String getAssignee() { return assignee; } public void setAssignee(String assignee) { this.assignee = assignee == null ? null : assignee.trim(); } public String getRoleId() { return roleId; } public void setRoleId(String roleId) { this.roleId = roleId == null ? null : roleId.trim(); } public Integer getAssigneeType() { return assigneeType; } public void setAssigneeType(Integer assigneeType) { this.assigneeType = assigneeType; } public String getActivtiName() { return activtiName; } public void setActivtiName(String activtiName) { this.activtiName = activtiName == null ? null : activtiName.trim(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/entity/ActDeployment.java ================================================ package com.open.capacity.activiti.entity; import lombok.Getter; import lombok.Setter; import org.activiti.engine.repository.Deployment; import java.io.Serializable; import java.util.Date; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:18] * @Description: [ 流程部署表 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Getter @Setter public class ActDeployment implements Serializable { private String id; private String name; private Date deploymentTime; private String category; private String tenantId; public ActDeployment() { } public ActDeployment(Deployment deployment) { this.id = deployment.getId(); this.name = deployment.getName(); this.deploymentTime = deployment.getDeploymentTime(); this.category = deployment.getCategory(); this.tenantId = deployment.getTenantId(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/entity/ActModel.java ================================================ package com.open.capacity.activiti.entity; import lombok.Getter; import lombok.Setter; import org.activiti.engine.repository.Model; import java.util.Date; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:19] * @Description: [ 模型列表 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Getter @Setter public class ActModel { private String id; private String name; private String key; private String category; private Date createTime; private Date lastUpdateTime; private Integer version; private String metaInfo; private String deploymentId; private String tenantId; private boolean hasEditorSource; public ActModel() { } public ActModel(Model model) { this.id = model.getId(); this.name = model.getName(); this.key = model.getKey(); this.category = model.getCategory(); this.createTime = model.getCreateTime(); this.lastUpdateTime = model.getLastUpdateTime(); this.version = model.getVersion(); this.metaInfo = model.getMetaInfo(); this.deploymentId = model.getDeploymentId(); this.tenantId = model.getTenantId(); this.hasEditorSource = model.hasEditorSource(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/entity/LeaveOpinion.java ================================================ package com.open.capacity.activiti.entity; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.util.Date; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:22] * @Description: [ 请假流程 审批信息 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Getter @Setter public class LeaveOpinion implements Serializable { //审批人id private String opId; //审批人姓名 private String opName; //审批意见 private String opinion; //审批时间 private Date createTime; //是否通过 private boolean flag; //流程id private String taskId; } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/entity/ProcessDefinition.java ================================================ package com.open.capacity.activiti.entity; import lombok.Getter; import lombok.Setter; import lombok.ToString; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:23] * @Description: [ 流程定义实体 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Getter @Setter @ToString public class ProcessDefinition { private String id; private String category; private String name; private String key; private String description; private int version; private String resourceName; private String deploymentId; private String diagramResourceName; private boolean hasStartFormKey; private boolean hasGraphicalNotation; private boolean isSuspended; private String tenantId; public ProcessDefinition() { } public ProcessDefinition(org.activiti.engine.repository.ProcessDefinition p) { this.id = p.getId(); this.category = p.getCategory(); this.name = p.getName(); this.key = p.getKey(); this.description = p.getDescription(); this.version = p.getVersion(); this.resourceName = p.getResourceName(); this.deploymentId = p.getDeploymentId(); this.diagramResourceName = p.getDiagramResourceName(); this.hasStartFormKey = p.hasStartFormKey(); this.hasGraphicalNotation = p.hasGraphicalNotation(); this.isSuspended = p.isSuspended(); this.tenantId = p.getTenantId(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/entity/Task.java ================================================ package com.open.capacity.activiti.entity; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.util.Date; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:23] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Getter @Setter @ToString public class Task { private String id; private String name; private Date createTime; private String assignee; private String processInstanceId;//流程实例id private String processDefinitionId;//流程定义id private String description; private String category; private String userName; private String reason; public Task() { } public Task(org.activiti.engine.task.Task t) { this.id = t.getId(); this.name = t.getName(); this.createTime = t.getCreateTime(); this.assignee = t.getAssignee(); this.processInstanceId = t.getProcessInstanceId(); this.processDefinitionId = t.getProcessDefinitionId(); this.description = t.getDescription(); this.category = t.getCategory(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/entity/UserLeave.java ================================================ package com.open.capacity.activiti.entity; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:24] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ public class UserLeave { private static final long serialVersionUID = 1L; private String id; private String userId; private String userName; private Date beginTime; private Date endTime; private String reason; private Integer days; private String processInstanceId; private String status; private Date createDate; private String createBy; private Date updateDate; private String updateBy; //***实时节点信息 private String taskName; //请假单审核信息 private List opinionList = new ArrayList<>(); public String getTaskName() { return taskName; } public void setTaskName(String taskName) { this.taskName = taskName; } public void leaveOpAdd(LeaveOpinion leaveOpinion) { this.opinionList.add(leaveOpinion); } public void leaveOpAddAll(List leaveOpinionList) { this.opinionList.addAll(leaveOpinionList); } public List getOpinionList() { return opinionList; } public void setOpinionList(List opinionList) { this.opinionList = opinionList; } public String getId() { return id; } public void setId(String id) { this.id = id == null ? null : id.trim(); } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId == null ? null : userId.trim(); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName == null ? null : userName.trim(); } public Date getBeginTime() { return beginTime; } public void setBeginTime(Date beginTime) { this.beginTime = beginTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason == null ? null : reason.trim(); } public Integer getDays() { return days; } public void setDays(Integer days) { this.days = days; } public String getProcessInstanceId() { return processInstanceId; } public void setProcessInstanceId(String processInstanceId) { this.processInstanceId = processInstanceId == null ? null : processInstanceId.trim(); } public String getStatus() { return status; } public void setStatus(String status) { this.status = status == null ? null : status.trim(); } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public String getCreateBy() { return createBy; } public void setCreateBy(String createBy) { this.createBy = createBy == null ? null : createBy.trim(); } public Date getUpdateDate() { return updateDate; } public void setUpdateDate(Date updateDate) { this.updateDate = updateDate; } public String getUpdateBy() { return updateBy; } public void setUpdateBy(String updateBy) { this.updateBy = updateBy == null ? null : updateBy.trim(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/mapper/ActAssigneeMapper.java ================================================ package com.open.capacity.activiti.mapper; import com.open.capacity.activiti.entity.ActAssignee; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * @Author: [gitgeek] * @Date: [2018-05-14 19:53] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Mapper public interface ActAssigneeMapper { int deleteByPrimaryKey(String id); int insert(ActAssignee record); int insertSelective(ActAssignee record); ActAssignee selectByPrimaryKey(String id); int updateByPrimaryKeySelective(ActAssignee record); int updateByPrimaryKey(ActAssignee record); int deleteByNodeId(String nodeId); List selectListByPage(ActAssignee record); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/mapper/ActAssigneeMapper.xml ================================================ id, sid, assignee, role_id, assignee_type, activti_name delete from act_assignee where id = #{id,jdbcType=VARCHAR} delete from act_assignee where sid = #{sid,jdbcType=VARCHAR} select replace(uuid(),"-","") from dual insert into act_assignee (id, sid, assignee, role_id, assignee_type, activti_name ) values (#{id,jdbcType=VARCHAR}, #{sid,jdbcType=VARCHAR}, #{assignee,jdbcType=VARCHAR}, #{roleId,jdbcType=VARCHAR}, #{assigneeType,jdbcType=INTEGER}, #{activtiName,jdbcType=VARCHAR} ) select replace(uuid(),"-","") from dual insert into act_assignee id, sid, assignee, role_id, assignee_type, activti_name, #{id,jdbcType=VARCHAR}, #{sid,jdbcType=VARCHAR}, #{assignee,jdbcType=VARCHAR}, #{roleId,jdbcType=VARCHAR}, #{assigneeType,jdbcType=INTEGER}, #{activtiName,jdbcType=VARCHAR}, update act_assignee sid = #{sid,jdbcType=VARCHAR}, assignee = #{assignee,jdbcType=VARCHAR}, role_id = #{roleId,jdbcType=VARCHAR}, assignee_type = #{assigneeType,jdbcType=INTEGER}, activti_name = #{activtiName,jdbcType=VARCHAR}, where id = #{id,jdbcType=VARCHAR} update act_assignee set sid = #{sid,jdbcType=VARCHAR}, assignee = #{assignee,jdbcType=VARCHAR}, role_id = #{roleId,jdbcType=VARCHAR}, assignee_type = #{assigneeType,jdbcType=INTEGER}, activti_name = #{activtiName,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR} ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/mapper/UserLeaveMapper.java ================================================ package com.open.capacity.activiti.mapper; import com.open.capacity.activiti.entity.UserLeave; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:05] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Mapper public interface UserLeaveMapper { int deleteByPrimaryKey(String id); int insert(UserLeave record); int insertSelective(UserLeave record); UserLeave selectByPrimaryKey(String id); int updateByPrimaryKeySelective(UserLeave record); int updateByPrimaryKey(UserLeave record); List selectListByPage(UserLeave userLeave); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/mapper/UserLeaveMapper.xml ================================================ id, user_id, user_name, begin_time, end_time, reason, days, process_instance_Id, status, create_date, create_by, update_date, update_by delete from user_leave where id = #{id,jdbcType=VARCHAR} select replace(uuid(),"-","") from dual insert into user_leave (id, user_id, user_name, begin_time, end_time, reason, days, process_instance_Id, status, create_date, create_by, update_date, update_by) values (#{id,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, #{beginTime,jdbcType=TIMESTAMP}, #{endTime,jdbcType=TIMESTAMP}, #{reason,jdbcType=VARCHAR}, #{days,jdbcType=INTEGER}, #{processInstanceId,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createDate,jdbcType=TIMESTAMP}, #{createBy,jdbcType=VARCHAR}, #{updateDate,jdbcType=TIMESTAMP}, #{updateBy,jdbcType=VARCHAR}) select replace(uuid(),"-","") from dual insert into user_leave id, user_id, user_name, begin_time, end_time, reason, days, process_instance_Id, status, create_date, create_by, update_date, update_by, #{id,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, #{beginTime,jdbcType=TIMESTAMP}, #{endTime,jdbcType=TIMESTAMP}, #{reason,jdbcType=VARCHAR}, #{days,jdbcType=INTEGER}, #{processInstanceId,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createDate,jdbcType=TIMESTAMP}, #{createBy,jdbcType=VARCHAR}, #{updateDate,jdbcType=TIMESTAMP}, #{updateBy,jdbcType=VARCHAR}, update user_leave user_id = #{userId,jdbcType=VARCHAR}, user_name = #{userName,jdbcType=VARCHAR}, begin_time = #{beginTime,jdbcType=TIMESTAMP}, end_time = #{endTime,jdbcType=TIMESTAMP}, reason = #{reason,jdbcType=VARCHAR}, days = #{days,jdbcType=INTEGER}, process_instance_Id = #{processInstanceId,jdbcType=VARCHAR}, status = #{status,jdbcType=VARCHAR}, create_date = #{createDate,jdbcType=TIMESTAMP}, create_by = #{createBy,jdbcType=VARCHAR}, update_date = #{updateDate,jdbcType=TIMESTAMP}, update_by = #{updateBy,jdbcType=VARCHAR}, where id = #{id,jdbcType=VARCHAR} update user_leave set user_id = #{userId,jdbcType=VARCHAR}, user_name = #{userName,jdbcType=VARCHAR}, begin_time = #{beginTime,jdbcType=TIMESTAMP}, end_time = #{endTime,jdbcType=TIMESTAMP}, reason = #{reason,jdbcType=VARCHAR}, days = #{days,jdbcType=INTEGER}, process_instance_Id = #{processInstanceId,jdbcType=VARCHAR}, status = #{status,jdbcType=VARCHAR}, create_date = #{createDate,jdbcType=TIMESTAMP}, create_by = #{createBy,jdbcType=VARCHAR}, update_date = #{updateDate,jdbcType=TIMESTAMP}, update_by = #{updateBy,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR} ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/rest/editor/main/StencilsetRestResource.java ================================================ package com.open.capacity.activiti.rest.editor.main; import org.activiti.engine.ActivitiException; import org.apache.commons.io.IOUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.io.InputStream; /** * @author Tijs Rademakers */ @RestController @RequestMapping("service") public class StencilsetRestResource { @RequestMapping(value = "/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8") @ResponseBody public String getStencilset() { InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json"); try { return IOUtils.toString(stencilsetStream, "utf-8"); } catch (Exception e) { throw new ActivitiException("Error while loading stencil set", e); } } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/rest/editor/model/ModelEditorJsonRestResource.java ================================================ package com.open.capacity.activiti.rest.editor.model; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.engine.ActivitiException; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Model; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; /** * @author Tijs Rademakers */ @RestController @RequestMapping("service") @Slf4j public class ModelEditorJsonRestResource implements ModelDataJsonConstants { @Autowired private RepositoryService repositoryService; @Autowired private ObjectMapper objectMapper; @RequestMapping(value = "/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json") public ObjectNode getEditorJson(@PathVariable String modelId) { ObjectNode modelNode = null; Model model = repositoryService.getModel(modelId); if (model != null) { try { if (StringUtils.isNotEmpty(model.getMetaInfo())) { modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo()); } else { modelNode = objectMapper.createObjectNode(); modelNode.put(MODEL_NAME, model.getName()); } modelNode.put(MODEL_ID, model.getId()); ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree( new String(repositoryService.getModelEditorSource(model.getId()), "utf-8")); modelNode.set("model", editorJsonNode); } catch (Exception e) { log.error("Error creating model JSON", e); throw new ActivitiException("Error creating model JSON", e); } } return modelNode; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/rest/editor/model/ModelSaveRestResource.java ================================================ package com.open.capacity.activiti.rest.editor.model; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.engine.ActivitiException; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Model; import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.PNGTranscoder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.Map; /** * @author Tijs Rademakers */ @RestController @RequestMapping("service") @Slf4j public class ModelSaveRestResource implements ModelDataJsonConstants { @Autowired private RepositoryService repositoryService; @PostMapping(value = "/model/{modelId}/save") @ResponseStatus(value = HttpStatus.OK) public void saveModel(@PathVariable String modelId , String name, String description , String json_xml, String svg_xml, HttpServletRequest request, HttpServletResponse response) { try { Map map = request.getParameterMap(); JSONObject jsonObject = new JSONObject(); //全跑到key了,可取方案 for (Map.Entry entry : map.entrySet()) { if (entry.getKey().equals("token")) { continue; } String data = entry.getKey() + "=" + (entry.getValue()[0]); jsonObject = JSON.parseObject(data); } name = (String) jsonObject.get("name"); description = (String) jsonObject.get("description"); json_xml = (String) jsonObject.get("json_xml"); svg_xml = (String) jsonObject.get("svg_xml"); Model model = repositoryService.getModel(modelId); JSONObject object = new JSONObject(); object.put(MODEL_NAME, name); object.put(MODEL_DESCRIPTION, description); model.setMetaInfo(object.toString()); model.setName(name); repositoryService.saveModel(model); repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes("utf-8")); InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes("utf-8")); TranscoderInput input = new TranscoderInput(svgStream); PNGTranscoder transcoder = new PNGTranscoder(); // Setup output ByteArrayOutputStream outStream = new ByteArrayOutputStream(); TranscoderOutput output = new TranscoderOutput(outStream); // Do the transformation transcoder.transcode(input, output); final byte[] result = outStream.toByteArray(); repositoryService.addModelEditorSourceExtra(model.getId(), result); outStream.close(); } catch (Exception e) { log.error("Error saving model", e); throw new ActivitiException("Error saving model", e); } } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/service/ActAssigneeService.java ================================================ package com.open.capacity.activiti.service; import com.open.capacity.activiti.entity.ActAssignee; import java.util.List; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:14] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ public interface ActAssigneeService { int deleteByNodeId(String nodeId); List selectListByPage(ActAssignee record); int insertSelective(ActAssignee record); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/service/UserLeaveService.java ================================================ package com.open.capacity.activiti.service; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:14] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ public interface UserLeaveService { } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/service/impl/ActAssigneeServiceImpl.java ================================================ package com.open.capacity.activiti.service.impl; import com.open.capacity.activiti.entity.ActAssignee; import com.open.capacity.activiti.mapper.ActAssigneeMapper; import com.open.capacity.activiti.service.ActAssigneeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:15] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Service public class ActAssigneeServiceImpl implements ActAssigneeService { @Autowired ActAssigneeMapper actAssigneeMapper; @Override public int deleteByNodeId(String nodeId) { return actAssigneeMapper.deleteByNodeId(nodeId); } @Override public List selectListByPage(ActAssignee record) { return actAssigneeMapper.selectListByPage(record); } @Override public int insertSelective(ActAssignee record) { return actAssigneeMapper.insertSelective(record); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/service/impl/UserLeaveServiceImpl.java ================================================ package com.open.capacity.activiti.service.impl; import com.open.capacity.activiti.service.UserLeaveService; import org.springframework.stereotype.Service; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:16] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Service public class UserLeaveServiceImpl implements UserLeaveService { } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/util/AssigneeType.java ================================================ package com.open.capacity.activiti.util; /** * @Author: [gitgeek] * @Date: [2018-05-14 20:16] * @Description: [ 工作流节点绑定类型 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ public class AssigneeType { public static final int USER_TYPE = 1; public static final int USER_S_TYPE = 2; public static final int GROUP_TYPE = 3; } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/util/Checkbox.java ================================================ package com.open.capacity.activiti.util; import lombok.Getter; import lombok.Setter; /** * @Author: [gitgeek] * @Date: [2018-05-17 21:18] * @Description: [ 复选框类 ] * @Version: [1.0.0] * @Copy: [com.zzg] */ @Getter @Setter public class Checkbox { private String id; private String name; /** * 默认未选择 */ private boolean check = false; } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/util/JsonUtil.java ================================================ package com.open.capacity.activiti.util; import com.alibaba.fastjson.JSONObject; /** * @Author: [gitgeek] * @Date: [2018-05-15 20:12] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ public class JsonUtil { //默认成功 private boolean flag = true; private String msg; private JSONObject josnObj; public JsonUtil() { } public JsonUtil(boolean flag, String msg) { this.flag = flag; this.msg = msg; } /** * restful 返回 */ public static JsonUtil error(String msg) { return new JsonUtil(false, msg); } public static JsonUtil sucess(String msg) { return new JsonUtil(true, msg); } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public JSONObject getJosnObj() { return josnObj; } public void setJosnObj(JSONObject josnObj) { this.josnObj = josnObj; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/activiti/util/ResultType.java ================================================ package com.open.capacity.activiti.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import java.io.Serializable; import java.util.List; import java.util.Map; /** * @Author: [gitgeek] * @Date: [2018-05-15 19:23] * @Description: [ ] * @Version: [1.0.0] * @Copy: [com.zzg] */ public class ResultType implements Serializable { /** * 状态 */ public int code = 0; /** * 状态信息 */ public String msg = ""; /** * 数据总数 */ public long count; public List data; public ResultType() { } public ResultType(long count, List data) { this.count = count; this.data = data; } /** * 动态添加属性 map 用法可以参考 activiti 模块中 com.len.JsonTest 测试类中用法 * * @param count * @param data * @param map * @param node 绑定节点字符串 这样可以更加灵活 * @return */ public static String jsonStrng(long count, List data, Map> map, String node) { JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(data)); JSONObject object = new JSONObject(); for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonData = (JSONObject) jsonArray.get(i); jsonData.putAll(map.get(jsonData.get(node))); } object.put("count", count); object.put("data", jsonArray); object.put("code", 0); object.put("msg", ""); return object.toJSONString(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/advice/ExceptionHandlerAdvice.java ================================================ package com.open.capacity.security.advice; import com.open.capacity.security.dto.ResponseInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.security.access.AccessDeniedException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.UnsatisfiedServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; /** * springmvc异常处理 * * @author 作者 owen E-mail: 624191343@qq.com * * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @RestControllerAdvice public class ExceptionHandlerAdvice { private static final Logger log = LoggerFactory.getLogger(ExceptionHandlerAdvice.class); @ExceptionHandler({IllegalArgumentException.class}) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseInfo badRequestException(IllegalArgumentException exception) { return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + "", exception.getMessage()); } @ExceptionHandler({AccessDeniedException.class}) @ResponseStatus(HttpStatus.FORBIDDEN) public ResponseInfo badRequestException(AccessDeniedException exception) { return new ResponseInfo(HttpStatus.FORBIDDEN.value() + "", exception.getMessage()); } @ExceptionHandler({MissingServletRequestParameterException.class, HttpMessageNotReadableException.class, UnsatisfiedServletRequestParameterException.class, MethodArgumentTypeMismatchException.class}) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseInfo badRequestException(Exception exception) { return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + "", exception.getMessage()); } @ExceptionHandler(Throwable.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ResponseInfo exception(Throwable throwable) { log.error("系统异常", throwable); return new ResponseInfo(HttpStatus.INTERNAL_SERVER_ERROR.value() + "", throwable.getMessage()); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/advice/LogAdvice.java ================================================ package com.open.capacity.security.advice; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.model.SysLogs; import com.open.capacity.security.service.SysLogService; import io.swagger.annotations.ApiOperation; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; /** * 统一日志处理 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @Aspect @Component public class LogAdvice { @Autowired private SysLogService logService; @Around(value = "@annotation(com.open.capacity.security.annotation.LogAnnotation)") public Object logSave(ProceedingJoinPoint joinPoint) throws Throwable { SysLogs sysLogs = new SysLogs(); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); String module = null; LogAnnotation logAnnotation = methodSignature.getMethod().getDeclaredAnnotation(LogAnnotation.class); module = logAnnotation.module(); if (StringUtils.isEmpty(module)) { ApiOperation apiOperation = methodSignature.getMethod().getDeclaredAnnotation(ApiOperation.class); if (apiOperation != null) { module = apiOperation.value(); } } if (StringUtils.isEmpty(module)) { throw new RuntimeException("没有指定日志module"); } sysLogs.setModule(module); try { Object object = joinPoint.proceed(); sysLogs.setFlag(true); logService.save(sysLogs); return object; } catch (Exception e) { sysLogs.setFlag(false); sysLogs.setRemark(e.getMessage()); logService.save(sysLogs); throw e; } } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/annotation/LogAnnotation.java ================================================ package com.open.capacity.security.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 日志注解 * * @author 作者 owen E-mail: 624191343@qq.com * * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface LogAnnotation { String module() default ""; } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/config/AsycTaskExecutorConfig.java ================================================ package com.open.capacity.security.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * 线程池配置、启用异步 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @EnableAsync(proxyTargetClass = true) @Configuration public class AsycTaskExecutorConfig { @Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(50); taskExecutor.setMaxPoolSize(100); return taskExecutor; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/config/LoginPageConfig.java ================================================ package com.open.capacity.security.config; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.view.RedirectView; @Controller public class LoginPageConfig { @RequestMapping("/") public RedirectView loginPage() { return new RedirectView("/login.html"); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/config/SecurityConfig.java ================================================ package com.open.capacity.security.config; import com.open.capacity.security.filter.TokenFilter; import com.open.capacity.security.service.TokenService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; /** * spring security配置 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月20日 下午10:13:18 类说明 * 类说明 */ //开启spring security 注解 @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuthenticationSuccessHandler authenticationSuccessHandler; @Autowired private AuthenticationFailureHandler authenticationFailureHandler; @Autowired private LogoutSuccessHandler logoutSuccessHandler; @Autowired private AuthenticationEntryPoint authenticationEntryPoint; @Autowired private UserDetailsService userDetailsService; @Autowired private TokenService tokenService; @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/js/**"); web.ignoring().antMatchers("/css/**"); web.ignoring().antMatchers("/layui/**"); web.ignoring().antMatchers("/img/**"); web.ignoring().antMatchers("/fonts/**"); web.ignoring().antMatchers("/lib/**"); web.ignoring().antMatchers("/pages/**"); web.ignoring().antMatchers("/assets/**"); web.ignoring().antMatchers("/base-component/**"); // 忽略登录界面 web.ignoring().antMatchers("/login.html"); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); // 基于token,所以不需要session http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); //前后分离时需要带上 http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll(); http.authorizeRequests() .antMatchers("/", "/*.html", "/favicon.ico", "/css/**", "/js/**", "/fonts/**", "/lib/**", "/img/**", "/v2/api-docs/**", "/swagger-resources/**", "/webjars/**", "/pages/**", "/druid/**", "/statics/**") .permitAll().anyRequest().authenticated(); http.formLogin().loginPage("/login.html").loginProcessingUrl("/login") .successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and() .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint); http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); // 解决不允许显示在iframe的问题 http.headers().frameOptions().disable(); http.headers().cacheControl(); //新增token过滤器 TokenFilter tokenFilter = new TokenFilter(); tokenFilter.setTokenService(tokenService); tokenFilter.setUserDetailsService(userDetailsService); tokenFilter.afterPropertiesSet(); http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/config/SecurityHandlerConfig.java ================================================ package com.open.capacity.security.config; import com.open.capacity.security.dto.LoginUser; import com.open.capacity.security.dto.ResponseInfo; import com.open.capacity.security.dto.Token; import com.open.capacity.security.filter.TokenFilter; import com.open.capacity.security.service.TokenService; import com.open.capacity.security.utils.ResponseUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * spring security处理器 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @Configuration public class SecurityHandlerConfig { @Autowired private TokenService tokenService; /** * 登陆成功,返回Token * * @return */ @Bean public AuthenticationSuccessHandler loginSuccessHandler() { return new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { LoginUser loginUser = (LoginUser) authentication.getPrincipal(); Token token = tokenService.saveToken(loginUser); ResponseUtil.responseJson(response, HttpStatus.OK.value(), token); } }; } /** * 登陆失败 * * @return */ @Bean public AuthenticationFailureHandler loginFailureHandler() { return new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { String msg = null; if (exception instanceof BadCredentialsException) { msg = "密码错误"; } else { msg = exception.getMessage(); } ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + "", msg); ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info); } }; } /** * 未登录,返回401 * * @return */ @Bean public AuthenticationEntryPoint authenticationEntryPoint() { return new AuthenticationEntryPoint() { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + "", "请先登录"); ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info); } }; } /** * 退出处理 * * @return */ @Bean public LogoutSuccessHandler logoutSussHandler() { return new LogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { ResponseInfo info = new ResponseInfo(HttpStatus.OK.value() + "", "退出成功"); String token = TokenFilter.getToken(request); tokenService.deleteToken(token); ResponseUtil.responseJson(response, HttpStatus.OK.value(), info); } }; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/config/SwaggerConfig.java ================================================ package com.open.capacity.security.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * swagger文档 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket docket() { return new Docket(DocumentationType.SWAGGER_2).groupName("swagger接口文档") .apiInfo(new ApiInfoBuilder().title("swagger接口文档") .contact(new Contact("owen", "", "624191343@qq.com")).version("1.0").build()) .select().paths(PathSelectors.any()).build(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/config/WebMvcConfig.java ================================================ package com.open.capacity.security.config; import com.open.capacity.security.page.table.PageTableArgumentResolver; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import org.springframework.util.ResourceUtils; import org.springframework.web.context.request.RequestContextListener; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import java.io.File; import java.util.List; @Component @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { /** * 上传文件根路径 */ @Value("${files.path}") private String filesPath; /** * 跨域支持 * * @return */ @Bean // 前后分离 ajax跨域调用处理 public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允许cookies跨域 config.addAllowedOrigin("*");// 允许向该服务器提交请求的URI,*表示全部允许。。这里尽量限制来源域,比如http://xxxx:8080 // ,以降低安全风险。。 config.addAllowedHeader("*");// 允许访问的头信息,*表示全部 config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许,也可以单独设置GET、PUT等 /* * config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET");// * 允许Get的请求方法 config.addAllowedMethod("PUT"); * config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); * config.addAllowedMethod("PATCH"); */ source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } @Bean public RequestContextListener requestContextListener() { return new RequestContextListener(); } /** * datatable分页解析 * * @return */ @Bean public PageTableArgumentResolver tableHandlerMethodArgumentResolver() { return new PageTableArgumentResolver(); } @Override public void addArgumentResolvers(List argumentResolvers) { argumentResolvers.add(tableHandlerMethodArgumentResolver()); } /** * 外部文件访问 */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/statics/**") .addResourceLocations(ResourceUtils.FILE_URL_PREFIX + filesPath + File.separator); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/ClientController.java ================================================ package com.open.capacity.security.controller; import com.google.common.collect.Maps; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.ClientDao; import com.open.capacity.security.dto.ClientDto; import com.open.capacity.security.model.Client; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import com.open.capacity.security.service.ClientService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; /** * 角色相关接口 * * @author owen 624191343@qq.com */ @Api(tags = "应用") @RestController @RequestMapping("/clients") public class ClientController { @Autowired private ClientService clientService; @Autowired private ClientDao clientDao; @LogAnnotation @PostMapping @ApiOperation(value = "保存应用") @PreAuthorize("hasAuthority('sys:role:add')") public void saveRole(@RequestBody ClientDto clientDto) { clientService.saveClient(clientDto); } @GetMapping @ApiOperation(value = "应用列表") @PreAuthorize("hasAuthority('sys:role:query')") public PageTableResponse listRoles(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return clientDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { List list = clientDao.list(request.getParams(), request.getOffset(), request.getLimit()); return list; } }).handle(request); } @GetMapping("/{id}") @ApiOperation(value = "根据id获取应用") @PreAuthorize("hasAuthority('sys:role:query')") public Client get(@PathVariable Long id) { return clientDao.getById(id); } @GetMapping("/all") @ApiOperation(value = "所有应用") @PreAuthorize("hasAnyAuthority('sys:user:query','sys:role:query')") public List roles() { return clientDao.list(Maps.newHashMap(), null, null); } @GetMapping(params = "userId") @ApiOperation(value = "根据用户id获取拥有的角色") @PreAuthorize("hasAnyAuthority('sys:user:query','sys:role:query')") public List roles(Long userId) { return clientDao.listByUserId(userId); } @LogAnnotation @DeleteMapping("/{id}") @ApiOperation(value = "删除应用") @PreAuthorize("hasAuthority('sys:role:del')") public void delete(@PathVariable Long id) { clientService.deleteClient(id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/DictController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.dao.DictDao; import com.open.capacity.security.model.Dict; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/dicts") public class DictController { @Autowired private DictDao dictDao; @PreAuthorize("hasAuthority('dict:add')") @PostMapping @ApiOperation(value = "保存") public Dict save(@RequestBody Dict dict) { Dict d = dictDao.getByTypeAndK(dict.getType(), dict.getK()); if (d != null) { throw new IllegalArgumentException("类型和key已存在"); } dictDao.save(dict); return dict; } @GetMapping("/{id}") @ApiOperation(value = "根据id获取") public Dict get(@PathVariable Long id) { return dictDao.getById(id); } @PreAuthorize("hasAuthority('dict:add')") @PutMapping @ApiOperation(value = "修改") public Dict update(@RequestBody Dict dict) { dictDao.update(dict); return dict; } @PreAuthorize("hasAuthority('dict:query')") @GetMapping(params = {"start", "length"}) @ApiOperation(value = "列表") public PageTableResponse list(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return dictDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { return dictDao.list(request.getParams(), request.getOffset(), request.getLimit()); } }).handle(request); } @PreAuthorize("hasAuthority('dict:del')") @DeleteMapping("/{id}") @ApiOperation(value = "删除") public void delete(@PathVariable Long id) { dictDao.delete(id); } @GetMapping(params = "type") public List listByType(String type) { return dictDao.listByType(type); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/EurekaController.java ================================================ package com.open.capacity.security.controller; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.io.StringWriter; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @Controller @RequestMapping("/eureka/") public class EurekaController { private static final Logger LOGGER = LoggerFactory.getLogger(EurekaController.class); @Autowired private DiscoveryClient discoveryClient; private static String getoperate(String url, int post2get, String... str) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(10 * 1000) .setConnectTimeout(10 * 1000).setSocketTimeout(10 * 1000).build(); if (post2get == -1) { HttpPut po = new HttpPut(url); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString.toString(); } if (post2get == 1) { HttpGet po = new HttpGet(url); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString.toString(); } if (post2get == 3) { HttpPost po = new HttpPost(url); po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0])); po.setConfig(requestConfig); String queryCase = "name=admin&password=admin&remember=0"; StringEntity reqEntity = new StringEntity(queryCase); reqEntity.setContentType("application/x-www-form-urlencoded"); po.setEntity(reqEntity); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } if (post2get == 4) { HttpGet po = new HttpGet(url); po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0] + ";DISCONF=" + str[1])); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } if (post2get == 5) { HttpPut po = new HttpPut(url); po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0] + ";DISCONF=" + str[1])); po.setConfig(requestConfig); String text = "fileContent=" + str[2]; StringEntity reqEntity = new StringEntity(text); reqEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); po.setEntity(reqEntity); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } if (post2get == 6) { HttpPost po = new HttpPost(url); po.setConfig(requestConfig); StringEntity reqEntity = new StringEntity(str[0]); reqEntity.setContentType("application/json;charset=utf-8"); po.setEntity(reqEntity); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } else { HttpPost po = new HttpPost(url); if (str != null && str.length > 0) { po.addHeader(new BasicHeader("Cookie", "JSESSIONID=" + str[0])); } StringEntity reqEntity = new StringEntity(""); reqEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); po.setEntity(reqEntity); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); LOGGER.info(bodyAsString.toString()); return bodyAsString; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return "{}"; } private static String getinfo(String url) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000) .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build(); HttpGet po = new HttpGet(url); if (url.indexOf("apps") > 0) { po.setHeader("Accept", "application/json"); } po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); if (url.indexOf("apps") > 0) { LOGGER.info(bodyAsString.toString()); return bodyAsString; } ObjectMapper objectMapper = new ObjectMapper(); XmlMapper xmlMapper = new XmlMapper(); StringWriter w = new StringWriter(); JsonParser jp; try { jp = xmlMapper.getFactory().createParser(bodyAsString); JsonGenerator jg = objectMapper.getFactory().createGenerator(w); while (jp.nextToken() != null) { jg.copyCurrentEvent(jp); } jp.close(); jg.close(); } catch (Exception e) { e.printStackTrace(); } LOGGER.info(w.toString()); return w.toString(); // logger.info("RestContr "+bodyAsString); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return "{}"; } private static String getinfo_put(String url) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50 * 1000) .setConnectTimeout(50 * 1000).setSocketTimeout(50 * 1000).build(); HttpPut po = new HttpPut(url); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); // LOGGER.info(w.toString()); return "{}"; // logger.info("RestContr "+bodyAsString); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return "{}"; } private static String getinfo_del(String url) { String bodyAsString = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); try { RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(50000) .setConnectTimeout(50000).setSocketTimeout(50000).build(); HttpDelete po = new HttpDelete(url); po.setConfig(requestConfig); CloseableHttpResponse response = httpClient.execute(po); bodyAsString = EntityUtils.toString(response.getEntity()); return "{}"; } catch (Exception e) { e.printStackTrace(); } return "{}"; } @ResponseBody @RequestMapping(value = "status", method = RequestMethod.GET) public String status() { String url = "http://127.0.0.1:1111/eureka/status"; return getinfo(url); } @ResponseBody @RequestMapping(value = "apps", method = RequestMethod.GET) public String apps() { String url = "http://127.0.0.1:1111/eureka/apps"; return getinfo(url); } @ResponseBody @RequestMapping(value = "list", method = RequestMethod.GET) public Map list() { List list = discoveryClient.getServices(); Map res = new HashMap<>(); for (Iterator it = list.iterator(); it.hasNext(); ) { String serviceName = it.next(); List instances = discoveryClient.getInstances(serviceName); for (Iterator its = instances.iterator(); its.hasNext(); ) { ServiceInstance instance = its.next(); res.putAll(instance.getMetadata()); } } return res; } @ResponseBody @RequestMapping(value = "appsmd", method = RequestMethod.POST) public String appsmd(@RequestParam(value = "name", required = false) String str) { String url = "http://127.0.0.1:1111/eureka/apps/" + str; return getinfo(url); } @ResponseBody @RequestMapping(value = {"appsmddel"}, method = RequestMethod.POST) public String appsmddel(@RequestParam(value = "name", required = false) String str) { String url = "http://127.0.0.1:1111/metadata/apps/" + str; return getinfo_del(url); } @ResponseBody @RequestMapping(value = "operate", method = RequestMethod.POST) public String operate(@RequestBody HashMap inmap) { LOGGER.info(inmap.toString()); String op = ""; int post2get = 0; if (inmap.get("operate").equals("1")) {// 暂停 op = "DOWN"; post2get = -1; } if (inmap.get("operate").equals("2")) {// 挂起 op = "OUT_OF_SERVICE"; post2get = -1; } if (inmap.get("operate").equals("3")) {// 恢复 op = "UP"; post2get = -1; } if (inmap.get("operate").equals("4")) {// 刷新 op = "refresh"; } if (inmap.get("operate").equals("5")) {// 主机性能指标 op = "metrics"; post2get = 1; } String name = inmap.get("app"); String instance = inmap.get("instanceId"); String path = ""; if ("OPEN-EUREKA-CLIENT".equals(name)) { path = "/client"; } String url = null; switch (post2get) { case -1: url = "http://127.0.0.1:1111/eureka/apps/" + name + "/" + instance + "" + "/status?value=" + op; break; default: url = "http://" + inmap.get("ip") + ":" + inmap.get("port") + path + "/" + op; break; } return getoperate(url, post2get, "", ""); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/ExcelController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.utils.ExcelUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.codec.digest.DigestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @Api(tags = "excel下载") @RestController @RequestMapping("/excels") public class ExcelController { private static final Logger log = LoggerFactory.getLogger(ExcelController.class); @Autowired private JdbcTemplate jdbcTemplate; @ApiOperation("校验sql,并返回sql返回的数量") @PostMapping("/sql-count") public Integer checkSql(String sql) { log.info(sql); sql = getAndCheckSql(sql); Integer count = 0; try { count = jdbcTemplate.queryForObject("select count(1) from (" + sql + ") t", Integer.class); } catch (Exception e) { throw new IllegalArgumentException(e.getMessage()); } return count; } private String getAndCheckSql(String sql) { sql = sql.trim().toLowerCase(); if (sql.endsWith(";") || sql.endsWith(";")) { sql = sql.substring(0, sql.length() - 1); } if (!sql.startsWith("select")) { throw new IllegalArgumentException("仅支持select语句"); } return sql; } @LogAnnotation @ApiOperation("根据sql导出excel") @PostMapping @PreAuthorize("hasAuthority('excel:down')") public void downloadExcel(String sql, String fileName, HttpServletResponse response) { sql = getAndCheckSql(sql); List> list = jdbcTemplate.queryForList(sql); if (!CollectionUtils.isEmpty(list)) { Map map = list.get(0); String[] headers = new String[map.size()]; int i = 0; for (String key : map.keySet()) { headers[i++] = key; } List datas = new ArrayList<>(list.size()); for (Map m : list) { Object[] objects = new Object[headers.length]; for (int j = 0; j < headers.length; j++) { objects[j] = m.get(headers[j]); } datas.add(objects); } ExcelUtil.excelExport( fileName == null || fileName.trim().length() <= 0 ? DigestUtils.md5Hex(sql) : fileName, headers, datas, response); } } @LogAnnotation @ApiOperation("根据sql在页面显示结果") @PostMapping("/show-datas") @PreAuthorize("hasAuthority('excel:show:datas')") public List showData(String sql) { sql = getAndCheckSql(sql); List> list = jdbcTemplate.queryForList(sql); if (!CollectionUtils.isEmpty(list)) { Map map = list.get(0); String[] headers = new String[map.size()]; int i = 0; for (String key : map.keySet()) { headers[i++] = key; } List datas = new ArrayList<>(list.size()); datas.add(headers); for (Map m : list) { Object[] objects = new Object[headers.length]; for (int j = 0; j < headers.length; j++) { objects[j] = m.get(headers[j]); } datas.add(objects); } return datas; } return Collections.emptyList(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/FileController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.FileInfoDao; import com.open.capacity.security.dto.LayuiFile; import com.open.capacity.security.dto.LayuiFile.LayuiFileData; import com.open.capacity.security.model.FileInfo; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import com.open.capacity.security.service.FileService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.List; @Api(tags = "文件") @RestController @RequestMapping("/files") public class FileController { @Autowired private FileService fileService; @Autowired private FileInfoDao fileInfoDao; @LogAnnotation @PostMapping @ApiOperation(value = "文件上传") public FileInfo uploadFile(MultipartFile file) throws IOException { return fileService.save(file); } /** * layui富文本文件自定义上传 * * @param file * @param domain * @return * @throws IOException */ @LogAnnotation @PostMapping("/layui") @ApiOperation(value = "layui富文本文件自定义上传") public LayuiFile uploadLayuiFile(MultipartFile file, String domain) throws IOException { FileInfo fileInfo = fileService.save(file); LayuiFile layuiFile = new LayuiFile(); layuiFile.setCode(0); LayuiFileData data = new LayuiFileData(); layuiFile.setData(data); data.setSrc(domain + "/statics" + fileInfo.getUrl()); data.setTitle(file.getOriginalFilename()); return layuiFile; } @GetMapping @ApiOperation(value = "文件查询") @PreAuthorize("hasAuthority('sys:file:query')") public PageTableResponse listFiles(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return fileInfoDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { List list = fileInfoDao.list(request.getParams(), request.getOffset(), request.getLimit()); return list; } }).handle(request); } @LogAnnotation @DeleteMapping("/{id}") @ApiOperation(value = "文件删除") @PreAuthorize("hasAuthority('sys:file:del')") public void delete(@PathVariable String id) { fileService.delete(id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/GenerateController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dto.BeanField; import com.open.capacity.security.dto.GenerateDetail; import com.open.capacity.security.dto.GenerateInput; import com.open.capacity.security.service.GenerateService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; /** * 代码生成接口 * * @author owen 624191343@qq.com */ @Api(tags = "代码生成") @RestController @RequestMapping("/generate") public class GenerateController { @Autowired private GenerateService generateService; @ApiOperation("根据表名显示表信息") @GetMapping(params = {"tableName"}) @PreAuthorize("hasAuthority('generate:edit')") public GenerateDetail generateByTableName(String tableName) { GenerateDetail detail = new GenerateDetail(); detail.setBeanName(generateService.upperFirstChar(tableName)); List fields = generateService.listBeanField(tableName); detail.setFields(fields); return detail; } @LogAnnotation @ApiOperation("生成代码") @PostMapping @PreAuthorize("hasAuthority('generate:edit')") public void save(@RequestBody GenerateInput input) { generateService.saveCode(input); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/MailController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.MailDao; import com.open.capacity.security.model.Mail; import com.open.capacity.security.model.MailTo; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import com.open.capacity.security.service.MailService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Api(tags = "邮件") @RestController @RequestMapping("/mails") public class MailController { @Autowired private MailDao mailDao; @Autowired private MailService mailService; @LogAnnotation @PostMapping @ApiOperation(value = "保存邮件") @PreAuthorize("hasAuthority('mail:send')") public Mail save(@RequestBody Mail mail) { String toUsers = mail.getToUsers().trim(); if (StringUtils.isBlank(toUsers)) { throw new IllegalArgumentException("收件人不能为空"); } toUsers = toUsers.replace(" ", ""); toUsers = toUsers.replace(";", ";"); String[] strings = toUsers.split(";"); List toUser = Arrays.asList(strings); toUser = toUser.stream().filter(u -> !StringUtils.isBlank(u)).map(u -> u.trim()).collect(Collectors.toList()); mailService.save(mail, toUser); return mail; } @GetMapping("/{id}") @ApiOperation(value = "根据id获取邮件") @PreAuthorize("hasAuthority('mail:all:query')") public Mail get(@PathVariable Long id) { return mailDao.getById(id); } @GetMapping("/{id}/to") @ApiOperation(value = "根据id获取邮件发送详情") @PreAuthorize("hasAuthority('mail:all:query')") public List getMailTo(@PathVariable Long id) { return mailDao.getToUsers(id); } @GetMapping @ApiOperation(value = "邮件列表") @PreAuthorize("hasAuthority('mail:all:query')") public PageTableResponse list(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return mailDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { return mailDao.list(request.getParams(), request.getOffset(), request.getLimit()); } }).handle(request); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/NoticeController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.NoticeDao; import com.open.capacity.security.dto.NoticeReadVO; import com.open.capacity.security.dto.NoticeVO; import com.open.capacity.security.model.Notice; import com.open.capacity.security.model.Notice.Status; import com.open.capacity.security.model.SysUser; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import com.open.capacity.security.utils.UserUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; @Api(tags = "公告") @RestController @RequestMapping("/notices") public class NoticeController { @Autowired private NoticeDao noticeDao; @LogAnnotation @PostMapping @ApiOperation(value = "保存公告") @PreAuthorize("hasAuthority('notice:add')") public Notice saveNotice(@RequestBody Notice notice) { noticeDao.save(notice); return notice; } @GetMapping("/{id}") @ApiOperation(value = "根据id获取公告") @PreAuthorize("hasAuthority('notice:query')") public Notice get(@PathVariable Long id) { return noticeDao.getById(id); } @GetMapping(params = "id") public NoticeVO readNotice(Long id) { NoticeVO vo = new NoticeVO(); Notice notice = noticeDao.getById(id); if (notice == null || notice.getStatus() == Status.DRAFT) { return vo; } vo.setNotice(notice); noticeDao.saveReadRecord(notice.getId(), UserUtil.getLoginUser().getId()); List users = noticeDao.listReadUsers(id); vo.setUsers(users); return vo; } @LogAnnotation @PutMapping @ApiOperation(value = "修改公告") @PreAuthorize("hasAuthority('notice:add')") public Notice updateNotice(@RequestBody Notice notice) { Notice no = noticeDao.getById(notice.getId()); if (no.getStatus() == Status.PUBLISH) { throw new IllegalArgumentException("发布状态的不能修改"); } noticeDao.update(notice); return notice; } @GetMapping @ApiOperation(value = "公告管理列表") @PreAuthorize("hasAuthority('notice:query')") public PageTableResponse listNotice(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return noticeDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { return noticeDao.list(request.getParams(), request.getOffset(), request.getLimit()); } }).handle(request); } @LogAnnotation @DeleteMapping("/{id}") @ApiOperation(value = "删除公告") @PreAuthorize("hasAuthority('notice:del')") public void delete(@PathVariable Long id) { noticeDao.delete(id); } @ApiOperation(value = "未读公告数") @GetMapping("/count-unread") public Integer countUnread() { SysUser user = UserUtil.getLoginUser(); return noticeDao.countUnread(user.getId()); } @GetMapping("/published") @ApiOperation(value = "公告列表") public PageTableResponse listNoticeReadVO(PageTableRequest request) { request.getParams().put("userId", UserUtil.getLoginUser().getId()); return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return noticeDao.countNotice(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { return noticeDao.listNotice(request.getParams(), request.getOffset(), request.getLimit()); } }).handle(request); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/PermissionController.java ================================================ package com.open.capacity.security.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.PermissionDao; import com.open.capacity.security.dto.LoginUser; import com.open.capacity.security.model.Permission; import com.open.capacity.security.service.PermissionService; import com.open.capacity.security.utils.UserUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * 权限相关接口 * * @author owen 624191343@qq.com */ @Api(tags = "权限") @RestController @RequestMapping("/permissions") public class PermissionController { @Autowired private PermissionDao permissionDao; @Autowired private PermissionService permissionService; @ApiOperation(value = "当前登录用户拥有的权限") @GetMapping("/current") public List permissionsCurrent() { LoginUser loginUser = UserUtil.getLoginUser(); List list = loginUser.getPermissions(); final List permissions = list.stream().filter(l -> l.getType().equals(1)) .collect(Collectors.toList()); setChild(permissions); return permissions.stream().filter(p -> p.getParentId().equals(0L)).collect(Collectors.toList()); } private void setChild(List permissions) { permissions.parallelStream().forEach(per -> { List child = permissions.stream().filter(p -> p.getParentId().equals(per.getId())) .collect(Collectors.toList()); per.setChild(child); }); } /** * 菜单列表 * * @param pId * @param permissionsAll * @param list */ private void setPermissionsList(Long pId, List permissionsAll, List list) { for (Permission per : permissionsAll) { if (per.getParentId().equals(pId)) { list.add(per); if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) { setPermissionsList(per.getId(), permissionsAll, list); } } } } @GetMapping @ApiOperation(value = "菜单列表") @PreAuthorize("hasAuthority('sys:menu:query')") public List permissionsList() { List permissionsAll = permissionDao.listAll(); List list = Lists.newArrayList(); setPermissionsList(0L, permissionsAll, list); return list; } @GetMapping("/all") @ApiOperation(value = "所有菜单") @PreAuthorize("hasAuthority('sys:menu:query')") public JSONArray permissionsAll() { List permissionsAll = permissionDao.listAll(); JSONArray array = new JSONArray(); setPermissionsTree(0L, permissionsAll, array); return array; } @GetMapping("/parents") @ApiOperation(value = "一级菜单") @PreAuthorize("hasAuthority('sys:menu:query')") public List parentMenu() { List parents = permissionDao.listParents(); return parents; } /** * 菜单树 * * @param pId * @param permissionsAll * @param array */ private void setPermissionsTree(Long pId, List permissionsAll, JSONArray array) { for (Permission per : permissionsAll) { if (per.getParentId().equals(pId)) { String string = JSONObject.toJSONString(per); JSONObject parent = (JSONObject) JSONObject.parse(string); array.add(parent); if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) { JSONArray child = new JSONArray(); parent.put("child", child); setPermissionsTree(per.getId(), permissionsAll, child); } } } } @GetMapping(params = "roleId") @ApiOperation(value = "根据角色id删除权限") @PreAuthorize("hasAnyAuthority('sys:menu:query','sys:role:query')") public List listByRoleId(Long roleId) { return permissionDao.listByRoleId(roleId); } @LogAnnotation @PostMapping @ApiOperation(value = "保存菜单") @PreAuthorize("hasAuthority('sys:menu:add')") public void save(@RequestBody Permission permission) { permissionDao.save(permission); } @GetMapping("/{id}") @ApiOperation(value = "根据菜单id获取菜单") @PreAuthorize("hasAuthority('sys:menu:query')") public Permission get(@PathVariable Long id) { return permissionDao.getById(id); } @LogAnnotation @PutMapping @ApiOperation(value = "修改菜单") @PreAuthorize("hasAuthority('sys:menu:add')") public void update(@RequestBody Permission permission) { permissionService.update(permission); } /** * 校验权限 * * @return */ @GetMapping("/owns") @ApiOperation(value = "校验当前用户的权限") public Set ownsPermission() { List permissions = UserUtil.getLoginUser().getPermissions(); if (CollectionUtils.isEmpty(permissions)) { return Collections.emptySet(); } return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission())) .map(Permission::getPermission).collect(Collectors.toSet()); } @LogAnnotation @DeleteMapping("/{id}") @ApiOperation(value = "删除菜单") @PreAuthorize("hasAuthority('sys:menu:del')") public void delete(@PathVariable Long id) { permissionService.delete(id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/RoleController.java ================================================ package com.open.capacity.security.controller; import com.google.common.collect.Maps; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.RoleDao; import com.open.capacity.security.dto.RoleDto; import com.open.capacity.security.model.Role; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import com.open.capacity.security.service.RoleService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; /** * 角色相关接口 * * @author owen 624191343@qq.com */ @Api(tags = "角色") @RestController @RequestMapping("/roles") public class RoleController { @Autowired private RoleService roleService; @Autowired private RoleDao roleDao; @LogAnnotation @PostMapping @ApiOperation(value = "保存角色") @PreAuthorize("hasAuthority('sys:role:add')") public void saveRole(@RequestBody RoleDto roleDto) { roleService.saveRole(roleDto); } @GetMapping @ApiOperation(value = "角色列表") @PreAuthorize("hasAuthority('sys:role:query')") public PageTableResponse listRoles(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return roleDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { List list = roleDao.list(request.getParams(), request.getOffset(), request.getLimit()); return list; } }).handle(request); } @GetMapping("/{id}") @ApiOperation(value = "根据id获取角色") @PreAuthorize("hasAuthority('sys:role:query')") public Role get(@PathVariable Long id) { return roleDao.getById(id); } @GetMapping("/all") @ApiOperation(value = "所有角色") @PreAuthorize("hasAnyAuthority('sys:user:query','sys:role:query')") public List roles() { return roleDao.list(Maps.newHashMap(), null, null); } @GetMapping(params = "userId") @ApiOperation(value = "根据用户id获取拥有的角色") @PreAuthorize("hasAnyAuthority('sys:user:query','sys:role:query')") public List roles(Long userId) { return roleDao.listByUserId(userId); } @LogAnnotation @DeleteMapping("/{id}") @ApiOperation(value = "删除角色") @PreAuthorize("hasAuthority('sys:role:del')") public void delete(@PathVariable Long id) { roleService.deleteRole(id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/ServiceController.java ================================================ package com.open.capacity.security.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.ServiceDao; import com.open.capacity.security.dto.LoginUser; import com.open.capacity.security.model.Permission; import com.open.capacity.security.service.MicroServiceService; import com.open.capacity.security.utils.UserUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * 权限相关接口 * * @author owen 624191343@qq.com */ @Api(tags = "服务") @RestController @RequestMapping("/services") public class ServiceController { @Autowired private ServiceDao serviceDao; @Autowired private MicroServiceService microServiceService; @ApiOperation(value = "当前登录用户拥有的权限") @GetMapping("/current") public List permissionsCurrent() { LoginUser loginUser = UserUtil.getLoginUser(); List list = loginUser.getPermissions(); final List permissions = list.stream().filter(l -> l.getType().equals(1)) .collect(Collectors.toList()); setChild(permissions); return permissions.stream().filter(p -> p.getParentId().equals(0L)).collect(Collectors.toList()); } private void setChild(List permissions) { permissions.parallelStream().forEach(per -> { List child = permissions.stream().filter(p -> p.getParentId().equals(per.getId())) .collect(Collectors.toList()); per.setChild(child); }); } /** * 菜单列表 * * @param pId * @param permissionsAll * @param list */ private void setPermissionsList(Long pId, List permissionsAll, List list) { for (Permission per : permissionsAll) { if (per.getParentId().equals(pId)) { list.add(per); if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) { setPermissionsList(per.getId(), permissionsAll, list); } } } } @GetMapping @ApiOperation(value = "服务列表") @PreAuthorize("hasAuthority('sys:menu:query')") public List permissionsList() { List permissionsAll = serviceDao.listAll(); List list = Lists.newArrayList(); setPermissionsList(0L, permissionsAll, list); return list; } @GetMapping("/all") @ApiOperation(value = "所有服务") @PreAuthorize("hasAuthority('sys:menu:query')") public JSONArray permissionsAll() { List permissionsAll = serviceDao.listAll(); JSONArray array = new JSONArray(); setPermissionsTree(0L, permissionsAll, array); return array; } @GetMapping("/parents") @ApiOperation(value = "一级服务") @PreAuthorize("hasAuthority('sys:menu:query')") public List parentMenu() { List parents = serviceDao.listParents(); return parents; } /** * 菜单树 * * @param pId * @param permissionsAll * @param array */ private void setPermissionsTree(Long pId, List permissionsAll, JSONArray array) { for (Permission per : permissionsAll) { if (per.getParentId().equals(pId)) { String string = JSONObject.toJSONString(per); JSONObject parent = (JSONObject) JSONObject.parse(string); array.add(parent); if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) { JSONArray child = new JSONArray(); parent.put("child", child); setPermissionsTree(per.getId(), permissionsAll, child); } } } } @GetMapping(params = "clientId") @ApiOperation(value = "根据应用id查询权限") @PreAuthorize("hasAnyAuthority('sys:menu:query','sys:role:query')") public List listByRoleId(Long clientId) { return serviceDao.listByClientId(clientId); } @LogAnnotation @PostMapping @ApiOperation(value = "保存服务") @PreAuthorize("hasAuthority('sys:menu:add')") public void save(@RequestBody Permission permission) { serviceDao.save(permission); } @GetMapping("/{id}") @ApiOperation(value = "根据服务id获取服务") @PreAuthorize("hasAuthority('sys:menu:query')") public Permission get(@PathVariable Long id) { return serviceDao.getById(id); } @LogAnnotation @PutMapping @ApiOperation(value = "修改服务") @PreAuthorize("hasAuthority('sys:menu:add')") public void update(@RequestBody Permission permission) { microServiceService.update(permission); } /** * 校验权限 * * @return */ @GetMapping("/owns") @ApiOperation(value = "校验当前用户的权限") public Set ownsPermission() { List permissions = UserUtil.getLoginUser().getPermissions(); if (CollectionUtils.isEmpty(permissions)) { return Collections.emptySet(); } return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission())) .map(Permission::getPermission).collect(Collectors.toSet()); } @LogAnnotation @DeleteMapping("/{id}") @ApiOperation(value = "删除服务") @PreAuthorize("hasAuthority('sys:menu:del')") public void delete(@PathVariable Long id) { microServiceService.delete(id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/SysLogsController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.dao.SysLogsDao; import com.open.capacity.security.model.SysLogs; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @Api(tags = "日志") @RestController @RequestMapping("/logs") public class SysLogsController { @Autowired private SysLogsDao sysLogsDao; @GetMapping @PreAuthorize("hasAuthority('sys:log:query')") @ApiOperation(value = "日志列表") public PageTableResponse list(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return sysLogsDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { return sysLogsDao.list(request.getParams(), request.getOffset(), request.getLimit()); } }).handle(request); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/controller/UserController.java ================================================ package com.open.capacity.security.controller; import com.open.capacity.security.annotation.LogAnnotation; import com.open.capacity.security.dao.UserDao; import com.open.capacity.security.dto.UserDto; import com.open.capacity.security.model.SysUser; import com.open.capacity.security.page.table.PageTableHandler; import com.open.capacity.security.page.table.PageTableHandler.CountHandler; import com.open.capacity.security.page.table.PageTableHandler.ListHandler; import com.open.capacity.security.page.table.PageTableRequest; import com.open.capacity.security.page.table.PageTableResponse; import com.open.capacity.security.service.UserService; import com.open.capacity.security.utils.UserUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; /** * 用户相关接口 * * @author 624191343@qq.com */ @Api(tags = "用户") @RestController @RequestMapping("/users") public class UserController { private static final Logger log = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @Autowired private UserDao userDao; @LogAnnotation @PostMapping @ApiOperation(value = "保存用户") @PreAuthorize("hasAuthority('sys:user:add')") public SysUser saveUser(@RequestBody UserDto userDto) { SysUser u = userService.getUser(userDto.getUsername()); if (u != null) { throw new IllegalArgumentException(userDto.getUsername() + "已存在"); } return userService.saveUser(userDto); } @LogAnnotation @PutMapping @ApiOperation(value = "修改用户") @PreAuthorize("hasAuthority('sys:user:add')") public SysUser updateUser(@RequestBody UserDto userDto) { return userService.updateUser(userDto); } @LogAnnotation @PutMapping(params = "headImgUrl") @ApiOperation(value = "修改头像") public void updateHeadImgUrl(String headImgUrl) { SysUser user = UserUtil.getLoginUser(); UserDto userDto = new UserDto(); BeanUtils.copyProperties(user, userDto); userDto.setHeadImgUrl(headImgUrl); userService.updateUser(userDto); log.debug("{}修改了头像", user.getUsername()); } @LogAnnotation @PutMapping("/{username}") @ApiOperation(value = "修改密码") @PreAuthorize("hasAuthority('sys:user:password')") public void changePassword(@PathVariable String username, String oldPassword, String newPassword) { userService.changePassword(username, oldPassword, newPassword); } @GetMapping @ApiOperation(value = "用户列表") @PreAuthorize("hasAuthority('sys:user:query')") public PageTableResponse listUsers(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return userDao.count(request.getParams()); } }, new ListHandler() { @Override public List list(PageTableRequest request) { List list = userDao.list(request.getParams(), request.getOffset(), request.getLimit()); return list; } }).handle(request); } @ApiOperation(value = "当前登录用户") @GetMapping("/current") public SysUser currentUser() { return UserUtil.getLoginUser(); } @ApiOperation(value = "根据用户id获取用户") @GetMapping("/{id}") @PreAuthorize("hasAuthority('sys:user:query')") public SysUser user(@PathVariable Long id) { return userDao.getById(id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/ClientDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.Client; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @Mapper public interface ClientDao { @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into oauth_client_details(client_id, resource_ids, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove) values(#{clientId}, #{resourceIds}, #{clientSecret}, #{scope}, #{authorizedGrantTypes}, #{webServerRedirectUri}, #{authorities}, #{accessTokenValidity}, #{refreshTokenValidity}, #{additionalInformation}, #{autoapprove})") int save(Client client); int count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); @Select("select id id , client_id clientId , resource_ids resourceIds ,client_secret clientSecret ,web_server_redirect_uri webServerRedirectUri from oauth_client_details t where t.id = #{id}") Client getById(Long id); @Select("select * from oauth_client_details t where t.client_id = #{clientId}") Client getClient(String clientId); @Update("update oauth_client_details t set t.client_secret = #{clientSecret} where t.id = #{id}") int update(Client client); @Select("select * from sys_role r inner join sys_role_user ru on r.id = ru.roleId where ru.userId = #{userId}") List listByUserId(Long userId); @Delete("delete from sys_client_permission where clientId = #{clientId}") int deleteClientPermission(Long clientId); int saveClientPermission(@Param("clientId") Long clientId, @Param("permissionIds") List permissionIds); @Delete("delete from oauth_client_details where id = #{id}") int delete(Long id); @Delete("delete from sys_role_user where roleId = #{clientId}") int deleteRoleUser(Long clientId); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/ClientDao.xml ================================================ and client_id = #{params.clientId} and resource_ids = #{params.resourceIds} and client_secret = #{params.clientSecret} and scope = #{params.scope} and authorized_grant_types = #{params.authorizedGrantTypes} and web_server_redirect_uri = #{params.webServerRedirectUri} and authorities = #{params.authorities} and access_token_validity = #{params.accessTokenValidity} and refresh_token_validity = #{params.refreshTokenValidity} and additional_information = #{params.additionalInformation} and autoapprove = #{params.autoapprove} insert into sys_client_permission(clientId, permissionId) values (#{clientId}, #{permissionId}) ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/DictDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.Dict; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @Mapper public interface DictDao { @Select("select * from t_dict t where t.id = #{id}") Dict getById(Long id); @Delete("delete from t_dict where id = #{id}") int delete(Long id); int update(Dict dict); @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into t_dict(type, k, val, createTime, updateTime) values(#{type}, #{k}, #{val}, now(), now())") int save(Dict dict); int count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); @Select("select * from t_dict t where t.type = #{type} and k = #{k}") Dict getByTypeAndK(@Param("type") String type, @Param("k") String k); @Select("select * from t_dict t where t.type = #{type}") List listByType(String type); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/DictDaoxml ================================================ and id = #{params.id} and type = #{params.type} and k = #{params.k} and val = #{params.val} update t_dict t type = #{type}, k = #{k}, val = #{val}, updateTime = now() where t.id = #{id} ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/FileDao.xml ================================================ ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/FileInfoDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.FileInfo; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @Mapper public interface FileInfoDao { @Select("select * from file_info t where t.id = #{id}") FileInfo getById(String id); @Insert("insert into file_info(id, contentType, size, path, url, type, createTime, updateTime) values(#{id}, #{contentType}, #{size}, #{path}, #{url}, #{type}, now(), now())") int save(FileInfo fileInfo); @Update("update file_info t set t.updateTime = now(),t.path=#{path},t.url=#{url} where t.id = #{id}") int update(FileInfo fileInfo); @Delete("delete from file_info where id = #{id}") int delete(String id); int count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/MailDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.Mail; import com.open.capacity.security.model.MailTo; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @Mapper public interface MailDao { @Select("select * from t_mail t where t.id = #{id}") Mail getById(Long id); // @Delete("delete from t_mail where id = #{id}") // int delete(Long id); // @Update("update t_mail t set subject = #{subject}, content = #{content}, updateTime = now() where t.id = #{id}") // int update(Mail mail); @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into t_mail(userId, subject, content, createTime, updateTime) values(#{userId}, #{subject}, #{content}, now(), now())") int save(Mail mail); @Insert("insert into t_mail_to(mailId, toUser, status) values(#{mailId}, #{toUser}, #{status})") int saveToUser(@Param("mailId") Long mailId, @Param("toUser") String toUser, @Param("status") int status); @Select("select t.* from t_mail_to t where t.mailId = #{mailId}") List getToUsers(Long mailId); int count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/MailDao.xml ================================================ and t.subject like concat('%', #{params.subject}, '%') and t.createTime >= #{params.beginTime} and DATE(t.createTime) <= #{params.endTime} ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/NoticeDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.dto.NoticeReadVO; import com.open.capacity.security.model.Notice; import com.open.capacity.security.model.SysUser; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @Mapper public interface NoticeDao { @Select("select * from t_notice t where t.id = #{id}") Notice getById(Long id); @Delete("delete from t_notice where id = #{id}") int delete(Long id); @Update("update t_notice t set title = #{title}, content = #{content}, status = #{status}, updateTime = #{updateTime} where t.id = #{id}") int update(Notice notice); @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into t_notice(title, content, status, createTime, updateTime) values(#{title}, #{content}, #{status}, #{createTime}, #{updateTime})") int save(Notice notice); int count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); @Insert("insert ignore into t_notice_read(noticeId, userId, createTime) values(#{noticeId}, #{userId}, now())") int saveReadRecord(@Param("noticeId") Long noticeId, @Param("userId") Long userId); List listReadUsers(Long noticeId); @Select("select count(1) from t_notice t left join t_notice_read r on r.noticeId = t.id and r.userId = #{userId} where t.status = 1 and r.userId is null") int countUnread(Long userId); int countNotice(@Param("params") Map params); List listNotice(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/NoticeDao.xml ================================================ and t.title like concat('%', #{params.title}, '%') and t.status = #{params.status} and t.updateTime >= #{params.beginTime} and DATE(t.updateTime) <= #{params.endTime} t.status = 1 and t.title like concat('%', #{params.title}, '%') and t.updateTime >= #{params.beginTime} and DATE(t.updateTime) <= #{params.endTime} and r.createTime is null and r.createTime is not null ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/PermissionDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.Permission; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Set; @Mapper public interface PermissionDao { @Select("select * from sys_permission t order by t.sort") List listAll(); @Select("select * from sys_permission t where t.type = 1 order by t.sort") List listParents(); @Select("select distinct p.* from sys_permission p inner join sys_role_permission rp on p.id = rp.permissionId inner join sys_role_user ru on ru.roleId = rp.roleId where ru.userId = #{userId} order by p.sort") List listByUserId(Long userId); @Select("select p.* from sys_permission p inner join sys_role_permission rp on p.id = rp.permissionId where rp.roleId = #{roleId} order by p.sort") List listByRoleId(Long roleId); @Select("select * from sys_permission t where t.id = #{id}") Permission getById(Long id); @Insert("insert into sys_permission(parentId, name, css, href, type, permission, sort) values(#{parentId}, #{name}, #{css}, #{href}, #{type}, #{permission}, #{sort})") int save(Permission permission); @Update("update sys_permission t set parentId = #{parentId}, name = #{name}, css = #{css}, href = #{href}, type = #{type}, permission = #{permission}, sort = #{sort} where t.id = #{id}") int update(Permission permission); @Delete("delete from sys_permission where id = #{id}") int delete(Long id); @Delete("delete from sys_permission where parentId = #{id}") int deleteByParentId(Long id); @Delete("delete from sys_role_permission where permissionId = #{permissionId}") int deleteRolePermission(Long permissionId); @Select("select ru.userId from sys_role_permission rp inner join sys_role_user ru on ru.roleId = rp.roleId where rp.permissionId = #{permissionId}") Set listUserIds(Long permissionId); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/RoleDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.Role; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @Mapper public interface RoleDao { @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into sys_role(name, description, createTime, updateTime) values(#{name}, #{description}, now(),now())") int save(Role role); int count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); @Select("select * from sys_role t where t.id = #{id}") Role getById(Long id); @Select("select * from sys_role t where t.name = #{name}") Role getRole(String name); @Update("update sys_role t set t.name = #{name}, t.description = #{description}, updateTime = now() where t.id = #{id}") int update(Role role); @Select("select * from sys_role r inner join sys_role_user ru on r.id = ru.roleId where ru.userId = #{userId}") List listByUserId(Long userId); @Delete("delete from sys_role_permission where roleId = #{roleId}") int deleteRolePermission(Long roleId); int saveRolePermission(@Param("roleId") Long roleId, @Param("permissionIds") List permissionIds); @Delete("delete from sys_role where id = #{id}") int delete(Long id); @Delete("delete from sys_role_user where roleId = #{roleId}") int deleteRoleUser(Long roleId); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/RoleDao.xml ================================================ and t.name like concat('%', #{params.name}, '%') insert into sys_role_permission(roleId, permissionId) values (#{roleId}, #{permissionId}) ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/ServiceDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.Permission; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Set; @Mapper public interface ServiceDao { @Select("select * from sys_services t order by t.sort") List listAll(); @Select("select * from sys_services t where t.type = 1 order by t.sort") List listParents(); @Select("select distinct p.* from sys_services p inner join sys_client_permission rp on p.id = rp.permissionId inner join sys_role_user ru on ru.roleId = rp.roleId where ru.userId = #{userId} order by p.sort") List listByUserId(Long userId); @Select("select p.* from sys_services p inner join sys_client_permission rp on p.id = rp.permissionId where rp.clientId = #{clientId} order by p.sort") List listByClientId(Long clientId); @Select("select * from sys_services t where t.id = #{id}") Permission getById(Long id); @Insert("insert into sys_services(parentId, name, css, href, type, permission, sort) values(#{parentId}, #{name}, #{css}, #{href}, #{type}, #{permission}, #{sort})") int save(Permission permission); @Update("update sys_services t set parentId = #{parentId}, name = #{name}, css = #{css}, href = #{href}, type = #{type}, permission = #{permission}, sort = #{sort} where t.id = #{id}") int update(Permission permission); @Delete("delete from sys_services where id = #{id}") int delete(Long id); @Delete("delete from sys_services where parentId = #{id}") int deleteByParentId(Long id); @Select("select ru.userId from sys_role_permission rp inner join sys_role_user ru on ru.roleId = rp.roleId where rp.permissionId = #{permissionId}") Set listUserIds(Long permissionId); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/SysLogsDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.SysLogs; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; @Mapper public interface SysLogsDao { @Insert("insert into sys_logs(userId, module, flag, remark, createTime) values(#{user.id}, #{module}, #{flag}, #{remark}, now())") int save(SysLogs sysLogs); int count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); @Delete("delete from sys_logs where createTime <= #{time}") int deleteLogs(String time); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/SysLogsDao.xml ================================================ and t.flag = #{params.flag} and u.nickname like concat('%', #{params.nickname}, '%') and t.createTime >= #{params.beginTime} and DATE(t.createTime) <= #{params.endTime} ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/TokenDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.TokenModel; import org.apache.ibatis.annotations.*; @Mapper public interface TokenDao { @Insert("insert into t_token(id, val, expireTime, createTime, updateTime) values (#{id}, #{val}, #{expireTime}, #{createTime}, #{updateTime})") int save(TokenModel model); @Select("select * from t_token t where t.id = #{id}") TokenModel getById(String id); @Update("update t_token t set t.val = #{val}, t.expireTime = #{expireTime}, t.updateTime = #{updateTime} where t.id = #{id}") int update(TokenModel model); @Delete("delete from t_token where id = #{id}") int delete(String id); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/UserDao.java ================================================ package com.open.capacity.security.dao; import com.open.capacity.security.model.SysUser; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @Mapper public interface UserDao { @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into sys_user(username, password, nickname, headImgUrl, phone, telephone, email, birthday, sex, status, createTime, updateTime) values(#{username}, #{password}, #{nickname}, #{headImgUrl}, #{phone}, #{telephone}, #{email}, #{birthday}, #{sex}, #{status}, now(), now())") int save(SysUser user); @Select("select * from sys_user t where t.id = #{id}") SysUser getById(Long id); @Select("select * from sys_user t where t.username = #{username}") SysUser getUser(String username); @Update("update sys_user t set t.password = #{password} where t.id = #{id}") int changePassword(@Param("id") Long id, @Param("password") String password); Integer count(@Param("params") Map params); List list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); @Delete("delete from sys_role_user where userId = #{userId}") int deleteUserRole(Long userId); int saveUserRoles(@Param("userId") Long userId, @Param("roleIds") List roleIds); int update(SysUser user); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dao/UserDao.xml ================================================ and t.username like concat('%', #{params.username}, '%') and t.nickname like concat('%', #{params.nickname}, '%') and t.status = #{params.status} insert into sys_role_user(roleId, userId) values (#{roleId}, #{userId}) update sys_user t username = #{username}, nickname = #{nickname}, headImgUrl = #{headImgUrl}, phone = #{phone}, telephone = #{telephone}, email = #{email}, birthday = #{birthday}, sex = #{sex}, status = #{status}, updateTime = #{updateTime} where t.id = #{id} ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/BeanField.java ================================================ package com.open.capacity.security.dto; import java.io.Serializable; public class BeanField implements Serializable { private static final long serialVersionUID = 4279960350136806659L; private String columnName; private String columnType; private String columnComment; private String columnDefault; private String name; private String type; public String getColumnName() { return columnName; } public void setColumnName(String columnName) { this.columnName = columnName; } public String getColumnType() { return columnType; } public void setColumnType(String columnType) { this.columnType = columnType; } public String getColumnComment() { return columnComment; } public void setColumnComment(String columnComment) { this.columnComment = columnComment; } public String getColumnDefault() { return columnDefault; } public void setColumnDefault(String columnDefault) { this.columnDefault = columnDefault; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/ClientDto.java ================================================ package com.open.capacity.security.dto; import com.open.capacity.security.model.Client; import java.util.List; public class ClientDto extends Client { private static final long serialVersionUID = 1475637288060027265L; private List permissionIds; public List getPermissionIds() { return permissionIds; } public void setPermissionIds(List permissionIds) { this.permissionIds = permissionIds; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/GenerateDetail.java ================================================ package com.open.capacity.security.dto; import java.io.Serializable; import java.util.List; public class GenerateDetail implements Serializable { private static final long serialVersionUID = -164567294469931676L; private String beanName; private List fields; public String getBeanName() { return beanName; } public void setBeanName(String beanName) { this.beanName = beanName; } public List getFields() { return fields; } public void setFields(List fields) { this.fields = fields; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/GenerateInput.java ================================================ package com.open.capacity.security.dto; import java.io.Serializable; import java.util.List; public class GenerateInput implements Serializable { private static final long serialVersionUID = -2870071259702969061L; /** * 保存路径 */ private String path; private String tableName; /** * bean包名 */ private String beanPackageName; /** * java类名 */ private String beanName; /** * dao包名 */ private String daoPackageName; /** * dao类名 */ private String daoName; /** * controller包名 */ private String controllerPkgName; /** * controller类名 */ private String controllerName; /** * 字段名 */ private List columnNames; /** * 属性名 */ private List beanFieldName; /** * 成员变量类型 */ private List beanFieldType; /** * 默认值 */ private List beanFieldValue; public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public String getBeanPackageName() { return beanPackageName; } public void setBeanPackageName(String beanPackageName) { this.beanPackageName = beanPackageName; } public String getBeanName() { return beanName; } public void setBeanName(String beanName) { this.beanName = beanName; } public String getDaoPackageName() { return daoPackageName; } public void setDaoPackageName(String daoPackageName) { this.daoPackageName = daoPackageName; } public String getDaoName() { return daoName; } public void setDaoName(String daoName) { this.daoName = daoName; } public String getControllerPkgName() { return controllerPkgName; } public void setControllerPkgName(String controllerPkgName) { this.controllerPkgName = controllerPkgName; } public String getControllerName() { return controllerName; } public void setControllerName(String controllerName) { this.controllerName = controllerName; } public List getColumnNames() { return columnNames; } public void setColumnNames(List columnNames) { this.columnNames = columnNames; } public List getBeanFieldName() { return beanFieldName; } public void setBeanFieldName(List beanFieldName) { this.beanFieldName = beanFieldName; } public List getBeanFieldType() { return beanFieldType; } public void setBeanFieldType(List beanFieldType) { this.beanFieldType = beanFieldType; } public List getBeanFieldValue() { return beanFieldValue; } public void setBeanFieldValue(List beanFieldValue) { this.beanFieldValue = beanFieldValue; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/LayuiFile.java ================================================ package com.open.capacity.security.dto; import java.io.Serializable; public class LayuiFile implements Serializable { private static final long serialVersionUID = 35435494737590569L; private Integer code; private String msg; private LayuiFileData data; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public LayuiFileData getData() { return data; } public void setData(LayuiFileData data) { this.data = data; } public static class LayuiFileData implements Serializable { private static final long serialVersionUID = 7907356434695924597L; private String src; private String title; public String getSrc() { return src; } public void setSrc(String src) { this.src = src; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/LoginUser.java ================================================ package com.open.capacity.security.dto; import com.fasterxml.jackson.annotation.JsonIgnore; import com.open.capacity.security.model.Permission; import com.open.capacity.security.model.SysUser; import org.apache.commons.lang3.StringUtils; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; public class LoginUser extends SysUser implements UserDetails { private static final long serialVersionUID = -1379274258881257107L; private List permissions; private String jwtToken; private String token; /** * 登陆时间戳(毫秒) */ private Long loginTime; /** * 过期时间戳 */ private Long expireTime; public List getPermissions() { return permissions; } public void setPermissions(List permissions) { this.permissions = permissions; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } @Override @JsonIgnore public Collection getAuthorities() { List auths = new ArrayList(); for (Iterator it = permissions.iterator(); it.hasNext(); ) { Permission p = it.next(); if (!StringUtils.isEmpty(p.getPermission())) { auths.add(new SimpleGrantedAuthority(p.getPermission())); } } return auths; // return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission())) // .map(p -> new SimpleGrantedAuthority(p.getPermission())).collect(Collectors.toSet()); } public void setAuthorities(Collection authorities) { // do nothing } // 账户是否未过期 @JsonIgnore @Override public boolean isAccountNonExpired() { return true; } // 账户是否未锁定 @JsonIgnore @Override public boolean isAccountNonLocked() { return getStatus() != Status.LOCKED; } // 密码是否未过期 @JsonIgnore @Override public boolean isCredentialsNonExpired() { return true; } // 账户是否激活 @JsonIgnore @Override public boolean isEnabled() { return true; } public Long getLoginTime() { return loginTime; } public void setLoginTime(Long loginTime) { this.loginTime = loginTime; } public Long getExpireTime() { return expireTime; } public void setExpireTime(Long expireTime) { this.expireTime = expireTime; } @JsonIgnore public String getJwtToken() { return jwtToken; } public void setJwtToken(String jwtToken) { this.jwtToken = jwtToken; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/NoticeReadVO.java ================================================ package com.open.capacity.security.dto; import com.open.capacity.security.model.Notice; import java.util.Date; public class NoticeReadVO extends Notice { private static final long serialVersionUID = -3842182350180882396L; private Long userId; private Date readTime; private Boolean isRead; public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public Date getReadTime() { return readTime; } public void setReadTime(Date readTime) { this.readTime = readTime; } public Boolean getIsRead() { return isRead; } public void setIsRead(Boolean isRead) { this.isRead = isRead; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/NoticeVO.java ================================================ package com.open.capacity.security.dto; import com.open.capacity.security.model.Notice; import com.open.capacity.security.model.SysUser; import java.io.Serializable; import java.util.List; public class NoticeVO implements Serializable { private static final long serialVersionUID = 7363353918096951799L; private Notice notice; private List users; public Notice getNotice() { return notice; } public void setNotice(Notice notice) { this.notice = notice; } public List getUsers() { return users; } public void setUsers(List users) { this.users = users; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/ResponseInfo.java ================================================ package com.open.capacity.security.dto; import java.io.Serializable; public class ResponseInfo implements Serializable { private static final long serialVersionUID = -4417715614021482064L; private String code; private String message; public ResponseInfo(String code, String message) { super(); this.code = code; this.message = message; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/RoleDto.java ================================================ package com.open.capacity.security.dto; import com.open.capacity.security.model.Role; import java.util.List; public class RoleDto extends Role { private static final long serialVersionUID = 4218495592167610193L; private List permissionIds; public List getPermissionIds() { return permissionIds; } public void setPermissionIds(List permissionIds) { this.permissionIds = permissionIds; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/Token.java ================================================ package com.open.capacity.security.dto; import java.io.Serializable; /** * Restful方式登陆token * * @author owen 624191343@qq.com *

    * 2017年8月4日 */ public class Token implements Serializable { private static final long serialVersionUID = 6314027741784310221L; private String token; /** * 登陆时间戳(毫秒) */ private Long loginTime; public Token(String token, Long loginTime) { super(); this.token = token; this.loginTime = loginTime; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public Long getLoginTime() { return loginTime; } public void setLoginTime(Long loginTime) { this.loginTime = loginTime; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/dto/UserDto.java ================================================ package com.open.capacity.security.dto; import com.open.capacity.security.model.SysUser; import java.util.List; public class UserDto extends SysUser { private static final long serialVersionUID = -184009306207076712L; private List roleIds; public List getRoleIds() { return roleIds; } public void setRoleIds(List roleIds) { this.roleIds = roleIds; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/filter/TokenFilter.java ================================================ package com.open.capacity.security.filter; import com.open.capacity.security.dto.LoginUser; import com.open.capacity.security.service.TokenService; import org.apache.commons.lang3.StringUtils; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Token过滤器 * * @author owen 624191343@qq.com *

    * 2017年10月14日 */ public class TokenFilter extends OncePerRequestFilter { private static final String TOKEN_KEY = "access_token"; private static final Long MINUTES_10 = 10 * 60 * 1000L; private TokenService tokenService; private UserDetailsService userDetailsService; /** * 根据参数或者header获取token * * @param request * @return */ public static String getToken(HttpServletRequest request) { String token = request.getParameter(TOKEN_KEY); if (StringUtils.isBlank(token)) { token = request.getHeader(TOKEN_KEY); } return token; } public TokenService getTokenService() { return tokenService; } public void setTokenService(TokenService tokenService) { this.tokenService = tokenService; } public UserDetailsService getUserDetailsService() { return userDetailsService; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = getToken(request); if (StringUtils.isNotBlank(token)) { LoginUser loginUser = tokenService.getLoginUser(token); if (loginUser != null) { loginUser = checkLoginTime(loginUser); UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); } } filterChain.doFilter(request, response); } /** * 校验时间
    * 过期时间与当前时间对比,临近过期10分钟内的话,自动刷新缓存 * * @param loginUser * @return */ private LoginUser checkLoginTime(LoginUser loginUser) { long expireTime = loginUser.getExpireTime(); long currentTime = System.currentTimeMillis(); if (expireTime - currentTime <= MINUTES_10) { String token = loginUser.getToken(); loginUser = (LoginUser) userDetailsService.loadUserByUsername(loginUser.getUsername()); loginUser.setToken(token); tokenService.refresh(loginUser); } return loginUser; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/BaseEntity.java ================================================ package com.open.capacity.security.model; import java.io.Serializable; import java.util.Date; public abstract class BaseEntity implements Serializable { private static final long serialVersionUID = 2054813493011812469L; private ID id; private Date createTime = new Date(); private Date updateTime = new Date(); public ID getId() { return id; } public void setId(ID id) { this.id = id; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/Client.java ================================================ package com.open.capacity.security.model; public class Client extends BaseEntity { /** * */ private static final long serialVersionUID = -8185413579135897885L; private Long id; private String clientId; private String resourceIds = ""; private String clientSecret; private String scope = "all"; private String authorizedGrantTypes = "authorization_code,password,refresh_token,client_credentials"; private String webServerRedirectUri; private String authorities = ""; private Integer accessTokenValidity = 18000; private Integer refreshTokenValidity = 18000; private String additionalInformation = "{}"; private String autoapprove = "true"; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getClientId() { return clientId; } public String setClientId() { return clientId; } public String getResourceIds() { return resourceIds; } public String setResourceIds() { return resourceIds; } public String getClientSecret() { return clientSecret; } public String setClientSecret() { return clientSecret; } public String getScope() { return scope; } public String setScope() { return scope; } public String getAuthorizedGrantTypes() { return authorizedGrantTypes; } public String setAuthorizedGrantTypes() { return authorizedGrantTypes; } public String getWebServerRedirectUri() { return webServerRedirectUri; } public String setWebServerRedirectUri() { return webServerRedirectUri; } public String getAuthorities() { return authorities; } public String setAuthorities() { return authorities; } public Integer getAccessTokenValidity() { return accessTokenValidity; } public Integer setAccessTokenValidity() { return accessTokenValidity; } public Integer getRefreshTokenValidity() { return refreshTokenValidity; } public Integer setRefreshTokenValidity() { return refreshTokenValidity; } public String getAdditionalInformation() { return additionalInformation; } public String setAdditionalInformation() { return additionalInformation; } public String getAutoapprove() { return autoapprove; } public String setAutoapprove() { return autoapprove; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/Dict.java ================================================ package com.open.capacity.security.model; public class Dict extends BaseEntity { private static final long serialVersionUID = -2431140186410912787L; private String type; private String k; private String val; public String getType() { return type; } public String setType() { return type; } public String getK() { return k; } public String setK() { return k; } public String getVal() { return val; } public String setVal() { return val; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/FileInfo.java ================================================ package com.open.capacity.security.model; public class FileInfo extends BaseEntity { private static final long serialVersionUID = -5761547882766615438L; private String contentType; private long size; private String path; private String url; private Integer type; public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/Mail.java ================================================ package com.open.capacity.security.model; public class Mail extends BaseEntity { private static final long serialVersionUID = 5613231124043303948L; private Long userId; private String toUsers; private String subject; private String content; public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public String getToUsers() { return toUsers; } public void setToUsers(String toUsers) { this.toUsers = toUsers; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/MailTo.java ================================================ package com.open.capacity.security.model; public class MailTo extends BaseEntity { private static final long serialVersionUID = -8238779033956731073L; private Long mailId; private String toUser; private Boolean status; public Long getMailId() { return mailId; } public void setMailId(Long mailId) { this.mailId = mailId; } public String getToUser() { return toUser; } public void setToUser(String toUser) { this.toUser = toUser; } public Boolean getStatus() { return status; } public void setStatus(Boolean status) { this.status = status; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/Notice.java ================================================ package com.open.capacity.security.model; public class Notice extends BaseEntity { private static final long serialVersionUID = -4401913568806243090L; private String title; private String content; private Integer status; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public interface Status { int DRAFT = 0; int PUBLISH = 1; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/Permission.java ================================================ package com.open.capacity.security.model; import java.util.List; public class Permission extends BaseEntity { private static final long serialVersionUID = 6180869216498363919L; private Long parentId; private String name; private String css; private String href; private Integer type; private String permission; private Integer sort; private List child; public Long getParentId() { return parentId; } public void setParentId(Long parentId) { this.parentId = parentId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCss() { return css; } public void setCss(String css) { this.css = css; } public String getHref() { return href; } public void setHref(String href) { this.href = href; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public String getPermission() { return permission; } public void setPermission(String permission) { this.permission = permission; } public Integer getSort() { return sort; } public void setSort(Integer sort) { this.sort = sort; } public List getChild() { return child; } public void setChild(List child) { this.child = child; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/Role.java ================================================ package com.open.capacity.security.model; public class Role extends BaseEntity { private static final long serialVersionUID = -3802292814767103648L; private String name; private String description; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/SysLogs.java ================================================ package com.open.capacity.security.model; public class SysLogs extends BaseEntity { private static final long serialVersionUID = -7809315432127036583L; private SysUser user; private String module; private Boolean flag; private String remark; public SysUser getUser() { return user; } public void setUser(SysUser user) { this.user = user; } public String getModule() { return module; } public void setModule(String module) { this.module = module; } public Boolean getFlag() { return flag; } public void setFlag(Boolean flag) { this.flag = flag; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/SysUser.java ================================================ package com.open.capacity.security.model; import com.fasterxml.jackson.annotation.JsonFormat; import java.util.Date; public class SysUser extends BaseEntity { private static final long serialVersionUID = -6525908145032868837L; private String username; private String password; private String nickname; private String headImgUrl; private String phone; private String telephone; private String email; @JsonFormat(pattern = "yyyy-MM-dd") private Date birthday; private Integer sex; private Integer status; private String intro; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getHeadImgUrl() { return headImgUrl; } public void setHeadImgUrl(String headImgUrl) { this.headImgUrl = headImgUrl; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getIntro() { return intro; } public void setIntro(String intro) { this.intro = intro; } public interface Status { int DISABLED = 0; int VALID = 1; int LOCKED = 2; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/model/TokenModel.java ================================================ package com.open.capacity.security.model; import java.util.Date; public class TokenModel extends BaseEntity { private static final long serialVersionUID = 4566334160572911795L; /** * 过期时间 */ private Date expireTime; /** * LoginUser的json串 */ private String val; public Date getExpireTime() { return expireTime; } public void setExpireTime(Date expireTime) { this.expireTime = expireTime; } public String getVal() { return val; } public void setVal(String val) { this.val = val; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableArgumentResolver.java ================================================ package com.open.capacity.security.page.table; import com.google.common.collect.Maps; import org.apache.commons.lang3.StringUtils; import org.springframework.core.MethodParameter; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import javax.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * 分页、查询参数解析 * * @author 624191343@qq.com */ public class PageTableArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { Class cla = parameter.getParameterType(); return cla.isAssignableFrom(PageTableRequest.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); PageTableRequest tableRequest = new PageTableRequest(); Map param = request.getParameterMap(); if (param.containsKey("start")) { tableRequest.setOffset(Integer.parseInt(request.getParameter("start"))); } if (param.containsKey("length")) { tableRequest.setLimit(Integer.parseInt(request.getParameter("length"))); } Map map = Maps.newHashMap(); tableRequest.setParams(map); param.forEach((k, v) -> { if (v.length == 1) { map.put(k, v[0]); } else { map.put(k, Arrays.asList(v)); } }); setOrderBy(tableRequest, map); removeParam(tableRequest); return tableRequest; } /** * 去除datatables分页带的一些复杂参数 * * @param tableRequest */ private void removeParam(PageTableRequest tableRequest) { Map map = tableRequest.getParams(); if (!CollectionUtils.isEmpty(map)) { Map param = new HashMap<>(); map.forEach((k, v) -> { if (k.indexOf("[") < 0 && k.indexOf("]") < 0 && !"_".equals(k)) { param.put(k, v); } }); tableRequest.setParams(param); } } /** * 从datatables分页请求数据中解析排序 * * @param tableRequest * @param map */ private void setOrderBy(PageTableRequest tableRequest, Map map) { StringBuilder orderBy = new StringBuilder(); int size = map.size(); for (int i = 0; i < size; i++) { String index = (String) map.get("order[" + i + "][column]"); if (StringUtils.isEmpty(index)) { break; } String column = (String) map.get("columns[" + index + "][data]"); if (StringUtils.isBlank(column)) { continue; } String sort = (String) map.get("order[" + i + "][dir]"); orderBy.append(column).append(" ").append(sort).append(", "); } if (orderBy.length() > 0) { tableRequest.getParams().put("orderBy", " order by " + StringUtils.substringBeforeLast(orderBy.toString(), ",")); } } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableHandler.java ================================================ package com.open.capacity.security.page.table; import java.util.ArrayList; import java.util.List; /** * 分页查询处理器 * * @author 624191343@qq.com */ public class PageTableHandler { private CountHandler countHandler; private ListHandler listHandler; private OrderHandler orderHandler; public PageTableHandler(CountHandler countHandler, ListHandler listHandler) { super(); this.countHandler = countHandler; this.listHandler = listHandler; } public PageTableHandler(CountHandler countHandler, ListHandler listHandler, OrderHandler orderHandler) { this(countHandler, listHandler); this.orderHandler = orderHandler; } public PageTableResponse handle(PageTableRequest dtRequest) { int count = 0; List list = null; count = this.countHandler.count(dtRequest); if (count > 0) { if (orderHandler != null) { dtRequest = orderHandler.order(dtRequest); } list = this.listHandler.list(dtRequest); } if (list == null) { list = new ArrayList<>(); } return new PageTableResponse(count, count, list); } public interface ListHandler { List list(PageTableRequest request); } public interface CountHandler { int count(PageTableRequest request); } public interface OrderHandler { PageTableRequest order(PageTableRequest request); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableRequest.java ================================================ package com.open.capacity.security.page.table; import java.io.Serializable; import java.util.Map; /** * 分页查询参数 * * @author 624191343@qq.com */ public class PageTableRequest implements Serializable { private static final long serialVersionUID = 7328071045193618467L; private Integer offset; private Integer limit; private Map params; public Integer getOffset() { return offset; } public void setOffset(Integer offset) { this.offset = offset; } public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } public Map getParams() { return params; } public void setParams(Map params) { this.params = params; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/page/table/PageTableResponse.java ================================================ package com.open.capacity.security.page.table; import java.io.Serializable; import java.util.List; /** * 分页查询返回 * * @author 624191343@qq.com */ public class PageTableResponse implements Serializable { private static final long serialVersionUID = 620421858510718076L; private Integer recordsTotal; private Integer recordsFiltered; private List data; public PageTableResponse(Integer recordsTotal, Integer recordsFiltered, List data) { super(); this.recordsTotal = recordsTotal; this.recordsFiltered = recordsFiltered; this.data = data; } public Integer getRecordsTotal() { return recordsTotal; } public void setRecordsTotal(Integer recordsTotal) { this.recordsTotal = recordsTotal; } public Integer getRecordsFiltered() { return recordsFiltered; } public void setRecordsFiltered(Integer recordsFiltered) { this.recordsFiltered = recordsFiltered; } public List getData() { return data; } public void setData(List data) { this.data = data; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/ClientService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.dto.ClientDto; public interface ClientService { void saveClient(ClientDto clientDto); void deleteClient(Long id); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/FileService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.model.FileInfo; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; public interface FileService { FileInfo save(MultipartFile file) throws IOException; void delete(String id); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/GenerateService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.dto.BeanField; import com.open.capacity.security.dto.GenerateInput; import java.util.List; public interface GenerateService { /** * 获取数据库表信息 * * @param tableName * @return */ List listBeanField(String tableName); /** * 转成驼峰并大写第一个字母 * * @param string * @return */ String upperFirstChar(String string); /** * 生成代码 * * @param input */ void saveCode(GenerateInput input); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/MailService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.model.Mail; import java.util.List; public interface MailService { void save(Mail mail, List toUser); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/MicroServiceService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.model.Permission; public interface MicroServiceService { void save(Permission permission); void update(Permission permission); void delete(Long id); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/PermissionService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.model.Permission; public interface PermissionService { void save(Permission permission); void update(Permission permission); void delete(Long id); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/RoleService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.dto.RoleDto; public interface RoleService { void saveRole(RoleDto roleDto); void deleteRole(Long id); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/SendMailSevice.java ================================================ package com.open.capacity.security.service; import javax.mail.MessagingException; import java.util.List; public interface SendMailSevice { /** * @param toUser * @param subject 标题 * @param text 内容(支持html格式) */ void sendMail(List toUser, String subject, String text); void sendMail(String toUser, String subject, String text) throws MessagingException; } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/SysLogService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.model.SysLogs; /** * 日志service * * @author 624191343@qq.com *

    * 2017年8月19日 */ public interface SysLogService { void save(SysLogs sysLogs); void save(Long userId, String module, Boolean flag, String remark); void deleteLogs(); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/TokenService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.dto.LoginUser; import com.open.capacity.security.dto.Token; /** * Token管理器
    * 可存储到redis或者数据库
    * 具体可看实现类
    * 默认基于redis,实现类为 com.boot.security.server.service.impl.TokenServiceJWTImpl
    * 如要换成数据库存储,将TokenServiceImpl类上的注解@Primary挪到com.boot.security.server.service.impl.TokenServiceDbImpl * * @author 624191343@qq.com *

    * 2017年10月14日 */ public interface TokenService { Token saveToken(LoginUser loginUser); void refresh(LoginUser loginUser); LoginUser getLoginUser(String token); boolean deleteToken(String token); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/UserService.java ================================================ package com.open.capacity.security.service; import com.open.capacity.security.dto.UserDto; import com.open.capacity.security.model.SysUser; public interface UserService { SysUser saveUser(UserDto userDto); SysUser updateUser(UserDto userDto); SysUser getUser(String username); void changePassword(String username, String oldPassword, String newPassword); } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/ClientServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.alibaba.fastjson.JSONObject; import com.open.capacity.security.dao.ClientDao; import com.open.capacity.security.dto.ClientDto; import com.open.capacity.security.model.Client; import com.open.capacity.security.service.ClientService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.List; @Service public class ClientServiceImpl implements ClientService { private static final Logger log = LoggerFactory.getLogger(ClientServiceImpl.class); /** * 缓存client的redis key,这里是hash结构存储 */ private static final String CACHE_CLIENT_KEY = "oauth_client_details"; @Autowired private ClientDao clientDao; @Autowired private RedisTemplate redisTemplate; @Override @Transactional public void saveClient(ClientDto clientDto) { Client client = clientDto; List permissionIds = clientDto.getPermissionIds(); permissionIds.remove(0L); if (client.getId() != null) {// 修改 updateClient(client, permissionIds); } else {// 新增 saveClient(client, permissionIds); } } private void saveClient(Client client, List permissionIds) { Client r = clientDao.getClient(client.getClientId()); if (r != null) { throw new IllegalArgumentException(client.getClientId() + "已存在"); } clientDao.save(client); if (!CollectionUtils.isEmpty(permissionIds)) { clientDao.saveClientPermission(client.getId(), permissionIds); } log.debug("新增应用{}", client.getClientId()); } private void updateClient(Client client, List permissionIds) { // Client r = clientDao.getClient(client.getClientId()); // if (r != null && r.getId() != client.getId()) { // throw new IllegalArgumentException(client.getClientId() + "已存在"); // } clientDao.update(client); clientDao.deleteClientPermission(client.getId()); if (!CollectionUtils.isEmpty(permissionIds)) { clientDao.saveClientPermission(client.getId(), permissionIds); } String clientId = clientDao.getById(client.getId()).getClientId(); BaseClientDetails clientDetails = null; // 先从redis获取 try { String value = (String) redisTemplate.boundHashOps(CACHE_CLIENT_KEY).get(clientId); clientDetails = JSONObject.parseObject(value, BaseClientDetails.class); clientDetails.setClientSecret(client.getClientSecret()); redisTemplate.boundHashOps(CACHE_CLIENT_KEY).put(clientId, JSONObject.toJSONString(clientDetails)); } catch (Exception e) { } log.debug("修改应用{}", client.getClientId()); } @Override @Transactional public void deleteClient(Long id) { clientDao.deleteClientPermission(id); clientDao.delete(id); log.debug("删除应用id:{}", id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/FileServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.FileInfoDao; import com.open.capacity.security.model.FileInfo; import com.open.capacity.security.service.FileService; import com.open.capacity.security.utils.FileUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @Service public class FileServiceImpl implements FileService { private static final Logger log = LoggerFactory.getLogger(FileServiceImpl.class); @Value("${files.path}") private String filesPath; @Autowired private FileInfoDao fileInfoDao; @Override public FileInfo save(MultipartFile file) throws IOException { String fileOrigName = file.getOriginalFilename(); if (!fileOrigName.contains(".")) { throw new IllegalArgumentException("缺少后缀名"); } String md5 = FileUtil.fileMd5(file.getInputStream()); FileInfo fileInfo = fileInfoDao.getById(md5); fileOrigName = fileOrigName.substring(fileOrigName.lastIndexOf(".")); String pathname = FileUtil.getPath() + md5 + fileOrigName; String fullPath = filesPath + pathname; FileUtil.saveFile(file, fullPath); if (fileInfo != null) { fileInfo.setPath(fullPath); fileInfo.setUrl(pathname); fileInfoDao.update(fileInfo); return fileInfo; } long size = file.getSize(); String contentType = file.getContentType(); fileInfo = new FileInfo(); fileInfo.setId(md5); fileInfo.setContentType(contentType); fileInfo.setSize(size); fileInfo.setPath(fullPath); fileInfo.setUrl(pathname); fileInfo.setType(contentType.startsWith("image/") ? 1 : 0); fileInfoDao.save(fileInfo); log.debug("上传文件{}", fullPath); return fileInfo; } @Override public void delete(String id) { FileInfo fileInfo = fileInfoDao.getById(id); if (fileInfo != null) { String fullPath = fileInfo.getPath(); FileUtil.deleteFile(fullPath); fileInfoDao.delete(id); log.debug("删除文件:{}", fileInfo.getPath()); } } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/GenerateServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.google.common.collect.Maps; import com.open.capacity.security.dto.BeanField; import com.open.capacity.security.dto.GenerateInput; import com.open.capacity.security.service.GenerateService; import com.open.capacity.security.utils.StrUtil; import com.open.capacity.security.utils.TemplateUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Date; import java.util.List; import java.util.Map; @Service public class GenerateServiceImpl implements GenerateService { /** * mysql类型与java类型部分对应关系 */ private static Map map = Maps.newHashMap(); static { map.put("int", Integer.class.getSimpleName()); map.put("tinyint", Integer.class.getSimpleName()); map.put("double", Double.class.getSimpleName()); map.put("float", Float.class.getSimpleName()); map.put("decimal", BigDecimal.class.getSimpleName()); map.put("date", Date.class.getSimpleName()); map.put("timestamp", Date.class.getSimpleName()); map.put("datetime", Date.class.getSimpleName()); map.put("varchar", String.class.getSimpleName()); map.put("text", String.class.getSimpleName()); map.put("longtext", String.class.getSimpleName()); } @Autowired private JdbcTemplate jdbcTemplate; private RowMapper beanFieldMapper = new RowMapper() { @Override public BeanField mapRow(ResultSet rs, int paramInt) throws SQLException { BeanField beanField = new BeanField(); beanField.setColumnName(rs.getString("column_name")); beanField.setColumnType(rs.getString("data_type")); beanField.setColumnComment(rs.getString("column_comment")); beanField.setColumnDefault(rs.getString("column_default")); return beanField; } }; @Override public List listBeanField(String tableName) { List beanFields = jdbcTemplate.query( "select column_name, data_type, column_comment, column_default FROM information_schema.columns WHERE table_name= ? and table_schema = (select database())", new String[]{tableName}, beanFieldMapper); if (CollectionUtils.isEmpty(beanFields)) { throw new IllegalArgumentException("表" + tableName + "不存在"); } beanFields.parallelStream().forEach(b -> { b.setName(StrUtil.str2hump(b.getColumnName())); String type = map.get(b.getColumnType()); if (type == null) { type = String.class.getSimpleName(); } b.setType(type); if ("id".equals(b.getName())) { b.setType(Long.class.getSimpleName()); } b.setColumnDefault(b.getColumnDefault() == null ? "" : b.getColumnDefault()); }); return beanFields; } @Override public String upperFirstChar(String string) { String name = StrUtil.str2hump(string); String firstChar = name.substring(0, 1); name = name.replaceFirst(firstChar, firstChar.toUpperCase()); return name; } @Override public void saveCode(GenerateInput input) { TemplateUtil.saveJava(input); TemplateUtil.saveJavaDao(input); TemplateUtil.saveController(input); TemplateUtil.saveHtmlList(input); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/MailServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.MailDao; import com.open.capacity.security.model.Mail; import com.open.capacity.security.service.MailService; import com.open.capacity.security.service.SendMailSevice; import com.open.capacity.security.utils.UserUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service public class MailServiceImpl implements MailService { private static final Logger log = LoggerFactory.getLogger(MailServiceImpl.class); @Autowired private SendMailSevice sendMailSevice; @Autowired private MailDao mailDao; @Override @Transactional public void save(Mail mail, List toUser) { mail.setUserId(UserUtil.getLoginUser().getId()); mailDao.save(mail); toUser.forEach(u -> { int status = 1; try { sendMailSevice.sendMail(u, mail.getSubject(), mail.getContent()); } catch (Exception e) { log.error("发送邮件失败", e); status = 0; } mailDao.saveToUser(mail.getId(), u, status); }); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/MicroServicesServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.ServiceDao; import com.open.capacity.security.model.Permission; import com.open.capacity.security.service.MicroServiceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class MicroServicesServiceImpl implements MicroServiceService { private static final Logger log = LoggerFactory.getLogger(MicroServicesServiceImpl.class); @Autowired private ServiceDao serviceDao; @Override public void save(Permission permission) { serviceDao.save(permission); log.debug("新增服务{}", permission.getName()); } @Override public void update(Permission permission) { serviceDao.update(permission); } @Override @Transactional public void delete(Long id) { serviceDao.delete(id); serviceDao.deleteByParentId(id); log.debug("删除菜单id:{}", id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/PermissionServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.PermissionDao; import com.open.capacity.security.model.Permission; import com.open.capacity.security.service.PermissionService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class PermissionServiceImpl implements PermissionService { private static final Logger log = LoggerFactory.getLogger(PermissionServiceImpl.class); @Autowired private PermissionDao permissionDao; @Override public void save(Permission permission) { permissionDao.save(permission); log.debug("新增菜单{}", permission.getName()); } @Override public void update(Permission permission) { permissionDao.update(permission); } @Override @Transactional public void delete(Long id) { permissionDao.deleteRolePermission(id); permissionDao.delete(id); permissionDao.deleteByParentId(id); log.debug("删除菜单id:{}", id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/RoleServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.RoleDao; import com.open.capacity.security.dto.RoleDto; import com.open.capacity.security.model.Role; import com.open.capacity.security.service.RoleService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.List; @Service public class RoleServiceImpl implements RoleService { private static final Logger log = LoggerFactory.getLogger(RoleServiceImpl.class); @Autowired private RoleDao roleDao; @Override @Transactional public void saveRole(RoleDto roleDto) { Role role = roleDto; List permissionIds = roleDto.getPermissionIds(); permissionIds.remove(0L); if (role.getId() != null) {// 修改 updateRole(role, permissionIds); } else {// 新增 saveRole(role, permissionIds); } } private void saveRole(Role role, List permissionIds) { Role r = roleDao.getRole(role.getName()); if (r != null) { throw new IllegalArgumentException(role.getName() + "已存在"); } roleDao.save(role); if (!CollectionUtils.isEmpty(permissionIds)) { roleDao.saveRolePermission(role.getId(), permissionIds); } log.debug("新增角色{}", role.getName()); } private void updateRole(Role role, List permissionIds) { Role r = roleDao.getRole(role.getName()); if (r != null && r.getId() != role.getId()) { throw new IllegalArgumentException(role.getName() + "已存在"); } roleDao.update(role); roleDao.deleteRolePermission(role.getId()); if (!CollectionUtils.isEmpty(permissionIds)) { roleDao.saveRolePermission(role.getId(), permissionIds); } log.debug("修改角色{}", role.getName()); } @Override @Transactional public void deleteRole(Long id) { roleDao.deleteRolePermission(id); roleDao.deleteRoleUser(id); roleDao.delete(id); log.debug("删除角色id:{}", id); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/SendMailSeviceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.service.SendMailSevice; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.util.List; @Service public class SendMailSeviceImpl implements SendMailSevice { @Autowired private JavaMailSender javaMailSender; @Value("${spring.mail.username}") private String serverMail; @Override public void sendMail(List toUser, String subject, String text) { MimeMessage message = javaMailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(serverMail); helper.setTo(toUser.toArray(new String[toUser.size()])); helper.setSubject(subject); helper.setText(text, true); javaMailSender.send(message); } catch (MessagingException e) { e.printStackTrace(); } } @Override public void sendMail(String toUser, String subject, String text) throws MessagingException { MimeMessage message = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(serverMail); helper.setTo(toUser); helper.setSubject(subject); helper.setText(text, true); javaMailSender.send(message); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/SysLogServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.SysLogsDao; import com.open.capacity.security.model.SysLogs; import com.open.capacity.security.model.SysUser; import com.open.capacity.security.service.SysLogService; import com.open.capacity.security.utils.UserUtil; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.Date; @Service public class SysLogServiceImpl implements SysLogService { private static final Logger log = LoggerFactory.getLogger(SysLogServiceImpl.class); @Autowired private SysLogsDao sysLogsDao; @Override public void save(SysLogs sysLogs) { SysUser user = UserUtil.getLoginUser(); if (user == null || user.getId() == null) { return; } sysLogs.setUser(user); sysLogsDao.save(sysLogs); } @Async @Override public void save(Long userId, String module, Boolean flag, String remark) { SysLogs sysLogs = new SysLogs(); sysLogs.setFlag(flag); sysLogs.setModule(module); sysLogs.setRemark(remark); SysUser user = new SysUser(); user.setId(userId); sysLogs.setUser(user); sysLogsDao.save(sysLogs); } @Override public void deleteLogs() { Date date = DateUtils.addMonths(new Date(), -3); String time = DateFormatUtils.format(date, DateFormatUtils.ISO_8601_EXTENDED_DATE_FORMAT.getPattern()); int n = sysLogsDao.deleteLogs(time); log.info("删除{}之前日志{}条", time, n); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/TokenServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dto.LoginUser; import com.open.capacity.security.dto.Token; import com.open.capacity.security.service.SysLogService; import com.open.capacity.security.service.TokenService; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import java.security.Key; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; /** * token存到redis的实现类
    * jwt实现的token * * @author owen 624191343@qq.com */ @Primary @Service public class TokenServiceImpl implements TokenService { private static final Logger log = LoggerFactory.getLogger(TokenServiceImpl.class); private static final String LOGIN_USER_KEY = "LOGIN_USER_KEY"; private static Key KEY = null; /** * token过期秒数 */ @Value("${token.expire.seconds}") private Integer expireSeconds; @Autowired private RedisTemplate redisTemplate; @Autowired private SysLogService logService; /** * 私钥 */ @Value("${token.jwtSecret}") private String jwtSecret; @Override public Token saveToken(LoginUser loginUser) { loginUser.setToken(UUID.randomUUID().toString()); String jwtToken = createJWTToken(loginUser); loginUser.setJwtToken(jwtToken); cacheLoginUser(loginUser); // 登陆日志 logService.save(loginUser.getId(), "登陆", true, null); return new Token(jwtToken, loginUser.getLoginTime()); } /** * 生成jwt * * @param loginUser * @return */ private String createJWTToken(LoginUser loginUser) { Map claims = new HashMap<>(); claims.put(LOGIN_USER_KEY, loginUser.getToken());// 放入一个随机字符串,通过该串可找到登陆用户 String jwtToken = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, getKeyInstance()) .compact(); return jwtToken; } private void cacheLoginUser(LoginUser loginUser) { loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setExpireTime(loginUser.getLoginTime() + expireSeconds * 1000); // 根据uuid将loginUser缓存 redisTemplate.boundValueOps(getTokenKey(loginUser.getToken())).set(loginUser, expireSeconds, TimeUnit.SECONDS); } /** * 更新缓存的用户信息 */ @Override public void refresh(LoginUser loginUser) { cacheLoginUser(loginUser); } @Override public LoginUser getLoginUser(String jwtToken) { String uuid = getUUIDFromJWT(jwtToken); if (uuid != null) { return (LoginUser) redisTemplate.boundValueOps(getTokenKey(uuid)).get(); } return null; } @Override public boolean deleteToken(String jwtToken) { String uuid = getUUIDFromJWT(jwtToken); if (uuid != null) { String key = getTokenKey(uuid); LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get(key); if (loginUser != null) { redisTemplate.delete(key); // 退出日志 logService.save(loginUser.getId(), "退出", true, null); return true; } } return false; } private String getTokenKey(String uuid) { return "tokens:" + uuid; } private Key getKeyInstance() { if (KEY == null) { synchronized (TokenServiceImpl.class) { if (KEY == null) {// 双重锁 byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(jwtSecret); KEY = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName()); } } } return KEY; } private String getUUIDFromJWT(String jwtToken) { if ("null".equals(jwtToken) || StringUtils.isBlank(jwtToken)) { return null; } Map jwtClaims = null; try { jwtClaims = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwtToken).getBody(); return MapUtils.getString(jwtClaims, LOGIN_USER_KEY); } catch (ExpiredJwtException e) { log.error("{}已过期", jwtToken); } catch (Exception e) { log.error("{}", e); } return null; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/UserDetailsServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.PermissionDao; import com.open.capacity.security.dto.LoginUser; import com.open.capacity.security.model.Permission; import com.open.capacity.security.model.SysUser; import com.open.capacity.security.model.SysUser.Status; import com.open.capacity.security.service.UserService; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.List; /** * spring security登陆处理 * * @author owen 624191343@qq.com */ @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserService userService; @Autowired private PermissionDao permissionDao; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { SysUser sysUser = userService.getUser(username); if (sysUser == null) { throw new AuthenticationCredentialsNotFoundException("用户名不存在"); } else if (sysUser.getStatus() == Status.LOCKED) { throw new LockedException("用户被锁定,请联系管理员"); } else if (sysUser.getStatus() == Status.DISABLED) { throw new DisabledException("用户已作废"); } LoginUser loginUser = new LoginUser(); BeanUtils.copyProperties(sysUser, loginUser); List permissions = permissionDao.listByUserId(sysUser.getId()); loginUser.setPermissions(permissions); return loginUser; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/service/impl/UserServiceImpl.java ================================================ package com.open.capacity.security.service.impl; import com.open.capacity.security.dao.UserDao; import com.open.capacity.security.dto.UserDto; import com.open.capacity.security.model.SysUser; import com.open.capacity.security.model.SysUser.Status; import com.open.capacity.security.service.UserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.List; @Service public class UserServiceImpl implements UserService { private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class); @Autowired private UserDao userDao; @Autowired private BCryptPasswordEncoder passwordEncoder; @Override @Transactional public SysUser saveUser(UserDto userDto) { SysUser user = userDto; user.setPassword(passwordEncoder.encode(user.getPassword())); user.setStatus(Status.VALID); userDao.save(user); saveUserRoles(user.getId(), userDto.getRoleIds()); log.debug("新增用户{}", user.getUsername()); return user; } private void saveUserRoles(Long userId, List roleIds) { if (roleIds != null) { userDao.deleteUserRole(userId); if (!CollectionUtils.isEmpty(roleIds)) { userDao.saveUserRoles(userId, roleIds); } } } @Override public SysUser getUser(String username) { return userDao.getUser(username); } @Override public void changePassword(String username, String oldPassword, String newPassword) { SysUser u = userDao.getUser(username); if (u == null) { throw new IllegalArgumentException("用户不存在"); } if (!passwordEncoder.matches(oldPassword, u.getPassword())) { throw new IllegalArgumentException("旧密码错误"); } userDao.changePassword(u.getId(), passwordEncoder.encode(newPassword)); log.debug("修改{}的密码", username); } @Override @Transactional public SysUser updateUser(UserDto userDto) { userDao.update(userDto); saveUserRoles(userDto.getId(), userDto.getRoleIds()); return userDto; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/utils/ExcelUtil.java ================================================ package com.open.capacity.security.utils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.List; /** * excel工具类 * * @author 624191343@qq.com */ public class ExcelUtil { public static void excelLocal(String path, String fileName, String[] headers, List datas) { Workbook workbook = getWorkbook(headers, datas); if (workbook != null) { ByteArrayOutputStream byteArrayOutputStream = null; FileOutputStream fileOutputStream = null; try { byteArrayOutputStream = new ByteArrayOutputStream(); workbook.write(byteArrayOutputStream); String suffix = ".xls"; File file = new File(path + File.separator + fileName + suffix); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } fileOutputStream = new FileOutputStream(file); fileOutputStream.write(byteArrayOutputStream.toByteArray()); } catch (Exception e) { e.printStackTrace(); } finally { try { if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (byteArrayOutputStream != null) { byteArrayOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } try { workbook.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 导出excel * * @param fileName * @param headers * @param datas * @param response */ public static void excelExport(String fileName, String[] headers, List datas, HttpServletResponse response) { Workbook workbook = getWorkbook(headers, datas); if (workbook != null) { ByteArrayOutputStream byteArrayOutputStream = null; try { byteArrayOutputStream = new ByteArrayOutputStream(); workbook.write(byteArrayOutputStream); String suffix = ".xls"; response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName + suffix).getBytes(), "iso-8859-1")); OutputStream outputStream = response.getOutputStream(); outputStream.write(byteArrayOutputStream.toByteArray()); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (byteArrayOutputStream != null) { byteArrayOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } try { workbook.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * @param headers 列头 * @param datas 数据 * @return */ public static Workbook getWorkbook(String[] headers, List datas) { Workbook workbook = new HSSFWorkbook(); Sheet sheet = workbook.createSheet(); Row row = null; Cell cell = null; CellStyle style = workbook.createCellStyle(); style.setAlignment(HorizontalAlignment.CENTER_SELECTION); Font font = workbook.createFont(); int line = 0, maxColumn = 0; if (headers != null && headers.length > 0) {// 设置列头 row = sheet.createRow(line++); row.setHeightInPoints(23); font.setBold(true); font.setFontHeightInPoints((short) 13); style.setFont(font); maxColumn = headers.length; for (int i = 0; i < maxColumn; i++) { cell = row.createCell(i); cell.setCellValue(headers[i]); cell.setCellStyle(style); } } if (datas != null && datas.size() > 0) {// 渲染数据 for (int index = 0, size = datas.size(); index < size; index++) { Object[] data = datas.get(index); if (data != null && data.length > 0) { row = sheet.createRow(line++); row.setHeightInPoints(20); int length = data.length; if (length > maxColumn) { maxColumn = length; } for (int i = 0; i < length; i++) { cell = row.createCell(i); cell.setCellValue(data[i] == null ? null : data[i].toString()); } } } } for (int i = 0; i < maxColumn; i++) { sheet.autoSizeColumn(i); } return workbook; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/utils/FileUtil.java ================================================ package com.open.capacity.security.utils; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.time.LocalDate; /** * 文件工具类 * * @author 624191343@qq.com */ public class FileUtil { public static String saveFile(MultipartFile file, String pathname) { try { File targetFile = new File(pathname); if (targetFile.exists()) { return pathname; } if (!targetFile.getParentFile().exists()) { targetFile.getParentFile().mkdirs(); } file.transferTo(targetFile); return pathname; } catch (Exception e) { e.printStackTrace(); } return null; } public static boolean deleteFile(String pathname) { File file = new File(pathname); if (file.exists()) { boolean flag = file.delete(); if (flag) { File[] files = file.getParentFile().listFiles(); if (files == null || files.length == 0) { file.getParentFile().delete(); } } return flag; } return false; } public static String fileMd5(InputStream inputStream) { try { return DigestUtils.md5Hex(inputStream); } catch (IOException e) { e.printStackTrace(); } return null; } public static String getPath() { return "/" + LocalDate.now().toString().replace("-", "/") + "/"; } /** * 将文本写入文件 * * @param value * @param path */ public static void saveTextFile(String value, String path) { FileWriter writer = null; try { File file = new File(path); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } writer = new FileWriter(file); writer.write(value); writer.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (writer != null) { writer.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static String getText(String path) { File file = new File(path); if (!file.exists()) { return null; } try { return getText(new FileInputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } public static String getText(InputStream inputStream) { InputStreamReader isr = null; BufferedReader bufferedReader = null; try { isr = new InputStreamReader(inputStream, "utf-8"); bufferedReader = new BufferedReader(isr); StringBuilder builder = new StringBuilder(); String string; while ((string = bufferedReader.readLine()) != null) { string = string + "\n"; builder.append(string); } return builder.toString(); } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (isr != null) { try { isr.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/utils/ResponseUtil.java ================================================ package com.open.capacity.security.utils; import com.alibaba.fastjson.JSONObject; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ResponseUtil { public static void responseJson(HttpServletResponse response, int status, Object data) { try { response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "*"); response.setContentType("application/json;charset=UTF-8"); response.setStatus(status); response.getWriter().write(JSONObject.toJSONString(data)); } catch (IOException e) { e.printStackTrace(); } } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/utils/SpringUtil.java ================================================ package com.open.capacity.security.utils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; /** * spring获取bean工具类 * * @author 作者 owen E-mail: 624191343@qq.com * @version 创建时间:2018年3月20日 下午10:13:18 类说明 */ @Component public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext = null; public static T getBean(Class cla) { return applicationContext.getBean(cla); } public static T getBean(String name, Class cal) { return applicationContext.getBean(name, cal); } public static String getProperty(String key) { return applicationContext.getBean(Environment.class).getProperty(key); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringUtil.applicationContext = applicationContext; } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/utils/StrUtil.java ================================================ package com.open.capacity.security.utils; import com.google.common.collect.Lists; import java.util.List; /** * 字符串转化工具类 * * @author 624191343@qq.com */ public class StrUtil { /** * 字符串转为驼峰 * * @param str * @return */ public static String str2hump(String str) { StringBuffer buffer = new StringBuffer(); if (str != null && str.length() > 0) { if (str.contains("_")) { String[] chars = str.split("_"); int size = chars.length; if (size > 0) { List list = Lists.newArrayList(); for (String s : chars) { if (s != null && s.trim().length() > 0) { list.add(s); } } size = list.size(); if (size > 0) { buffer.append(list.get(0)); for (int i = 1; i < size; i++) { String s = list.get(i); buffer.append(s.substring(0, 1).toUpperCase()); if (s.length() > 1) { buffer.append(s.substring(1)); } } } } } else { buffer.append(str); } } return buffer.toString(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/utils/TemplateUtil.java ================================================ package com.open.capacity.security.utils; import com.open.capacity.security.dto.GenerateInput; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.math.BigDecimal; import java.util.Date; import java.util.List; public class TemplateUtil { private static final Logger log = LoggerFactory.getLogger(TemplateUtil.class); public static String getTemplete(String fileName) { return FileUtil.getText(TemplateUtil.class.getClassLoader().getResourceAsStream("generate/" + fileName)); } public static void saveJava(GenerateInput input) { String path = input.getPath(); String beanPackageName = input.getBeanPackageName(); String beanName = input.getBeanName(); List beanFieldName = input.getBeanFieldName(); List beanFieldType = input.getBeanFieldType(); List beanFieldValue = input.getBeanFieldValue(); String text = getTemplete("java.ftl"); text = text.replace("{beanPackageName}", beanPackageName).replace("{beanName}", beanName); String imports = ""; if (beanFieldType.contains(BigDecimal.class.getSimpleName())) { imports += "import " + BigDecimal.class.getName() + ";\n"; } if (beanFieldType.contains(Date.class.getSimpleName())) { imports += "import " + Date.class.getName() + ";"; } text = text.replace("{import}", imports); String filelds = getFields(beanFieldName, beanFieldType, beanFieldValue); text = text.replace("{filelds}", filelds); text = text.replace("{getset}", getset(beanFieldName, beanFieldType)); FileUtil.saveTextFile(text, path + File.separator + getPackagePath(beanPackageName) + beanName + ".java"); log.debug("生成java model:{}模板", beanName); } private static String getFields(List beanFieldName, List beanFieldType, List beanFieldValue) { StringBuffer buffer = new StringBuffer(); int size = beanFieldName.size(); for (int i = 0; i < size; i++) { String name = beanFieldName.get(i); if ("id".equals(name) || "createTime".equals(name) || "updateTime".equals(name)) { continue; } String type = beanFieldType.get(i); buffer.append("\tprivate ").append(type).append(" ").append(name); // 默认值 // String value = beanFieldValue.get(i); // if (!StringUtils.isEmpty(value)) { // buffer.append(" = "); // if (type.equals(String.class.getSimpleName())) { // value = "\"" + value + "\""; // } else if (type.equals(Double.class.getSimpleName())) { // value = value + "D"; // } else if (type.equals(Float.class.getSimpleName())) { // value = value + "F"; // } else if (type.equals(BigDecimal.class.getSimpleName())) { // value = "new BigDecimal(" + value + ")"; // } // // buffer.append(value); // } buffer.append(";\n"); } return buffer.toString(); } private static String getset(List beanFieldName, List beanFieldType) { StringBuffer buffer = new StringBuffer(); int size = beanFieldName.size(); for (int i = 0; i < size; i++) { String name = beanFieldName.get(i); if ("id".equals(name) || "createTime".equals(name) || "updateTime".equals(name)) { continue; } String type = beanFieldType.get(i); buffer.append("\tpublic ").append(type).append(" get") .append(StringUtils.substring(name, 0, 1).toUpperCase() + name.substring(1, name.length())) .append("() {\n"); buffer.append("\t\treturn ").append(name).append(";\n"); buffer.append("\t}\n"); buffer.append("\tpublic ").append(type).append(" set") .append(StringUtils.substring(name, 0, 1).toUpperCase() + name.substring(1, name.length())) .append("() {\n"); buffer.append("\t\treturn ").append(name).append(";\n"); buffer.append("\t}\n"); } return buffer.toString(); } public static void saveJavaDao(GenerateInput input) { String path = input.getPath(); String tableName = input.getTableName(); String beanPackageName = input.getBeanPackageName(); String beanName = input.getBeanName(); String daoPackageName = input.getDaoPackageName(); String daoName = input.getDaoName(); String text = getTemplete("dao.ftl"); text = text.replace("{daoPackageName}", daoPackageName); text = text.replace("{beanPackageName}", beanPackageName); text = text.replace("{daoName}", daoName); text = text.replace("{table_name}", tableName); text = text.replace("{beanName}", beanName); text = text.replace("{beanParamName}", lowerFirstChar(beanName)); String insertColumns = getInsertColumns(input.getColumnNames()); text = text.replace("{insert_columns}", insertColumns); String insertValues = getInsertValues(input.getColumnNames(), input.getBeanFieldName()); text = text.replace("{insert_values}", insertValues); FileUtil.saveTextFile(text, path + File.separator + getPackagePath(daoPackageName) + daoName + ".java"); log.debug("生成java dao:{}模板", beanName); text = getTemplete("mapper.xml"); text = text.replace("{daoPackageName}", daoPackageName); text = text.replace("{daoName}", daoName); text = text.replace("{table_name}", tableName); text = text.replace("{beanName}", beanName); String sets = getUpdateSets(input.getColumnNames(), input.getBeanFieldName()); text = text.replace("{update_sets}", sets); String where = getWhere(input.getColumnNames(), input.getBeanFieldName()); text = text.replace("{where}", where); FileUtil.saveTextFile(text, path + File.separator + beanName + "Mapper.xml"); } private static String getInsertValues(List columnNames, List beanFieldName) { StringBuffer buffer = new StringBuffer(); int size = columnNames.size(); for (int i = 0; i < size; i++) { String column = columnNames.get(i); if (!"id".equals(column)) { buffer.append("#{").append(beanFieldName.get(i)).append("}, "); } } String sets = StringUtils.substringBeforeLast(buffer.toString(), ","); return sets; } private static String getInsertColumns(List columnNames) { StringBuffer buffer = new StringBuffer(); int size = columnNames.size(); for (int i = 0; i < size; i++) { String column = columnNames.get(i); if (!"id".equals(column)) { buffer.append(column).append(", "); } } String insertColumns = StringUtils.substringBeforeLast(buffer.toString(), ","); return insertColumns; } private static String getUpdateSets(List columnNames, List beanFieldName) { StringBuffer buffer = new StringBuffer(); int size = columnNames.size(); for (int i = 0; i < size; i++) { String column = columnNames.get(i); if (!"id".equals(column)) { buffer.append("\t\t\t\n"); buffer.append("\t\t\t\t" + column).append(" = ").append("#{").append(beanFieldName.get(i)) .append("}, \n"); buffer.append("\t\t\t\n"); } } return buffer.toString(); } private static String getWhere(List columnNames, List beanFieldName) { StringBuffer buffer = new StringBuffer(); int size = columnNames.size(); for (int i = 0; i < size; i++) { String column = columnNames.get(i); buffer.append("\t\t\t\n"); buffer.append("\t\t\t\tand " + column).append(" = ").append("#{params.").append(beanFieldName.get(i)) .append("} \n"); buffer.append("\t\t\t\n"); } return buffer.toString(); } /** * 变量名 * * @param beanName * @return */ public static String lowerFirstChar(String beanName) { String name = StrUtil.str2hump(beanName); String firstChar = name.substring(0, 1); name = name.replaceFirst(firstChar, firstChar.toLowerCase()); return name; } private static String getPackagePath(String packageName) { String packagePath = packageName.replace(".", "/"); if (!packagePath.endsWith("/")) { packagePath = packagePath + "/"; } return packagePath; } public static void saveController(GenerateInput input) { String path = input.getPath(); String beanPackageName = input.getBeanPackageName(); String beanName = input.getBeanName(); String daoPackageName = input.getDaoPackageName(); String daoName = input.getDaoName(); String text = getTemplete("controller.ftl"); text = text.replace("{daoPackageName}", daoPackageName); text = text.replace("{beanPackageName}", beanPackageName); text = text.replace("{daoName}", daoName); text = text.replace("{daoParamName}", lowerFirstChar(daoName)); text = text.replace("{beanName}", beanName); text = text.replace("{beanParamName}", lowerFirstChar(beanName)); text = text.replace("{controllerPkgName}", input.getControllerPkgName()); text = text.replace("{controllerName}", input.getControllerName()); FileUtil.saveTextFile(text, path + File.separator + getPackagePath(input.getControllerPkgName()) + input.getControllerName() + ".java"); log.debug("生成controller:{}模板", beanName); } public static void saveHtmlList(GenerateInput input) { String path = input.getPath(); String beanName = input.getBeanName(); String beanParamName = lowerFirstChar(beanName); String text = getTemplete("htmlList.ftl"); text = text.replace("{beanParamName}", beanParamName); text = text.replace("{beanName}", beanName); List beanFieldNames = input.getBeanFieldName(); text = text.replace("{columnsDatas}", getHtmlColumnsDatas(beanFieldNames)); text = text.replace("{ths}", getHtmlThs(beanFieldNames)); FileUtil.saveTextFile(text, path + File.separator + beanParamName + "List.html"); log.debug("生成查询页面:{}模板", beanName); text = getTemplete("htmlAdd.ftl"); text = text.replace("{beanParamName}", beanParamName); text = text.replace("{addDivs}", getAddDivs(beanFieldNames)); FileUtil.saveTextFile(text, path + File.separator + "add" + beanName + ".html"); log.debug("生成添加页面:{}模板", beanName); text = getTemplete("htmlUpdate.ftl"); text = text.replace("{beanParamName}", beanParamName); text = text.replace("{addDivs}", getAddDivs(beanFieldNames)); text = text.replace("{initData}", getInitData(beanFieldNames)); FileUtil.saveTextFile(text, path + File.separator + "update" + beanName + ".html"); log.debug("生成修改页面:{}模板", beanName); } private static CharSequence getInitData(List beanFieldNames) { StringBuilder builder = new StringBuilder(); beanFieldNames.forEach(b -> { builder.append("\t\t\t\t\t\t$('#" + b + "').val(data." + b + ");\n"); }); return builder.toString(); } private static String getAddDivs(List beanFieldNames) { StringBuilder builder = new StringBuilder(); beanFieldNames.forEach(b -> { if (!"id".equals(b) && !"createTime".equals(b) && !"updateTime".equals(b)) { builder.append("\t\t\t

    \n"); builder.append("\t\t\t\t\n"); builder.append("\t\t\t\t
    \n"); builder.append("\t\t\t\t\t\n"); builder.append("\t\t\t\t
    \n"); builder.append("\t\t\t
    \n"); } }); return builder.toString(); } private static String getHtmlThs(List beanFieldNames) { StringBuilder builder = new StringBuilder(); beanFieldNames.forEach(b -> { builder.append("\t\t\t\t\t\t\t\t\t{beanFieldName}\n".replace("{beanFieldName}", b)); }); return builder.toString(); } private static String getHtmlColumnsDatas(List beanFieldNames) { StringBuilder builder = new StringBuilder(); beanFieldNames.forEach(b -> { builder.append("\t\t\t\t{\"data\" : \"{beanFieldName}\", \"defaultContent\" : \"\"},\n" .replace("{beanFieldName}", b)); }); builder.append(""); return builder.toString(); } } ================================================ FILE: open-layui-web/src/main/java/com/open/capacity/security/utils/UserUtil.java ================================================ package com.open.capacity.security.utils; import com.open.capacity.security.dto.LoginUser; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; public class UserUtil { public static LoginUser getLoginUser() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null) { if (authentication instanceof AnonymousAuthenticationToken) { return null; } if (authentication instanceof UsernamePasswordAuthenticationToken) { return (LoginUser) authentication.getPrincipal(); } } return null; } } ================================================ FILE: open-layui-web/src/main/resources/activiti.properties ================================================ # 演示模型禁止删除 modelId=142517 ================================================ FILE: open-layui-web/src/main/resources/application.yml ================================================ server: port: 9999 security: sessions: stateless spring: application: name: open-layui-web servlet: multipart: max-file-size: 100MB max-request-size: 100MB mvc: servlet: load-on-startup: 1 jackson: date-format: yyyy-MM-dd HH:mm:ss joda-date-time-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mail: host: smtp.163.com username: 18579068155@163.com password: 1q2w3e4r properties: mail.smtp.auth : true mail.smtp.timeout : 2000 mail.smtp.starttls.enable : true mail.smtp.starttls.required : true thymeleaf: cache: false prefix: classpath:static/pages/ mode: LEGACYHTML5 content-type: text/html http: encoding: charset: utf8 force: true enabled: true datasource: type: com.alibaba.druid.pool.DruidDataSource # driver-class-name: oracle.jdbc.OracleDriver # url: jdbc:oracle:thin:@127.0.0.1:1521:orcl # username: crm_owner_user # password: bss_crm_test # filters: stat,wall ################## mysql start ############################ driver-class-name: com.mysql.jdbc.Driver # 192.168.3.150 130.75.131.211 134.224.249.39 47.94.252.160 url: jdbc:mysql://47.94.252.160:3306/boot_security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false username: root password: root filters: stat,wall ################### mysq end l########################## redis: ################### redis 单机版 start ########################## host: 47.94.252.160 port: 6379 database: 1 ################### redis 单机版 end ########################## # cluster: # nodes: 192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001 ## #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 # #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001 # timeout: 1000 # 连接超时时间(毫秒) # pool: # max-active: 10 # 连接池最大连接数(使用负值表示没有限制) # max-idle: 8 # 连接池中的最大空闲连接 # min-idle: 2 # 连接池中的最小空闲连接 # max-wait: 100 # 连接池最大阻塞等待时间(使用负值表示没有限制) mybatis: config-location: classpath:mybatis.cfg.xml mapper-locations: classpath*:com/open/**/dao/*.xml files: path: ${file-path:d:/files} logging: config: classpath:logback-admin.xml log: level: root: info com.open: debug file: logs/admin-server.log maxsize: 30MB token: expire: seconds: 7200 jwtSecret: open-layui-web eureka: client: healthcheck: enabled: true serviceUrl: defaultZone: http://127.0.0.1:1111/eureka #http://130.75.131.241:8761/eureka,http://130.75.131.248:8762/eureka #http://134.224.249.33:1111/eureka/ 正式库 #http://134.224.249.33:1111/eureka/ 测试库 #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} #instance-id: ${spring.application.name}:${docker.ipAddress}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 5 #每隔几秒告诉eureka服务器我还存活,用于心跳检测 lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送,10秒后会从eureka服务器中将此服务剔除 #注册实例文档 # status-page-url: http://${docker.ipAddress}:${server.port}/auth/doc.html # ${server.port}为该服务的端口号 ================================================ FILE: open-layui-web/src/main/resources/bootstrap.yml ================================================ spring: application: name: open-web-server ================================================ FILE: open-layui-web/src/main/resources/bpmn/demo.xml ================================================ ================================================ FILE: open-layui-web/src/main/resources/bpmn/leave.bpmn ================================================ ================================================ FILE: open-layui-web/src/main/resources/bpmn/leave2.bpmn ================================================ ================================================ FILE: open-layui-web/src/main/resources/bpmn/vacationRequest.bpmn ================================================ ================================================ FILE: open-layui-web/src/main/resources/db/boot_security.sql ================================================ CREATE DATABASE IF NOT EXISTS `boot_security` DEFAULT CHARACTER SET = utf8mb4; Use `boot_security`; set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; SET FOREIGN_KEY_CHECKS=0; # Host: 192.168.3.150 (Version 5.7.22) # Date: 2018-06-24 11:52:30 # Generator: MySQL-Front 5.4 (Build 4.153) - http://www.mysqlfront.de/ /*!40101 SET NAMES utf8 */; # # Structure for table "act_assignee" # DROP TABLE IF EXISTS `act_assignee`; CREATE TABLE `act_assignee` ( `id` varchar(32) NOT NULL, `sid` varchar(32) NOT NULL COMMENT '节点id', `assignee` varchar(64) DEFAULT NULL COMMENT '办理人', `role_id` varchar(32) DEFAULT NULL COMMENT '候选组(角色)', `assignee_type` int(11) NOT NULL COMMENT '办理人类型1办理人2候选人3组', `activti_name` varchar(128) DEFAULT NULL COMMENT '节点名称', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "act_assignee" # # # Structure for table "act_evt_log" # DROP TABLE IF EXISTS `act_evt_log`; CREATE TABLE `act_evt_log` ( `LOG_NR_` bigint(20) NOT NULL AUTO_INCREMENT, `TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TIME_STAMP_` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `DATA_` longblob, `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `LOCK_TIME_` timestamp(3) NULL DEFAULT NULL, `IS_PROCESSED_` tinyint(4) DEFAULT '0', PRIMARY KEY (`LOG_NR_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_evt_log" # # # Structure for table "act_ge_property" # DROP TABLE IF EXISTS `act_ge_property`; CREATE TABLE `act_ge_property` ( `NAME_` varchar(64) COLLATE utf8_bin NOT NULL, `VALUE_` varchar(300) COLLATE utf8_bin DEFAULT NULL, `REV_` int(11) DEFAULT NULL, PRIMARY KEY (`NAME_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ge_property" # INSERT INTO `act_ge_property` VALUES ('next.dbid','215001',87),('schema.history','create(5.22.0.0)',1),('schema.version','5.22.0.0',1); # # Structure for table "act_hi_actinst" # DROP TABLE IF EXISTS `act_hi_actinst`; CREATE TABLE `act_hi_actinst` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `ACT_ID_` varchar(255) COLLATE utf8_bin NOT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `CALL_PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `ACT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `ACT_TYPE_` varchar(255) COLLATE utf8_bin NOT NULL, `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `START_TIME_` datetime(3) NOT NULL, `END_TIME_` datetime(3) DEFAULT NULL, `DURATION_` bigint(20) DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', PRIMARY KEY (`ID_`), KEY `ACT_IDX_HI_ACT_INST_START` (`START_TIME_`), KEY `ACT_IDX_HI_ACT_INST_END` (`END_TIME_`), KEY `ACT_IDX_HI_ACT_INST_PROCINST` (`PROC_INST_ID_`,`ACT_ID_`), KEY `ACT_IDX_HI_ACT_INST_EXEC` (`EXECUTION_ID_`,`ACT_ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_actinst" # INSERT INTO `act_hi_actinst` VALUES ('122506','leave_process:1:120011','122505','122505','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:06:38.000','2018-01-24 23:06:38.000',67,''),('122507','leave_process:1:120011','122505','122505','user1','122508',NULL,'经理审批','userTask',NULL,'2018-01-24 23:06:38.000',NULL,NULL,''),('130010','leave_process:1:120011','130009','130009','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:47:12.000','2018-01-24 23:47:12.000',3,''),('130011','leave_process:1:120011','130009','130009','user1','130012',NULL,'经理审批','userTask',NULL,'2018-01-24 23:47:12.000',NULL,NULL,''),('130015','leave_process:1:120011','130014','130014','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:50:10.000','2018-01-24 23:50:10.000',1,''),('130016','leave_process:1:120011','130014','130014','user1','130017',NULL,'经理审批','userTask',NULL,'2018-01-24 23:50:10.000',NULL,NULL,''),('130020','leave_process:1:120011','130019','130019','start',NULL,NULL,'start','startEvent',NULL,'2018-01-24 23:52:30.000','2018-01-24 23:52:30.000',7,''),('130024','leave_process:1:120011','130019','130019','user1','130025',NULL,'经理审批','userTask',NULL,'2018-01-24 23:52:30.000',NULL,NULL,''); # # Structure for table "act_hi_attachment" # DROP TABLE IF EXISTS `act_hi_attachment`; CREATE TABLE `act_hi_attachment` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `URL_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `CONTENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TIME_` datetime(3) DEFAULT NULL, PRIMARY KEY (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_attachment" # # # Structure for table "act_hi_comment" # DROP TABLE IF EXISTS `act_hi_comment`; CREATE TABLE `act_hi_comment` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TIME_` datetime(3) NOT NULL, `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `ACTION_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `MESSAGE_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `FULL_MSG_` longblob, PRIMARY KEY (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_comment" # # # Structure for table "act_hi_detail" # DROP TABLE IF EXISTS `act_hi_detail`; CREATE TABLE `act_hi_detail` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `ACT_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin NOT NULL, `VAR_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `REV_` int(11) DEFAULT NULL, `TIME_` datetime(3) NOT NULL, `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `DOUBLE_` double DEFAULT NULL, `LONG_` bigint(20) DEFAULT NULL, `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_HI_DETAIL_PROC_INST` (`PROC_INST_ID_`), KEY `ACT_IDX_HI_DETAIL_ACT_INST` (`ACT_INST_ID_`), KEY `ACT_IDX_HI_DETAIL_TIME` (`TIME_`), KEY `ACT_IDX_HI_DETAIL_NAME` (`NAME_`), KEY `ACT_IDX_HI_DETAIL_TASK_ID` (`TASK_ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_detail" # # # Structure for table "act_hi_identitylink" # DROP TABLE IF EXISTS `act_hi_identitylink`; CREATE TABLE `act_hi_identitylink` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_HI_IDENT_LNK_USER` (`USER_ID_`), KEY `ACT_IDX_HI_IDENT_LNK_TASK` (`TASK_ID_`), KEY `ACT_IDX_HI_IDENT_LNK_PROCINST` (`PROC_INST_ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_identitylink" # INSERT INTO `act_hi_identitylink` VALUES ('130013','0ea934e5e55411e7b983201a068c6482','candidate',NULL,'130012',NULL),('130018','0ea934e5e55411e7b983201a068c6482','candidate',NULL,'130017',NULL),('130026','0ea934e5e55411e7b983201a068c6482','candidate',NULL,'130025',NULL); # # Structure for table "act_hi_procinst" # DROP TABLE IF EXISTS `act_hi_procinst`; CREATE TABLE `act_hi_procinst` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `START_TIME_` datetime(3) NOT NULL, `END_TIME_` datetime(3) DEFAULT NULL, `DURATION_` bigint(20) DEFAULT NULL, `START_USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `START_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `END_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `SUPER_PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), UNIQUE KEY `PROC_INST_ID_` (`PROC_INST_ID_`), KEY `ACT_IDX_HI_PRO_INST_END` (`END_TIME_`), KEY `ACT_IDX_HI_PRO_I_BUSKEY` (`BUSINESS_KEY_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_procinst" # INSERT INTO `act_hi_procinst` VALUES ('122505','122505',NULL,'leave_process:1:120011','2018-01-24 23:06:38.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL),('130009','130009',NULL,'leave_process:1:120011','2018-01-24 23:47:12.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL),('130014','130014',NULL,'leave_process:1:120011','2018-01-24 23:50:10.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL),('130019','130019',NULL,'leave_process:1:120011','2018-01-24 23:52:30.000',NULL,NULL,NULL,'start',NULL,NULL,NULL,'',NULL); # # Structure for table "act_hi_taskinst" # DROP TABLE IF EXISTS `act_hi_taskinst`; CREATE TABLE `act_hi_taskinst` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TASK_DEF_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PARENT_TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `START_TIME_` datetime(3) NOT NULL, `CLAIM_TIME_` datetime(3) DEFAULT NULL, `END_TIME_` datetime(3) DEFAULT NULL, `DURATION_` bigint(20) DEFAULT NULL, `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `PRIORITY_` int(11) DEFAULT NULL, `DUE_DATE_` datetime(3) DEFAULT NULL, `FORM_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', PRIMARY KEY (`ID_`), KEY `ACT_IDX_HI_TASK_INST_PROCINST` (`PROC_INST_ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_taskinst" # INSERT INTO `act_hi_taskinst` VALUES ('122508','leave_process:1:120011','user1','122505','122505','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:06:38.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,''),('130012','leave_process:1:120011','user1','130009','130009','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:47:12.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,''),('130017','leave_process:1:120011','user1','130014','130014','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:50:10.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,''),('130025','leave_process:1:120011','user1','130019','130019','经理审批',NULL,NULL,NULL,NULL,'2018-01-24 23:52:30.000',NULL,NULL,NULL,NULL,50,NULL,NULL,NULL,''); # # Structure for table "act_hi_varinst" # DROP TABLE IF EXISTS `act_hi_varinst`; CREATE TABLE `act_hi_varinst` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin NOT NULL, `VAR_TYPE_` varchar(100) COLLATE utf8_bin DEFAULT NULL, `REV_` int(11) DEFAULT NULL, `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `DOUBLE_` double DEFAULT NULL, `LONG_` bigint(20) DEFAULT NULL, `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `CREATE_TIME_` datetime(3) DEFAULT NULL, `LAST_UPDATED_TIME_` datetime(3) DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_HI_PROCVAR_PROC_INST` (`PROC_INST_ID_`), KEY `ACT_IDX_HI_PROCVAR_NAME_TYPE` (`NAME_`,`VAR_TYPE_`), KEY `ACT_IDX_HI_PROCVAR_TASK_ID` (`TASK_ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_hi_varinst" # INSERT INTO `act_hi_varinst` VALUES ('130022','130019','130019',NULL,'userLeave','serializable',0,'130023',NULL,NULL,NULL,NULL,'2018-01-24 23:52:30.000','2018-01-24 23:52:30.000'); # # Structure for table "act_id_group" # DROP TABLE IF EXISTS `act_id_group`; CREATE TABLE `act_id_group` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_id_group" # INSERT INTO `act_id_group` VALUES ('023366f3457511e8bcf1309c2315f9aa',1,'hr',NULL),('0ea934e5e55411e7b983201a068c6482',1,'manage',NULL),('2619a672e53811e7b983201a068c6482',1,'admin',NULL),('dcb0f642fe9611e7b472201a068c6482',1,'dev',NULL); # # Structure for table "act_id_info" # DROP TABLE IF EXISTS `act_id_info`; CREATE TABLE `act_id_info` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `USER_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `VALUE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PASSWORD_` longblob, `PARENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_id_info" # # # Structure for table "act_id_user" # DROP TABLE IF EXISTS `act_id_user`; CREATE TABLE `act_id_user` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `FIRST_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `LAST_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `EMAIL_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PWD_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PICTURE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_id_user" # INSERT INTO `act_id_user` VALUES ('2211fec3e17c11e795ed201a068c6482',1,'Tom Curise',NULL,'154040976@qq.com',NULL,NULL),('51d2179c457911e8bcf1309c2315f9aa',1,'333',NULL,'',NULL,NULL),('5354d45a018311e8a1a2201a068c6482',1,'111',NULL,'',NULL,NULL),('6a038f15019711e8a1a2201a068c6482',1,'张三',NULL,'',NULL,NULL),('a4a743bffe9711e7b472201a068c6482',1,'zxm',NULL,'1544040976@qq.com',NULL,NULL),('acfc0e9232f54732a5d9ffe9071bf572',1,'管理员',NULL,'',NULL,NULL),('c7f1a7d7018311e8a1a2201a068c6482',1,'666',NULL,'',NULL,NULL),('ce1f6f35018211e8a1a2201a068c6482',1,'123',NULL,'',NULL,NULL); # # Structure for table "act_id_membership" # DROP TABLE IF EXISTS `act_id_membership`; CREATE TABLE `act_id_membership` ( `USER_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `GROUP_ID_` varchar(64) COLLATE utf8_bin NOT NULL, PRIMARY KEY (`USER_ID_`,`GROUP_ID_`), KEY `ACT_FK_MEMB_GROUP` (`GROUP_ID_`), CONSTRAINT `ACT_FK_MEMB_GROUP` FOREIGN KEY (`GROUP_ID_`) REFERENCES `act_id_group` (`ID_`), CONSTRAINT `ACT_FK_MEMB_USER` FOREIGN KEY (`USER_ID_`) REFERENCES `act_id_user` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_id_membership" # INSERT INTO `act_id_membership` VALUES ('2211fec3e17c11e795ed201a068c6482','0ea934e5e55411e7b983201a068c6482'),('51d2179c457911e8bcf1309c2315f9aa','023366f3457511e8bcf1309c2315f9aa'),('5354d45a018311e8a1a2201a068c6482','dcb0f642fe9611e7b472201a068c6482'),('6a038f15019711e8a1a2201a068c6482','dcb0f642fe9611e7b472201a068c6482'),('a4a743bffe9711e7b472201a068c6482','dcb0f642fe9611e7b472201a068c6482'),('acfc0e9232f54732a5d9ffe9071bf572','2619a672e53811e7b983201a068c6482'),('c7f1a7d7018311e8a1a2201a068c6482','dcb0f642fe9611e7b472201a068c6482'); # # Structure for table "act_re_deployment" # DROP TABLE IF EXISTS `act_re_deployment`; CREATE TABLE `act_re_deployment` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', `DEPLOY_TIME_` timestamp(3) NULL DEFAULT NULL, PRIMARY KEY (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_re_deployment" # INSERT INTO `act_re_deployment` VALUES ('212503','请假流程',NULL,'','2018-05-17 21:11:56.283'); # # Structure for table "act_ge_bytearray" # DROP TABLE IF EXISTS `act_ge_bytearray`; CREATE TABLE `act_ge_bytearray` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `BYTES_` longblob, `GENERATED_` tinyint(4) DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_FK_BYTEARR_DEPL` (`DEPLOYMENT_ID_`), CONSTRAINT `ACT_FK_BYTEARR_DEPL` FOREIGN KEY (`DEPLOYMENT_ID_`) REFERENCES `act_re_deployment` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ge_bytearray" # INSERT INTO `act_ge_bytearray` VALUES ('142518',9,'source',NULL,X'7B227265736F757263654964223A22313432353137222C2270726F70657274696573223A7B2270726F636573735F6964223A2270726F636573735F6C65617665222C226E616D65223A22E8AFB7E58187E6B581E7A88B222C22646F63756D656E746174696F6E223A22222C2270726F636573735F617574686F72223A22222C2270726F636573735F76657273696F6E223A22222C2270726F636573735F6E616D657370616365223A22687474703A2F2F7777772E61637469766974692E6F72672F70726F63657373646566222C22657865637574696F6E6C697374656E657273223A22222C226576656E746C697374656E657273223A22222C227369676E616C646566696E6974696F6E73223A22222C226D657373616765646566696E6974696F6E73223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D227D2C227374656E63696C223A7B226964223A2242504D4E4469616772616D227D2C226368696C64536861706573223A5B7B227265736F757263654964223A227369642D41343530344644322D303230342D343246352D393036312D344134323938324442343938222C2270726F70657274696573223A7B226F766572726964656964223A227374617274222C226E616D65223A227374617274222C22646F63756D656E746174696F6E223A22222C22657865637574696F6E6C697374656E657273223A22222C22696E69746961746F72223A22222C22666F726D6B6579646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22227D2C227374656E63696C223A7B226964223A2253746172744E6F6E654576656E74227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A37352C2279223A38342E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A34352E30303030303030303030303030312C2279223A35342E39393939393733353039303436337D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834222C2270726F70657274696573223A7B226F766572726964656964223A227573657231222C226E616D65223A22E7BB8FE79086E5AEA1E689B9222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C22657865637574696F6E6C697374656E657273223A22222C226D756C7469696E7374616E63655F74797065223A224E6F6E65222C226D756C7469696E7374616E63655F63617264696E616C697479223A22222C226D756C7469696E7374616E63655F636F6C6C656374696F6E223A22222C226D756C7469696E7374616E63655F7661726961626C65223A22222C226D756C7469696E7374616E63655F636F6E646974696F6E223A22222C226973666F72636F6D70656E736174696F6E223A2266616C7365222C22757365727461736B61737369676E6D656E74223A22222C22666F726D6B6579646566696E6974696F6E223A22222C2264756564617465646566696E6974696F6E223A22222C227072696F72697479646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22222C227461736B6C697374656E657273223A7B227461736B4C697374656E657273223A5B7B226576656E74223A22637265617465222C22696D706C656D656E746174696F6E223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C22636C6173734E616D65223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C2265787072657373696F6E223A22222C2264656C656761746545787072657373696F6E223A22227D5D7D7D2C227374656E63696C223A7B226964223A22557365725461736B227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3235302C2279223A3130392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3135302E30303030303030303030303030332C2279223A32392E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3134392E37383132352C2279223A36392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A37352E32313837352C2279223A36392E39393939393733353039303436347D7D2C22646F636B657273223A5B7B2278223A31342E3939393939393939393939393939362C2279223A31357D2C7B2278223A34392E3939393939393939393939393938362C2279223A34307D5D2C22746172676574223A7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D7D2C7B227265736F757263654964223A227369642D37363845453443392D333233432D343744422D423438302D344230323746333136433835222C2270726F70657274696573223A7B226F766572726964656964223A227573657232222C226E616D65223A22E4BABAE4BA8BE5AEA1E689B9222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C22657865637574696F6E6C697374656E657273223A22222C226D756C7469696E7374616E63655F74797065223A224E6F6E65222C226D756C7469696E7374616E63655F63617264696E616C697479223A22222C226D756C7469696E7374616E63655F636F6C6C656374696F6E223A22222C226D756C7469696E7374616E63655F7661726961626C65223A22222C226D756C7469696E7374616E63655F636F6E646974696F6E223A22222C226973666F72636F6D70656E736174696F6E223A2266616C7365222C22757365727461736B61737369676E6D656E74223A22222C22666F726D6B6579646566696E6974696F6E223A22222C2264756564617465646566696E6974696F6E223A22222C227072696F72697479646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22222C227461736B6C697374656E657273223A7B227461736B4C697374656E657273223A5B7B226576656E74223A22637265617465222C22696D706C656D656E746174696F6E223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C22636C6173734E616D65223A22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222C2265787072657373696F6E223A22222C2264656C656761746545787072657373696F6E223A22227D5D7D7D2C227374656E63696C223A7B226964223A22557365725461736B227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3535342E353435343431333138323233312C2279223A3130392E39393939393634353638333530367D2C2275707065724C656674223A7B2278223A3435342E353435343431333138323233322C2279223A32392E3939393939363435363833353036337D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C2273657175656E6365666C6F776F72646572223A22227D2C227374656E63696C223A7B226964223A224578636C757369766547617465776179227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935227D2C7B227265736F757263654964223A227369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3730302E303030303030303030303030312C2279223A38392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3636302E303030303030303030303030312C2279223A34392E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3635392E353637363531363836373836382C2279223A37302E343430353134393838323432347D2C2275707065724C656674223A7B2278223A3535352E303332363536393130303136322C2279223A37302E31343334363333343436373330357D7D2C22646F636B657273223A5B7B2278223A34392E39393939393939393939393939342C2279223A34307D2C7B2278223A32302E352C2279223A32302E3439393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831227D7D2C7B227265736F757263654964223A227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C2273657175656E6365666C6F776F72646572223A22227D2C227374656E63696C223A7B226964223A224578636C757369766547617465776179227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334227D2C7B227265736F757263654964223A227369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3335352E303030303030303030303030312C2279223A38392E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3331352E303030303030303030303030312C2279223A34392E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731222C2270726F70657274696573223A7B226F766572726964656964223A2275736572222C226E616D65223A22E8B083E695B4222C22646F63756D656E746174696F6E223A22222C226173796E6368726F6E6F7573646566696E6974696F6E223A2266616C7365222C226578636C7573697665646566696E6974696F6E223A2266616C7365222C22657865637574696F6E6C697374656E657273223A22222C226D756C7469696E7374616E63655F74797065223A224E6F6E65222C226D756C7469696E7374616E63655F63617264696E616C697479223A22222C226D756C7469696E7374616E63655F636F6C6C656374696F6E223A22222C226D756C7469696E7374616E63655F7661726961626C65223A22222C226D756C7469696E7374616E63655F636F6E646974696F6E223A22222C226973666F72636F6D70656E736174696F6E223A2266616C7365222C22757365727461736B61737369676E6D656E74223A22222C22666F726D6B6579646566696E6974696F6E223A22222C2264756564617465646566696E6974696F6E223A22222C227072696F72697479646566696E6974696F6E223A22222C22666F726D70726F70657274696573223A22222C227461736B6C697374656E657273223A7B227461736B4C697374656E657273223A5B7B226576656E74223A22637265617465222C22696D706C656D656E746174696F6E223A22636F6D2E6C656E2E6163746C697374656E65722E4C656176654C697374656E6572496D706C222C22636C6173734E616D65223A22636F6D2E6C656E2E6163746C697374656E65722E4C656176654C697374656E6572496D706C222C2265787072657373696F6E223A22222C2264656C656761746545787072657373696F6E223A22227D5D7D7D2C227374656E63696C223A7B226964223A22557365725461736B227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332227D2C7B227265736F757263654964223A227369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3338352E303030303030303030303030332C2279223A3237357D2C2275707065724C656674223A7B2278223A3238352E30303030303030303030303030362C2279223A3139352E30303030303030303030303030337D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345222C2270726F70657274696573223A7B226F766572726964656964223A22656E64222C226E616D65223A22656E64222C22646F63756D656E746174696F6E223A22222C22657865637574696F6E6C697374656E657273223A22227D2C227374656E63696C223A7B226964223A22456E644E6F6E654576656E74227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3835332E303030303030303030303030322C2279223A38332E39393939393733353039303436347D2C2275707065724C656674223A7B2278223A3832352E303030303030303030303030322C2279223A35352E39393939393733353039303436347D7D2C22646F636B657273223A5B5D7D2C7B227265736F757263654964223A227369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3331342E333836373235353538313136372C2279223A37302E34323230383835383931323634377D2C2275707065724C656674223A7B2278223A3235302E37353338393934343138383334322C2279223A37302E313837323831313132363832387D7D2C22646F636B657273223A5B7B2278223A34392E39393939393939393939393939392C2279223A34307D2C7B2278223A32302E352C2279223A32302E3439393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535227D7D2C7B227265736F757263654964223A227369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D37363845453443392D333233432D343744422D423438302D344230323746333136433835227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3435342E303230343134303536323536372C2279223A37302E34343233353139373631383238337D2C2275707065724C656674223A7B2278223A3335342E3938393334303736393934392C2279223A37302E31343934333838373037303234377D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E3439393939393939393939393939367D2C7B2278223A34392E39393939393939393939393939342C2279223A34307D5D2C22746172676574223A7B227265736F757263654964223A227369642D37363845453443392D333233432D343744422D423438302D344230323746333136433835227D7D2C7B227265736F757263654964223A227369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3832342E333738393131323235363332312C2279223A37302E34333832343930343234363831347D2C2275707065724C656674223A7B2278223A3730302E303734323133373734333638332C2279223A37302E30343631323036353933343131337D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E357D2C7B2278223A31342C2279223A31332E3939393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D7D2C7B227265736F757263654964223A227369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E4B88DE5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D66616C73657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365222C2273686F776469616D6F6E646D61726B6572223A66616C73657D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3638302E353030303030303030303030312C2279223A3233352E30303030303030303030303030367D2C2275707065724C656674223A7B2278223A3338352E353739313031353632353030312C2279223A39302E373737333431343131333435357D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E357D2C7B2278223A3638302E353030303030303030303030312C2279223A3233352E30303030303030303030303030367D2C7B2278223A39392C2279223A34302E3030303030303030303030303031347D5D2C22746172676574223A7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D7D2C7B227265736F757263654964223A227369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E9878DE696B0E794B3E8AFB7222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D747275657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365222C2273686F776469616D6F6E646D61726B6572223A66616C73657D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3238352E30303030303030303030303030362C2279223A3233352E303030303030303030303030317D2C2275707065724C656674223A7B2278223A3230302C2279223A3131302E39363039333534393234383234367D7D2C22646F636B657273223A5B7B2278223A302E393939393939393939393939393939392C2279223A34302E30303030303030303030303030377D2C7B2278223A3230302C2279223A3233352E303030303030303030303030317D2C7B2278223A34392E3939393939393939393939393938362C2279223A34307D5D2C22746172676574223A7B227265736F757263654964223A227369642D34363841393635452D393339422D343733312D413232392D353137384436413042423834227D7D2C7B227265736F757263654964223A227369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E4B88DE5908CE6848F222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D66616C73657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365227D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3333352E34333833363637353034313136362C2279223A3139342E31363031363032323737313137347D2C2275707065724C656674223A7B2278223A3333352E31323431333332343935383835372C2279223A39302E37373733333637393230353539367D7D2C22646F636B657273223A5B7B2278223A32302E352C2279223A32302E357D2C7B2278223A35302E3030303030303030303030303131342C2279223A33392E3939393939393939393939393938367D5D2C22746172676574223A7B227265736F757263654964223A227369642D42324633433135342D434432322D343230412D424538422D363836444534373531423731227D7D2C7B227265736F757263654964223A227369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136222C2270726F70657274696573223A7B226F766572726964656964223A22222C226E616D65223A22E58F96E6B688E8AFB7E58187222C22646F63756D656E746174696F6E223A22222C22636F6E646974696F6E73657175656E6365666C6F77223A22247B666C61673D3D66616C73657D222C22657865637574696F6E6C697374656E657273223A22222C2264656661756C74666C6F77223A2266616C7365222C2273686F776469616D6F6E646D61726B6572223A66616C73657D2C227374656E63696C223A7B226964223A2253657175656E6365466C6F77227D2C226368696C64536861706573223A5B5D2C226F7574676F696E67223A5B7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A3833392E303030303030303030303030322C2279223A3332317D2C2275707065724C656674223A7B2278223A3333352E30303030303030303030303031372C2279223A38342E37323635353939393537373730327D7D2C22646F636B657273223A5B7B2278223A35302E3030303030303030303030303131342C2279223A37382E39393939393939393939393939377D2C7B2278223A3333352E30303030303030303030303031372C2279223A3332317D2C7B2278223A3833392E303030303030303030303030322C2279223A3332317D2C7B2278223A31342C2279223A31332E3939393939393939393939393939367D5D2C22746172676574223A7B227265736F757263654964223A227369642D46313234303339432D394237422D344134382D384531332D413635353335384246443345227D7D5D2C22626F756E6473223A7B226C6F7765725269676874223A7B2278223A313230302C2279223A313035307D2C2275707065724C656674223A7B2278223A302C2279223A307D7D2C227374656E63696C736574223A7B2275726C223A227374656E63696C736574732F62706D6E322E302F62706D6E322E302E6A736F6E222C226E616D657370616365223A22687474703A2F2F62336D6E2E6F72672F7374656E63696C7365742F62706D6E322E3023227D2C227373657874656E73696F6E73223A5B5D7D',NULL),('142519',7,'source-extra',NULL,X'89504E470D0A1A0A0000000D49484452000003870000017308060000008D717CB0000000206348524D00007A26000080840000FA00000080E8000075300000EA6000003A98000017709CBA513C0000000467414D410000B18E7CFB5193000000017352474200AECE1CE900000006624B474400FF00FF00FFA0BDA793000000097048597300000EC400000EC401952B0E1B000020004944415478DAEDDD077C5455DAF8F133E9A1841288A14A559466C1B22E2AFA22A06B4111490C2A2AAEAFE5B5FC755504165450B1B27617150491203694559A8880055730405040A49700218D402690CCFC9FE7CE9D30840402A44CF97D3F9FC73B73A710CFDC39739E7BCE3DC71800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008EC04111A03ACD9E3DFB0C87C3D14F6EF690E8261143A99CB022893489F9129F5C76D9653F512400F517F5170080E4107E69D6AC591DC2C2C2FE1511117166E3C68DB7346AD4A849BD7AF512651F8573825C2ED7C6ECECECF48C8C8CBCACACACAE6EB77B9BEC7BB077EFDEE9940E5069F5D7CB125DE2E3E357262424346ED0A081EE23393CF1FACB999797F7DB8E1D3B76676666B62E2E2EDE40FD05002487086273E7CEEDE970383E6AD9B265718B162D1AC96D0AA5EA6C484F4F9F2349E25552CE77F4ECD9730645029C58FDE576BB27376DDA7475DBB66DFF22DFAB084AA5EAAC5BB76EF1962D5B5A4B39DF4EFD0500D52F9C22405537AC2223233FEED4A953FD8484845A2486554ECBF9ECBA75EBCEDAB56BD7E09B6FBE79EDC48913D7502CC0F1D55F5267BDDBA54B9768490E3BC86D863A54B1060D1A348F8F8FDFBF73E7CECB6FBAE9A6D5D45F0040728820A143B1222222BE95C4B06E5C5C1C05528D6263634F9704F11B6960DD3370E0C0591F7CF0C14E4A0538B6FA2B2C2CEC3F921846D5AB572F9E12A93E515151B10D1B360CCFC8C8B8322525E52BEA2F00A83E0C8F4195898989F9A0458B16B5CA4B0C0BF377985D6B679B7DD9EB8DDBED32B1F54F3609ED7A9998B866145E2590C6553F89715959592FCBDDCB2811A0E2F41AC3962D5B164862D8A2ACC7B5CECADAB8C8E46CFDC51C28C83211D171262EB18B896F75B1098F8CA5004F509D3A756AB56EDDDAB97EFDFA57E4EEA5940800540F7A0E5125162C5870AEC3E118D2A14387F0B286926A62B879E97BC6B967BB34B28AA5A5E5920656B6C9CB586E6AC7B7B31A5A3871090909F19B366D8AB9E9A69B964E9A34690B25021C9DCE4A1A191939A453A74E89E50D85DFB16ABA24870B8DABA8C0BAEF2A2E3405B99B8C336F8B896B72866108FD898B8B8B8BDDBE7D7BAD94949445D45F00503DB87E0255222626E691264D9A4496D740D24655D1FEBD87ED7715EF3799EBE7538095A755C3860D97C9B61F4501548C2E5791989858545EFDA53D85B9DB9696F9988E84D89BB99A42AC24F23B124EFD050024870870070E1CE85EAF5EBD721F2FC8DB5AEE63DAAB88CA238D5CED86ED41490015131E1EDE273E3EFEA472EBAFDC2DD6B052EAB0AAD7A0418346F2795C41490040F5E09A435409A7D39950B76EDD721F77171F28FFC5476874E1B81A579D64C3859C4005B95CAEAE47ACBF5C45477CBD9B3AACD2D4A953C714171777A0240080E41081DDB872B0C0BD7F90CFE1644A01A838B7DB1D49FDE537F597B5A12400A09AEA5D8A00000000004072881A1119DBA0DCC722A2EB52400002B2FE52E1517528240000C92150510D5B5E6022A26A1FDEA88A8C350D4FEE4E0101F05BBA266B9D46A796F998AED31A97703A8504002039042AAA4EE3D34CED321A57BABF6E42470A0880DF7238C2CC491DAE2AF3B184F67DE8390400901C02C7AAF840C161FB8A0AF7503000FCBFFE2A639D56EA300000C921708CF6EFDD65362D79D7E4EFFAFDB0C7F6EEFEC36CFA659CF51C00F047591B1799CDBF4E28F3B1ED2B3F363BD67CC57216008080C45216A856B9DB969A5D6B6799A272CEBAAB7D391BCD869FDF348DDBF634F55B9C6F0DE102809A76C0996376ACFAD2E467AE2EF7399A14666FFAC13873379B26A75F67A26A37A6E000002487802FED09D4B3E9DA335811AEE2FDD6F3F7ECFADD249C728589A9DB8442045063B2B7FC6C32FF9C53E670F8B2144872B87EF1EBA651EB1EA661AB8B38C905000808FC5AA15A684F604513435FFBB2D79B8DFF7D9B0284DF193468507D4A2134E830D21DABBEA87062E8E57615995D7FCEB55E0F803A162039046CDA1378BCB48105F8931B6EB8A1A7D3E9CC4E4E4EEE4369507F518701D4B140B0605829AA45879EA3280404851B6FBCF10CB7DB3DF58C33CED89196963655EE5FFCE1871FA65132C1AB519B4BAD00401D0B043B7A0E01E0D81A2DDF0C1A34C8FDC8238F9C74FFFDF73BE5FE77494949DD281D00A08E05480E01200424272777D046CB4D37DD54D0AB57AF78DD77DE79E7254823668FC3E1982E8D97567EFEBFD0814F1100752CF52C70240C2B0580A3D046495858D8D7D75D779DEBF2CB2F6FE6FB9834629A498366D3C4891317C8F32E4A4D4DDD50457FC6BD12E9A5F6254AC4F8DCEF2771954F23C5E9F3588AC4629FF7D06B791695F19E00108A752CF52C10ECC9614A4A4AF3A2A2A2BE0E87E362B97B86FD05AF637F9133A4B24993C7BE0F0F0F4F9D3C79F2160E070065355A222222E64B83A59E345CCA9C3DAF77EFDE2D0B0A0AB64C9B364D873F5D5C458D974612F3CB794CEBB57C8956A5F6699D778DC4F712B3B4DEB31B2B6D255EB75F0300D4B1D4B321895C214492C3E4E464FD90FF2F2A2AEA7491D5BD7BF73AAD5BB78E6ADCB8718C3052C1ECCEC9C9D9BF62C58AE8050B165CBA7EFDFABBA4B2D924AF7977CA94291FF05501A0742AF5E2E2E2593D7BF68CBBF1C61B8F38AD7ADFBE7D9BE7E6E6FE3173E6CC85529F5C58458D17FD1B7AD83F5CDEFABBB9DD08B9B554DDFE8B7D7B95FEAF487C6CDFBF5362884491BD7F8644269F3600EAD89204F17A73688FE0B1D6B3B753CFFA7FAE209B7BE4F8EB2EEDFF98329EA2FB5AC9637A32A0AF3CEF7939EEE68742AE1054C9A13D2CE1EDBA75EB761D3C78709D33CF3CB3B664FA89A59F171B1BDB4CC23469D2E4945EBD7AE92EA754368B274D9AF4A0BCC79D7200DC3A6DDAB4B57C7580D06EB4B85CAE05E79E7B6E624A4A4A5C455E73CB2DB7B497C64BFA8F3FFEB8B07FFFFEE7483D9251C97F568EC4E715789E3664CEF079CD4F7652A9FE23D1D3AEFF37D889268D1600D4B11E5A1FBE7582F5EC2CEA59FFCD1564F3A6DBED3E9E65527AC8EB7A047BAE1034C9E180010392222323DFB8EEBAEB22AEBAEAAABA92141ECBCB63FAF4E9932C91F3C20B2F7CB264C99285C9C9C9FFA01711084DD2E8A8B37FFFFE79D268697ED75D77C51D4B7D72DF7DF775DAB76FDF9AB4B4B4AFA51EB94CEA91CA6E10781B1CDEB3DAE71BCFF52C337C9EB3C18E41C6734D4CE906D479C6735DCC0C3E6D00D4B115AA6775398D9965D4B3238D67E86826F5ACFFE70AB279D5787A872D7AEC75EAD449273F32EDDAB533F5EBD73775EBD635728C999C9C1CB361C306F3F3CF3F1BC90DDC4545450EFB65DDE575BFCAF1775730E60A41315BE9CD37DF7C4D5C5CDCBF870F1FDEA06FDFBEC79A18FAAAFFF0C30FDFFEF8E38FFFEC703846CB873E98AF12105A060D1A1453BB76ED19679D7556DB7BEFBDB7C1F1D4278F3DF6D8291D3B7674B85CAE39DA08AAE43F51CF56EB10A6F976C4D8F7CBB3C127BCD7BE78CF660300756CC5EAD945E53C5793C22DD4B37E9F185E296DFB49DEC4508FBB2BAFBCD2BCFCF2CB7A3C994B2EB9C4B468D1C24A0C55AD5AB54CD3A64DCD05175C601E78E001F3EAABAF3AF4F96161616EFB2DEBB8DDEE49C1982B047C723870E0C094D8D8D80F478F1E5DB77DFBF695F29E9D3B77BEFAB9E79EDB2C07D170F9D007F2950242A7D12295FD976DDBB63DF79E7BEE893B81134D66F8F0E15DE57DA22322223ED3F7ADE23FBDA882CFCBB41B2B0C6F02401D7B6C1A95B33F9F7AD6EF13C32469D37F6627EC56D2F7CC33CFE86434A671E3C6157A0FED51D4E73FFBECB38E66CD9A157BF7CBF13C2ED87285804E0E75DC705454D4B8871E7AA856453FDC8A920FFEAF8F3DF6589A7CE8CFEBDA3B7CB58090F0719B366DFEFAE8A38FC6EAE45527EAC9279F3C4D1A2F098585855F5672E345274B1824A117D4EBB52E89E53C4F8741C5D8CFD1B3EBDEB3DBDF98C3879A020075ECB1D5B311D4B3FE9F2B4862F8AA37313CF5D453CDC89123AD5EC2E3A1AF93E32EBC73E7CE6E9F04F1CD60CA15023A396CD0A0C167D75E7B6D6C65F51896A63D88679F7DF67FF4AC005F2F20B80D1E3C38352121A1E7C30F3F1C1B19195929EFA967C5E547A84B6262E2494EA773528F1E3D2AE33A6F9D0DEF358909C63339CD58E39908A1B44E76A3E554BBB132576284F19CCDD6FDED24AEE49307401D7B981915AC673B50CFFA37490CB50D6FF5FA6A8FE1430F3D543274F478E990D3071E78C0B707B14E30E50A013B21CDEDB7DFDE5F3E9C4EBD7BF7AED27F472AB17E2929299BB5CB98096A80E074D34D37BD5FAF5EBD6B860D1B16AD95BED20BD1EFBAEBAEC39EFBCA2BAF1C320C452F5A97FAE8B0E7BDFEFAEBA661C38656E3E5E9A79FEE2C3F48B1B27B9C345EEE983F7F7ED109FCB965AD99A59325E899EB689F7DB748FCC3BEAD67B4F5DFF49D5A5D1B3D0FD90D1E863F01A08E3D28F304EAD9077DEA596D37DE4F3D5B3374B90A49DA7A7A4F24E8B583279A18FA2688F7DF7F7FF8638F3DE676B95C3A514DF760C91502B6E7502A99676EBCF1C688CA3AFB7404F56FB9E596E57270DDC9D70C083E77DF7DF7AB8D1A351A3062C48818DF1F0DBDBE401B2EDE868C5561868599B7DE3A7486F37FFFFBDFC6B71E6AD0A0815E0B6D355ABC74F8D4D8B163DBC5C5C55D90989838EE38CF6E1F69F15D6D78E8040A53EDFBAD7C6EEB7698F1CCA8A717CEFFAFF1CCC01763278B34580050C71E4CF08EA79E7DDFA79EBD57E231BB9E8DA09EAD51F7786F5C7EF9E5C73D94B43CFA7E575D7595770653132CB942402687C3860D6BBB7FFFFED65DBB76AD967FAF57AF5EFDA4C26A6AAF8D1212E4FF75989E71A9C4211A80DF1D93F7DC73CF0BB2B973C89021D1659D4DBCE8A28B743DD492FB2E97CBAC5FBFDEFCF28B67DDE3D5AB579B152B569803070E58F72322228C344E4C9F3E872F9FA48D9B975F7EF96469C4FC8F345E5E3E8E3FF79DA33CAE672BD3ECDB1BCCC1C599D3EC068B377478D46B474936395E00EAD850AB638D5D3F1E4F3DBBAA543D3B3214EA597F3E265352529AEB9A847A5B7B0D3539AC0A7A2CCA71E9BDFEB07B30E40A01F9A359AF5EBD21AD5AB50A3B9159AE8E514CFBF6ED574925A51727BF1022DFC9A7E44B654E3AE9A40239D0BFD631DB4545458BA64D9B964F75851A3E2673E4989C21C7E4E4133926EFBDF7DE31F2FAFB9F7CF2C988234D6825CF3343870EB58636A9828202F3CE3BEF5817B5BFFAEAAB25FB959E01FFFBDFFF6ECAAB9BE4F1E83163C6243CF2C823FD070C18B07AEAD4A9AFF1B156F9F1922BC7CB97277ABC54176D1C6BEF4945E5E7E75BC7DDB1BC06A88EEF0C752C2AF198DC239FE71752CF7D50D163529ED7578E612BCFD1CE24DF9EE6CAA43DE0679F7DB663F1E2C5DE5D019F2B04E4AF495E5EDEC5BA606575BAE0820BB4DBF8E250FB56CA174BC7F05F275FCEAFA532DE9E9C9CFC91449F6A9A36BA429E7EFA699391E199106CD9B26566E6CC9925F1E69B6F9A4D9B369534BABCE6CE9D6B2D6AFAFEFBEF9B2FBEF8E290B8EFBEFBCAFDB77478CBCE9D3B8FF8F7E8B511FADE4EA753AFB3D00ACA535B5C7F7DC96D9CD031595F3603ED6372BD3462C61FEB31F9F0C30FDFB77FFFFE87860F1F1E71B4998E131313AD3383B1B1B125FBB4B1327AF468AD8B4AF6E959F1BFFCE52FA64D9B36477CBF848484E8175F7CB14E7474F423F2B7FF2F9F68951F2FF57C8E970DC773BC5427AD93A4E153E1E72F58B04067CE3B649F3488ADA4913A0C35F59DA18E45251F93752552EC63724B458E49797E499BFDDC73CFADD2BFAFD4FB077CAE10903D873939392D4F3EF9E46AFD373B77EEDC5636B542FCFBA9B331F5976D7F693414CA1753D78C99BA7DFBF6199570F1F771D1844FAF3FD01F17D5B1634773DA69A7953CFEE8A38F9A1B6EB8C1BABD74E952B365CB163371E244BD48D96CDDBAD57AEDD5575F6D5DF7A089A4FAFAEBAF4B5EAFC35974888BEFBFF7C61B6F98B3CE3AAB64DFF2E5CB4DBF7EFD4AFEDDA8A828ABA2901F4673E9A5975AC36094FE407A6FA3D2E80C6483E4B81C24C764BEFC607C2C3F08D38F744CDE7DF7DDF7666767BFF4F8E38F87EBCC651571DD75D799EFBEFBCE3AA3AD7488939E74D0339A2595A97CB6DE63ED68E2E3E36B3FFFFCF3C50F3DF4D02839168BA64C99F20E1F65B5883FD6E3A5BA690F6079C39FF498D37ACCB79750EF2B3DB1E5FB1E9B376FB6EA24EA3054F777863A1655AC9ECF3159209FAF9E4DFBAC8C63F20CEF8DA39D503851AD5AB53265FDBB2487D5282F2F2F52BB71AB93FC7BF5EC03121ED1F2C54C926D922466F9F2E59C27B7DF8C8E8E9E3F61C2046775FD1152115867B6B52770F7EEDDBAD069C963DA8B78F1C517EB8F8475BF5BB76E567CFBEDB7A67FFFFE66D1A2455682A867D8F56C785967DAF57D1F7CF0C192FB7A365DCF64F6EC694D7E659D59D7B3F0DAA8D2469AFE986DD8B0C15A434787C4A07A4F5E787F30E498CC946352A7147FDFF7981C3264C8EDF279BDAC8D9663F9B1D0214CFFF77FFF67A4B161F6EEDD6BEDF36DB4687D74DB6DB71D32B1C2D1242424C43DF9E4937B860D1BF69234B8725253533FE623ACB1E3254B8E97D9DEE3A526FF289DC1D19BD895D6B2654B2B9E7BEE39D3A143D94B6A7DF0C107E6A38F3EA20E43557F6776CB77660E752C6A58AC1C2737CBF6663926F3E4739EED7038DED56352EAB644DFE3A78A7304DFBB8D480E6B406161A1A332164F3D1692389CA45B39F046F25D3CFC0743BE9C57CBF66A6D684819ADDFB56B5795FFA3DAA0D1864E7676B6D5A8D121283E9F9779EFBDF74C794B9D788755FDF1C71FD67BECD8B1C3DAFAD246D215575C616DBD3D937FFEF9A78E7DB7CEA8ABD9B3679B6BAEB9C6BAAD67E23566CD9A6535ACF4396FBFFDB6F51C3D5BAFF7B76DDB660DEB7AECB1C74C751DC399999956F984D8B1DBC87BF2428FC9010306AC95CF6D724646C6706928871DCF59446D2877EEDCD93A4E7C87286B2F4DF3E6CDAD130FC7AA75EBD675EFBEFBEE9CD75E7BED7D7BCAEDB5542735A2A1EFF1A2C33A9B356B66DAB66D5BED7F8826665A2F95951C96B4866263AD110F4A7BF99477820EDF910FC15287697DCE6FAFDF890F943A76E8D0A159A3468D7A9B3A36E8C5495C2F9FF1F57A4CFAAAACE52BCA53EAA4454CA01764402687FA83A41F7C752688DF7CF38DF7E608BE7F47AF8FB572D7614A557D1C74E9D2C56AF49C73CE3987247E13264C3063C68C317BF6ECB17A1675DD246D20E9F02A8D7FFDEB5FA65DBB76D6EB75D894360675ABBCD7FBE8197A6D0C0D1F3EDC5C72C925D6BEF4F474ABB7D1DBB0D204D47778962FFD71D36B21CF3CF34C6B3896FE2DEBD6ADB3CED8FBFEF055B5850B179A5F7FFD35A48F5D87C3D14E8E8B113A5C4F1B1FC74BA74FF7B9E8DCA267B7AFBDF6DAE37ECFEDDBB7D7B7DF2785AAC33F68CF9AF6BE0D1932A4DAFF6D4D4ABD3D27E566B20D1B960C23F50E2BF5D649BE27C482A50E5BB3660DBFBDD4B1C7FD9EA79F7E7AC3A64D9BEE91E39E3A364469DD559509A2EFA449C6B38409C961B59F1A888B2BCAC9C989F09E09AD0E9244644D9F3E5DCBEBE510F92E55E48758C77C680B21BCD48FC4BA6EDDBAB5A986E3C074EFDEDDFCF6DB6F562348E924347AE2E091471E294920870D1B665DC7A0B35569E8B052ED65D4B3E17A8D83D2B3F5DEC656E9464FFBF6EDAD7F47698FA84EBB7DFEF9E75BF7BFFCF24BEB8CA69736B8B4F1A4134268634C1350EF6B7578ABF77675BAF0C20BCDC68D1B35417C22048EC9F21A2EEB6AD7AE3DE9FBEFBF1F76EAA9A7869F77DE79C7F53E1F7EF8A1BED721C39DF4ACB6D40DDA0039AEF7AC55AB5696BCA79E76FC84B3DAD57EBCB8A4CC5DDE19ED7CEB96AA3EB95516AD5FF4DFD63A487BCBEAD4A973D873F4BA693996CB7D8F4F3EF9C4AAE75AB76E1D3475D829A79C120CF557D0D7B172BCBE2375EC53FE56C72E5AB468D7B66DDBA274F655EAD8D0A9C7E5FE01D96F2D90A9C3F5AB3239D4F7F711F06B5A066472D8B469D37DD2D88DABCEE4303737778F6C56A4A6A68E0C856F63525252B95F48F9B215CB974E13429DC1355CEEE7C8FDB95AF1464747CFD46B0F6EBBED367755FF8DDA801A3C78B0D5E397959565CE38E30CEBACBB0E9BD269B0F53A42F97BACB3CECF3CF3CC61AFD7DE463D03AE3F3C3A14CB3B4CEBCA2BAF3CAC319696E659D648932CED55F0F65AEB70542FEFCCA83AE44BAF7DF49E99AF698D1A35B27A061E7DF4D191417C4CBA1DDAA23878FFB06352F78F1C3972A97C4E9FEDDBB72FCCDB935251BADE964EDC51FAE4417171B1755CE8BA5CC73AECE9C71F7FDC3979F2E448798FAB3EFAE8A3B9B403AAE578D10FB058421B0D61728C84953E5EFAF7EF5FA0094975D3994A759A7E1D2A3A7EFC786BA2ACD275915EDBE2BD5ED0F7649677E4830E09D5496834B9F4F6E0047A1DA64972A8FCF6FA6B1D5B469D5B5E1DBBD2DFEA58F97BB48EBD9E3A36788E4939FE8AEC0430A2BC7ADCE9744E329E6525AC135EBA607D55D10E061F69248735A049932669E9E9E9171DEF99A9E3B178F1623D2DF05DA87E41E54B57285FB868FBCBA889A1CEDE325362AA3424E6CA0F434E75FF4D9AD4BDFEFAEBC63B4DB6FEB068634863DEBC7956E3C89BF0F9FEF82C59B2C44C9932C5BA9EE8F7DF7FB7662CF5F61CEA0F905EC3F8CF7FFEB3A4E1A5B3A6791B499A706A78EFEBE3DE75C974FA776DD4956ED0954527CFF14E948313672786473D26A5E1F28524C9177EF8E187DF4A6321CAB7917D24DA3879EDB5D70E99B4C8F7EC766E6EAED598D733DB159D3061EEDCB999F29A48397E7A49A3E5173EC5AA3D9724A15F5ACD88C2EC28F7784949A9FED1677A524B9320ED3954BAA0B74E9AE5DB53A743A3EC21962556AD5A656DBDAFDBBE7DBBF53EDE194DA9C35089A863E117F5B84F2F61B9C7E4800103BE93E759C9A15EEAA413145695527356047CAE1090C9E199679EF9E1B871E32ED2CAA4BC85502BDB8A152BB49B326467BAB213C37CBB0CFE13131333A33A67252D8F76E5A7A6A65A67D37D672A2D8BCEF0A7C3B174E8A977B896776D1ADF9E435F3A1C552B146F034DCFB2EBD4DCBAD692D264D2CB3B314459BCEB307A6982DAAB572FAAFACA69AC1CD3313966CC981FA40173E6E79F7FBE44EA9098F2262DF2F5E9A79F1E724D8136DCF538D0C939B4E1AD74ABD7A90D1A34E8A8EF27C7DBEEC993273BE535974C9B368D614ED5702EC94E0CFDAE0EF3265A3A8CF3F1C71F2FD9A7A322EEB9E71EABD1EC6DD4E82435DA48D6FAC49BFC79275EF036AA7508A9CE64EA5D42803A0CD4B1D4B1A1588F4744447CEE72B9C6BADDEE709DBD5E4798E9F5DA55D10EF55EFB6D0BF85C212093C3CE9D3BBF9F9090F09A7CD811E55D485F99962F5FBEBFB0B070BD24211B42ED9BA8DDF4B2992F0D11EF74D539FEF2B7E950295DAF4B1B54DA7BA867C3BD67C07D693278F6D967975C87689D7E2AE379BECFEFD4A993751D8EF62AFA3680F4357A42C2DB88BAF5D65B4B1ED37F5FD761F20E89D15942E7CC99634DFEA043C5F44CBD3E47F7EB1007D4DC31290D97DFE433E9F4D9679F2D97C6722DED292AEF4493368AF598F06DB8E8B0BBA143875A3336EA0F8ED25E9D9F7EFAC95C74D145475C53491A3739D3A74F97C3C4752D8D96D0AEC39477289D6F62E8F5F2CB2F5B1374CC9831C3DC7CF3CDD6A808EFB5825A9F683DA4758ED64BDED94A4B9FE4A20E03752C42F1989C3C79F296E4E4E46FE5664F3DC9A69D0055312A448F5DEF090CB128187285804C0E1D0E87532A9C8FE403B8512FBCAFEADEC371E3C6ED964AE6F510FB2E0E9772DE101313F3B1BF9C5D2F4D93376D3C79E92CA57AF6C6BB48B3367EF44BEB6DE478879F2AFD81D1E1577A7652E9D017EF8434FA25D7C4D37792062F7D0F6D6C95451B543AC5BBB75752AFF5D319D6744D4575E79D779A499326597F5F550E6FE098AC18F9ACFE94C64B97C58B172F954649DC1D77DC51665DF2D65B6F1D72ED950E69D2F5B6F4E2F67BEFBDD7EA91F6F6DE682F8D3E5FAF712DEBBDB4D122C759BE1C2B1786E2C926EAB043E9B076AD37BC7544695A87694F89D663A597B6D0B510F5DA423DD674129A8AA20E03752C42E898D4B6BB35B65993433DB15099D71E6A3DAC27EF7CF293B783A1D01D017C162166E4C891B9DDBA758B2A3D814865FAEAABAF0A3EFCF0C3655BB76EBD70FEFCF9457C4F2B66CE9C396EFD12C23F2C58B0C05C76D9650E4AE270528F34CACBCBFBBD7DFBF68D4A375EF49A2F5D16C57769016DA47BAF49557A8242274AF0F6B6E8B015AD93744A775FE3C78FCF9D376FDED6E2E2E28BA74C999249C9537F81FA8B3A963A16552B393979BEE40CD6D92C1DAAAC6BB856C6CCA5DAD3ADEFA509A2F770CEC8C8B824187285B080CD6A1D0EA7540C77FDE73FFFB1160CAE0A7A2DC6D4A9530BA542BA95C41008DA864B665656568B356BD66C7FF5D5574B8687E875043AE151E935E774789D2FED4DF19D5D4F87404D9C38B1642894B7D12275C8BAC2C2C2F368B400A08EA58E45F590C47050585858B6DED66B585F7CF1456B88F289268663C78EF54D0CF3252FB923587285803F13377DFAF47973E7CEBD4417F9F51D3678A2742DA861C386E5CB01749754341FF0F53A369C79F72F9C793FBAFEFDFBD769DDBAF58A7AF5EAB5FAC73FFE5132E4F844E8750E6FBDF5D69E254B96AC901FA8BFF9DBF56EA0FEA2FE02752C82DD800103922441FC4027A7D1FBDA83F8C0030F1CD710534D08F524874F62A81D56370553AE1016E8FF03575F7D752FF9D158F6D4534F555A0FA2F618FEF39FFF2C282C2C7C9EC410080DD3A64DCBDFB973E769B9B9B96B9E7FFEF9926B5C8E97BE5EDE679FDD68F91F1A2D00A863A96351FDA64E9D9A2AC7C86049E2748D5BAB0771C890213A694DE905ECCBE59D1D5F5FE79B18CAFB0E09B65C213CD0FF079E78E209D7871F7EF84E5151D1C5E3C78F6FA5EBE2E8FA75E5CD447934BA80F01B6FBC51E072B91E94F77B89AFD4F1B9F9E69B479E7CF2C914849FD0131E93264D7A829238B2B4B4B4A2F6EDDBBF131D1D7DD5F7DF7F9FA8D3FD7B27383A163A6C6AD4A85107366DDAF4BDD4257DFC754214507F517F813A16A1203D3D3DAD63C78E6BC2C3C37B4B4217AD6B68EABAB13AE197AE33AB3331EBF5B09A3FC8F1690D1DD551843AF1D7E79F7F6E5D1BBB72E5CA92B5378D67498D3B25F17C2DD8CA2A2218FE272421D431BE3D7EFAE9A7DBE6CC99F3D682050B2275BA5A9DC9B4A2F4C3970FB868F7EEDD7F161414F4C8A6A4BD00002000494441549D3265CA2ABE4A40E8B11B19670C1D3AF4FB9123475EA0D3A91FCBC5EBFA83F2F4D34F17656666CE901F9C1BB85E1900A86351F3B407312929E9274900DF71B95CFFA3FB7468B2CE745F6AADC2A359A4D718066BAE101E4CFF33EFBCF3CEAFF3E6CD7B3E3737B7DD8F3FFE78DAC71F7F1CA65DC7DE35EDF4EC94860E45C8CECE366BD7AE35DF7CF38D79EFBDF7DCBFFEFAEBD6BCBCBCA1AB57AFBE7DC68C193BF90A9D18CEBCFB17CEBC1FBB850B17BE77E185175EFAF5D75FB73CE79C731CB56BD73EEA6BF42CE3134F3C519C9393F3D59A356BFAD368A1FE02F517A863E13FD2D3D37356AC5831B153A74E2B25C16B28A1957D45871B2E9218919191F15030E70A11C1F63FA4B398CA26D9ED76DFBA72E5CADB962C5992220960A7CD9B37D792E42F4287224882E8964AA8283E3E7E5BC3860D7F6ADBB6ED98FBEEBBEF57BE32007C3DFBECB3173FF2C8235F3EF9E4937F1B3A74A8233131B1DCE7EAEC674F3FFD74714141C1177FFCF10767B301803A167E2A3535F563D97C9C9292D2DCE5725D2F79C35FE57E37094D1675022C1D3FBA55224DE23B7D6EA8AC9D1911ACFF637692F8861D00705C9E7BEEB9AB5E78E18537478F1E7D67798D173D9B3D6AD4A8E2B0B0B07FAD5EBDFA511A2D00401D0BFF3779F2E42DB219AB3168D0A018A7D359E04D25626262DA87E2F5AC611C160070640F3FFCF05D2D5AB418357CF870F7BA75EB0E794C87BCC97E5783060D468F1D3BF6211A2D00401D8BC02389E1F9BEF70B0B0B7B846239901C0240053CFAE8A3FF6CD3A6CD33A3468D72FFF6DB6FD6BED5AB575B3326376DDAF419D98EA09400803A1601EB96A3DCF78A92E84B72080021EEF1C71F1FDABE7DFB075E7AE9A5625DEF68ECD8B1C5D298797CC48811C3281D00A08E45E072BBDD87247CBA4C4A8F1E3DCABA044FA7D71D47720800D0C6CB2B898989C3A64F9F6E9A356BF6D4F0E1C3C7502A00401D8B80A1095F33DF3C283939B9BBC3E1A8EF932816E9FD8484841EA55ED724140A27187D2471430DBE1E4010FBF3CF3F6374BB72E54A07A50100D4B10818B74A3C24A16B147691B84F62A6E687BE4F92E4304292439DE07280DC9D6BBFEE3989C512AD480EFD5B8C9DF9EFF3D9777519CFAB656FF755E03DAFE6BB03000000048D7612FF90384B426721D5652BE6489C22C9E055BE4FD4F5D195248757366EDCB8DDAE5DBB9E95BBA74BEC92682CF11BC9A1FFD1646FBAFDFF502871AA446BE359BA22DA78D62631F6FED512EBEC03E11489BF49A47B4F0E483C28F1A8C44289CC325E9FCFF7090000000858E749C44A8CF7D9D7262929A9876C5B947E727171B1090F0F4F4C4848B84992C3797662A85CC15C48819C1CF691D86B0ECE16D4CCDEDE2D719BCF7D63278DFBEDDBFF6B3CDDC9B7FA3CBEC7E7F9AE325E0F00000020B0FD2071A7CFFD3B24461FE905CD9B37FFEBCA952BB7874A01057272A8DDB97FB5B3FFD912F38EF05C1D2FDC5FE26CFB8CC1AC528FBFCB7705000000085A7ABDA02E78AFB38D7A933DCD0D92CA7A727878B8B5AD5FBF7E5787C3D1DEED76D7319ED1845D480EFD935E48DA49A2A7442F89D7253A9B83C341BDF471ED29FC9BFD585F3B5904000000101AD64AFC3F895F249648B44A4848D0D18309E5BD4092C23CD9346ADAB4E9B4AD5BB7FE6927952B490EFD935E44BA5B62B21DDF19CFF5849A001619CFC5A23A36F82489353E4963C70ABCB7EFEB0100000004BE4976E8DC25FB2FB9E492E7657B41794F76BBDD91BABDF0C20B77A7A6A6B6379EF94BF6931CFAA736123F4BFC28116F3C13CE7C6B3FF6A2C44F123B8DA79770B8FDBCBAF6598382A3BCB7EFEB2F334C4803000000040B6BF50287C3D1F728CF8BB5B73D7BF4E8B16FFEFCF945C15E30819C1C6A2278929DF91795CAE24798831797EAFE0E7602996D0E9F61A8AC35744ABF1E40F0D57D7AED404F7B3BA1D4E3BA4FCF260E91C8A1B800E0B8D532652F23D6C06E97013562C08001E79B8AAF59D82E3131B1BB6CE7931C0648E65F86D249DDEE637C5F924220780D369EEB96B592BF52A27EA924501F1F43620800C725CE4EFEF4529E4DE6E0F2615EBA5E9C8EEA4AA6A85053A64E9DAAA3040FE9244A4A4A1A693C9D444FA4A6A68E0CC57289E0D000108266DA49E17C3B319C663C43CEF55A826F243E97B85E628B442AC50500C7447B5874D28EAFEC44F076E3991B42696F61671243C03F855104A892032B2CCCED72B928083F209FC346E3197A8D435D2331D0787A0775522B9DE27ABAF19CE1DE20F182443B8A29F4381C8E03D45F7E537F591B4A22E0E8F262CFFBDCBFD44E121BDBF5EA54E33941F70A4505901C2204C4C4C4ECDCB3670F05E107B2B3B335D949A3240EA3D7152F2AE7B10724BA19465784E60F6358D832EA2FFF909F9FAF6B8DADA22402D2ABC6B316B5D75A3BD6D9F767489C463101248708019191918B72737329083F909191A16BF4CCA7244AE830D297EDDB1B7CF67B7B575B19CFF588BF5054A1A9B8B878E6EEDDBB775012352F3B3B3B533E8FAF288980A31301EAB586B796F3F81CDAA100C9214288D3E97C6EFBF6ED07DC6E378551B3366465657595ED2714C521C9E1709FDB2579B4BDD5EB0C67DAB7EB515CA147EAAD4F32323222A8BF6A9EFC8E14537F051C9D8CE6DC233CDECA789609538CCE00480E110A2EBAE8A29FA561B57CDBB66D14460D4A4F4F9F239FC3B6CB2EBBEC274AE360C26C3C6B97FECD78868F7A797B0EF58CF79B124F49D07B14827AF5EA95565454F4DF4D9B366DA6346ACE962D5BB20E1C38F01BF557C0D1D12A13EDDBE3CB686B6EA01D0A901C2204399DCE811B366CD89797974761D4809C9C9CE959595957B95CAE07298D32E9CC79238DA7F77080C4FD76E87D5DC6E25DE39994062148BF37921CC6E6E6E6B29C490DD8BB776FE1FAF5EBDDC5C5C5F7511A01EB1E893BCCC109851A9B8313D2FC28F1BD4412C504901C2244F4EEDD7B9534B0AE59B972652E0962F527862B56ACE8EC7038EE90CF219D122953BEB7B8242E97B8D68E0FECC64B4F89188A2974EB2FD924A7A7A7EF9104713725528D5FCCFCFCECB4B4B45D727310F557407BDD1C1C91A13397EA440451123ADBD385127F95D84A3101248708213D7BF69C5B545474FDB265CBF2366DDA94C5353C556E833466C72D5FBEFC3CB97DBF94FF0C8AA44C99C633E18C267F19653C3ED77866323D9FA20AEDFACBE572DD26F59763EDDAB50BA9BFAADEFAF5EBFFBB74E9D22229F7BBA8BF025AAC44A47D5BAF2B4CF3094DF86B49BC26D186A202FC4B384580AA3671E2C4752929299FE7E6E676DDB66D5B9CD3E95C131616E6888E8EAEE37038FCF6EF5EB76E9D79FBEDB74D93264D4CC3860DFDF6EFD4750CB3B2B2BE9746D592D5AB57C717141444C8BE945EBD7A2DE2E82BD77E3BF4ACF6DA232490EBCA7AA053A74E3D64A3F19D24E3F329CEE0AEBF060E1CF8457E7EFEA55BB66CA9B577EFDE9FA4FEDA131313535FEA2F26D338F1FACB29BF0DCB376EDC982EF5973B27276787ECBB91FA2BE03925B2ECDB655DBB5D28A1B3D06653C7C29F70EC314B14AA893D44ABF7ECD9B3CFD8BE7D7B3F09FDE2E9B55D7E3B6CEFD34F3FD569D4CDD8B1634DFFFEFDFDB9789B49E810ACDF255E61F2860AB9D778D6D83A9A2DE6E0B0288476FD75B9D65FBB76EDEA27D18352A9D476885E93B64CE29FD45F416395A9D8845E7A9D37EBF002248708553A0B6020FC100C1A3428C6E97416E86DBD5E72F2E4C9B113264C70F209068D938CE7CCE0919C2AA1D79A31290D02AAFE02FCC07512BF55A01E1EC4770A203904FC9E2486875C6B565858A889C44C4A2668FC293141E24AE3E941AC630E4E50E3D5DD78CE7E03008E8F2688A7DB75ED7C7BDF5512538C67E4D0188A08F02F4C480394ED16DF3B6EB7FB768A24E8E8B0E67EF6ED39C6B3AEE1488961F63EBD163193620280E3E69D6DB681C469765C6BEFDB48F100248740409064B04FA95D3DFAF7EF5F8792092ABA84C577F6EDB72586DBC9A177228C0C8A08002AC51289FFDA0180E410081CC9C9C97D1C0E47A2CF2E9DD5B2517878781F4A070000002487408870B95CBD4BEDF22E6E760DA513129A53040050A9E2259AD80180E410080C3D7AF48870381CB795DA1D6D6FFBEA2CA69452506A653C434A35064834A24800E08445D95B5D6EA9B61DA32816C07F315B29E0A3499326E7BBDDEEB8321ED2652CEA141616EAD0D2CF29A9A0E19D2C6124450100956EA0BD65E66780E410083C479895B45022461EBF86E43028B4329EF5B554A7233C4F27A5610913003836BAB8FD2947798E8E5ECB95B89AE202480E01BFA3434A75965287C351D6C3F5ECE45187963E3861C2841C4A2CA04DA8C07362A82301E0B8DC491100248740404B4848E8516A96D2434862B8471EAF5F5050A08BA3CFA0C402DA068A000000E0504C480378BF0C6161479C8D5412C3227B7B0BA515F0DE349EA1A5A5E95A969C340380139326D1B88CFDC91271140F407208048294A33CDE40FFE376BB7BEA10548A2BA06D2D635F07892F8D67382900E0F85D56C63EBDA65FAF43CCA378009243C0AFDD70C30D3DBDC9DFD1E8D0D2934E3AE97A4A2DA02D92C8F7B95F5FE21989FEA5F603004E9CFEBEEA1AB24F501400C921E0F724E1EB768CCFEF40A905BC4C9FDB8325EE28B50F005039869318028181A17180983A75EAB3B279D6775F5252D248D98CD01FB4D4D4D4919452D0D1DEE2B912ED247E213104804A3547E23A895A12FF32655F83A89D143B282A80E410006A9A0E251D6F27876B25CA9A68E87B8977282A0038667ADDE1D9128F4A3C68CABE742392E410203904007FF0B11D0F1B4F0F621A450200956AA6C46CE399219AB50F8100C035870042DD0B12BA7665278A02002A9DCB4E0C87521400C921000482D724FA18CF3A870080CAF7A2C41914034072080081942002002ABF7DE9349E6B1001901C02805FD1464A4C19FB32241A513C0070427492995D65EC7F57E2648A07F05F4C48032014FD54CEFE45D48B0050A536520480FFA2E710000E55441100000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C5204000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C02000000008E2C82220080F20D1830E03187C3F14C390F8F484A4A1AE1BB233535D541A90100804044CF21001CA9920C0B4BA314000000C9210084B82953A6CC944D56059FBE851203000024870010A4DC6EF7A74779CA01FB7933292D000040720800C19B1C4E3DCAE32EDD3A1C8EC994160000203904802055AB56AD4592F8ED2CEF71792C5A36991919198B282D000040720800416AC284094EB7DBFD55390F5BBD86F2F8E7F3E7CF2FA2B4000000C9210004B7F7CBD95F6C55A661619F5044000080E41000829C3D6434AF8C872225B66CDFBE7D2EA5040000480E0120C8D943462796DAED1D523A9321A5000080E4100042842481B34ADD77D937BFA174000000C9210084881D3B76E83A86DBBDF71D0E47846C325D2ED70C4A070000901C024088B0878ECE2AB57BE6B469D3F2291D000040720800A1E590594B1D0E07B39402000092430008353131313FF9DE8F8E8E9E4FA9000000924300083113264C70CA6695DE76381CEBE47E0EA50200008241044500A0A6B9DDEE98F5EBD7DF9B9F9F3F70DFBE7DA7EEDDBB37C6E572F9EDDF9B9999697EFEF96773F6D967B7B9EDB6DBDCFEFA774AF2EA8E8E8EDE1D1515F5F38103075EE8DEBDFBB71C6D000080E410805F92A4F07F7FF9E597179D4E67ADC4C444A351B76E5D1316E6DF031BAEBBEE3ABF2F5B49B01D927037CACBCBBB222323A3E782050B7E2F282818D8BB77EF748E3C0000501AC34A01D4984D9B367DBE71E3C637E3E3E36B9D73CE39A665CB96A65EBD7A7E9F18064C052FE5181717679A376F6EBA75EB16D5A2458BAEDA8B386FDEBC6B281D0000407208C06F1243896B3A76EC689A356BA6432029942AD6B46953D3B56BD758491A27CD9D3BF74A4A040000901C02A8513A9474DDBA75D79C7AEAA956CF566985F93BCC96B44966CDB74F9AD5F3469A4D4BC71B67DE560AAE12D4AE5DDB74E9D2A5AE24E39366CD9AD589120100002487006A844E3E939999F9A20E212D2F31DCBCF43D939FB9DAB88AF71BB7ABC8ECCBFAD36C5AF22E0962252688AD5AB572858787BF426900000092430035426725D5C96774886359B2362E3445FBF71EB65F13C5CCF5F329C04AD2BC79F386111111EDE7CC99733EA5010000480E01543B5DAE4267242DEF1AC38223F40E6AAF222A4F424242866CFA5112000080E41040B5D3750C7546D2F2B88B0F94FF62B78B02AC448D1A356A269B1E9404000050AC7308A05AE902F7BA8E216A9E7C0E4D64D398920000008A9E4300D5CAE572B18EA1BFFC00783E074E12020000924300FE2732B641B98F4544D3E30800004072082024346C79818988AA7DD8FEF0C858D3F0E4EE1410000000C921805050A7F169A676A353CBDC5F37A123050400004072082054141F28386C5F51E11E0A06000080E4104028D8BF7797D9B4E45D93BFEBF7C31EDBBBFB0FB3E99771D6730000004072082048E56E5B2A89E13B665FF6FA729FB32F67A3D9F0F39B267BD30FC6CD9A87000000958A29CC01D428ED09DCB1E62BAB67B0225CC5FBADE7EFD9F5BB4938E50A13632DD5070000801345CF21801AA53D81154D0C7D690FE3C6FFBE4D01020000901C020806DA1378BCDCAE220A100000A09230AC14408DEAD0731485000000E007E8390400000000901C0238E1FA807A040000200830AC14F0FF84ADB1C49912F5EC6DBCFDD83F25B6977AFE5FECED8F3EDF71BD30AF8EC4DF25A2259E29E7DFEA2B71AEC463E53C1E23718DC4D452FBC7497C20F1ADC4C9121BF9D8000000480E01541E4D02CF96D82DB1C04ECCFE23B1D0E7391D2456D989DB60892D127F9338456280C42B12A74BAC95182F91EDF3DA2E128912DE05033BDB8FF7B4EF37B0B7D3ECAD53E277FB7D574BB4B15FDBD24E5C6F95E828F1301F1D000000C92180CAD1CE4EDE34F9AA25D1C24E14DB98833D87DAAB78B9C493129B25E64A4449DC213156E2FF493497D82AF14519FFC669F66BF6F824837BEC4454F5F14910BD964BA4DB7F97BEBEC0E7B18BCCE1BD8A00000008105C2B04F827EDE9FBDC4E08CB932431CC4E0CD52A3B59D4EFF51A73682FA1D7E9A5EE174AECB7E380F10C41F5DED7DBB9F6F39A495C67279D5DEC24748AFD376EB0B7B7DAFBEBF0F1010000041E7A0E01FFA5BD730DECC44BE9F582DBCCC161A53A7C74877DBB89F10C07D584F05D89D912FF90986927989A04EA904F1DFEF9A5CF7B5C650EF6FE9D6FDFF62677FABA25F66DED7DFC54E2528934FBB193EDBF5187BAF6B5FF3E4D30B567339F8F0F000080E41040E56963275EEA1C3BF9F30E2B3DC9E7793A31CD24FBB6F6EC69AFDE32E3B91E7091F10C2B6D2531BAD4FB7F592A91D3DB73EDDBDA7B1855CEDFA549638A393804D5FBF7AD344C48030000407208A052E9F050EDB1F3F6F2C5DB49E062FB7E3F9FE7FA5EA3E84D28F5F9E1127F1CE1FDEBFADC8F350767365531E6E0643565A96B27905E45A6EC6B1B010000407208E004E9904DEF75823AB94C6D73700299F77D9EB7D64E0E7598E93AE3E961D4E1A80F98436737F5A5CFE96A27754A673875DAA1128CA7F7B1B4C6F65687AA7E552A5904000000C921804A76A5F1F4E6C5FB245F453EF76F93C8349E6B00955E33F888F10CF7D424F15673709DC3B2CC2C755F7B0C7D8795CE2DE335DADBA84B66E85A897A8D615F9FC7CE29E73500000020390470024A0FD12C3D218DF60C5E613CCB4B6862F6A2CF7375E6525D03718DCFBEDA47F9F7222BF037E549BC6CDF3E60FF0D5A8F686F623D3E3200000092430095CBF71A422FBDAD8BD6FBF6D6696F622B73F03A44E393106E2FB53FFB28FFA60E13DD7394E73CE6737BB7BDD59E499DB8A6BBC4643E3A0000009243009567AD1DC7E3157BBBB8D4FE378EF2BA639D4C66B8CF6D9DA1F40E3EB6D071C30D37F40C0B0B3B3F35357514A5010000C921000495DDBB779B850B179ABE7DFB9A1F7EF8C1FCF6DB6F262121E190E74C9B36CD8C1933C6DA2FC99115F7DC738F19356A94993973A6494E4E3653A64C31B56BD736575F7D75D0944D8F1E3D22E4FFB987FCFF5E23776F9688B31F2239040080E41000824B7C7CBC69D4A8919931638689888830CD9B37377DFAF4316FBDF596E9D7AF9F69DCB8B1D9BA75AB69DAB4A9292A2A329F7DF699898C8CB46E6B52A90961464686993D7BB6B9F6DA6BCD175F7C613EF9E413337AF468EBBD0231216CD2A4C9F96EB7FBEF127D1C0E47638E120000480E01202474EFDEDDB85C2E2BC1D39E44ED299C3E7DBA292C2C34B1B1B14612244FE529C9A3F610DE7CF3CD25AF7DF5D557CD4B2FBD64EEB8E30E73C1051758BD89E3C78FB77A1703497272721F2983DE7273B02485D6BA97DEFF6F000040720800414D7BFCD2D2D2AC183870A0B54F7B12B5E770DEBC79E6FEFBEFB792C67FFFFBDF87BC2E2A2ACA4A14751B1D1D6D6AD5AA65F52EEA736362620222311C3468508CD3E93C5F12C05BE5EFBE5C12C2C624830000901C0238DC88A4A4244AA1922C5DBAD49C7EFAE9D6F04D7FA2D7105E7AE9A5562FA1F73AC3E5CB979B2D5BB658499EF612FEFEFBEFD69052AFC183079B9F7FFED96467679B5DBB76994F3FFDD44A12EBD7AF6F7AF7EE6DDE78E30DBFFE2CD6AD5B670D7B95C4B040EF4B5278CC3D84F2DD18C9510DA0B27F77290280E410E0872A04FCFAEBAFE6E4934FB6AEC9F327DAC3A7899D37F43AC2B3CE3ACB9C7BEEB9262E2ECEE4E7E75B7FF38409134A5E939B9B6B0D43AD57AF9EB9E4924BCC575F7D655AB76E6D25C093264DB27A1977ECD861EEBEFB6ED3B16347BFFB2C74C86C4E4E0EDF0D00004072081CC5048AA0F29D79E699232EBCF042BFFF3BF7EEDD6B4E3BED346B88A9F6102E5EBCD874EAD4A9E4F13FFFFCD31A76EA4D2CD7AC59630D4D3D70E08095FCEA4CA73ADC5427B2F1C7C450F5EFDFDF8C1D3BD64A724B29B27B112BF21BF1044735007E8701924320A8A5A6A66E90CD484AA272DD7EFBED23FC6D4869694EA7D36CDBB6CDEA05D4F02E4951A74E9D9244AA6DDBB6A6499326D6B585E1E1E1A64B972ED6EBF6ECD963F5362ADD6A82E8AFDAB46963AEBFFE7A3379F2E4D88282829E920CEA24347D259AFB0C2F3D20E196882AE77BC277040000924300083E3A9CF4B5D75EB36E6B8FE0FAF5EBAD2529B4E7F0F2CB2F3FE4B93AF98CD2994DDBB76F6F5D9BF8FDF7DF5BB39A6EDEBCD9ECDFBFDF3CF8E0837EFFFF3C61C204A76C6668F4E8D1E3C1C4C4C4BE6EB7BBB724887D3451F43E4FF6154A99C8C61DC391020000C921000435BDB65097A798356B96755F2799D1DEBF6EDDBA59C9A25E33599A2453D64435AB56AD32E79D775E494FA3D2496C7498A93791F477F3E7CF2F92CDC776E884333D64D34F42D7396CA7C34D010000C9210004BDF7DF7FDF2C5BB6CC0C1830C05349DAC34235F9D3896674B90AF5C30F3F987DFBF659899F5E53F8C71F7F5813D76812A8B7BD56AF5E7DC850D340939A9A3A5F7346BD2D6572BE6C6E2FDDA3080000480E01202875EDDAB5CCFD3A7BA986D245EEBD744869798EF458A0993A75EA4FB2F98923040080E01446110000000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487000000000092430000000000C9210000000080E410000000004072080000000020390400000000901C02F08B4A272CCCED72B928083F209FC346D9145112000080E41040B58B8989D9B967CF1E0AC20F646767A7CB268D92000000248700AA5D6464E4A2DCDC5C0AC20F646464E4C9663E25010000480E01543BA7D3F9DCF6EDDB0FB8DD6E0AA3666DC8CACAEA2ADB4F280A0000407208A0DA5D74D1453F4B62B87CDBB66D14460D4A4F4F9F239FC3B6CB2EBBEC274A030000901C02A8114EA773E0860D1BF6E5E5E5511835202727677A5656D6552E97EB414A030000901C02A831BD7BF75E2589C9352B57AECC2541ACFEC470C58A159D1D0EC71DF239A45322000080E410408DEAD9B3E7DCA2A2A2EB972D5B96B769D3A62CAE41AC721BD2D3D3C72D5FBEFC3CB97DBF94FF0C8A040000F80AA70800D494891327AE4B4949F93C3737B7EBB66DDBE29C4EE79AB0B030477474741D87C3E1B77F776666A699356B9669DCB8B1A955AB96DFFE9DBA8E615656D6F7EBD7AF5FB27AF5EAF882828208D997D2AB57AF451C7D00001CAA53A74E3D64A3F15D7A7AFAFC502C83080E030035498798EA66F6ECD9676CDFBEBD9F8456CAF52562FCF56F5EBA74A9F9F5D75FCDC68D1BCD59679DE5CFC5DB4C6297C4EF12AF30F90C0000203904E0F77AF5EAA58BB107C482EC4949492365334212C4271E7DF4D1917C7A0000201870CD210000000080E410000000004072080000000020390400000000901C0200000000480E01000000002487004257339FDB2DCA794E5CA9E70100000435D63904108A264844D9B775FB8CC45089111233EDFD6F4A3C4051010000924300085EF74BFC66DF9E2CB150A2AF844B62925D37BE2FB18BA202000024870010BC9AFA2487D13EFB3A482C91F8AF61D83D000020390480A0B7D7E7F69312D91299C6D38BE8358062020000A18433E30042517F896FED785B224662BEFDD84B124D24A64ADC4D510100805041CF218050F48E39F49A43A7F10C25554FD9C9A27A8FA202000024870010BCDA19CFE4335E1D7CB60DECE4B09EBD6F15C5050000480E0120387536077B0A1FB6B7F7DBDB5C9FE7D5A6A8000000C9210004A75A12D74AF494785CA2ABC4B2729E7B9EC4588A0C0000901C0240F0D927D1CDBE7D92C44D12BB25BE2EE3B92B282E000040720800C16F87F1CC48AA75A12E5D319922010000A18AA52C0050FF19534462080000421D3D87004291CE48FAA9C41B7692B844A29F397CE98A5D141500000815F41C020845D912DB2492253EB1F77591F8ABF15C8778A9C4E912DF52FE932C07000003F5494441545400002054D073082014F5B5B7C34AED4F97586B3C6B20EAF588D75154000080E4100082538C9D149E2DD1CADE774B19CFDB4D51010000924300085E4EE359CA4227A0192DB1C627490400002039048010D4C74E0EF5FAEBCE12E37C1ED37D7B25AEA098000000C9210004AF27ECC430CE4E04BBD8FBE30D434A0100400862B65200A1EA747BABCB5AACF2D9AF89E1788A070000841A7A0E0184A2A1E6E09A868F4B9C52EA713D713656E2018A0A0000901C0240F01AED73FB55E359C202000020A431AC1440A8DB4A11000000901C02403645000000C0B05200A1E96EE359A2E24A895F8C67C90A1525B1DFE7796324BEA2B8000000C9210004A73724DE329EE52C6E349E252D543B890D1245127524FE4E720800004205C34A0184A29B24EA19CF8CA40DEC7D174B1CB01342633FFE0A45050000480E012078E9BA86ED7C423D24B151A2BF7D5F27AA29A2A8000000C9210004AFFFDAF1A6F10C236D2C7197FDD80289161411000008355C73082054FD3F896EF6F6050997BD5F7B0BF51A44BDD690994C010000C9210004B9977CB62F957A2C46E23C893612E3292A0000100A18560A20542D2C753F4EE212FBB653E23B1243000040720800C16DB4C4FFF824859A08E6497C6B3C3398B6A188000000C92100043F1D46EA5DECFE79E359C6C2EB01899E121F514C0000209470CD218050B4DBE7F69D653CFE6F899F29260000104AE8390480B2A5510400002094D0730820547D616F9F92D829B1D91C5CCE42FDDDAE23DF38C27B8C484A4AA2240100080E23480E0120343D26B156A2AE44BCC4B3C673EDA10E336D29D14262383F24000080E41000829F4E4AB3DB8E4724A22466D9DBBF1EE17513283A00008216BFF30010624EB7B78D25FE22F1B644079FC78750440000000010DC3E9538C778868ED63AC2F352282A0000102A18560A20144D918891686547794EA1A80000000020789D6227878D7D6E4FB6B76FDB5B8D3A141500000815F41C0208554EBB0E8CB16F7BF74D9328B203000080E41000825C3BE3E9196C2011EDB32FD77826A8594811010080501246110008510724B225D6D9B71FB7B73B255EA6780000000020F8C51CE5F1361411000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040D9FE3F95B3FBD6F91ADCBB0000000049454E44AE426082',NULL),('212504',1,'请假流程.bpmn20.xml','212503',X'3C3F786D6C2076657273696F6E3D27312E302720656E636F64696E673D275554462D38273F3E0A3C646566696E6974696F6E7320786D6C6E733D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F4D4F44454C2220786D6C6E733A7873693D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612D696E7374616E63652220786D6C6E733A7873643D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612220786D6C6E733A61637469766974693D22687474703A2F2F61637469766974692E6F72672F62706D6E2220786D6C6E733A62706D6E64693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F44492220786D6C6E733A6F6D6764633D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F44432220786D6C6E733A6F6D6764693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F44492220747970654C616E67756167653D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D61222065787072657373696F6E4C616E67756167653D22687474703A2F2F7777772E77332E6F72672F313939392F585061746822207461726765744E616D6573706163653D22687474703A2F2F7777772E61637469766974692E6F72672F70726F63657373646566223E0A20203C70726F636573732069643D2270726F636573735F6C6561766522206E616D653D22E8AFB7E58187E6B581E7A88B2220697345786563757461626C653D2274727565223E0A202020203C73746172744576656E742069643D22737461727422206E616D653D227374617274222F3E0A202020203C757365725461736B2069643D22757365723122206E616D653D22E7BB8FE79086E5AEA1E689B9223E0A2020202020203C657874656E73696F6E456C656D656E74733E0A20202020202020203C61637469766974693A7461736B4C697374656E6572206576656E743D226372656174652220636C6173733D22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222F3E0A2020202020203C2F657874656E73696F6E456C656D656E74733E0A202020203C2F757365725461736B3E0A202020203C73657175656E6365466C6F772069643D227369642D30443235384332342D314631392D343233332D413937362D4130443843423944414541432220736F757263655265663D22737461727422207461726765745265663D227573657231222F3E0A202020203C757365725461736B2069643D22757365723222206E616D653D22E4BABAE4BA8BE5AEA1E689B9223E0A2020202020203C657874656E73696F6E456C656D656E74733E0A20202020202020203C61637469766974693A7461736B4C697374656E6572206576656E743D226372656174652220636C6173733D22636F6D2E6C656E2E6163746C697374656E65722E4163744E6F64654C697374656E6572222F3E0A2020202020203C2F657874656E73696F6E456C656D656E74733E0A202020203C2F757365725461736B3E0A202020203C6578636C7573697665476174657761792069643D227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222F3E0A202020203C73657175656E6365466C6F772069643D227369642D33334642463234452D464537302D343730412D394442352D3942313838314531333834372220736F757263655265663D22757365723222207461726765745265663D227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222F3E0A202020203C6578636C7573697665476174657761792069643D227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222F3E0A202020203C757365725461736B2069643D227573657222206E616D653D22E8B083E695B4223E0A2020202020203C657874656E73696F6E456C656D656E74733E0A20202020202020203C61637469766974693A7461736B4C697374656E6572206576656E743D226372656174652220636C6173733D22636F6D2E6C656E2E6163746C697374656E65722E4C656176654C697374656E6572496D706C222F3E0A2020202020203C2F657874656E73696F6E456C656D656E74733E0A202020203C2F757365725461736B3E0A202020203C656E644576656E742069643D22656E6422206E616D653D22656E64222F3E0A202020203C73657175656E6365466C6F772069643D227369642D35343537313339312D463242332D344342342D383041302D3039324441303237373341372220736F757263655265663D22757365723122207461726765745265663D227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222F3E0A202020203C73657175656E6365466C6F772069643D227369642D41453541454438342D303734362D343738372D393836462D36413739323743333443333422206E616D653D22E5908CE6848F2220736F757263655265663D227369642D42453337324431342D463530392D344544422D383745382D37423231303738333541453522207461726765745265663D227573657232223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D747275657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D34373638373538312D333535422D343335342D383433432D43333034323333323836414622206E616D653D22E5908CE6848F2220736F757263655265663D227369642D35353636443037362D414234432D344134322D393938462D32353337373839463831383122207461726765745265663D22656E64223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D747275657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D46423539344242452D383030352D344544432D423343382D39373831454432323643393522206E616D653D22E4B88DE5908CE6848F2220736F757263655265663D227369642D35353636443037362D414234432D344134322D393938462D32353337373839463831383122207461726765745265663D2275736572223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D66616C73657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D39394343413337462D413233352D343835332D383437322D44453233334144324544333222206E616D653D22E9878DE696B0E794B3E8AFB72220736F757263655265663D227573657222207461726765745265663D227573657231223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D747275657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D35313046453036322D433042432D343643382D394231372D38413338303732413242433622206E616D653D22E4B88DE5908CE6848F2220736F757263655265663D227369642D42453337324431342D463530392D344544422D383745382D37423231303738333541453522207461726765745265663D2275736572223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D66616C73657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A202020203C73657175656E6365466C6F772069643D227369642D30344339463239412D304242352D343639312D383034432D37363445344530413237313622206E616D653D22E58F96E6B688E8AFB7E581872220736F757263655265663D227573657222207461726765745265663D22656E64223E0A2020202020203C636F6E646974696F6E45787072657373696F6E207873693A747970653D2274466F726D616C45787072657373696F6E223E3C215B43444154415B247B666C61673D3D66616C73657D5D5D3E3C2F636F6E646974696F6E45787072657373696F6E3E0A202020203C2F73657175656E6365466C6F773E0A20203C2F70726F636573733E0A20203C62706D6E64693A42504D4E4469616772616D2069643D2242504D4E4469616772616D5F70726F636573735F6C65617665223E0A202020203C62706D6E64693A42504D4E506C616E652062706D6E456C656D656E743D2270726F636573735F6C65617665222069643D2242504D4E506C616E655F70726F636573735F6C65617665223E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227374617274222069643D2242504D4E53686170655F7374617274223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2233302E303030303030303030303030303037222077696474683D2232392E3939393939393939393939393939332220783D2234352E30303030303030303030303030312220793D2235342E3939393939373335303930343633222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227573657231222069643D2242504D4E53686170655F7573657231223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2238302E30222077696474683D2239392E39393939393939393939393939372220783D223135302E30303030303030303030303030332220793D2232392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227573657232222069643D2242504D4E53686170655F7573657232223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2238302E30222077696474683D2239392E39393939393939393939393938392220783D223435342E353435343431333138323233322220793D2232392E393939393936343536383335303633222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831222069643D2242504D4E53686170655F7369642D35353636443037362D414234432D344134322D393938462D323533373738394638313831223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2233392E3939393939393939393939393939222077696474683D2234302E302220783D223636302E303030303030303030303030312220793D2234392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D227369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535222069643D2242504D4E53686170655F7369642D42453337324431342D463530392D344544422D383745382D374232313037383335414535223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2233392E3939393939393939393939393939222077696474683D2234302E302220783D223331352E303030303030303030303030312220793D2234392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D2275736572222069643D2242504D4E53686170655F75736572223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2237392E3939393939393939393939393937222077696474683D223130302E30303030303030303030303032332220783D223238352E30303030303030303030303030362220793D223139352E3030303030303030303030303033222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E53686170652062706D6E456C656D656E743D22656E64222069643D2242504D4E53686170655F656E64223E0A20202020202020203C6F6D6764633A426F756E6473206865696768743D2232372E393939393939393939393939393933222077696474683D2232382E302220783D223832352E303030303030303030303030322220793D2235352E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E53686170653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136222069643D2242504D4E456467655F7369642D30344339463239412D304242352D343639312D383034432D373634453445304132373136223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E30303030303030303030303031372220793D223237352E30222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E30303030303030303030303031372220793D223332312E30222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223833392E303030303030303030303030322220793D223332312E30222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223833392E303030303030303030303030322220793D2238332E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336222069643D2242504D4E456467655F7369642D35313046453036322D433042432D343643382D394231372D384133383037324132424336223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E343432303733313731363637352220793D2238392E3535373932343137393233373233222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223333352E313231353830353435313534372220793D223139352E3030303030303030303030303033222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143222069643D2242504D4E456467655F7369642D30443235384332342D314631392D343233332D413937362D413044384342394441454143223E0A20202020202020203C6F6D6764693A776179706F696E7420783D2237352E302220793D2236392E3939393939373335303930343634222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223135302E30303030303030303030303030332220793D2236392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332222069643D2242504D4E456467655F7369642D39394343413337462D413233352D343835332D383437322D444532333341443245443332223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223238352E30303030303030303030303030362220793D223233352E30303030303030303030303031222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223230302E302220793D223233352E30303030303030303030303031222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223230302E302220793D223130392E3939393939373335303930343634222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334222069643D2242504D4E456467655F7369642D41453541454438342D303734362D343738372D393836462D364137393237433334433334223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223335342E353536333634373232353534352220793D2237302E34343336333236323833353032222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223435342E353435343431333138323233322220793D2237302E3134373838353935303338353032222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935222069643D2242504D4E456467655F7369642D46423539344242452D383030352D344544432D423343382D393738314544323236433935223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223638302E353030303030303030303030312220793D2238392E3439393939373335303930343634222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223638302E353030303030303030303030312220793D223233352E3030303030303030303030303036222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223338352E303030303030303030303030332220793D223233352E3030303030303030303030303036222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437222069643D2242504D4E456467655F7369642D33334642463234452D464537302D343730412D394442352D394231383831453133383437223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223535342E353435343431333138323233312220793D2237302E3134323037383834393533323231222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223636302E3434333030353038333433392220793D2237302E3434333030323433343334333434222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137222069643D2242504D4E456467655F7369642D35343537313339312D463242332D344342342D383041302D303932444130323737334137223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223235302E302220793D2237302E31383434393931393539323331222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223331352E34323539323539323539323630342220793D2237302E3432353932333237363833303536222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A2020202020203C62706D6E64693A42504D4E456467652062706D6E456C656D656E743D227369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146222069643D2242504D4E456467655F7369642D34373638373538312D333535422D343335342D383433432D433330343233333238364146223E0A20202020202020203C6F6D6764693A776179706F696E7420783D223639392E353630313236353832323738362220793D2237302E3433393837303736383632363135222F3E0A20202020202020203C6F6D6764693A776179706F696E7420783D223832352E303030303639363538383436312220793D2237302E3034343136313136393031353535222F3E0A2020202020203C2F62706D6E64693A42504D4E456467653E0A202020203C2F62706D6E64693A42504D4E506C616E653E0A20203C2F62706D6E64693A42504D4E4469616772616D3E0A3C2F646566696E6974696F6E733E',0),('212505',1,'请假流程.process_leave.png','212503',X'89504E470D0A1A0A0000000D494844520000035F0000014B0806000000299E36CD000022BE4944415478DAEDDD0D8C94F5B928F04D0AA949DBD4269AB4699BDA734F9A93DEA4C734986A3C369BA64D6C6A234DC57559AA5B6BA1D7A245D1D45AA8D61B2247AD043C0D6AF1B3AD4288410FF5822E2B5F453842391641A920C8C7F2B1A80B0559387CBCF77DA6F36E8665665976677767677FBFE49F9D9D995DE0E5F93FFFE779BFA6A6060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006429224C3B66CD93277D5AA55279A9B9B93A6A626A31FC7A2458B9265CB96BD978E31A211E42FF90B00AA58142ECB972F4F5A5B5B93A3478F1A0330F6EDDB972C5DBAF4405AC85C252241FE92BF00A04AC51E63854B451430479B9A9ADE1291207FC95F0050A5E2541DC543658CB47839262241FE92BF00A04AC579FB0A878A295E121109F297FC050043BC7839B47F77B265F513C98645F7E4463C8EE7141D8A1790BF0CF90B00CA54BC1C6C6B49D6BF3439F9EB8BB79F32E2B9784DE1A17801F94BFE1291005086E265C786FF3CAD70C9C6CE0DF3151E8A1790BFE42FF90B00CA51BCBCB5F8DF4B162FF19AC243F102F297FC252201A00CC5CBFAA6BB4B162FF19AC243F102F297FC25220140F1A27801F94BFE92BF006070142F7177B052C54BBCA6F050BC80FC257F8948002843F1B269C57F942C5EE2358587E205E42FF94B440240198A97F75BD625EB5FBEEBF45376D2E7E2358587E205E42FF94B440240198A97185BD73C7D5AF112CF293A142F207F19F2170094AB78397224D9F4EACCD34FD9499F8BD7141E8A1790BFE42F110900BD2C5E0EB6B5246FAF78A8E43513F15ABC47F1A17801F94BFE02007A52BC1C3992ECDEF44AF2C6C23B4B162ED988F7C47BED4556BC80FC257F01006751BC9C696FB1BDC88A1790BF0CF90B00CA50BC74676F71577B9115228A970A73AE4D207FC95FF217722C4045162F3D2D5CB2A11051BC5490CBD391E4BF227FC95FF217722C4065152F86E2A54A8C4C475B3AEE4FC7BE745C6393C85F86FC851C0BA07831142FE5D5982F066AF3DF5F98FFFE069B46FE32E42FE45800C58BE245F152DEA26044A7E71507F297217F21C702285E0CC54B99DC918E1DE9B8B8C4EBFF928EADE9186F53C95F86FC851C0B43527D7DFD79757575E3AFB9E69ADFA763753A0EA62349477BFAFC7FA7AF3F9B3EBE6DD4A8519FB6B5142F8A174AB83B5F145C7086F77D2E1D6FA463663A86D96CF297217F21C7A2571812D28D74414343C3A3D75E7BED7B93274FDEF4FCF3CFEFDAB061436B7B7BFBB12475F8F0E19D1B376EDC3C67CE9C2513274E5C9E6ED8F7D29F99996ED87FB6F5142F8A170A4CEB665190895B23AF4EC7EF1507F297217F21C752B9BD42D4FEE9D8976FB6CE34DAF50A25A40DD71DE938347BF6ECF60F3FFC30E98EB4296B9F39736653BA51F7A76392ADA87851BC90FA5D3AFE3B1D67BBB72B8A83A6743CA13890BF0CF90B39968A6BBC6E2B38C275B6E3985E212FED443F3E7EFCF895F7DE7BEF91D6D6D6A427DE7BEFBD0337DD74D37FA51B757E6363A30FF753BC285E86A6610545C1793DFC1DE7A463793AE6E51F237F19F217722C03DC2BD4D5D5CDEBDC504D9E3C39993F7F7EB27DFBF6E4EF7FFF7BAE278803382D2D2DC9C2850B932953A6146BC28676AF70F7DD779FFBB39FFD6CDF534F3D951C3F7E3CE9ADE9D3A7BF515F5FFFD7380F54A82A5E142F434A2CE2F3D3B1B8077B634BFDAE26C581FC65C85FC8B10C6CE395BFA6EB94A6EBEDB7DFEE566FF0EEBBEF26F7DC73CF290D58FE9AB0A1D72B44E375C71D77BC3777EEDCA49C1E7FFCF177A20173044CF1A27819527B6317142CE4C3D331A687BF6B4CFEE7E3773E912F34E412F9CB90BFE45839968169BC1617364ED137F4E4804DFC5C4343C3290DD890EB15A64C99F2B7993367267DE1BEFBEEDB986ED8B9C256F1A278A97A913857E60B836C0FEAE3E948F25F8777F3F70C2FF8B9C70A9EBFBFA677A7D8207FC95FC8B1722C3D90D6F24F64CD52344E2B56ACE8557FB07AF5EAE4073FF841E151B0A1D32BA44DD7BD13264C48BA7B638DB3D5DEDE9EFCF0873FDC9976B5D7085DC58BE2A5AA8B82D535A75EBC3D26BFB867A3B91B7B55CFCDBFAFF0E7C6742A0EDE4A873B25C95F86FC25C7CAB1F44FE375557D7DFDF1AC515AB26449597A8455AB56753E05B1FA7B85C58B177FFCE69B6F3E1EDD675F7AE38D370E8E1E3D7A5B1CB214C28A17C54BD5F95C91A220DBBBFA58A745FECD747CB1C4EFF9A7FCA25FF8FEC78AECCD8DE260ABE240FE32E42F39568EA56FD5D6D60E4B1BAFCD598354EE33E566CD9A55D8806DADFA5EE1B1C71E7BE181071E48FAC3A44993D6A7FF791384B1E245F152552E48C7A674DC5B53FA76C5BF48C7C982C5BE351D97747ACF25F9E7B3F79CCCFF5C2993F2C5C105FE0BE42F43FE9263E558FA46DA10FD246B8EAEBFFEFA8E3B19964B9C79F7E31FFFB8A301ABEA5E21FDF79EF3CB5FFEF25877EF50D25B9B376F3E3A7AF4E875C258F1A278A9AAA22016E7FFDB8DF75E9D8EF68285BF3DFFDC995EEBCA4FF24589BDB3F297217FC9B1722C7DD37CADCC1AA3B8957C5F885BD117DE7CA36A37E69A356BFECFEDB7DF5E96DBCA77D70D37DCF0AE4FB5AEA949BBFAA674FC9BE245F132D862B2C085E9D8978E3BCEE2678AED797DA9C81EDB8BCFE27736E68B930B2D9195152FF297FC851CCBE08EC9B419BA20BBD6ABB1B1B14FEF0F1147D5B206AC6A7B85A79E7A6AE9134F3C91F4A769D3A6BD1E9F886D2F42C7A1D5A6B4C3BF58F1A278192C31D9A928B8A1077F545C8BF066CDA9D71C74E75A85AE8CC9FF7D46584E2B275EE42FF90B3996C11D93E9F3E3B3F7DD77DF7D7DDA23CC9831A3F0DAAFEAEC15A64E9D7AE02F7FF94BBF365F6BD6ACD91A9F662DE04FFB84EF05C5F63E285E142F951693A96FE617E19FF4E28FFB423A3EE854147C907FBEC7FF84FCDFEB9B96D4CA8817F94BFE428E6570C764DCFEBDDC77382C256E5D5FF077A9CE5EE1E69B6F3EB67BF7EE7E6DBEF6ECD9D39A6ED01D02FEB480EFD8FB5018F88A17C54B85C5E4B9F9457C662FFEA86277DBEAED5ED9CCEFF2BFC787845640BCC85FF217722C833B26D3EF3765CF6FDFBEBD4F7B84969696C2BF4775F60A71EE669C63D99FE2CF4B3768BB802F1EF0857B1FE210B0E245F152693199DFEBD9968E2B7AF0C774F77A844B7AF0BBB3BFD7E596D4CA88973FFEF18F7287FC851CCB208EC9741CCEBE2FF75D0E8BDDF5B0E0CF6EAFDA8D3E10BAF19F6DE4477F375F6BD7AECD25E79800EFBFFF7EC778F3CD3793952B5776F9B35BB76E3DE5FBB6B6B664E3C68D25DF1F7FCEF4E9D3BBFC9DF19EDB6EBBADE371DC65277BFCDA6BAFF57BF12226FF31F28BEFD916077D7127AECE45C115FE7F2A6F0C44B3117174E38D3776FBFDCF3DF75CF2A52F7DE994E722EF5553FEEA66B165C8B172AC5174F4778F5095CDD775D75D77B2BF8F7C1D3E7C788F235F5D2E80ABEBEAEAAE880FB41B88D3762229FFE217BFC83D8E736FF7EDDB976BBEE2F9ABAFBEBAE37DBB76ED4AFEF0873F24975C7249F2F4D34F278F3EFA68EE3DF3E6CDCB7DBDE1861B92B973E7763472F1334B972E4D5E78E185E4DA6BAFCD7DFDEC673F9B7CED6B5FCB3D8E11C5CF17BFF8C5D3FE3EF1E17BD9E3679E79E6B4C7F61CF76F4C765A8C0F76B338B8B3E6CC77DB3ADBCFA0C9F4A448A11FE265208FDC470C7DF7BBDF2DF9FA45175D941B593EFACC673E931B593E7AF8E18773BF63E7CE9DF21772AC1C3B6463327D7CD091AF32BAE9A69B8EF6F7355F69D1FE37D77C150DF8A2C9B73F8B97ECA857E7BDBAE79F7F7E72E9A597962C70A2F0C81EBFFEFAEBB9AF4F3EF964B26DDBB6DCE368D48A151C1FFDE84793A953A7767C3F7CF8F08EC6EF9D77DEC9FDDEF899749B2473E6CCC93DCEF644C7E375EBD6C50D5C142FFD1C93A5F68696787D783A1EAFE9FE3507C5EED2F578FEF7141377DEDAA728A8CC7819E8E62B9AA9AEDE130DD557BEF295D39AAFDFFEF6B7C9C73EF6B1D37E9FFC851CCB508B49D77C95D9E4C99337AD5AB5AA5F9BAF975E7AE9FFB9DBE12901BFB2BEBE7E64A9E4DB5FC54B140B5971F1E52F7F39F9C637BE917B3E8E6AC5E3F81AC5C88E1D3B8A365F070F1ECC3D8EA361350547BE0A8B9F03070EE41ABC68C662647B85E3719C9E58AC50EABCE7F8539FFA546E0F733C5EB06041EE6B7CAF78E9BF983CCBBDA2633A2DF2CD3567BE50FBDCFCFB0A7FAEA14451127B85475A422B335E06AAF98A333A226E3EF9C94F76F9BEC8515FFDEA577339289AB018D951FDCF7FFEF3A7BC57FE428E6528C6A4BB1D96D9FDF7DF3F2B1686FE74D75D77BDE873BE72C1DC9D3D5EFD56BCC451AAD873BB69D3A65C228E662C0A97071F7CB0E33DB197365E8BBF53345BD9698571CA611C258BC7D9298AD1C465054A61C316DF472397356BF13BE2715C0BD1794F73F6FEB80E23FBB3B3EBCEE2F185175EE8B49D0188C92E8A838335C52FC4CEF6CA3ED6C5DED5627B731F2BF8B9527B831505151C2F03D57CC5F55435F9235FD188957ADF65975D96DC7AEBADB91C14F924463C8E26ABB9B9B9683E92BF9063194A31D99F9FF3356DDAB4EAFF9CAF499326FDAFF1E3C79F387EFC78BFDDEC70F4E8D1EFC4A7650BF9EEE9CFE265CF9E3DB9A220AEF38AC629CEBD8DC2221B2FBEF862AE49EBEAB4C3AC218BEB22E2F1E2C58B4F7B7F9CC2989D92139F669E9DF273E5955776BC6FF9F2E5491A2B1DCD5EE1EFCF1EC7A93C8A978A927D36CDE54516F9861EFECE31458A09D71FC85F673CE5F0DBDFFE762E8FC4E3520D58E4B462D77CC5F55CD134153BD22F7F21C732943434347C2EADDB8F4543943ECEED64EF0B7193B63163C69C2C68BEAAB757B8F5D65B37F7D7072DBFF4D24B7F4837E672A15C79C54B769A4E5CC710A7DCC469343FFFF9CF73D725D4E4AFE18A862C2647E762248E92455396153835F9235FD1C4156BD60A0B90AC718B53700A4F11CAEEB658D3E922F5C29F8DBF5B577BB5152F03225BB4FBEA56C46E752C7F752B97C511AA2C57C4DEDACE47FAE374EA68D08A355F93274F4E264C9890FBD9C2EBB2E42FE45886A2F8DCAFAC298A1AB12F3CFBECB38547BDAABB57F8D18F7E346AE2C489C7FAE1E857DBE8D1A3D7A6FF8163847165162FD12C658FE3C61985CD54B1BDB4710A4D4DFE8E627121799C7A93ED118E8226AE65883DC09D9BAF287A3AEF393EEFBCF372C5CE99AE9988D389E29CE0789CDDD063FDFAF58A97CA2B0EF6F5C1E2FD6F8A02F9AB3B47BDC68D1BD7F17DE487C266AC3B47BE221F7DEF7BDF2BFABBE52FE4588660F335326B8CE2E857B96FBC11BF2FED114E167CC873F5F70AE942B52E0AE7BE14D7974527DBC3739D152F7D3CE233BAA210888BCC63AF46612356D87CD5E46FBD1CA7E3C4E352D74514EEEDCD6ED5DCD59D128B35825971127B8BB3BDD935057763CCEECE987D8E8EE2A5A2947BEF691405BB6B9C06237F9DA1F18AD3FD8A7D8657BC1637D7E87CF43EDBC914392B3B321547F3E3FAD733FD59F217722C43455AC32FCE9AA3B856B65CB79D8F3305264E9C78BCF0A8D790E815E2BCCAEBAFBFFEF0DB6FBFDD278DD7BA75EB5E48FF8CDD6927FB2FC2B7728B97C20F498E2225FB0C9B285CB2CFB2890BD43B7FD8725C2B16178FC7293CF19E983C8D8D8DB9C7F13960714A4EA9E225FBD0D162235EAB29B848BDB0D089D7BEF5AD6FE5FECC52CD9DE2A522F6CE96A3385014C85F5D8EC80171C3A0B8757C57B7958F7C52ECC3E0E3E854BC76D75D779D55A3277F21C732849AAF0BD2B12F6B92225FF6B6018BC66BCA942985D7791D1C52BDC29831631AC68D1BF7616B6B6B591BAF7461F9F3E8D1A3B739DD7070EC39EEEF6B3306D3DF57F13220C5415F5FDF80FC257F21C7CAB174435D5DDD35D9CD37B223603D3D05317EAED311AF6448F60A0D0D0DD78F1D3BF660B98E80C511AF68BCD2FFAC3B84ACE265B00FC54B8FF5F4F41877DC92BF0CF90B39960A9236498D850D585C031697ABC45904DDBDAB61DC5CA3F01AAF1843BA5788AE76CC9831079E7FFEF943BDB80947DB6F7EF39B27E254C3F84F12AA8A17C58BBDB367591CD81B2B7F19F217722C15DA2BA4A3ADB0798A262CEE2C1B1FC41C47B5B25312E3D4C2969696DCCD8666CC98915C77DD75270A7F2E4E35D42BFCA3ABBD20ED489BC78D1BB767EDDAB587CFE673BC5E7EF9E567D3E66D755C30E71A2FC58BE2854E7B67BB7387AEDA9A7F7C98A8BDB1F297217F21C752A1BD42E12DE87B38F40A4536EC55D184353636B64E9D3A75C39FFFFCE76D69F7BA3BCE750F870F1FDEB36BD7AEBF2D5AB4E84F77DF7DF782B4EBDD121B323A58773554BC285E28B1B7B5AB453F8A82B8F0DB5E30F9CB90BF90631904BD42BE093B76364D975EE10CE2D3ADD30D3B21DD5073D3B1351DEDF98D175F77A4637E3A6EABEA4FA356BC285E142F7D5D1C7477AF2DF297217F21C752D9BDC209BD028A1743F15239BED9A938C88A02A7C1C85F86FC851CCB20565757777176242C6DC834FB285E0CC54B85C8F6CE4EABB13756FE32E42FE458AAA5F99A57708AE16A5B04C58BA178A91CB13736B6ABBDB1F297217F21C732C8A5CDD688CED77FA5CD98F843F162285E2AC8B93681FC65C85FC8B15445F335BFC80D3656BBB9068A1743F1523989DA7695BF0CF90B3996C11F6B234ADDF5B0BEBE7EA42D84E2C550BC280C90BFE42FE458284FAC2DE8E2F6F22B6D21142F86E2456180FC257F21C742EFE36CC4993EEBCBB55F285E0CC58BC200F94BFE428E85DEC7D9FC6E7CB8B23B1FA27831142F0A03E42FF90B3916C41E285E142F9233F297217F21C722F640F1A278417246FE92BF906341ECA17831142F9233F297217FC9B1722C620F142F8A172467F9CB90BF9063117BA07831142F9233F297FC851C0B620FC58BA178919C91BF0CF90B3916B1078A17C50B9233F297FC851C8BD8137B285E0CC58BE48CFC257F21C782D803C58BE2457246FE32E42FE458C41E285E0CC58BE48CFC257F21C782D843F162285E2467E42F43FE428E45EC416F3437372B1C2A63B4A7C5CB31112939237FC95FC8B120F6A852CB962DDBDDDADAAA7818E0D1D2D2323B2D5EDE12919233F297FC851C0B628F2AF5CA2BAF5CB964C992FD7BF7EE3DAC8818983DC651B82C5AB4685B3AAE12919233F297FC851C0B628F2A962E9A57343535AD8ED346E2BC7DA35F476CF3B7142E9233F297FC851C0B620F06C3E41B6102223903C8B1883DA0EF27DFFC9880B5B5B5C36C0D2467003916B107F481BABABA8BD3C9772C26607D7DFDE5B6089233801C8BD803FAA6F99A17932F3F56DB2248CE00722C620F28FFA41B911DF5CA46DA8C5D61CB203903C8B1883DA0BC936E7E61E3951DFD72ED179233801C8BD803CA37E14E3BEA958DFAFAFA91B6109233801C8BD803CA33E116146BBCF263A52D84E40C20C722F680DE4FB69247BD5CFB85E40C20C722F680F24DB6F95D355EEE7C88E40C20C722F6001310B10120C782D8031310B101801C8BD8034C40C406801C0B620F4C40C406801C0B620F4C40C40600722C620F3001111B00722C883D3001111B00C8B1883DC004446C00C8B1883DC004446C00C8B120F6C004446C0020C722F6001310B10120C782D8031310B101801C8BD8031310C406801C8BD8034C40C406801C0B620F4C40C40600722C620F3001111B00722C883D3001111B00722C883D3001111B00C8B1883DC004446C00C8B120F6C004446C0020C722F6001310B10120C722F6001310B10120C782D8031310B101801C8BD8034C40C406801C0B620F4C40C406801C2BC722F6C00404B10120C722F6001310B10120C782D8031310B101801C8BD8034C40C406801C8BD8137B6002223600E458107B60022236009063117B800988D800906341EC810988D800408E45EC0126206203408E45EC0126206203408E05B10726206203003916B1079880880D003916C41E9880880D003916C41E9880203600E458C41E6002223600E458107B60022236009063117B800988D8009063117B800988D800906341EC810988D800408E45EC0126206203408E05B10726206203003916B10726A00988D8009063117B800988D800906341EC810988D800408E45EC0126206203408E05B10726206203408E05B1072620880D003916B1079880880D003916C41E9880880D00E458C41E6002223600E458C41E6002223600E458107B60022236009063117B800988D800906341EC810988D800408E45EC8109086203408E45EC0126206203408E05B10726206203003916B1079880880D003916C41E9880880D003916C41E9880880DB10120C722F600139032C7C1FC8885338CD5B61480F517B1079880F42E0E46A4E35857CD575D5DDD15B61480F517B1079880F43E161674D17CADACADAD1D662B01587F117B800948EF636144A9E6ABBEBE7EA42D0460FD45EC012620E58B8762D77EAD76D40BC0FA8BD8034C40CA1B0FA75DFBE55A2F00EB2F620F3001E90369B335CF512F00EB2F620F3001E9FBE6EBE2826BBD2EB74500ACBF883DC004A4EFE22277ED97A35E00D65FC41E6002D2B77131426C00587F117B800958D1922419B665CB96B9AB56AD3AD1DCDC9C34353519FD3C162D5A942C5BB6ECBD748C119180F517C41E9880552A1AAFE5CB9727ADADADC9D1A3478D011AFBF6ED4B962E5D7A206DC4AE129580F517C41E988055288E7869BC2AA6013BDAD4D4F496A804ACBF20F6C004AC4271AAA1C6A77246DA7C1D139580F517C41E98805528AE39D2F45454F325C601EB2F883D30018772F37568FFEE64CBEA27920D8BEEC98D781CCF6998345F80F517C41E988094A9F93AD8D692AC7F6972F2D7176F3F65C473F19AA649F305587F41EC810948199AAF1D1BFEF3B4C62B1B3B37CCD73469BE00EB2F883D30012947F3F5D6E27F2FD97CC56B9A26CD1760FD05B10726206568BED637DD5DB2F98AD7344D9A2FC0FA0B620F4C40345F9A2F00EB2F620F30010747F31577372CD57CC56B9A26CD1760FD05B10726206568BE36ADF88F92CD57BCA669D27C01D65F107B60025286E6EBFD9675C9FA97EF3AFD94C3F4B9784DD3A4F902ACBF20F6C004A40CCD578CAD6B9E3EADF98AE7344C9A2FC0FA0B620F4C40CAD57C1D39926C7A75E6E9A71CA6CFC56B9A26CD1760FD05B1072620BD6CBE0EB6B5246FAF78A8E4355FF15ABC47E3A4F902ACBF20F6C004A427CDD79123C9EE4DAF246F2CBCB364E3958D784FBCD75130CD1760FD05B107262067D17C9DE96897A3609A2FC0FA0B620F4C40CAD07C75E768575747C134519A2FC0FA0B620F4C40BAD17CF5B4F1CA86264AF305587F41EC810948379A2F43F30560FD45EC810968026ABE345F00D65FC41E60026ABE0CCD1760FD05B10726209A2FCD1780F517B10798809A2F43F305587F41EC8109A8F932345F80F517C41E988068BE345F00D65FC41E60026ABE0CCD1760FD05B10726A0E64BF3A5F902B0FE22F6001350F3A5F902B0FE22F6001350F36568BE00EB2F883D3001D17C69BE00ACBF883DC004D47C199A2FC0FA0B620F4CC02A525B5B3B4CF3A5F902B0FE22F60013B08F2449F2E99D3B77AE5CB162453269D2A489A59A30CDD7E06ABED23930A2AEAE6E9E0807ACBF883DC004AC00DBB76F9FDCDEDE7E2CC93B72E4C8FFCC9E3D7BD34F7FFAD3FFADF91A9CCD57345DE9989F8E63E60160FD45EC0126E0003B74E8D0BFEEDDBBF7DDA484AD5BB7B64F9D3AF5E1C6C6C673345F83A3F9EADC746543B403D65FC41E60020E80B4AF3A67C78E1DBF3F71E2C4C9E40C4E9E3C7962E1C285EFDD72CB2DDFD57C556EF355575777719C5ED8B9E9D27C01D65FC41E60020E90BD7BF77E7FFFFEFD0792B3D4D6D67664E6CC99CDF3E7CFD7F45458F355EC4897E60BB0FE22F6807E9F80C6A963C68C19D148253D68BE723F1BBFA3A5A5A5629B91F7DF7F3F926EEEEFDBDEDE9EAC5DBB36F75CE158BC78F1693F173F73DF7DF7257BF6ECE9F87ECA942983A5F9320CC3A8B8A10A41F3050C790D0D0D9F1B3B76EC9F5E7DF5D5DD274F9E3CDE9DC66BFFFEFDCF8C1B376E719CD696AAF886E4231FF94872D96597E59AAF68A2A2018BAF0F3CF040477396BDF7139FF844F2E69B6FE69E5BBA74691247F6D6AF5F9FFBFEB5D75E4B162C58907BBC6FDFBE8A3EEDF0EAABAFFE66BAE0AC540401A0F902A830F5F5F5237FFDEB5FEF686B6B6BEDE27AAFF58F3CF2C8EFD244B629DE1F3F3758AEF93A70E040C711ACA79F7E3AF7F5D24B2FCD9A958EF745B3357DFAF4DC734F3EF964EEEBE8D1A393679E79A6E3E7E7CC9933686EB891FE3F5D9EFE7F2DD77C01A0F902A820A3468DFA784343C3F4E79E7BAEF5C48913870BFAAEF6CD9B373F9CBEB6BEAEAE6E5A6363E3B9D9CF5472F31547A7E273CAA2614AFF4D1DCD5376642B8E686DDCB8F194E6EB85175E48264F9E7C4A931647BC962F5FDEF1FDC1830707DDADE6F347C2966BBE00D07C015456A21A71CB2DB7ACDBB2654BCBE1C38797DE79E79D73F2A7B08DE8FCDEC170E42B1AA6ECF4C878FCD0430F25DFFFFEF7936BAFBD3679F9E5974F69BEB66DDB96CC9A352BF7DC45175DD4F1739B366DCA3DF79DEF7C67507FC872FE48D84A510E80E60BA042D4D6D60E4B0BF50991B4E26B7C5FEC7D83B1F98A1147B8E26BE7235FE79D775EEE5AAF786EE7CE9DB9EBC5621BC4B55EF1FA8D37DE987BADB9B97950365F00A0F902A8E026ACABD7074BF315A7186EDDBAB5E37AAEEC461BD9CD34E27DBB76EDCA7D8DC62A8E74C588D315BFFEF5AFE71EAF59B326D78C7DF8E18783F6C8170068BE0006A9C1D27C0D1F3E3C77038DECA856DC3423BEC66986350547BE0A7F26AE0DCB8E90655F1F7CF0C1417DDA210068BE00345F7DDA7CC56779D5E46F11FFFAEBAFE79ECF6E9C51AAF95AB76E5DAEE9FAC217BE70CA6BD91132CD170068BE00345F9D465CDB15A718163E17A711D6E46FAC5178ABF968B8CE3FFFFCDCD7B8F9467C46D8F8F1E373DF3FFAE8A3B99FC96E5DAFF90200CD1780E66B080ECD170068BE00CD97A1F90200CD1780E64BF305009A2F00CD97A1F90200CD17A0F9D2F468BE0040F305A0F9D27C0180E60B40F36568BE0040F305A0F9D27C0180E60B40F36568BE0040F30568BE0CCD170068BE00345F9A2F00D07C0168BE0CCD170068BE00345F9A2F00D07C0168BE345F161900D07C019A2F43F305009A2F00CD97E60B00345F009A2F43F305009A2F40F36568BE0040F305A0F9D27C0180E60B40F36568BE0040F305A0F9D27C0180E60B40F36568BE0040F30568BE0CCD170068BE00345F9A2F00D07C0168BE0CCD170068BE00345F9A2F00D07C01F4AFE6E6664D4FE58CF6B4F93A262A0140F30554A165CB96ED6E6D6DD5F854C0686969999D365F6F894A00D07C0155E895575EB972C99225FBF7EEDD7B5803347047BCA2F15AB468D1B6745C252A0140F30554A9B4E0BFA2A9A969759CF216D71C0DC6316FDEBC64B0FEDDF3DBFD2D8D170068BE002ADADEBD7BBF3F63C68C244DD017D81A00A0F902A00F244972CE071F7CD0964AC68E1DFB275B0400345F00F4811D3B76FC3EC97BF5D5575BEAEBEB47DA2A00A0F902A08C0E1D3AF4AF274E9C389914983265CA8EC6C6C6736D1D00D07C0150267BF6ECD99274B27FFFFE3D0D0D0DD36D1D00D07C015006DBB76F9F9C94306FDEBC3D69B21E612B0180E60B805E48FBAB4F1F3972E47F4A355F274F9E3C7ACB2DB7ACABADAD1D666B0180E60B801EDAB973E7CAE40CB66CD9B2A3BEBE7E82AD05009A2F007A68C58A1567EABD92F6F6F62591B01B1B1BCFB1C50040F305400FFCEA57BFFA6957A71D46EF75E79D77CE71E40B00345F00F4D2ECD9B3FF56AAF3DABC79F3C369B25EE99A2F00D07C01D04BA3468DFAE7B4C96A2F72B38DF50D0D0DEBDDED1000345F0094C9FDF7DFFF50DA6C9D286CBE66CD9AF5585D5DDD345B0700345F0094499C56B870E1C2D6820F587E264DD29B1A1B1BCFB5750040F30540198D1F3FFE1B6D6D6D47D2918C1D3B76517D7DFD485B0500345F00F481471E7964C18C193392BABABA79B6060068BE00E823719A6124E7B80987AD01009A2F00246700C0FA0E20390300D67700246700B0BE0320390300D67700C91900B0BE0320390300D67700C91900B0BE0320390380F51D00C91900B0BE0348CE0080F51D00C91900B0BE0348CE0080F51D40720600ACEF0048CE0080F51D40720600ACEF0048CE00607D0740720600ACEF00923300607D0740720600ACEF00923300607D0740720600EB3B00923300607D07909C0100EB3B0092330058DFADEF00923300607D07909C0100EB3B00923300607D07909C0100EB3B0092330058DF0118E8E46C1886611846F50D550E00000000000000000000000000000000000000000000000000000000005075FE3F9FEF977BF087DB470000000049454E44AE426082',1); # # Structure for table "act_re_model" # DROP TABLE IF EXISTS `act_re_model`; CREATE TABLE `act_re_model` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL, `LAST_UPDATE_TIME_` timestamp(3) NULL DEFAULT NULL, `VERSION_` int(11) DEFAULT NULL, `META_INFO_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `EDITOR_SOURCE_VALUE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `EDITOR_SOURCE_EXTRA_VALUE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', PRIMARY KEY (`ID_`), KEY `ACT_FK_MODEL_SOURCE` (`EDITOR_SOURCE_VALUE_ID_`), KEY `ACT_FK_MODEL_SOURCE_EXTRA` (`EDITOR_SOURCE_EXTRA_VALUE_ID_`), KEY `ACT_FK_MODEL_DEPLOYMENT` (`DEPLOYMENT_ID_`), CONSTRAINT `ACT_FK_MODEL_DEPLOYMENT` FOREIGN KEY (`DEPLOYMENT_ID_`) REFERENCES `act_re_deployment` (`ID_`), CONSTRAINT `ACT_FK_MODEL_SOURCE` FOREIGN KEY (`EDITOR_SOURCE_VALUE_ID_`) REFERENCES `act_ge_bytearray` (`ID_`), CONSTRAINT `ACT_FK_MODEL_SOURCE_EXTRA` FOREIGN KEY (`EDITOR_SOURCE_EXTRA_VALUE_ID_`) REFERENCES `act_ge_bytearray` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_re_model" # INSERT INTO `act_re_model` VALUES ('142517',53,'请假流程','processKey',NULL,'2018-01-25 17:21:39.000','2018-05-17 21:11:56.681',1,'{\"name\":\"请假流程\",\"description\":\"\"}','212503','142518','142519',''); # # Structure for table "act_re_procdef" # DROP TABLE IF EXISTS `act_re_procdef`; CREATE TABLE `act_re_procdef` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `KEY_` varchar(255) COLLATE utf8_bin NOT NULL, `VERSION_` int(11) NOT NULL, `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `RESOURCE_NAME_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `DGRM_RESOURCE_NAME_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `HAS_START_FORM_KEY_` tinyint(4) DEFAULT NULL, `HAS_GRAPHICAL_NOTATION_` tinyint(4) DEFAULT NULL, `SUSPENSION_STATE_` int(11) DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', PRIMARY KEY (`ID_`), UNIQUE KEY `ACT_UNIQ_PROCDEF` (`KEY_`,`VERSION_`,`TENANT_ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_re_procdef" # INSERT INTO `act_re_procdef` VALUES ('process_leave:1:212506',1,'http://www.activiti.org/processdef','请假流程','process_leave',1,'212503','请假流程.bpmn20.xml','请假流程.process_leave.png',NULL,0,1,1,''); # # Structure for table "act_procdef_info" # DROP TABLE IF EXISTS `act_procdef_info`; CREATE TABLE `act_procdef_info` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `INFO_JSON_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), UNIQUE KEY `ACT_UNIQ_INFO_PROCDEF` (`PROC_DEF_ID_`), KEY `ACT_IDX_INFO_PROCDEF` (`PROC_DEF_ID_`), KEY `ACT_FK_INFO_JSON_BA` (`INFO_JSON_ID_`), CONSTRAINT `ACT_FK_INFO_JSON_BA` FOREIGN KEY (`INFO_JSON_ID_`) REFERENCES `act_ge_bytearray` (`ID_`), CONSTRAINT `ACT_FK_INFO_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_procdef_info" # # # Structure for table "act_ru_execution" # DROP TABLE IF EXISTS `act_ru_execution`; CREATE TABLE `act_ru_execution` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PARENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `SUPER_EXEC_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `IS_ACTIVE_` tinyint(4) DEFAULT NULL, `IS_CONCURRENT_` tinyint(4) DEFAULT NULL, `IS_SCOPE_` tinyint(4) DEFAULT NULL, `IS_EVENT_SCOPE_` tinyint(4) DEFAULT NULL, `SUSPENSION_STATE_` int(11) DEFAULT NULL, `CACHED_ENT_STATE_` int(11) DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `LOCK_TIME_` timestamp(3) NULL DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_EXEC_BUSKEY` (`BUSINESS_KEY_`), KEY `ACT_FK_EXE_PROCINST` (`PROC_INST_ID_`), KEY `ACT_FK_EXE_PARENT` (`PARENT_ID_`), KEY `ACT_FK_EXE_SUPER` (`SUPER_EXEC_`), KEY `ACT_FK_EXE_PROCDEF` (`PROC_DEF_ID_`), CONSTRAINT `ACT_FK_EXE_PARENT` FOREIGN KEY (`PARENT_ID_`) REFERENCES `act_ru_execution` (`ID_`), CONSTRAINT `ACT_FK_EXE_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`), CONSTRAINT `ACT_FK_EXE_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `ACT_FK_EXE_SUPER` FOREIGN KEY (`SUPER_EXEC_`) REFERENCES `act_ru_execution` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ru_execution" # # # Structure for table "act_ru_event_subscr" # DROP TABLE IF EXISTS `act_ru_event_subscr`; CREATE TABLE `act_ru_event_subscr` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `EVENT_TYPE_` varchar(255) COLLATE utf8_bin NOT NULL, `EVENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `ACTIVITY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `CONFIGURATION_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `CREATED_` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', PRIMARY KEY (`ID_`), KEY `ACT_IDX_EVENT_SUBSCR_CONFIG_` (`CONFIGURATION_`), KEY `ACT_FK_EVENT_EXEC` (`EXECUTION_ID_`), CONSTRAINT `ACT_FK_EVENT_EXEC` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `act_ru_execution` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ru_event_subscr" # # # Structure for table "act_ru_job" # DROP TABLE IF EXISTS `act_ru_job`; CREATE TABLE `act_ru_job` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL, `LOCK_EXP_TIME_` timestamp(3) NULL DEFAULT NULL, `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `EXCLUSIVE_` tinyint(1) DEFAULT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `RETRIES_` int(11) DEFAULT NULL, `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `DUEDATE_` timestamp(3) NULL DEFAULT NULL, `REPEAT_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', PRIMARY KEY (`ID_`), KEY `ACT_FK_JOB_EXCEPTION` (`EXCEPTION_STACK_ID_`), CONSTRAINT `ACT_FK_JOB_EXCEPTION` FOREIGN KEY (`EXCEPTION_STACK_ID_`) REFERENCES `act_ge_bytearray` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ru_job" # # # Structure for table "act_ru_task" # DROP TABLE IF EXISTS `act_ru_task`; CREATE TABLE `act_ru_task` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `PARENT_TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TASK_DEF_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `DELEGATION_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PRIORITY_` int(11) DEFAULT NULL, `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL, `DUE_DATE_` datetime(3) DEFAULT NULL, `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `SUSPENSION_STATE_` int(11) DEFAULT NULL, `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '', `FORM_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_TASK_CREATE` (`CREATE_TIME_`), KEY `ACT_FK_TASK_EXE` (`EXECUTION_ID_`), KEY `ACT_FK_TASK_PROCINST` (`PROC_INST_ID_`), KEY `ACT_FK_TASK_PROCDEF` (`PROC_DEF_ID_`), CONSTRAINT `ACT_FK_TASK_EXE` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `act_ru_execution` (`ID_`), CONSTRAINT `ACT_FK_TASK_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`), CONSTRAINT `ACT_FK_TASK_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ru_task" # # # Structure for table "act_ru_identitylink" # DROP TABLE IF EXISTS `act_ru_identitylink`; CREATE TABLE `act_ru_identitylink` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_IDENT_LNK_USER` (`USER_ID_`), KEY `ACT_IDX_IDENT_LNK_GROUP` (`GROUP_ID_`), KEY `ACT_IDX_ATHRZ_PROCEDEF` (`PROC_DEF_ID_`), KEY `ACT_FK_TSKASS_TASK` (`TASK_ID_`), KEY `ACT_FK_IDL_PROCINST` (`PROC_INST_ID_`), CONSTRAINT `ACT_FK_ATHRZ_PROCEDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `act_re_procdef` (`ID_`), CONSTRAINT `ACT_FK_IDL_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`), CONSTRAINT `ACT_FK_TSKASS_TASK` FOREIGN KEY (`TASK_ID_`) REFERENCES `act_ru_task` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ru_identitylink" # # # Structure for table "act_ru_variable" # DROP TABLE IF EXISTS `act_ru_variable`; CREATE TABLE `act_ru_variable` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL, `REV_` int(11) DEFAULT NULL, `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL, `NAME_` varchar(255) COLLATE utf8_bin NOT NULL, `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, `DOUBLE_` double DEFAULT NULL, `LONG_` bigint(20) DEFAULT NULL, `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`), KEY `ACT_IDX_VARIABLE_TASK_ID` (`TASK_ID_`), KEY `ACT_FK_VAR_EXE` (`EXECUTION_ID_`), KEY `ACT_FK_VAR_PROCINST` (`PROC_INST_ID_`), KEY `ACT_FK_VAR_BYTEARRAY` (`BYTEARRAY_ID_`), CONSTRAINT `ACT_FK_VAR_BYTEARRAY` FOREIGN KEY (`BYTEARRAY_ID_`) REFERENCES `act_ge_bytearray` (`ID_`), CONSTRAINT `ACT_FK_VAR_EXE` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `act_ru_execution` (`ID_`), CONSTRAINT `ACT_FK_VAR_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `act_ru_execution` (`ID_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; # # Data for table "act_ru_variable" # # # Structure for table "file_info" # DROP TABLE IF EXISTS `file_info`; CREATE TABLE `file_info` ( `id` varchar(32) NOT NULL COMMENT '文件md5', `contentType` varchar(128) NOT NULL, `size` int(11) NOT NULL, `path` varchar(255) NOT NULL COMMENT '物理路径', `url` varchar(1024) NOT NULL, `type` int(1) NOT NULL, `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "file_info" # INSERT INTO `file_info` VALUES ('c5ca69c2971ac9add9efe91115bf500c','image/png',12105,'d:/files/2018/05/28/c5ca69c2971ac9add9efe91115bf500c.png','/2018/05/28/c5ca69c2971ac9add9efe91115bf500c.png',1,'2018-05-28 02:54:47','2018-05-28 02:54:47'); # # Structure for table "oauth_access_token" # DROP TABLE IF EXISTS `oauth_access_token`; CREATE TABLE `oauth_access_token` ( `token_id` varchar(256) DEFAULT NULL, `token` blob, `authentication_id` varchar(48) NOT NULL, `user_name` varchar(256) DEFAULT NULL, `client_id` varchar(256) DEFAULT NULL, `authentication` blob, `refresh_token` varchar(256) DEFAULT NULL, PRIMARY KEY (`authentication_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "oauth_access_token" # # # Structure for table "oauth_approvals" # DROP TABLE IF EXISTS `oauth_approvals`; CREATE TABLE `oauth_approvals` ( `userId` varchar(256) DEFAULT NULL, `clientId` varchar(256) DEFAULT NULL, `scope` varchar(256) DEFAULT NULL, `status` varchar(10) DEFAULT NULL, `expiresAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastModifiedAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "oauth_approvals" # # # Structure for table "oauth_client_details" # DROP TABLE IF EXISTS `oauth_client_details`; CREATE TABLE `oauth_client_details` ( `id` int(11) NOT NULL AUTO_INCREMENT, `client_id` varchar(48) NOT NULL, `resource_ids` varchar(256) DEFAULT NULL, `client_secret` varchar(256) DEFAULT NULL, `scope` varchar(256) DEFAULT NULL, `authorized_grant_types` varchar(256) DEFAULT NULL, `web_server_redirect_uri` varchar(256) DEFAULT NULL, `authorities` varchar(256) DEFAULT NULL, `access_token_validity` int(11) DEFAULT NULL, `refresh_token_validity` int(11) DEFAULT NULL, `additional_information` varchar(4096) DEFAULT NULL, `autoapprove` varchar(256) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; # # Data for table "oauth_client_details" # INSERT INTO `oauth_client_details` VALUES (1,'app',NULL,'app','app','password,refresh_token',NULL,NULL,180000,NULL,'{}','true'),(2,'mobile','mobile,test','mobile','all','password,refresh_token',NULL,NULL,180000,NULL,'{}','true'),(3,'test','test','test','test','password,refresh_token',NULL,NULL,180000,NULL,'{}','true'),(4,'webApp',NULL,'webApp','app','authorization_code,password,refresh_token,client_credentials',NULL,NULL,180000,NULL,'{}','true'),(5,'clientId','','clientSecret','all','authorization_code,password,refresh_token,client_credentials','http://www.baidu.com','',180000,NULL,'{}','true'),(6,'owen',NULL,'owen','app','authorization_code,password,refresh_token,client_credentials','http://127.0.0.1:9997/clientOne/login',NULL,180000,NULL,'{}','true'); # # Structure for table "oauth_client_token" # DROP TABLE IF EXISTS `oauth_client_token`; CREATE TABLE `oauth_client_token` ( `token_id` varchar(256) DEFAULT NULL, `token` blob, `authentication_id` varchar(48) NOT NULL, `user_name` varchar(256) DEFAULT NULL, `client_id` varchar(256) DEFAULT NULL, PRIMARY KEY (`authentication_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "oauth_client_token" # # # Structure for table "oauth_code" # DROP TABLE IF EXISTS `oauth_code`; CREATE TABLE `oauth_code` ( `code` varchar(256) DEFAULT NULL, `authentication` blob ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "oauth_code" # # # Structure for table "oauth_refresh_token" # DROP TABLE IF EXISTS `oauth_refresh_token`; CREATE TABLE `oauth_refresh_token` ( `token_id` varchar(256) DEFAULT NULL, `token` blob, `authentication` blob ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "oauth_refresh_token" # INSERT INTO `oauth_refresh_token` VALUES ('b96e057b4e1c4920428e833db48d4c15',X'ACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002462303132643438372D613930382D343361662D613865662D3533633533393963386264367372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001613B74C98E78',X'ACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000009770400000009737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B787074000A524F4C455F61646D696E7371007E000D740006617069646F637371007E000D74000C64617461626173652F6C6F677371007E000D74000673797374656D7371007E000D740008757365722F6164647371007E000D74000B757365722F64656C6574657371007E000D740009757365722F656469747371007E000D740009757365722F766965777371007E000D740008757365724C6973747871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0024787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00224C000573636F706571007E00247870740006776562417070737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00227870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000037708000000040000000274000A6772616E745F7479706574000870617373776F7264740008757365726E616D6574000561646D696E78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000174000361707078017371007E0033770C000000103F40000000000000787371007E002A3F40000000000000770800000010000000007870707371007E0033770C000000103F40000000000000787371007E0033770C000000103F40000000000000787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000001A40200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B0000000977040000000971007E000F71007E001171007E001371007E001571007E001771007E001971007E001B71007E001D71007E001F7871007E003D737200176A6176612E7574696C2E4C696E6B6564486173684D617034C04E5C106CC0FB0200015A000B6163636573734F726465727871007E002A3F400000000000067708000000080000000271007E002C71007E002D71007E002E71007E002F780070737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000001A40200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00244C000870617373776F726471007E000E4C0008757365726E616D6571007E000E7870010101017371007E0030737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F7200000000000001A4020000787077040000000971007E000F71007E001171007E001371007E001571007E001771007E001971007E001B71007E001D71007E001F787074000561646D696E'); # # Structure for table "properties" # DROP TABLE IF EXISTS `properties`; CREATE TABLE `properties` ( `id` int(11) NOT NULL, `key` varchar(50) DEFAULT NULL, `value` varchar(500) DEFAULT NULL, `application` varchar(50) DEFAULT NULL, `profile` varchar(50) DEFAULT NULL, `lable` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "properties" # INSERT INTO `properties` VALUES (1,'zuul.debug.request','false','unieap-eureka-config-client','dev','master'); # # Structure for table "sys_client_permission" # DROP TABLE IF EXISTS `sys_client_permission`; CREATE TABLE `sys_client_permission` ( `clientId` int(11) NOT NULL, `permissionId` int(11) NOT NULL, PRIMARY KEY (`clientId`,`permissionId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "sys_client_permission" # INSERT INTO `sys_client_permission` VALUES (1,71),(1,72),(1,73),(1,74),(1,75),(2,71),(2,72),(2,73),(2,74),(2,75),(3,71),(3,72),(3,73),(3,74),(3,75),(4,71),(4,72),(4,73),(4,74),(4,75),(5,71),(5,72),(5,73),(5,74),(5,75); # # Structure for table "sys_client_server" # DROP TABLE IF EXISTS `sys_client_server`; CREATE TABLE `sys_client_server` ( `id` int(11) NOT NULL AUTO_INCREMENT, `clientId` int(11) DEFAULT NULL, `moduleId` int(11) DEFAULT NULL COMMENT '模块ID', `serverId` int(11) DEFAULT NULL COMMENT '服务ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='服务授权表'; # # Data for table "sys_client_server" # # # Structure for table "sys_logs" # DROP TABLE IF EXISTS `sys_logs`; CREATE TABLE `sys_logs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `module` varchar(50) DEFAULT NULL COMMENT '模块名', `flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '成功失败', `remark` text COMMENT '备注', `createTime` datetime NOT NULL, PRIMARY KEY (`id`), KEY `userId` (`userId`), KEY `createTime` (`createTime`) ) ENGINE=InnoDB AUTO_INCREMENT=362 DEFAULT CHARSET=utf8mb4; # # Data for table "sys_logs" # INSERT INTO `sys_logs` VALUES (1,1,'登陆',1,NULL,'2018-03-14 03:59:44'),(2,1,'登陆',1,NULL,'2018-03-14 06:26:11'),(3,1,'登陆',1,NULL,'2018-03-14 08:39:16'),(4,1,'保存用户',1,NULL,'2018-03-14 08:43:48'),(5,1,'修改用户',1,NULL,'2018-03-14 08:43:56'),(6,1,'登陆',1,NULL,'2018-03-14 10:12:39'),(7,1,'登陆',1,NULL,'2018-03-14 13:01:21'),(8,1,'保存用户',1,NULL,'2018-03-14 13:02:36'),(9,1,'保存角色',1,NULL,'2018-03-14 13:03:08'),(10,1,'保存角色',1,NULL,'2018-03-14 13:03:18'),(11,1,'保存角色',1,NULL,'2018-03-14 13:03:36'),(12,1,'修改用户',1,NULL,'2018-03-14 13:03:43'),(13,1,'退出',1,NULL,'2018-03-14 13:03:50'),(14,4,'登陆',1,NULL,'2018-03-14 13:03:55'),(15,4,'退出',1,NULL,'2018-03-14 13:04:04'),(16,1,'登陆',1,NULL,'2018-03-14 13:04:09'),(17,1,'保存角色',1,NULL,'2018-03-14 13:04:18'),(18,1,'退出',1,NULL,'2018-03-14 13:04:22'),(19,4,'登陆',1,NULL,'2018-03-14 13:04:27'),(20,4,'退出',1,NULL,'2018-03-14 13:13:39'),(21,4,'登陆',1,NULL,'2018-03-14 13:13:45'),(22,4,'退出',1,NULL,'2018-03-14 13:22:28'),(23,4,'登陆',1,NULL,'2018-03-14 13:22:32'),(24,4,'退出',1,NULL,'2018-03-14 13:24:27'),(25,4,'登陆',1,NULL,'2018-03-14 13:24:31'),(26,4,'退出',1,NULL,'2018-03-14 13:24:50'),(27,4,'登陆',1,NULL,'2018-03-14 13:24:54'),(28,4,'登陆',1,NULL,'2018-03-14 15:49:48'),(29,4,'退出',1,NULL,'2018-03-14 15:51:00'),(30,4,'登陆',1,NULL,'2018-03-14 15:51:03'),(31,4,'退出',1,NULL,'2018-03-14 15:52:06'),(32,4,'登陆',1,NULL,'2018-03-14 15:52:09'),(33,4,'退出',1,NULL,'2018-03-14 15:56:29'),(34,4,'登陆',1,NULL,'2018-03-14 15:56:32'),(35,4,'登陆',1,NULL,'2018-03-14 15:57:21'),(36,4,'退出',1,NULL,'2018-03-14 16:03:58'),(37,4,'登陆',1,NULL,'2018-03-14 16:04:01'),(38,4,'退出',1,NULL,'2018-03-14 16:26:27'),(39,1,'登陆',1,NULL,'2018-03-14 16:26:31'),(40,1,'退出',1,NULL,'2018-03-14 16:26:48'),(41,4,'登陆',1,NULL,'2018-03-14 16:26:51'),(42,4,'退出',1,NULL,'2018-03-14 16:34:39'),(43,1,'登陆',1,NULL,'2018-03-14 16:35:19'),(44,1,'登陆',1,NULL,'2018-03-14 18:45:34'),(45,1,'登陆',1,NULL,'2018-03-14 23:30:14'),(46,1,'添加定时任务',1,NULL,'2018-03-15 00:00:08'),(47,4,'��½',1,NULL,'2018-03-15 04:37:19'),(48,1,'登陆',1,NULL,'2018-03-15 04:43:52'),(49,1,'生成代码',0,NULL,'2018-03-15 04:44:50'),(50,1,'生成代码',0,NULL,'2018-03-15 04:45:13'),(51,1,'修改菜单',1,NULL,'2018-03-15 04:45:57'),(52,1,'登陆',1,NULL,'2018-03-25 23:30:29'),(53,1,'登陆',1,NULL,'2018-03-26 18:16:00'),(54,1,'保存角色',1,NULL,'2018-03-26 18:16:20'),(55,1,'退出',1,NULL,'2018-03-26 18:16:29'),(56,1,'登陆',1,NULL,'2018-03-26 18:16:34'),(57,1,'退出',1,NULL,'2018-03-26 19:29:52'),(58,1,'登陆',1,NULL,'2018-03-26 19:29:57'),(59,1,'退出',1,NULL,'2018-03-26 19:31:43'),(60,1,'登陆',1,NULL,'2018-03-26 19:31:52'),(61,1,'登陆',1,NULL,'2018-03-26 22:36:47'),(62,1,'登陆',1,NULL,'2018-03-27 00:38:15'),(63,1,'登陆',1,NULL,'2018-03-27 00:46:41'),(64,1,'登陆',1,NULL,'2018-03-27 00:52:14'),(65,1,'登陆',1,NULL,'2018-03-27 00:54:55'),(66,1,'登陆',1,NULL,'2018-03-27 01:23:12'),(67,1,'登陆',1,NULL,'2018-03-27 02:20:42'),(68,1,'登陆',1,NULL,'2018-03-27 03:42:26'),(69,1,'登陆',1,NULL,'2018-03-27 04:56:58'),(70,1,'登陆',1,NULL,'2018-03-27 04:57:23'),(71,1,'登陆',1,NULL,'2018-03-27 04:58:41'),(72,1,'登陆',1,NULL,'2018-03-27 05:02:02'),(73,1,'登陆',1,NULL,'2018-03-27 19:17:50'),(74,4,'登陆',1,NULL,'2018-03-28 23:12:13'),(75,4,'登陆',1,NULL,'2018-03-28 23:41:49'),(76,4,'退出',1,NULL,'2018-03-28 23:41:53'),(77,1,'登陆',1,NULL,'2018-03-28 23:41:58'),(78,1,'退出',1,NULL,'2018-03-28 23:44:53'),(79,1,'登陆',1,NULL,'2018-03-28 23:44:57'),(80,1,'退出',1,NULL,'2018-03-28 23:46:18'),(81,1,'登陆',1,NULL,'2018-03-28 23:46:23'),(82,1,'登陆',1,NULL,'2018-03-31 03:31:00'),(83,1,'登陆',1,NULL,'2018-03-31 04:08:08'),(84,1,'登陆',1,NULL,'2018-04-03 00:08:01'),(85,1,'保存角色',1,NULL,'2018-04-03 00:08:29'),(86,1,'退出',1,NULL,'2018-04-03 00:08:37'),(87,1,'登陆',1,NULL,'2018-04-03 00:08:42'),(88,1,'登陆',1,NULL,'2018-04-03 01:18:56'),(89,1,'登陆',1,NULL,'2018-04-04 23:00:02'),(90,1,'登陆',1,NULL,'2018-04-09 06:48:29'),(91,1,'登陆',1,NULL,'2018-04-12 00:19:47'),(92,1,'登陆',1,NULL,'2018-04-14 20:01:20'),(93,1,'退出',1,NULL,'2018-04-14 20:01:26'),(94,1,'登陆',1,NULL,'2018-04-14 20:16:46'),(95,1,'登陆',1,NULL,'2018-04-14 20:42:45'),(96,1,'登陆',1,NULL,'2018-04-14 21:22:18'),(97,1,'登陆',1,NULL,'2018-04-14 21:42:05'),(98,1,'保存用户',1,NULL,'2018-04-14 21:42:43'),(99,1,'修改菜单',1,NULL,'2018-04-14 21:43:11'),(100,1,'生成代码',0,NULL,'2018-04-14 21:44:00'),(101,1,'生成代码',0,NULL,'2018-04-14 21:46:30'),(102,1,'生成代码',0,NULL,'2018-04-14 21:47:02'),(103,1,'生成代码',0,NULL,'2018-04-14 21:49:52'),(104,1,'生成代码',0,NULL,'2018-04-14 21:50:10'),(105,1,'生成代码',1,NULL,'2018-04-14 22:04:21'),(106,1,'文件上传',1,NULL,'2018-04-14 22:12:57'),(107,1,'文件删除',1,NULL,'2018-04-14 22:14:21'),(108,1,'登陆',1,NULL,'2018-04-15 01:43:48'),(109,1,'退出',1,NULL,'2018-04-15 01:49:59'),(110,1,'登陆',1,NULL,'2018-04-15 01:50:09'),(111,1,'登陆',1,NULL,'2018-04-15 11:36:18'),(112,1,'保存角色',1,NULL,'2018-04-15 11:39:42'),(113,1,'退出',1,NULL,'2018-04-15 11:39:46'),(114,1,'登陆',1,NULL,'2018-04-15 11:39:51'),(115,1,'生成代码',1,NULL,'2018-04-15 11:42:35'),(116,1,'退出',1,NULL,'2018-04-15 11:47:17'),(117,1,'登陆',1,NULL,'2018-04-15 11:47:21'),(118,1,'退出',1,NULL,'2018-04-15 12:11:38'),(119,1,'登陆',1,NULL,'2018-04-15 12:11:44'),(120,1,'登陆',1,NULL,'2018-04-24 10:29:06'),(121,1,'登陆',1,NULL,'2018-04-24 10:32:11'),(122,1,'登陆',1,NULL,'2018-04-24 10:34:41'),(123,1,'登陆',1,NULL,'2018-04-24 10:55:53'),(124,1,'登陆',1,NULL,'2018-04-24 10:57:04'),(125,1,'登陆',1,NULL,'2018-04-24 10:59:25'),(126,1,'退出',1,NULL,'2018-04-24 11:07:13'),(127,1,'登陆',1,NULL,'2018-04-24 11:09:14'),(128,1,'保存角色',1,NULL,'2018-04-24 11:09:34'),(129,1,'文件上传',1,NULL,'2018-04-24 11:09:48'),(130,1,'文件删除',1,NULL,'2018-04-24 11:09:58'),(131,1,'登陆',1,NULL,'2018-04-24 17:46:26'),(132,1,'保存角色',1,NULL,'2018-04-24 17:47:12'),(133,1,'登陆',1,NULL,'2018-04-25 14:38:39'),(134,1,'退出',1,NULL,'2018-04-25 14:39:03'),(135,1,'登陆',1,NULL,'2018-04-25 14:39:09'),(136,1,'退出',1,NULL,'2018-04-25 14:46:06'),(137,1,'登陆',1,NULL,'2018-04-25 14:57:04'),(138,1,'退出',1,NULL,'2018-04-25 14:57:42'),(139,1,'登陆',1,NULL,'2018-04-25 15:03:02'),(140,1,'退出',1,NULL,'2018-04-25 15:03:08'),(141,1,'登陆',1,NULL,'2018-04-25 15:08:17'),(142,1,'退出',1,NULL,'2018-04-25 15:09:17'),(143,1,'登陆',1,NULL,'2018-04-25 15:23:24'),(144,1,'退出',1,NULL,'2018-04-25 15:30:49'),(145,1,'登陆',1,NULL,'2018-04-25 15:30:57'),(146,1,'保存角色',1,NULL,'2018-04-25 15:52:18'),(147,1,'保存角色',1,NULL,'2018-04-25 15:53:03'),(148,1,'登陆',1,NULL,'2018-04-25 16:02:21'),(149,1,'退出',1,NULL,'2018-04-25 16:03:22'),(150,1,'登陆',1,NULL,'2018-04-26 09:32:24'),(151,1,'修改菜单',1,NULL,'2018-04-26 09:33:47'),(152,1,'退出',1,NULL,'2018-04-26 09:33:59'),(153,1,'登陆',1,NULL,'2018-04-26 09:34:07'),(154,1,'退出',1,NULL,'2018-04-26 09:36:21'),(155,1,'登陆',1,NULL,'2018-04-26 09:36:36'),(156,1,'修改菜单',1,NULL,'2018-04-26 09:37:12'),(157,1,'退出',1,NULL,'2018-04-26 09:37:22'),(158,1,'登陆',1,NULL,'2018-04-26 09:37:33'),(159,1,'登陆',1,NULL,'2018-04-26 09:39:50'),(160,1,'退出',1,NULL,'2018-04-26 10:25:09'),(161,1,'登陆',1,NULL,'2018-04-26 10:25:16'),(162,1,'保存角色',1,NULL,'2018-04-26 10:49:07'),(163,1,'退出',1,NULL,'2018-04-26 10:51:52'),(164,1,'登陆',1,NULL,'2018-04-26 10:52:46'),(165,1,'登陆',1,NULL,'2018-04-26 10:57:38'),(166,1,'保存角色',1,NULL,'2018-04-26 11:16:36'),(167,1,'登陆',1,NULL,'2018-04-26 17:48:38'),(168,1,'登陆',1,NULL,'2018-04-27 10:30:53'),(169,1,'登陆',1,NULL,'2018-05-02 11:58:33'),(170,1,'登陆',1,NULL,'2018-05-02 15:05:51'),(171,1,'登陆',1,NULL,'2018-05-03 14:44:52'),(172,1,'退出',1,NULL,'2018-05-03 14:53:01'),(173,1,'登陆',1,NULL,'2018-05-03 14:53:08'),(174,1,'退出',1,NULL,'2018-05-03 14:54:07'),(175,1,'登陆',1,NULL,'2018-05-03 14:54:18'),(176,1,'登陆',1,NULL,'2018-05-03 15:12:14'),(177,1,'登陆',1,NULL,'2018-05-04 09:43:22'),(178,1,'登陆',1,NULL,'2018-05-04 10:05:30'),(179,1,'登陆',1,NULL,'2018-05-04 12:16:22'),(180,1,'登陆',1,NULL,'2018-05-14 15:25:11'),(181,1,'保存角色',1,NULL,'2018-05-14 15:25:53'),(182,1,'退出',1,NULL,'2018-05-14 15:25:56'),(183,1,'登陆',1,NULL,'2018-05-14 15:26:01'),(184,1,'退出',1,NULL,'2018-05-14 15:26:15'),(185,1,'登陆',1,NULL,'2018-05-14 15:26:23'),(186,1,'保存模块',1,NULL,'2018-05-14 15:27:33'),(187,1,'保存模块',1,NULL,'2018-05-14 15:28:06'),(188,1,'保存服务',1,NULL,'2018-05-14 15:29:41'),(189,1,'保存服务',1,NULL,'2018-05-14 15:30:10'),(190,1,'修改服务',1,NULL,'2018-05-14 15:30:24'),(191,1,'退出',1,NULL,'2018-05-15 20:25:15'),(192,1,'登陆',1,NULL,'2018-05-15 20:25:16'),(193,1,'退出',1,NULL,'2018-05-15 20:29:35'),(194,1,'登陆',1,NULL,'2018-05-15 20:29:36'),(195,1,'退出',1,NULL,'2018-05-15 20:30:02'),(196,1,'登陆',1,NULL,'2018-05-15 20:30:03'),(197,1,'退出',1,NULL,'2018-05-15 20:43:21'),(198,1,'登陆',1,NULL,'2018-05-15 20:43:22'),(199,1,'退出',1,NULL,'2018-05-15 21:12:00'),(200,1,'登陆',1,NULL,'2018-05-15 21:12:02'),(201,1,'退出',1,NULL,'2018-05-15 21:21:59'),(202,1,'登陆',1,NULL,'2018-05-15 21:22:00'),(203,1,'登陆',1,NULL,'2018-05-16 10:45:32'),(204,1,'登陆',1,NULL,'2018-05-16 11:12:57'),(205,1,'登陆',1,NULL,'2018-05-16 11:16:12'),(206,1,'登陆',1,NULL,'2018-05-16 11:37:20'),(207,1,'退出',1,NULL,'2018-05-16 11:54:56'),(208,1,'登陆',1,NULL,'2018-05-16 11:54:57'),(209,1,'退出',1,NULL,'2018-05-16 14:05:34'),(210,1,'登陆',1,NULL,'2018-05-16 14:05:36'),(211,1,'退出',1,NULL,'2018-05-16 14:13:04'),(212,1,'登陆',1,NULL,'2018-05-16 14:13:05'),(213,1,'登陆',1,NULL,'2018-05-16 14:20:20'),(214,1,'登陆',1,NULL,'2018-05-16 14:33:50'),(215,1,'登陆',1,NULL,'2018-05-16 14:44:44'),(216,1,'退出',1,NULL,'2018-05-16 14:46:48'),(217,1,'登陆',1,NULL,'2018-05-16 14:46:49'),(218,1,'退出',1,NULL,'2018-05-16 14:55:08'),(219,1,'登陆',1,NULL,'2018-05-16 14:55:09'),(220,1,'登陆',1,NULL,'2018-05-16 15:29:35'),(221,1,'退出',1,NULL,'2018-05-16 16:12:33'),(222,1,'登陆',1,NULL,'2018-05-16 16:12:34'),(223,1,'登陆',1,NULL,'2018-05-16 16:12:40'),(224,1,'登陆',1,NULL,'2018-05-16 16:36:01'),(225,1,'登陆',1,NULL,'2018-05-16 17:07:55'),(226,1,'登陆',1,NULL,'2018-05-16 17:31:19'),(227,1,'登陆',1,NULL,'2018-05-16 17:49:52'),(228,1,'登陆',1,NULL,'2018-05-16 17:55:27'),(229,1,'登陆',1,NULL,'2018-05-17 14:12:25'),(230,1,'登陆',1,NULL,'2018-05-17 14:48:04'),(231,1,'登陆',1,NULL,'2018-05-17 14:52:12'),(232,1,'登陆',1,NULL,'2018-05-17 15:08:28'),(233,1,'登陆',1,NULL,'2018-05-17 15:09:36'),(234,1,'登陆',1,NULL,'2018-05-17 15:13:14'),(235,1,'登陆',1,NULL,'2018-05-17 15:43:52'),(236,1,'登陆',1,NULL,'2018-05-17 15:46:45'),(237,1,'登陆',1,NULL,'2018-05-17 15:50:35'),(238,1,'登陆',1,NULL,'2018-05-17 15:51:46'),(239,1,'登陆',1,NULL,'2018-05-17 15:57:28'),(240,1,'退出',1,NULL,'2018-05-17 17:05:21'),(241,1,'登陆',1,NULL,'2018-05-17 17:05:25'),(242,1,'登陆',1,NULL,'2018-05-17 17:05:34'),(243,1,'登陆',1,NULL,'2018-05-17 17:46:35'),(244,1,'登陆',1,NULL,'2018-05-17 17:47:56'),(245,1,'登陆',1,NULL,'2018-05-17 17:49:23'),(246,1,'登陆',1,NULL,'2018-05-17 17:56:50'),(247,1,'登陆',1,NULL,'2018-05-17 18:00:28'),(248,1,'登陆',1,NULL,'2018-05-17 18:01:21'),(249,1,'退出',1,NULL,'2018-05-17 20:01:38'),(250,1,'登陆',1,NULL,'2018-05-17 20:01:39'),(251,1,'退出',1,NULL,'2018-05-17 20:02:27'),(252,1,'登陆',1,NULL,'2018-05-17 20:02:34'),(253,1,'登陆',1,NULL,'2018-05-17 20:05:36'),(254,1,'登陆',1,NULL,'2018-05-17 20:07:47'),(255,1,'登陆',1,NULL,'2018-05-17 20:08:29'),(256,1,'登陆',1,NULL,'2018-05-17 20:10:24'),(257,1,'登陆',1,NULL,'2018-05-17 21:07:53'),(258,1,'登陆',1,NULL,'2018-05-17 21:26:35'),(259,1,'退出',1,NULL,'2018-05-17 21:36:48'),(260,1,'登陆',1,NULL,'2018-05-17 21:37:01'),(261,1,'登陆',1,NULL,'2018-05-17 21:43:10'),(262,1,'登陆',1,NULL,'2018-05-17 21:51:16'),(263,1,'登陆',1,NULL,'2018-05-18 11:09:20'),(264,1,'登陆',1,NULL,'2018-06-07 10:00:30'),(265,1,'退出',1,NULL,'2018-06-07 10:01:04'),(266,1,'登陆',1,NULL,'2018-06-11 05:00:07'),(267,1,'退出',1,NULL,'2018-06-11 05:02:34'),(268,1,'登陆',1,NULL,'2018-06-11 05:26:20'),(269,1,'退出',1,NULL,'2018-06-11 05:29:11'),(270,1,'登陆',1,NULL,'2018-06-11 05:29:34'),(271,1,'修改菜单',1,NULL,'2018-06-11 05:30:12'),(272,1,'退出',1,NULL,'2018-06-11 05:30:16'),(273,1,'登陆',1,NULL,'2018-06-11 05:30:22'),(274,1,'登陆',1,NULL,'2018-06-12 04:19:00'),(275,1,'登陆',1,NULL,'2018-06-22 06:44:06'),(276,1,'登陆',1,NULL,'2018-06-22 11:56:38'),(277,1,'删除应用',1,NULL,'2018-06-22 11:56:50'),(278,1,'删除应用',1,NULL,'2018-06-22 11:56:53'),(279,1,'删除应用',1,NULL,'2018-06-22 11:56:56'),(280,1,'删除应用',1,NULL,'2018-06-22 11:56:58'),(281,1,'删除应用',1,NULL,'2018-06-22 11:57:00'),(282,1,'保存应用',1,NULL,'2018-06-22 11:59:22'),(283,1,'删除应用',1,NULL,'2018-06-22 12:00:12'),(284,1,'保存应用',1,NULL,'2018-06-22 12:00:25'),(285,1,'登陆',1,NULL,'2018-06-22 17:01:36'),(286,1,'保存菜单',1,NULL,'2018-06-22 17:09:40'),(287,1,'保存角色',1,NULL,'2018-06-22 17:09:54'),(288,1,'退出',1,NULL,'2018-06-22 17:09:57'),(289,1,'登陆',1,NULL,'2018-06-22 17:10:01'),(290,1,'退出',1,NULL,'2018-06-22 17:25:57'),(291,1,'登陆',1,NULL,'2018-06-22 17:26:01'),(292,1,'删除菜单',1,NULL,'2018-06-22 17:32:50'),(293,1,'删除菜单',1,NULL,'2018-06-22 17:33:18'),(294,1,'退出',1,NULL,'2018-06-22 17:44:04'),(295,1,'登陆',1,NULL,'2018-06-22 17:44:09'),(296,1,'修改服务',1,NULL,'2018-06-22 17:53:35'),(297,1,'保存服务',1,NULL,'2018-06-22 17:53:55'),(298,1,'删除服务',0,'\r\n### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column \'permissionId\' in \'where clause\'\r\n### The error may involve com.open.capacity.security.dao.ServiceDao.deleteRolePermission-Inline\r\n### The error occurred while setting parameters\r\n### SQL: delete from sys_services where permissionId = ?\r\n### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column \'permissionId\' in \'where clause\'\n; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column \'permissionId\' in \'where clause\'','2018-06-22 17:54:10'),(299,1,'删除服务',1,NULL,'2018-06-22 17:57:45'),(300,1,'删除服务',1,NULL,'2018-06-22 17:59:05'),(301,1,'删除服务',1,NULL,'2018-06-22 17:59:08'),(302,1,'删除服务',1,NULL,'2018-06-22 17:59:10'),(303,1,'删除服务',1,NULL,'2018-06-22 17:59:13'),(304,1,'删除服务',1,NULL,'2018-06-22 17:59:15'),(305,1,'删除服务',1,NULL,'2018-06-22 17:59:17'),(306,1,'删除服务',1,NULL,'2018-06-22 17:59:19'),(307,1,'删除服务',1,NULL,'2018-06-22 17:59:21'),(308,1,'删除服务',1,NULL,'2018-06-22 17:59:24'),(309,1,'删除服务',1,NULL,'2018-06-22 17:59:26'),(310,1,'修改服务',1,NULL,'2018-06-22 17:59:42'),(311,1,'删除服务',1,NULL,'2018-06-22 18:00:25'),(312,1,'删除服务',1,NULL,'2018-06-22 18:00:29'),(313,1,'删除服务',1,NULL,'2018-06-22 18:00:38'),(314,1,'退出',1,NULL,'2018-06-22 07:23:01'),(315,1,'登陆',1,NULL,'2018-06-22 07:23:06'),(316,1,'保存服务',1,NULL,'2018-06-22 07:23:44'),(317,1,'保存服务',1,NULL,'2018-06-22 07:24:18'),(318,1,'修改服务',1,NULL,'2018-06-22 07:24:57'),(319,1,'保存服务',1,NULL,'2018-06-22 07:27:46'),(320,1,'修改服务',1,NULL,'2018-06-22 07:28:14'),(321,1,'保存服务',1,NULL,'2018-06-22 07:28:36'),(322,1,'保存服务',1,NULL,'2018-06-22 07:28:53'),(323,1,'保存服务',1,NULL,'2018-06-22 07:34:15'),(324,1,'保存服务',1,NULL,'2018-06-22 07:35:51'),(325,1,'修改服务',1,NULL,'2018-06-22 07:36:29'),(326,1,'修改服务',1,NULL,'2018-06-22 07:37:17'),(327,1,'保存服务',1,NULL,'2018-06-22 07:38:37'),(328,1,'修改服务',1,NULL,'2018-06-22 07:38:52'),(329,1,'保存菜单',1,NULL,'2018-06-22 07:44:33'),(330,1,'修改菜单',1,NULL,'2018-06-22 07:44:49'),(331,1,'修改菜单',1,NULL,'2018-06-22 07:45:05'),(332,1,'退出',1,NULL,'2018-06-22 07:45:10'),(333,1,'登陆',1,NULL,'2018-06-22 07:45:16'),(334,1,'保存角色',1,NULL,'2018-06-22 07:45:57'),(335,1,'退出',1,NULL,'2018-06-22 07:46:02'),(336,1,'登陆',1,NULL,'2018-06-22 07:46:07'),(337,1,'保存角色',1,NULL,'2018-06-22 07:46:48'),(338,1,'删除菜单',1,NULL,'2018-06-22 07:47:03'),(339,1,'退出',1,NULL,'2018-06-22 07:47:06'),(340,1,'登陆',1,NULL,'2018-06-22 07:47:12'),(341,1,'修改菜单',1,NULL,'2018-06-22 07:47:33'),(342,1,'退出',1,NULL,'2018-06-22 07:47:37'),(343,1,'登陆',1,NULL,'2018-06-22 07:47:45'),(344,1,'修改菜单',1,NULL,'2018-06-22 07:48:01'),(345,1,'退出',1,NULL,'2018-06-22 07:48:05'),(346,1,'登陆',1,NULL,'2018-06-22 07:48:11'),(347,1,'登陆',1,NULL,'2018-06-22 07:51:15'),(348,1,'退出',1,NULL,'2018-06-22 07:52:00'),(349,1,'登陆',1,NULL,'2018-06-22 07:52:05'),(350,1,'登陆',1,NULL,'2018-06-22 07:52:37'),(351,1,'登陆',1,NULL,'2018-06-22 07:54:01'),(352,1,'登陆',1,NULL,'2018-06-22 07:54:35'),(353,1,'登陆',1,NULL,'2018-06-22 07:54:51'),(354,1,'登陆',1,NULL,'2018-06-22 08:40:43'),(355,1,'保存应用',0,'webApp已存在','2018-06-22 08:40:57'),(356,1,'保存应用',0,'webApp已存在','2018-06-22 08:43:01'),(357,1,'保存应用',0,'webApp已存在','2018-06-22 08:44:30'),(358,1,'保存应用',0,'webApp已存在','2018-06-22 08:44:47'),(359,1,'保存服务',1,NULL,'2018-06-22 08:52:37'),(360,1,'修改服务',1,NULL,'2018-06-22 08:53:04'),(361,1,'保存服务',1,NULL,'2018-06-22 08:53:31'); # # Structure for table "sys_module" # DROP TABLE IF EXISTS `sys_module`; CREATE TABLE `sys_module` ( `id` int(11) NOT NULL AUTO_INCREMENT, `version` bigint(20) DEFAULT '0' COMMENT '版本号', `description` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '描述', `image` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '图片', `name` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '模块名', `index_page` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '模块首页', `if_show` varchar(1) COLLATE utf8_bin DEFAULT '1' COMMENT '是否显示(1:显示;0:不显示)', `sort` int(20) DEFAULT NULL COMMENT '排序', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='模块表'; # # Data for table "sys_module" # INSERT INTO `sys_module` VALUES (1,NULL,'',NULL,'认证中心','/auth','1',100),(2,NULL,'',NULL,'演示demo','/client','1',100); # # Structure for table "sys_permission" # DROP TABLE IF EXISTS `sys_permission`; CREATE TABLE `sys_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parentId` int(11) NOT NULL, `name` varchar(50) NOT NULL, `css` varchar(30) DEFAULT NULL, `href` varchar(1000) DEFAULT NULL, `type` tinyint(1) NOT NULL, `permission` varchar(50) DEFAULT NULL, `sort` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8mb4; # # Data for table "sys_permission" # INSERT INTO `sys_permission` VALUES (1,0,'用户管理','fa-users','',1,'',2),(2,1,'用户查询','fa-user','pages/user/userList.html',1,'',3),(3,2,'查询','','',2,'sys:user:query',100),(4,2,'新增','','',2,'sys:user:add',100),(6,1,'修改密码','fa-pencil-square-o','pages/user/changePassword.html',1,'sys:user:password',4),(7,0,'系统设置','fa-gears','',1,'',5),(8,7,'菜单','fa-cog','pages/menu/menuList.html',1,'',6),(9,8,'查询','','',2,'sys:menu:query',100),(10,8,'新增','','',2,'sys:menu:add',100),(11,8,'删除','','',2,'sys:menu:del',100),(12,7,'角色','fa-user-secret','pages/role/roleList.html',1,'',7),(13,12,'查询','','',2,'sys:role:query',100),(14,12,'新增','','',2,'sys:role:add',100),(15,12,'删除','','',2,'sys:role:del',100),(16,0,'文件管理','fa-folder-open','pages/file/fileList.html',1,'',8),(17,16,'查询','','',2,'sys:file:query',100),(18,16,'删除','','',2,'sys:file:del',100),(19,0,'数据源监控','fa-eye','druid/index.html',1,'',9),(26,0,'日志查询','fa-reorder','pages/log/logList.html',1,'sys:log:query',13),(41,0,'注册中心','fa-th-list','pages/euraka/euraka.html',1,'',18),(42,0,'配置中心','fa-th-list','http://127.0.0.1:8070',1,'',19),(56,0,'工作流管理','fa-th-list',NULL,1,NULL,22),(57,56,'流程管理',NULL,'/pages/activiti/actList.html',1,NULL,21),(58,56,'模型列表','','/pages/activiti/actModelList.html',1,'',22),(60,41,'操作','','',2,'job:add',100),(61,66,'应用管理','','pages/client/clientList.html',1,'',10),(62,61,'查询','','',2,'sys:role:query',100),(63,61,'新增','','',2,'sys:role:add',100),(64,61,'删除','','',2,'sys:role:del',100),(65,66,'服务管理','','pages/service/serviceList.html',1,'',1),(66,0,'资源管理','','',1,'',100); # # Structure for table "sys_role" # DROP TABLE IF EXISTS `sys_role`; CREATE TABLE `sys_role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `description` varchar(100) DEFAULT NULL, `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4; # # Data for table "sys_role" # INSERT INTO `sys_role` VALUES (1,'ADMIN','管理员','2017-05-01 13:25:39','2018-06-22 07:46:48'),(2,'USER','11','2017-08-01 21:47:31','2018-06-21 11:09:12'),(3,'test1','test1','2018-03-14 13:03:36','2018-06-21 11:09:32'),(4,'ttttt','ttt1','2018-04-24 11:09:34','2018-06-21 11:12:26'),(5,'11111','222222','2018-04-24 17:47:12','2018-04-26 10:49:07'); # # Structure for table "sys_role_permission" # DROP TABLE IF EXISTS `sys_role_permission`; CREATE TABLE `sys_role_permission` ( `roleId` int(11) NOT NULL, `permissionId` int(11) NOT NULL, PRIMARY KEY (`roleId`,`permissionId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "sys_role_permission" # INSERT INTO `sys_role_permission` VALUES (1,1),(1,2),(1,3),(1,4),(1,6),(1,7),(1,8),(1,9),(1,10),(1,11),(1,12),(1,13),(1,14),(1,15),(1,16),(1,17),(1,18),(1,19),(1,26),(1,41),(1,42),(1,56),(1,57),(1,58),(1,60),(1,61),(1,62),(1,63),(1,64),(1,65),(1,66),(2,1),(2,2),(2,3),(2,4),(2,6),(2,7),(2,8),(2,9),(2,10),(2,11),(2,12),(2,13),(2,14),(2,15),(2,16),(2,17),(2,18),(2,19),(3,1),(3,2),(3,3),(3,7),(3,12),(3,13),(3,14),(3,15),(4,1),(4,2),(4,3),(4,4),(4,6),(4,7),(4,8),(4,9),(4,10),(4,11),(4,12),(4,13),(4,14),(4,15),(4,16),(4,17),(4,18),(4,19),(4,26),(4,41),(4,42),(5,1),(5,2),(5,3),(5,4),(5,6),(5,7),(5,8),(5,9),(5,10),(5,11),(5,12),(5,13),(5,14),(5,15),(5,16),(5,17),(5,18),(5,19),(5,26),(5,38),(5,39),(5,40),(5,41),(5,42); # # Structure for table "sys_role_user" # DROP TABLE IF EXISTS `sys_role_user`; CREATE TABLE `sys_role_user` ( `userId` int(11) NOT NULL, `roleId` int(11) NOT NULL, PRIMARY KEY (`userId`,`roleId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "sys_role_user" # INSERT INTO `sys_role_user` VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(2,1),(2,2),(2,3),(2,4),(2,5),(3,1),(3,2),(4,3),(5,1),(5,2); # # Structure for table "sys_server" # DROP TABLE IF EXISTS `sys_server`; CREATE TABLE `sys_server` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parentId` int(11) DEFAULT NULL COMMENT '父ID', `moduleId` int(11) DEFAULT NULL COMMENT '模块ID', `name` varchar(100) DEFAULT NULL COMMENT '服务名称', `path` varchar(100) DEFAULT NULL COMMENT '访问路径', `description` varchar(255) DEFAULT NULL COMMENT '服务描述', `sort` int(11) DEFAULT NULL COMMENT '排序', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='服务管理表'; # # Data for table "sys_server" # INSERT INTO `sys_server` VALUES (1,0,1,'token服务','/user/token','用户名密码获取token',100),(2,0,1,'token服务','/client/token','clientId获取token',100); # # Structure for table "sys_services" # DROP TABLE IF EXISTS `sys_services`; CREATE TABLE `sys_services` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parentId` int(11) NOT NULL, `name` varchar(50) NOT NULL, `css` varchar(30) DEFAULT NULL, `href` varchar(1000) DEFAULT NULL, `type` tinyint(1) NOT NULL, `permission` varchar(50) DEFAULT NULL, `sort` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=74 DEFAULT CHARSET=utf8mb4; # # Data for table "sys_services" # INSERT INTO `sys_services` VALUES (71,0,'授权服务','','/auth',1,'',1),(72,71,'用户授权token','','/auth/user/token',1,'',100),(73,71,'应用申请token','','/auth/client/token',1,'',100),(74,0,'测试微服务','','/client',1,'',100),(75,74,'hello接口','','/client/hello',1,'',100); # # Structure for table "sys_user" # DROP TABLE IF EXISTS `sys_user`; CREATE TABLE `sys_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(60) NOT NULL, `nickname` varchar(255) DEFAULT NULL, `headImgUrl` varchar(255) DEFAULT NULL, `phone` varchar(11) DEFAULT NULL, `telephone` varchar(30) DEFAULT NULL, `email` varchar(50) DEFAULT NULL, `birthday` date DEFAULT NULL, `sex` tinyint(1) DEFAULT NULL, `status` tinyint(1) NOT NULL DEFAULT '1', `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4; # # Data for table "sys_user" # INSERT INTO `sys_user` VALUES (1,'admin','$2a$10$q54rooCXqDTWYkf29d4ZFu/L3zkq5Uoa6jdA/spRNSwpxksEqJYpy','管理员',NULL,'','','','1998-07-01',0,1,'2017-04-10 15:21:38','2018-05-28 02:49:01'),(2,'user','$2a$10$ooGb4wjT7Hg3zgU2RhZp6eVu3jvG29i/U4L6VRwiZZ4.DZ0OOEAHu','用户',NULL,'22222','2222','',NULL,1,1,'2017-08-01 21:47:18','2018-06-21 21:05:02'),(3,'test123','$2a$10$MGxO0dynaARStolVS9tzk.ZGwzlC2WZ2LZ/LzxixWxCUoftU5Xtnq','test111',NULL,'18571111111','221','22','2018-03-14',1,1,'2018-03-14 08:43:48','2018-06-21 21:04:47'),(4,'owen','$2a$10$JTuOh..ec2N1BBi6NOsn1.beg72gN7je7uNvFn.VWbfkrAsPZ3otC','test',NULL,'18571111111','','11@11.com','2018-03-20',0,1,'2018-03-14 13:02:36','2018-06-12 20:56:07'),(5,'111111111','$2a$10$mJuBGzs67CyExiTZkk5iLOF9sE09GDK7jLf2O6gosMh.g/fDeKEiS','111111',NULL,'11111111111','11111111111','11@11.com','2018-04-11',0,1,'2018-04-14 21:42:43','2018-04-14 21:42:43'); # # Structure for table "t_dict" # DROP TABLE IF EXISTS `t_dict`; CREATE TABLE `t_dict` ( `id` int(11) NOT NULL AUTO_INCREMENT, `type` varchar(16) NOT NULL, `k` varchar(16) NOT NULL, `val` varchar(64) NOT NULL, `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `type` (`type`,`k`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4; # # Data for table "t_dict" # INSERT INTO `t_dict` VALUES (1,'sex','0','女','2017-11-17 09:58:24','2017-11-18 14:21:05'),(2,'sex','1','男','2017-11-17 10:03:46','2017-11-17 10:03:46'),(3,'userStatus','0','无效','2017-11-17 16:26:06','2017-11-17 16:26:09'),(4,'userStatus','1','正常','2017-11-17 16:26:06','2017-11-17 16:26:09'),(5,'userStatus','2','锁定','2017-11-17 16:26:06','2017-11-17 16:26:09'),(6,'noticeStatus','0','草稿','2017-11-17 16:26:06','2017-11-17 16:26:09'),(7,'noticeStatus','1','发布','2017-11-17 16:26:06','2017-11-17 16:26:09'),(8,'isRead','0','未读','2017-11-17 16:26:06','2017-11-17 16:26:09'),(9,'isRead','1','已读','2017-11-17 16:26:06','2017-11-17 16:26:09'); # # Structure for table "t_job" # DROP TABLE IF EXISTS `t_job`; CREATE TABLE `t_job` ( `id` int(11) NOT NULL AUTO_INCREMENT, `jobName` varchar(64) NOT NULL, `description` varchar(255) DEFAULT NULL, `cron` varchar(64) NOT NULL, `springBeanName` varchar(64) NOT NULL COMMENT 'springBean名', `methodName` varchar(64) NOT NULL COMMENT '方法名', `isSysJob` tinyint(1) NOT NULL COMMENT '是否是系统job', `status` tinyint(1) NOT NULL DEFAULT '1', `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `jobName` (`jobName`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "t_job" # # # Structure for table "t_mail" # DROP TABLE IF EXISTS `t_mail`; CREATE TABLE `t_mail` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL COMMENT '发送人', `subject` varchar(255) NOT NULL COMMENT '标题', `content` longtext NOT NULL COMMENT '正文', `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "t_mail" # # # Structure for table "t_mail_to" # DROP TABLE IF EXISTS `t_mail_to`; CREATE TABLE `t_mail_to` ( `id` int(11) NOT NULL AUTO_INCREMENT, `mailId` int(11) NOT NULL, `toUser` varchar(128) NOT NULL, `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1成功,0失败', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "t_mail_to" # # # Structure for table "t_notice" # DROP TABLE IF EXISTS `t_notice`; CREATE TABLE `t_notice` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(128) NOT NULL, `content` text NOT NULL, `status` tinyint(1) NOT NULL DEFAULT '1', `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "t_notice" # # # Structure for table "t_notice_read" # DROP TABLE IF EXISTS `t_notice_read`; CREATE TABLE `t_notice_read` ( `noticeId` int(11) NOT NULL, `userId` int(11) NOT NULL, `createTime` datetime NOT NULL, PRIMARY KEY (`noticeId`,`userId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "t_notice_read" # # # Structure for table "t_token" # DROP TABLE IF EXISTS `t_token`; CREATE TABLE `t_token` ( `id` varchar(36) NOT NULL COMMENT 'token', `val` text NOT NULL COMMENT 'LoginUser的json串', `expireTime` datetime NOT NULL, `createTime` datetime NOT NULL, `updateTime` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # # Data for table "t_token" # # # Structure for table "user_leave" # DROP TABLE IF EXISTS `user_leave`; CREATE TABLE `user_leave` ( `id` varchar(32) NOT NULL, `user_id` varchar(32) NOT NULL, `user_name` varchar(18) DEFAULT NULL, `begin_time` datetime DEFAULT NULL, `end_time` datetime DEFAULT NULL, `reason` varchar(255) DEFAULT NULL, `days` int(11) DEFAULT NULL, `process_instance_Id` varchar(32) DEFAULT NULL, `status` varchar(64) DEFAULT NULL, `create_date` datetime DEFAULT NULL, `create_by` varchar(32) DEFAULT NULL, `update_date` datetime DEFAULT NULL, `update_by` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Data for table "user_leave" # ================================================ FILE: open-layui-web/src/main/resources/generate/controller.ftl ================================================ package {controllerPkgName}; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.boot.security.server.page.table.PageTableRequest; import com.boot.security.server.page.table.PageTableHandler; import com.boot.security.server.page.table.PageTableResponse; import com.boot.security.server.page.table.PageTableHandler.CountHandler; import com.boot.security.server.page.table.PageTableHandler.ListHandler; import {daoPackageName}.{daoName}; import {beanPackageName}.{beanName}; import io.swagger.annotations.ApiOperation; @RestController @RequestMapping("/{beanParamName}s") public class {controllerName} { @Autowired private {daoName} {daoParamName}; @PostMapping @ApiOperation(value = "保存") public {beanName} save(@RequestBody {beanName} {beanParamName}) { {daoParamName}.save({beanParamName}); return {beanParamName}; } @GetMapping("/{id}") @ApiOperation(value = "根据id获取") public {beanName} get(@PathVariable Long id) { return {daoParamName}.getById(id); } @PutMapping @ApiOperation(value = "修改") public {beanName} update(@RequestBody {beanName} {beanParamName}) { {daoParamName}.update({beanParamName}); return {beanParamName}; } @GetMapping @ApiOperation(value = "列表") public PageTableResponse list(PageTableRequest request) { return new PageTableHandler(new CountHandler() { @Override public int count(PageTableRequest request) { return {daoParamName}.count(request.getParams()); } }, new ListHandler() { @Override public List<{beanName}> list(PageTableRequest request) { return {daoParamName}.list(request.getParams(), request.getOffset(), request.getLimit()); } }).handle(request); } @DeleteMapping("/{id}") @ApiOperation(value = "删除") public void delete(@PathVariable Long id) { {daoParamName}.delete(id); } } ================================================ FILE: open-layui-web/src/main/resources/generate/dao.ftl ================================================ package {daoPackageName}; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import {beanPackageName}.{beanName}; @Mapper public interface {daoName} { @Select("select * from {table_name} t where t.id = #{id}") {beanName} getById(Long id); @Delete("delete from {table_name} where id = #{id}") int delete(Long id); int update({beanName} {beanParamName}); @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into {table_name}({insert_columns}) values({insert_values})") int save({beanName} {beanParamName}); int count(@Param("params") Map params); List<{beanName}> list(@Param("params") Map params, @Param("offset") Integer offset, @Param("limit") Integer limit); } ================================================ FILE: open-layui-web/src/main/resources/generate/htmlAdd.ftl ================================================
    {addDivs}
    ================================================ FILE: open-layui-web/src/main/resources/generate/htmlList.ftl ================================================ Insert title here
    id:
    {ths}
    操作
    ================================================ FILE: open-layui-web/src/main/resources/generate/htmlUpdate.ftl ================================================
    {addDivs}
    ================================================ FILE: open-layui-web/src/main/resources/generate/java.ftl ================================================ package {beanPackageName}; {import} public class {beanName} extends BaseEntity { {filelds} {getset} } ================================================ FILE: open-layui-web/src/main/resources/generate/mapper.ftl ================================================ {where} update {table_name} t {update_sets} where t.id = #{id} ================================================ FILE: open-layui-web/src/main/resources/logback-admin.xml ================================================ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n ../logs/open-layui-web-error.%d{yyyy-MM-dd}.%i.log 100MB 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n 100MB ERROR ACCEPT DENY ../logs/open-layui-web-info.%d{yyyy-MM-dd}.%i.log 100MB 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n INFO ACCEPT DENY ================================================ FILE: open-layui-web/src/main/resources/mybatis.cfg.xml ================================================ ================================================ FILE: open-layui-web/src/main/resources/stencilset.json ================================================ { "title" : "BPMN 2.0标准工具", "namespace" : "http://b3mn.org/stencilset/bpmn2.0#", "description" : "BPMN process editor", "propertyPackages" : [ { "name" : "process_idpackage", "properties" : [ { "id" : "process_id", "type" : "String", "title" : "流程名称", "value" : "process", "description" : "流程的特殊唯一的名称标识", "popular" : true } ] }, { "name" : "overrideidpackage", "properties" : [ { "id" : "overrideid", "type" : "String", "title" : "Id", "value" : "", "description" : "Unique identifier of the element.", "popular" : true } ] }, { "name" : "namepackage", "properties" : [ { "id" : "name", "type" : "String", "title" : "名称", "value" : "", "description" : "元素名称", "popular" : true, "refToView" : "text_name" } ] }, { "name" : "documentationpackage", "properties" : [ { "id" : "documentation", "type" : "Text", "title" : "描述", "value" : "", "description" : "元素描述", "popular" : true } ] }, { "name" : "process_authorpackage", "properties" : [ { "id" : "process_author", "type" : "String", "title" : "流程作者", "value" : "", "description" : "流程定义者姓名", "popular" : true } ] }, { "name" : "process_versionpackage", "properties" : [ { "id" : "process_version", "type" : "String", "title" : "流程版本", "value" : "", "description" : "标识文档版本", "popular" : true } ] }, { "name" : "process_namespacepackage", "properties" : [ { "id" : "process_namespace", "type" : "String", "title" : "目标命名空间", "value" : "http://www.activiti.org/processdef", "description" : "工作流目标命名空间", "popular" : true } ] }, { "name" : "asynchronousdefinitionpackage", "properties" : [ { "id" : "asynchronousdefinition", "type" : "Boolean", "title" : "异步", "value" : "false", "description" : "Define the activity as asynchronous.", "popular" : true } ] }, { "name" : "exclusivedefinitionpackage", "properties" : [ { "id" : "exclusivedefinition", "type" : "Boolean", "title" : "单独", "value" : "false", "description" : "Define the activity as exclusive.", "popular" : true } ] }, { "name" : "executionlistenerspackage", "properties" : [ { "id" : "executionlisteners", "type" : "multiplecomplex", "title" : "执行监听器", "value" : "", "description" : "Listeners for an activity, process, sequence flow, start and end event.", "popular" : true } ] }, { "name" : "tasklistenerspackage", "properties" : [ { "id" : "tasklisteners", "type" : "multiplecomplex", "title" : "任务监听器", "value" : "", "description" : "Listeners for a user task", "popular" : true } ] }, { "name" : "eventlistenerspackage", "properties" : [ { "id" : "eventlisteners", "type" : "multiplecomplex", "title" : "事件监听器", "value" : "", "description" : "Listeners for any event happening in the Activiti Engine. It's also possible to rethrow the event as a signal, message or error event", "popular" : true } ] }, { "name" : "usertaskassignmentpackage", "properties" : [ { "id" : "usertaskassignment", "type" : "Complex", "title" : "代理", "value" : "", "description" : "Assignment definition for the user task", "popular" : true } ] }, { "name" : "formpropertiespackage", "properties" : [ { "id" : "formproperties", "type" : "Complex", "title" : "动态表单属性", "value" : "", "description" : "Definition of the form with a list of form properties", "popular" : true } ] }, { "name" : "formkeydefinitionpackage", "properties" : [ { "id" : "formkeydefinition", "type" : "String", "title" : "自定义表单", "value" : "", "description" : "用户任务表单编号", "popular" : true } ] }, { "name" : "duedatedefinitionpackage", "properties" : [ { "id" : "duedatedefinition", "type" : "String", "title" : "到期日期", "value" : "", "description" : "用户任务到期时间", "popular" : true } ] }, { "name" : "prioritydefinitionpackage", "properties" : [ { "id" : "prioritydefinition", "type" : "String", "title" : "优先级", "value" : "", "description" : "用户任务优先级", "popular" : true } ] }, { "name" : "duedatedefinitionpackage", "properties" : [ { "id" : "duedatedefinition", "type" : "String", "title" : "到期日期", "value" : "", "description" : "Due date of the user task.", "popular" : true } ] }, { "name" : "servicetaskclasspackage", "properties" : [ { "id" : "servicetaskclass", "type" : "String", "title" : "监听类", "value" : "", "description" : "Class that implements the service task logic.", "popular" : true } ] }, { "name" : "servicetaskexpressionpackage", "properties" : [ { "id" : "servicetaskexpression", "type" : "String", "title" : "表达式", "value" : "", "description" : "Service task logic defined with an expression.", "popular" : true } ] }, { "name" : "servicetaskdelegateexpressionpackage", "properties" : [ { "id" : "servicetaskdelegateexpression", "type" : "String", "title" : "委托表达式", "value" : "", "description" : "Service task logic defined with a delegate expression.", "popular" : true } ] }, { "name" : "servicetaskfieldspackage", "properties" : [ { "id" : "servicetaskfields", "type" : "Complex", "title" : "字段", "value" : "", "description" : "Field extensions", "popular" : true } ] }, { "name" : "servicetaskresultvariablepackage", "properties" : [ { "id" : "servicetaskresultvariable", "type" : "String", "title" : "Result variable name", "value" : "", "description" : "Process variable name to store the service task result.", "popular" : true } ] }, { "name" : "scriptformatpackage", "properties" : [ { "id" : "scriptformat", "type" : "String", "title" : "脚本格式", "value" : "", "description" : "Script format of the script task.", "popular" : true } ] }, { "name" : "scripttextpackage", "properties" : [ { "id" : "scripttext", "type" : "Text", "title" : "脚本", "value" : "", "description" : "Script text of the script task.", "popular" : true } ] }, { "name" : "ruletask_rulespackage", "properties" : [ { "id" : "ruletask_rules", "type" : "String", "title" : "规则", "value" : "", "description" : "Rules of the rule task.", "popular" : true } ] }, { "name" : "ruletask_variables_inputpackage", "properties" : [ { "id" : "ruletask_variables_input", "type" : "String", "title" : "输入变量", "value" : "", "description" : "Input variables of the rule task.", "popular" : true } ] }, { "name" : "ruletask_excludepackage", "properties" : [ { "id" : "ruletask_exclude", "type" : "Boolean", "title" : "除外", "value" : "false", "description" : "Use the rules property as exclusion.", "popular" : true } ] }, { "name" : "ruletask_resultpackage", "properties" : [ { "id" : "ruletask_result", "type" : "String", "title" : "返回变量", "value" : "", "description" : "Result variable of the rule task.", "popular" : true } ] }, { "name" : "mailtasktopackage", "properties" : [ { "id" : "mailtaskto", "type" : "Text", "title" : "接收人", "value" : "", "description" : "The recipients if the e-mail. Multiple recipients are defined in a comma-separated list.", "popular" : true } ] }, { "name" : "mailtaskfrompackage", "properties" : [ { "id" : "mailtaskfrom", "type" : "Text", "title" : "发件人", "value" : "", "description" : "The sender e-mail address. If not provided, the default configured from address is used.", "popular" : true } ] }, { "name" : "mailtasksubjectpackage", "properties" : [ { "id" : "mailtasksubject", "type" : "Text", "title" : "主题", "value" : "", "description" : "The subject of the e-mail.", "popular" : true } ] }, { "name" : "mailtaskccpackage", "properties" : [ { "id" : "mailtaskcc", "type" : "Text", "title" : "转发", "value" : "", "description" : "The cc's of the e-mail. Multiple recipients are defined in a comma-separated list", "popular" : true } ] }, { "name" : "mailtaskbccpackage", "properties" : [ { "id" : "mailtaskbcc", "type" : "Text", "title" : "密送", "value" : "", "description" : "The bcc's of the e-mail. Multiple recipients are defined in a comma-separated list", "popular" : true } ] }, { "name" : "mailtasktextpackage", "properties" : [ { "id" : "mailtasktext", "type" : "Text", "title" : "内容", "value" : "", "description" : "The content of the e-mail, in case one needs to send plain none-rich e-mails. Can be used in combination with html, for e-mail clients that don't support rich content. The client will then fall back to this text-only alternative.", "popular" : true } ] }, { "name" : "mailtaskhtmlpackage", "properties" : [ { "id" : "mailtaskhtml", "type" : "Text", "title" : "Html", "value" : "", "description" : "A piece of HTML that is the content of the e-mail.", "popular" : true } ] }, { "name" : "mailtaskcharsetpackage", "properties" : [ { "id" : "mailtaskcharset", "type" : "String", "title" : "Charset", "value" : "", "description" : "Allows to change the charset of the email, which is necessary for many non-English languages. ", "popular" : true } ] }, { "name" : "callactivitycalledelementpackage", "properties" : [ { "id" : "callactivitycalledelement", "type" : "String", "title" : "被调用元素", "value" : "", "description" : "Process reference.", "popular" : true } ] }, { "name" : "callactivityinparameterspackage", "properties" : [ { "id" : "callactivityinparameters", "type" : "Complex", "title" : "输入参数", "value" : "", "description" : "Definition of the input parameters", "popular" : true } ] }, { "name" : "callactivityoutparameterspackage", "properties" : [ { "id" : "callactivityoutparameters", "type" : "Complex", "title" : "输出参数", "value" : "", "description" : "Definition of the output parameters", "popular" : true } ] }, { "name" : "cameltaskcamelcontextpackage", "properties" : [ { "id" : "cameltaskcamelcontext", "type" : "String", "title" : "Camel内容", "value" : "", "description" : "An optional camel context definition, if left empty the default is used.", "popular" : true } ] }, { "name" : "muletaskendpointurlpackage", "properties" : [ { "id" : "muletaskendpointurl", "type" : "String", "title" : "终端url", "value" : "", "description" : "A required endpoint url to sent the message to Mule.", "popular" : true } ] }, { "name" : "muletasklanguagepackage", "properties" : [ { "id" : "muletasklanguage", "type" : "String", "title" : "语言", "value" : "", "description" : "A required definition for the language to resolve the payload expression, like juel.", "popular" : true } ] }, { "name" : "muletaskpayloadexpressionpackage", "properties" : [ { "id" : "muletaskpayloadexpression", "type" : "String", "title" : "有效载荷表达式", "value" : "", "description" : "A required definition for the payload of the message sent to Mule.", "popular" : true } ] }, { "name" : "muletaskresultvariablepackage", "properties" : [ { "id" : "muletaskresultvariable", "type" : "String", "title" : "返回变量", "value" : "", "description" : "An optional result variable for the payload returned.", "popular" : true } ] }, { "name" : "conditionsequenceflowpackage", "properties" : [ { "id" : "conditionsequenceflow", "type" : "Complex", "title" : "流转条件", "value" : "", "description" : "The condition of the sequence flow", "popular" : true } ] }, { "name" : "defaultflowpackage", "properties" : [ { "id" : "defaultflow", "type" : "Boolean", "title" : "默认流转", "value" : "false", "description" : "Define the sequence flow as default", "popular" : true, "refToView" : "default" } ] }, { "name" : "conditionalflowpackage", "properties" : [ { "id" : "conditionalflow", "type" : "Boolean", "title" : "Conditional flow", "value" : "false", "description" : "Define the sequence flow with a condition", "popular" : true } ] }, { "name" : "timercycledefinitionpackage", "properties" : [ { "id" : "timercycledefinition", "type" : "String", "title" : "循环时间(例:R3/PT10H)", "value" : "", "description" : "Define the timer with a ISO-8601 cycle.", "popular" : true } ] }, { "name" : "timerdatedefinitionpackage", "properties" : [ { "id" : "timerdatedefinition", "type" : "String", "title" : "开始时间(ISO-8601)", "value" : "", "description" : "Define the timer with a ISO-8601 date definition.", "popular" : true } ] }, { "name" : "timerdurationdefinitionpackage", "properties" : [ { "id" : "timerdurationdefinition", "type" : "String", "title" : "持续时间(例:PT5M)", "value" : "", "description" : "Define the timer with a ISO-8601 duration.", "popular" : true } ] }, { "name" : "timerenddatedefinitionpackage", "properties" : [ { "id" : "timerenddatedefinition", "type" : "String", "title" : "结束时间(ISO-8601)", "value" : "", "description" : "Define the timer with a ISO-8601 duration.", "popular" : true } ] }, { "name" : "messagerefpackage", "properties" : [ { "id" : "messageref", "type" : "String", "title" : "消息引用", "value" : "", "description" : "Define the message name.", "popular" : true } ] }, { "name" : "signalrefpackage", "properties" : [ { "id" : "signalref", "type" : "String", "title" : "信号引用", "value" : "", "description" : "Define the signal name.", "popular" : true } ] }, { "name" : "errorrefpackage", "properties" : [ { "id" : "errorref", "type" : "String", "title" : "错误引用", "value" : "", "description" : "Define the error name.", "popular" : true } ] }, { "name" : "cancelactivitypackage", "properties" : [ { "id" : "cancelactivity", "type" : "Boolean", "title" : "取消活动", "value" : "true", "description" : "Should the activity be cancelled", "popular" : true, "refToView" : [ "frame", "frame2" ] } ] }, { "name" : "initiatorpackage", "properties" : [ { "id" : "initiator", "type" : "String", "title" : "发起人", "value" : "", "description" : "Initiator of the process.", "popular" : true } ] }, { "name" : "textpackage", "properties" : [ { "id" : "text", "type" : "String", "title" : "Text", "value" : "", "description" : "The text of the text annotation.", "popular" : true, "refToView" : "text" } ] }, { "name" : "multiinstance_typepackage", "properties" : [ { "id" : "multiinstance_type", "type" : "kisbpm-multiinstance", "title" : "多实例类型", "value" : "None", "description" : "Repeated activity execution (parallel or sequential) can be displayed through different loop types", "popular" : true, "refToView" : "multiinstance" } ] }, { "name" : "multiinstance_cardinalitypackage", "properties" : [ { "id" : "multiinstance_cardinality", "type" : "String", "title" : "基数(多实例)", "value" : "", "description" : "Define the cardinality of multi instance.", "popular" : true } ] }, { "name" : "multiinstance_collectionpackage", "properties" : [ { "id" : "multiinstance_collection", "type" : "String", "title" : "集合(多实例)", "value" : "", "description" : "Define the collection for the multi instance.", "popular" : true } ] }, { "name" : "multiinstance_variablepackage", "properties" : [ { "id" : "multiinstance_variable", "type" : "String", "title" : "元素变量(多实例)", "value" : "", "description" : "Define the element variable for the multi instance.", "popular" : true } ] }, { "name" : "multiinstance_conditionpackage", "properties" : [ { "id" : "multiinstance_condition", "type" : "String", "title" : "完成条件(多实例)", "value" : "", "description" : "Define the completion condition for the multi instance.", "popular" : true } ] }, { "name" : "isforcompensationpackage", "properties" : [ { "id" : "isforcompensation", "type" : "Boolean", "title" : "是否为补偿", "value" : "false", "description" : "一个标志,标识是否这个活动的目的是为了补偿.", "popular" : true, "refToView" : "compensation" } ] }, { "name" : "sequencefloworderpackage", "properties" : [ { "id" : "sequencefloworder", "type" : "Complex", "title" : "流动顺序", "value" : "", "description" : "Order outgoing sequence flows.", "popular" : true } ] }, { "name" : "signaldefinitionspackage", "properties" : [ { "id" : "signaldefinitions", "type" : "multiplecomplex", "title" : "信号定义", "value" : "", "description" : "Signal definitions", "popular" : true } ] }, { "name" : "messagedefinitionspackage", "properties" : [ { "id" : "messagedefinitions", "type" : "multiplecomplex", "title" : "消息定义", "value" : "", "description" : "Message definitions", "popular" : true } ] }, { "name" : "istransactionpackage", "properties" : [ { "id" : "istransaction", "type" : "Boolean", "title" : "是否事务处理子过程", "value" : "false", "description" : "A flag that identifies whether this sub process is of type transaction.", "popular" : true, "refToView" : "border" } ] }, { "name" : "terminateAllpackage", "properties" : [ { "id" : "terminateAll", "type" : "Boolean", "title" : "终止全部", "value" : "false", "description" : "Enable to terminate the process instance", "popular" : true } ] } ], "stencils" : [ { "type" : "node", "id" : "BPMNDiagram", "title" : "BPMN-Diagram", "description" : "A BPMN 2.0 diagram.", "view" : "\n\n \n \n \n \n \t\n \n", "icon" : "diagram.png", "groups" : [ "Diagram" ], "mayBeRoot" : true, "hide" : true, "propertyPackages" : [ "process_idpackage", "namepackage", "documentationpackage", "process_authorpackage", "process_versionpackage", "process_namespacepackage", "executionlistenerspackage", "eventlistenerspackage", "signaldefinitionspackage", "messagedefinitionspackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ ] }, { "type" : "node", "id" : "StartNoneEvent", "title" : "事件", "description" : "A start event without a specific trigger", "view" : "\n\n \n \n \t\n \n \n \n\t\n \n", "icon" : "startevent/none.png", "groups" : [ "启动事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "initiatorpackage", "formkeydefinitionpackage", "formpropertiespackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] }, { "type" : "node", "id" : "StartTimerEvent", "title" : "定时事件", "description" : "A start event with a timer trigger", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", "icon" : "startevent/timer.png", "groups" : [ "启动事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] }, { "type" : "node", "id" : "StartSignalEvent", "title" : "信号事件", "description" : "A start event with a signal trigger", "view" : "\n\n \n \n \t\n \n \n\n \n \n \n\t\n \n", "icon" : "startevent/signal.png", "groups" : [ "启动事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] }, { "type" : "node", "id" : "StartMessageEvent", "title" : "消息事件", "description" : "A start event with a message trigger", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", "icon" : "startevent/message.png", "groups" : [ "启动事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "messagerefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] }, { "type" : "node", "id" : "StartErrorEvent", "title" : "异常事件", "description" : "A start event that catches a thrown BPMN error", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", "icon" : "startevent/error.png", "groups" : [ "启动事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "errorrefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] }, { "type" : "node", "id" : "UserTask", "title" : "用户活动", "description" : "分配给特定人的任务 ", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.user.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "usertaskassignmentpackage", "formkeydefinitionpackage", "duedatedefinitionpackage", "prioritydefinitionpackage", "formpropertiespackage", "tasklistenerspackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "ServiceTask", "title" : "服务任务", "description" : "An automatic task with service logic", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.service.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "servicetaskclasspackage", "servicetaskexpressionpackage", "servicetaskdelegateexpressionpackage", "servicetaskfieldspackage", "servicetaskresultvariablepackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "ScriptTask", "title" : "脚本任务", "description" : "An automatic task with script logic", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.script.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "scriptformatpackage", "scripttextpackage", "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "BusinessRule", "title" : "规则任务", "description" : "An automatic task with rule logic", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n \t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.business.rule.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "ruletask_rulespackage", "ruletask_variables_inputpackage", "ruletask_excludepackage", "ruletask_resultpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "ReceiveTask", "title" : "接受任务", "description" : "An task that waits for a signal", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.receive.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "ManualTask", "title" : "手工任务", "description" : "An automatic task with no logic", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n \t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.manual.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "MailTask", "title" : "邮件任务", "description" : "An mail task", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.send.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "mailtasktopackage", "mailtaskfrompackage", "mailtasksubjectpackage", "mailtaskccpackage", "mailtaskbccpackage", "mailtasktextpackage", "mailtaskhtmlpackage", "mailtaskcharsetpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "CamelTask", "title" : "Camel任务", "description" : "An task that sends a message to Camel", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.camel.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "cameltaskcamelcontextpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "MuleTask", "title" : "Mule任务", "description" : "An task that sends a message to Mule", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.mule.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "muletaskendpointurlpackage", "muletasklanguagepackage", "muletaskpayloadexpressionpackage", "muletaskresultvariablepackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "SendTask", "title" : "Send task", "description" : "An task that sends a message", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/list/type.send.png", "groups" : [ "活动列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] }, { "type" : "node", "id" : "SubProcess", "title" : "子流程", "description" : "子流程范围", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n \n\t\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n", "icon" : "activity/expanded.subprocess.png", "groups" : [ "结构列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "istransactionpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "all" ] }, { "type" : "node", "id" : "EventSubProcess", "title" : "事件子流程", "description" : "一个事件周期的子流程", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n \t\n\t\t\n \t\n\t\n\t\n \n", "icon" : "activity/event.subprocess.png", "groups" : [ "结构列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "all" ] }, { "type" : "node", "id" : "CallActivity", "title" : "调用活动", "description" : "一个调用活动", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n \n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", "icon" : "activity/task.png", "groups" : [ "结构列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "callactivitycalledelementpackage", "callactivityinparameterspackage", "callactivityoutparameterspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "Activity", "sequence_start", "sequence_end", "all" ] }, { "type" : "node", "id" : "ExclusiveGateway", "title" : "互斥网关", "description" : "一个选择的网关", "view" : "\n\n \n \n \n \t\t\t\t\t\n \n \n \n \n \n \n \n\t\n\t\n\t\n \n\n", "icon" : "gateway/exclusive.databased.png", "groups" : [ "网关列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "ParallelGateway", "title" : "并行网关", "description" : "一个并行的网关", "view" : "\n\n \n \n \n \n \n \n \n \n\t\n\t\n \n\n", "icon" : "gateway/parallel.png", "groups" : [ "网关列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "InclusiveGateway", "title" : "包容性网关", "description" : "一个包容性网关", "view" : "\n\n \n \n \n \n\n \n \n \n\t\n\t\n \n\n", "icon" : "gateway/inclusive.png", "groups" : [ "网关列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "EventGateway", "title" : "事件网关", "description" : "一个事件网关", "view" : "\n\n \n \n \n \n \n \t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\n\t\n\t\n\t\n\t\n \t\n\t\n\n", "icon" : "gateway/eventbased.png", "groups" : [ "网关列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "BoundaryErrorEvent", "title" : "边界错误事件", "description" : "一个捕捉BPMN异常的边界事件", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", "icon" : "catching/error.png", "groups" : [ "边界事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "errorrefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] }, { "type" : "node", "id" : "BoundaryTimerEvent", "title" : "定时边界事件", "description" : "一个定时触发的边界事件", "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n \n \n \t\n\t\n \n", "icon" : "catching/timer.png", "groups" : [ "边界事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage", "timerenddatedefinitionpackage", "cancelactivitypackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] }, { "type" : "node", "id" : "BoundarySignalEvent", "title" : "边界信号事件", "description" : "一个信号触发的边界事件", "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n\t\n\t\n \n", "icon" : "catching/signal.png", "groups" : [ "边界事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "signalrefpackage", "cancelactivitypackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] }, { "type" : "node", "id" : "BoundaryMessageEvent", "title" : "边界消息事件", "description" : "一个边界消息事件", "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \t\n \n \n \n\t\n\t\t\n\t\n\t\n\t\n \n", "icon" : "catching/message.png", "groups" : [ "边界事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "messagerefpackage", "cancelactivitypackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] }, { "type" : "node", "id" : "BoundaryCancelEvent", "title" : "边界取消事件", "description" : "一个边界取消事件", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n \n\t\n \n", "icon" : "catching/cancel.png", "groups" : [ "边界事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] }, { "type" : "node", "id" : "BoundaryCompensationEvent", "title" : "边界修正事件", "description" : "一个边界修正事件", "view" : "\n\n \n \n \t\n \n \n \n\t\n \n \n \n \n \n\t\n \n", "icon" : "catching/compensation.png", "groups" : [ "边界事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary", "all" ] }, { "type" : "node", "id" : "CatchTimerEvent", "title" : "中间定时器捕获事件", "description" : "定时器触发的中间捕获事件", "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n \n \n \t\n\t\n \n", "icon" : "catching/timer.png", "groups" : [ "中间捕获事件列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] }, { "type" : "node", "id" : "CatchSignalEvent", "title" : "中间信号捕获事件", "description" : "信号触发的捕获事件", "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n\t\n\t\n \n", "icon" : "catching/signal.png", "groups" : [ "中间捕获事件列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] }, { "type" : "node", "id" : "CatchMessageEvent", "title" : "中间消息捕获事件", "description" : "一个消息触发的中间捕获事件", "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \t\n \n \n \n\t\n\t\t\n\t\n\t\n\t\n \n", "icon" : "catching/message.png", "groups" : [ "中间捕获事件列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "messagerefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] }, { "type" : "node", "id" : "ThrowNoneEvent", "title" : "中间抛出事件", "description" : "无触发器的中间抛出事件", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", "icon" : "throwing/none.png", "groups" : [ "中间抛出事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "ThrowEventsMorph", "sequence_start", "sequence_end", "all" ] }, { "type" : "node", "id" : "ThrowSignalEvent", "title" : "信号中间抛出事件", "description" : "一个信号触发的中间抛出事件", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", "icon" : "throwing/signal.png", "groups" : [ "中间抛出事件" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "ThrowEventsMorph", "sequence_start", "sequence_end", "all" ] }, { "type" : "node", "id" : "EndNoneEvent", "title" : "结束任务", "description" : "一个无触发器的结束任务", "view" : "\n\n \n \n \t\n \n \n \n\t\n \n", "icon" : "endevent/none.png", "groups" : [ "结束任务列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "EndEventsMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "EndErrorEvent", "title" : "结束错误任务", "description" : "An end event that throws an error event", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", "icon" : "endevent/error.png", "groups" : [ "结束任务列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "errorrefpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "EndEventsMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "EndCancelEvent", "title" : "结束取消任务", "description" : "A cancel end event", "view" : "\n\n \n \n \t\n \n \n \n \n \n\t\n \n", "icon" : "endevent/cancel.png", "groups" : [ "结束任务列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "EndEventsMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "EndTerminateEvent", "title" : "终结任务", "description" : "A terminate end event", "view" : "\n\n \n \n \t\n \n \n \n \n \n\t\n \n", "icon" : "endevent/terminate.png", "groups" : [ "结束任务列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "terminateAllpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "EndEventsMorph", "sequence_end", "all" ] }, { "type" : "node", "id" : "Pool", "title" : "池", "description" : "A pool to stucture the process definition", "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \n \n \n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t \t\n \t\n \n \n\t\n\t\n\t\n\t\n \n \n \n", "icon" : "swimlane/pool.png", "groups" : [ "泳道列表" ], "layout" : [ { "type" : "layout.bpmn2_0.pool" } ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "process_idpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "canContainArtifacts", "all" ] }, { "type" : "node", "id" : "Lane", "title" : "泳道", "description" : "A lane to stucture the process definition", "view" : "\n\n \n \n \n \n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n \t\t\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n \n\t\n \n", "icon" : "swimlane/lane.png", "groups" : [ "泳道列表" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "PoolChild", "canContainArtifacts", "all" ] }, { "type" : "edge", "id" : "SequenceFlow", "title" : "顺序流", "description" : "顺序流定义活动的执行顺序", "view" : "\r\n\r\n\t\r\n\t \t\r\n\t \t\t\r\n\t\t\t\r\n\t \t\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n", "icon" : "connector/sequenceflow.png", "groups" : [ "连接对象" ], "layout" : [ { "type" : "layout.bpmn2_0.sequenceflow" } ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "conditionsequenceflowpackage", "executionlistenerspackage", "defaultflowpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "ConnectingObjectsMorph", "all" ] }, { "type" : "edge", "id" : "MessageFlow", "title" : "消息流", "description" : "Message flow to connect elements in different pools.", "view" : "\r\n\r\n\t\r\n\t\t\r\n\t \t\t\r\n\t \t\t\r\n\t \t\r\n\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", "icon" : "connector/messageflow.png", "groups" : [ "连接对象" ], "layout" : [ { "type" : "layout.bpmn2_0.sequenceflow" } ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "ConnectingObjectsMorph", "all" ] }, { "type" : "edge", "id" : "Association", "title" : "注释", "description" : "连接一个注释到指定元素", "view" : "\r\n\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", "icon" : "connector/association.undirected.png", "groups" : [ "连接对象" ], "layout" : [ { "type" : "layout.bpmn2_0.sequenceflow" } ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "ConnectingObjectsMorph", "all" ] }, { "type" : "edge", "id" : "DataAssociation", "title" : "日期注释", "description" : "连接一个日期注释到指定元素", "view" : "\r\n\r\n\t\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", "icon" : "connector/association.unidirectional.png", "groups" : [ "连接对象" ], "layout" : [ { "type" : "layout.bpmn2_0.sequenceflow" } ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "ConnectingObjectsMorph", "all" ] }, { "type" : "node", "id" : "TextAnnotation", "title" : "文本注释", "description" : "连接一个文本注释到指定元素", "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", "icon" : "artifact/text.annotation.png", "groups" : [ "加工" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "textpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "all" ] }, { "type" : "node", "id" : "DataStore", "title" : "Data store", "description" : "Reference to a data store.", "view" : "\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t \t\r\n\t\t\r\n\t\t\t \r\n\t\r\n\r\n", "icon" : "dataobject/data.store.png", "groups" : [ "Artifacts" ], "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], "hiddenPropertyPackages" : [ ], "roles" : [ "all" ] } ], "rules" : { "cardinalityRules" : [ { "role" : "Startevents_all", "incomingEdges" : [ { "role" : "SequenceFlow", "maximum" : 0 } ] }, { "role" : "Endevents_all", "outgoingEdges" : [ { "role" : "SequenceFlow", "maximum" : 0 } ] } ], "connectionRules" : [ { "role" : "SequenceFlow", "connects" : [ { "from" : "sequence_start", "to" : [ "sequence_end" ] } ] }, { "role" : "Association", "connects" : [ { "from" : "sequence_start", "to" : [ "TextAnnotation" ] }, { "from" : "sequence_end", "to" : [ "TextAnnotation" ] }, { "from" : "TextAnnotation", "to" : [ "sequence_end" ] }, { "from" : "BoundaryCompensationEvent", "to" : [ "sequence_end" ] }, { "from" : "TextAnnotation", "to" : [ "sequence_start" ] }, { "from" : "BoundaryCompensationEvent", "to" : [ "sequence_start" ] } ] }, { "role" : "DataAssociation", "connects" : [ { "from" : "sequence_start", "to" : [ "DataStore" ] }, { "from" : "sequence_end", "to" : [ "DataStore" ] }, { "from" : "DataStore", "to" : [ "sequence_end" ] }, { "from" : "DataStore", "to" : [ "sequence_start" ] } ] }, { "role" : "IntermediateEventOnActivityBoundary", "connects" : [ { "from" : "Activity", "to" : [ "IntermediateEventOnActivityBoundary" ] } ] } ], "containmentRules" : [ { "role" : "BPMNDiagram", "contains" : [ "all" ] }, { "role" : "SubProcess", "contains" : [ "sequence_start", "sequence_end", "from_task_event", "to_task_event", "EventSubProcess", "TextAnnotation", "DataStore" ] }, { "role" : "EventSubProcess", "contains" : [ "sequence_start", "sequence_end", "from_task_event", "to_task_event", "TextAnnotation", "DataStore" ] }, { "role" : "Pool", "contains" : [ "Lane" ] }, { "role" : "Lane", "contains" : [ "sequence_start", "sequence_end", "EventSubProcess", "TextAnnotation", "DataStore" ] } ], "morphingRules" : [ { "role" : "ActivitiesMorph", "baseMorphs" : [ "UserTask" ], "preserveBounds" : true }, { "role" : "GatewaysMorph", "baseMorphs" : [ "ExclusiveGateway" ] }, { "role" : "StartEventsMorph", "baseMorphs" : [ "StartNoneEvent" ] }, { "role" : "EndEventsMorph", "baseMorphs" : [ "StartNoneEvent" ] }, { "role" : "CatchEventsMorph", "baseMorphs" : [ "CatchTimerEvent" ] }, { "role" : "ThrowEventsMorph", "baseMorphs" : [ "ThrowNoneEvent" ] }, { "role" : "BoundaryEventsMorph", "baseMorphs" : [ "ThrowNoneEvent" ] }, { "role" : "BoundaryCompensationEvent", "baseMorphs" : [ "BoundaryCompensationEvent" ] }, { "role" : "TextAnnotation", "baseMorphs" : [ "TextAnnotation" ] }, { "role" : "DataStore", "baseMorphs" : [ "DataStore" ] } ] } } ================================================ FILE: open-layui-web/src/main/view/static/admin.html ================================================  后台管理系统
    • Home
    ================================================ FILE: open-layui-web/src/main/view/static/assets/css/admin.css ================================================ /** * admin.css */ /* fixed-layout 固定头部和边栏布局 */ html, body { height: 100%; overflow: hidden; } *{ font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", Tahoma, "Hiragino Sans GB", STHeiti, "Microsoft YaHei"; } ul { margin-top: 0; } .admin-icon-yellow { color: #ffbe40; } .admin-header { border-width: 0 0 0px; position: fixed; top: 0; left: 0; right: 0; z-index: 1500; font-size: 1.4rem; margin-bottom: 0; } .admin-header-list a:hover :after { content: none; } .admin-main { position: relative; height: 100%; padding-top: 50px; background: #f3f3f3; } .admin-menu { position: fixed; z-index: 100; bottom: 15px; right: 20px; } .am-list>li>a{ padding:10px 0; } .admin-sidebar { color:#333 !important; font-size: 1.4rem; width: 260px; min-height: 100%; float: left; border-right: 1px solid #cecece; } .admin-sidebar.am-active { z-index: 1600; } .admin-sidebar-list { margin-bottom: 0; } .admin-sidebar-list li a { color: #333; padding-left: 24px; } .admin-sidebar-list li:first-child { border-top: none; } .admin-sidebar-sub { margin-top: 0; margin-bottom: 0; box-shadow: 0 16px 8px -15px #e2e2e2 inset; background: #ececec; padding-left: 24px; } .admin-sidebar-sub li:first-child { border-top: 1px solid #dedede; } .admin-sidebar-panel { margin: 10px; } .admin-content { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; background: #fff; } .admin-content, .admin-sidebar { height: 100%; overflow-x: hidden; /*overflow-y: scroll;*/ -webkit-overflow-scrolling: touch; } .admin-content-body { /*-webkit-box-flex: 1; -webkit-flex: 1 0 auto; -ms-flex: 1 0 auto; flex: 1 0 auto;*/ width: 100%; height: 100%; } .admin-tab-show{ height: 38px; overflow: hidden; position: absolute; top: 0px; border-bottom: none; z-index: 1000; width: 100%; } .admin-tab-left{ right: -1px; text-align: center; width: 20px; height: 39px; line-height: 39px; float: left; border-right: 1px solid #ddd; cursor: pointer; } .admin-tab-right{ text-align: center; width: 20px; height: 39px; line-height: 39px; float: right; border-left: 1px solid #ddd; cursor: pointer; } .admin-tab-min-hr{ position: absolute; bottom: 0px; width: 100%; height: 1px; display: block; background-color: #ddd; } .admin-tab-show-body{ height: 100%; padding-top: 40px; padding-bottom: 42px; } .admin-content-footer { width: 100%; background-color: #ffffff; position: absolute; bottom: 0px; font-size: 85%; color: #777; border-top: 1px solid #ddd; } .admin-content-footer-p{ margin: 10px !important; } .admin-content-list { border: 1px solid #e9ecf1; margin-top: 0; } .admin-content-list li { border: 1px solid #e9ecf1; border-width: 0 1px; margin-left: -1px; } .admin-content-list li:first-child { border-left: none; } .admin-content-list li:last-child { border-right: none; } .admin-content-table a { color: #535353; } .admin-content-file { margin-bottom: 0; color: #666; } .admin-content-file p { margin: 0 0 5px 0; font-size: 1.4rem; } .admin-content-file li { padding: 10px 0; } .admin-content-file li:first-child { border-top: none; } .admin-content-file li:last-child { border-bottom: none; } .admin-content-file li .am-progress { margin-bottom: 4px; } .admin-content-file li .am-progress-bar { line-height: 14px; } .admin-content-task { margin-bottom: 0; } .admin-content-task li { padding: 5px 0; border-color: #eee; } .admin-content-task li:first-child { border-top: none; } .admin-content-task li:last-child { border-bottom: none; } .admin-task-meta { font-size: 1.2rem; color: #999; } .admin-task-bd { font-size: 1.4rem; margin-bottom: 5px; } .admin-content-comment { margin-bottom: 0; } .admin-content-comment .am-comment-bd { font-size: 1.4rem; } .admin-content-pagination { margin-bottom: 0; } .admin-content-pagination li a { padding: 4px 8px; } @media only screen and (min-width: 641px) { .admin-sidebar { display: block; position: static; background: none; } .admin-offcanvas-bar { position: static; width: auto; background: none; -webkit-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); overflow-y: visible; /*min-height: 100%;*/ } .admin-offcanvas-bar:after { content: none; } } @media only screen and (max-width: 640px) { .admin-tab-show{ display: none; } .admin-tab-show-body{ padding-top: 0px; padding-bottom: 0px; } .admin-content-footer{ display: none; } .admin-sidebar { width: inherit; } .admin-offcanvas-bar { background: #f3f3f3; } .admin-offcanvas-bar:after { background: #BABABA; } .admin-sidebar-list a:hover, .admin-sidebar-list a:active{ -webkit-transition: background-color .3s ease; -moz-transition: background-color .3s ease; -ms-transition: background-color .3s ease; -o-transition: background-color .3s ease; transition: background-color .3s ease; background: #E4E4E4; } .admin-content-list li { padding: 10px; border-width: 1px 0; margin-top: -1px; } .admin-content-list li:first-child { border-top: none; } .admin-content-list li:last-child { border-bottom: none; } .admin-form-text { text-align: left !important; } .am-tab-panel{ padding: 0px !important; } } /* * user.html css */ .user-info { margin-bottom: 15px; } .user-info .am-progress { margin-bottom: 4px; } .user-info p { margin: 5px; } .user-info-order { font-size: 1.4rem; } /* * errorLog.html css */ .error-log .am-pre-scrollable { max-height: 40rem; } /* * table.html css */ .table-main { font-size: 1.4rem; padding: .5rem; } .table-main button { background: #fff; } .table-check { width: 30px; } .table-id { width: 50px; } @media only screen and (max-width: 640px) { .table-select { margin-top: 10px; margin-left: 5px; } } /* gallery.html css */ .gallery-list li { padding: 10px; } .gallery-list a { color: #666; } .gallery-list a:hover { color: #3bb4f2; } .gallery-title { margin-top: 6px; font-size: 1.4rem; } .gallery-desc { font-size: 1.2rem; margin-top: 4px; } .am-nav-tabs>li>a { padding: .5rem 2rem; /* padding: 1rem; */ margin-right: 0px !important; line-height: 1.6; border: 1px solid transparent; border-radius: 0; font-weight: 600; } /* 404.html css */ .page-404 { background: #fff; border: none; width: 200px; margin: 0 auto; } .am-tabs-nav li { position: relative; z-index: 1; } .am-tabs-nav .am-icon-close { position: absolute; top: 6px; right: 8px; color: #888; cursor: pointer; z-index: 100; } .am-tabs-nav .am-icon-close:hover { color: #333; } .am-tabs-nav .am-icon-close ~ a { padding-right: 25px!important; } .am-nav-tabs>li.am-active>a{ color:#333 !important; } .am-tab-refresh { font-size: 14px; position: absolute; top: 9px; left: 8px; color: #888; cursor: pointer; z-index: 100; } .am-tab-panel{ padding: 0px !important; } ================================================ FILE: open-layui-web/src/main/view/static/assets/css/amazeui.css ================================================ /*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ /* ========================================================================== Component: Base ============================================================================ */ /** * Fix the flawed CSS box model - Yes, IE6's box model is better * Browser support: IE8+ * via: http://paulirish.com/2012/box-sizing-border-box-ftw/ */ *, *:before, *:after { -webkit-box-sizing: border-box; box-sizing: border-box; } /* normalize.css v3.0.2 | git.io/normalize */ /* Set and to inherit the height of the viewport */ html, body { min-height: 100%; } /** * 1. Prevent iOS text size adjust after orientation change, without disabling * user zoom. * https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust */ html { -ms-text-size-adjust: 100%; /* 1 */ -webkit-text-size-adjust: 100%; /* 1 */ } /** * Remove default margin. */ body { margin: 0; } /* HTML5 display definitions ========================================================================== */ /** * Correct `block` display not defined for any HTML5 element in IE 8/9. * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. * Correct `block` display not defined for `main` in IE 11. * hgroup has been removed from the HTML5 (W3C) specification * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, main, nav, section, summary { display: block; } /** * 1. Correct `inline-block` display not defined in IE 8/9. * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. */ audio, canvas, progress, video { display: inline-block; /* 1 */ vertical-align: baseline; /* 2 */ } /** * Prevent modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */ audio:not([controls]) { display: none; height: 0; } /** * Address `[hidden]` styling not present in IE 8/9/10. * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. */ [hidden], template, script { display: none; } /* Links ========================================================================== */ /** * Remove the gray background color from active links in IE 10. */ a { background-color: transparent; } /** * Address `outline` inconsistency between Chrome and other browsers. */ a:focus { outline: thin dotted; } /** * Improve readability when focused and also mouse hovered in all browsers. */ a:active, a:hover { outline: 0; } /* Text-level semantics ========================================================================== */ /** * Remove text-decoration */ ins, a { text-decoration: none; } /** * Address styling not present in IE 8/9, Safari 5, and Chrome. */ abbr[title] { border-bottom: 1px dotted; } /** * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ b, strong { font-weight: bold; } /** * Improve readability of pre-formatted text in all browsers. */ pre { white-space: pre-wrap; } /** * Set consistent quote types. */ q { quotes: "\201C" "\201D" "\2018" "\2019"; } /** * Address inconsistent and variable font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } /* Embedded content ========================================================================== */ /** * 1. Corrects max-width behavior (2.) if padding and border are used * 2. Responsiveness: Sets a maxium width relative to the parent and auto scales the height * 3. Remove the gap between images and the bottom of their containers * 4. Remove border when inside `a` element in IE 8/9. * remove 2. for Issue #502 */ img { -webkit-box-sizing: border-box; box-sizing: border-box; /* 1 */ vertical-align: middle; /* 3 */ border: 0; /* 4 */ } /** * Correct overflow displayed oddly in IE 9. */ svg:not(:root) { overflow: hidden; } /* Grouping content ========================================================================== */ /** * Address margin not present in IE 8/9 and Safari. */ figure { margin: 0; } /** * Correct font family set oddly in Safari 5 and Chrome. */ code, kbd, pre, samp { font-family: Monaco, Menlo, Consolas, "Courier New", "FontAwesome", monospace; font-size: 1em; } /* Forms ========================================================================== */ /** * Define consistent border, margin, and padding. */ fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } /** * 1. Correct `color` not being inherited in IE 8/9. * 2. Remove padding so people aren't caught out if they zero out fieldsets. */ legend { border: 0; /* 1 */ padding: 0; /* 2 */ } /** * 1. Correct color not being inherited. * Known issue: affects color of disabled elements. * 2. Correct font properties not being inherited. * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */ button, input, optgroup, select, textarea { color: inherit; /* 1 */ font: inherit; /* 2 */ margin: 0; /* 3 */ } /** * Address `overflow` set to `hidden` in IE 8/9/10/11. */ button { overflow: visible; } /** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */ button, input { line-height: normal; } /** * Address inconsistent `text-transform` inheritance for `button` and `select`. * All other form control elements do not inherit `text-transform` values. * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. * Correct `select` style inheritance in Firefox. */ button, select { text-transform: none; } /** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` * and `video` controls. * 2. Correct inability to style clickable `input` types in iOS. * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */ button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } /* * 1. Improves consistency of cursor style for clickable elements * 2. Removes excess padding in IE 8/9. * 3. Address box sizing set to `content-box` in IE 8/9/10. */ input[type="radio"], input[type="checkbox"] { cursor: pointer; /*1*/ padding: 0; /*2*/ -webkit-box-sizing: border-box; box-sizing: border-box; /* 3 */ } /** * Re-set default cursor for disabled elements. */ button[disabled], html input[disabled] { cursor: default; } /** * Remove inner padding and border in Firefox 4+. */ button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } /** * Fix the cursor style for Chrome's increment/decrement buttons. For certain * `font-size` values of the `input`, it causes the cursor style of the * decrement button to change from `default` to `text`. */ input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Address `appearance` set to `searchfield` in Safari and Chrome. * 2. Address `box-sizing` set to `border-box` in Safari and Chrome * (include `-moz` to future-proof). */ input[type="search"] { -webkit-appearance: textfield; /* 1 */ -webkit-box-sizing: content-box; box-sizing: content-box; /* 2 */ } /** * Remove inner padding and search cancel button in Safari 5 and Chrome * on OS X. */ input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * 1. Remove default vertical scrollbar in IE 8/9. * 2. Improve readability and alignment in all browsers. */ textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ resize: vertical; } /** * Don't inherit the `font-weight` (applied by a rule above). * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. */ optgroup { font-weight: bold; } /* Tables ========================================================================== */ /** * Remove most spacing between table cells. */ table { border-collapse: collapse; border-spacing: 0; } td, th { padding: 0; } /* AMUI Base ========================================================================== */ /** * `font-size` is set in `html` element to support the `rem` unit for font-sizes * NOTE: IE9 & IE10 do not recognize `rem` units when used with the `font` shorthand property. */ html { font-size: 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { position: relative; background: #fff; font-family: "Segoe UI", "Lucida Grande", Helvetica, Arial, "Microsoft YaHei", FreeSans, Arimo, "Droid Sans", "wenquanyi micro hei", "Hiragino Sans GB", "Hiragino Sans GB W3", "FontAwesome", sans-serif; font-weight: normal; line-height: 1.6; color: #333333; font-size: 1.6rem; } /** * 1. http://usabilitypost.com/2012/11/15/w-optimizelegibility-on-mobile-devices/ * 2. http://maxvoltar.com/archive/-webkit-font-smoothing * NOTE: http://usabilitypost.com/2012/11/05/stop-fixing-font-smoothing/ * 3. http://maximilianhoffmann.com/posts/better-font-rendering-on-osx * http://jaydenseric.com/blog/css-font-smoothing-for-firefox-mac */ body, input, textarea, select, button { text-rendering: optimizeLegibility; /* 1 */ -webkit-font-smoothing: antialiased; /* 2 */ -moz-osx-font-smoothing: grayscale; /* 3 Default: auto */ -moz-font-feature-settings: "liga", "kern"; } /*Only phones */ @media only screen and (max-width: 640px) { /** * Break strings if their length exceeds the width of their container */ body { word-wrap: break-word; -webkit-hyphens: auto; -ms-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } } /** * links */ a { color: #0e90d2; } a:hover, a:focus { color: #095f8a; } a:focus { outline: thin dotted; outline: 1px auto -webkit-focus-ring-color; outline-offset: -2px; } /* Insert */ ins { background: #ffa; color: #333333; } /** * Mark * Note: Addresses styling not present in IE 8/9. */ mark { background: #ffa; color: #333333; } /** * Abbreviation and definition */ abbr[title], dfn[title] { cursor: help; } dfn[title] { border-bottom: 1px dotted; font-style: normal; } /* Spacing for block elements */ p, hr, ul, ol, dl, blockquote, pre, address, fieldset, figure { margin: 0 0 1.6rem 0; } * + p, * + hr, * + ul, * + ol, * + dl, * + blockquote, * + pre, * + address, * + fieldset, * + figure { margin-top: 1.6rem; } /* Headings ========================================================================== */ h1, h2, h3, h4, h5, h6 { margin: 0 0 1.6rem 0; font-weight: 600; font-size: 100%; } h1 { font-size: 1.5em; } h2 { font-size: 1.25em; } * + h1, * + h2, * + h3, * + h4, * + h5, * + h6 { margin-top: 2em; } /* Ordered and unordered lists */ ul, ol { padding-left: 2em; } /* Reset margin for nested lists */ ul > li > ul, ul > li > ol, ol > li > ol, ol > li > ul { margin: 1em 0; } /* Description lists */ dt { font-weight: bold; } dt + dd { margin-top: .5em; } dd { margin-left: 0; } dd + dt { margin-top: 1em; } /** * Horizontal rule * 1. Address differences between Firefox and other browsers. */ hr { display: block; padding: 0; border: 0; height: 0; border-top: 1px solid #eeeeee; /* 1 */ -webkit-box-sizing: content-box; box-sizing: content-box; /* 1 */ } /* Address */ address { font-style: normal; } /* Quotes */ blockquote { padding-top: 5px; padding-bottom: 5px; padding-left: 15px; border-left: 4px solid #ddd; font-family: Georgia, "Times New Roman", Times, Kai, "Kaiti SC", KaiTi, BiauKai, "FontAwesome", serif; /* Small print for identifying the source */ /* Smaller margin if `small` follows */ } blockquote small { display: block; color: #999999; font-family: "Segoe UI", "Lucida Grande", Helvetica, Arial, "Microsoft YaHei", FreeSans, Arimo, "Droid Sans", "wenquanyi micro hei", "Hiragino Sans GB", "Hiragino Sans GB W3", "FontAwesome", sans-serif; text-align: right; } blockquote p:last-of-type { margin-bottom: 0; } /* iframe */ iframe { border: 0; } /* Forms ========================================================================== */ /** * Vertical alignment * Exclude `radio` and `checkbox` elements because the default `baseline` value aligns better with text */ button, input:not([type="radio"]):not([type="checkbox"]), select { vertical-align: middle; } /** * Fix viewport for IE10 snap mode * http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ * http://msdn.microsoft.com/en-us/library/ie/hh869615%28v=vs.85%29.aspx * http://msdn.microsoft.com/zh-cn/library/ie/hh708740(v=vs.85).aspx * @2014.01.20: 设置一下属性以后,windows Phone 8 上显示的字体过小,暂时注释掉 * ========================================================================== */ /* @-ms-viewport { width: device-width; } */ .am-scrollbar-measure { width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px; } /* ========================================================================== Component: Grid ============================================================================ */ .am-container { -webkit-box-sizing: border-box; box-sizing: border-box; margin-left: auto; margin-right: auto; padding-left: 1rem; padding-right: 1rem; width: 100%; max-width: 1300px; } .am-container:before, .am-container:after { content: " "; display: table; } .am-container:after { clear: both; } @media only screen and (min-width:641px) { .am-container { padding-left: 1.5rem; padding-right: 1.5rem; } } .am-container > .am-g { width: auto; margin-left: -1rem; margin-right: -1rem; } @media only screen and (min-width:641px) { .am-container > .am-g { margin-left: -1.5rem; margin-right: -1.5rem; } } .am-g { margin: 0 auto; width: 100%; } .am-g:before, .am-g:after { content: " "; display: table; } .am-g:after { clear: both; } .am-g .am-g { margin-left: -1rem; margin-right: -1rem; width: auto; } .am-g .am-g.am-g-collapse { margin-left: 0; margin-right: 0; width: auto; } @media only screen and (min-width:641px) { .am-g .am-g { margin-left: -1.5rem; margin-right: -1.5rem; } } .am-g.am-g-collapse .am-g { margin-left: 0; margin-right: 0; } .am-g-collapse [class*="am-u-"] { padding-left: 0; padding-right: 0; } .am-g-fixed { max-width: 1000px; } [class*="am-u-"] { width: 100%; padding-left: 1rem; padding-right: 1rem; float: left; position: relative; } [class*="am-u-"] + [class*="am-u-"]:last-child { float: right; } [class*="am-u-"] + [class*="am-u-"].am-u-end { float: left; } @media only screen and (min-width:641px) { [class*="am-u-"] { padding-left: 1.5rem; padding-right: 1.5rem; } } [class*="am-u-pull-"] { left: auto; } [class*="am-u-push-"] { right: auto; } @media only screen { .am-u-sm-1 { width: 8.33333333%; } .am-u-sm-2 { width: 16.66666667%; } .am-u-sm-3 { width: 25%; } .am-u-sm-4 { width: 33.33333333%; } .am-u-sm-5 { width: 41.66666667%; } .am-u-sm-6 { width: 50%; } .am-u-sm-7 { width: 58.33333333%; } .am-u-sm-8 { width: 66.66666667%; } .am-u-sm-9 { width: 75%; } .am-u-sm-10 { width: 83.33333333%; } .am-u-sm-11 { width: 91.66666667%; } .am-u-sm-12 { width: 100%; } .am-u-sm-pull-0 { right: 0; } .am-u-sm-pull-1 { right: 8.33333333%; } .am-u-sm-pull-2 { right: 16.66666667%; } .am-u-sm-pull-3 { right: 25%; } .am-u-sm-pull-4 { right: 33.33333333%; } .am-u-sm-pull-5 { right: 41.66666667%; } .am-u-sm-pull-6 { right: 50%; } .am-u-sm-pull-7 { right: 58.33333333%; } .am-u-sm-pull-8 { right: 66.66666667%; } .am-u-sm-pull-9 { right: 75%; } .am-u-sm-pull-10 { right: 83.33333333%; } .am-u-sm-pull-11 { right: 91.66666667%; } .am-u-sm-push-0 { left: 0; } .am-u-sm-push-1 { left: 8.33333333%; } .am-u-sm-push-2 { left: 16.66666667%; } .am-u-sm-push-3 { left: 25%; } .am-u-sm-push-4 { left: 33.33333333%; } .am-u-sm-push-5 { left: 41.66666667%; } .am-u-sm-push-6 { left: 50%; } .am-u-sm-push-7 { left: 58.33333333%; } .am-u-sm-push-8 { left: 66.66666667%; } .am-u-sm-push-9 { left: 75%; } .am-u-sm-push-10 { left: 83.33333333%; } .am-u-sm-push-11 { left: 91.66666667%; } .am-u-sm-offset-0 { margin-left: 0; } .am-u-sm-offset-1 { margin-left: 8.33333333%; } .am-u-sm-offset-2 { margin-left: 16.66666667%; } .am-u-sm-offset-3 { margin-left: 25%; } .am-u-sm-offset-4 { margin-left: 33.33333333%; } .am-u-sm-offset-5 { margin-left: 41.66666667%; } .am-u-sm-offset-6 { margin-left: 50%; } .am-u-sm-offset-7 { margin-left: 58.33333333%; } .am-u-sm-offset-8 { margin-left: 66.66666667%; } .am-u-sm-offset-9 { margin-left: 75%; } .am-u-sm-offset-10 { margin-left: 83.33333333%; } .am-u-sm-offset-11 { margin-left: 91.66666667%; } .am-u-sm-reset-order { margin-left: 0; margin-right: 0; left: auto; right: auto; float: left; } [class*="am-u-"].am-u-sm-centered { margin-left: auto; margin-right: auto; float: none; } [class*="am-u-"].am-u-sm-centered:last-child { float: none; } [class*="am-u-"].am-u-sm-uncentered { margin-left: 0; margin-right: 0; float: left; } [class*="am-u-"].am-u-sm-uncentered:last-child { float: left; } } @media only screen and (min-width:641px) { .am-u-md-1 { width: 8.33333333%; } .am-u-md-2 { width: 16.66666667%; } .am-u-md-3 { width: 25%; } .am-u-md-4 { width: 33.33333333%; } .am-u-md-5 { width: 41.66666667%; } .am-u-md-6 { width: 50%; } .am-u-md-7 { width: 58.33333333%; } .am-u-md-8 { width: 66.66666667%; } .am-u-md-9 { width: 75%; } .am-u-md-10 { width: 83.33333333%; } .am-u-md-11 { width: 91.66666667%; } .am-u-md-12 { width: 100%; } .am-u-md-pull-0 { right: 0; } .am-u-md-pull-1 { right: 8.33333333%; } .am-u-md-pull-2 { right: 16.66666667%; } .am-u-md-pull-3 { right: 25%; } .am-u-md-pull-4 { right: 33.33333333%; } .am-u-md-pull-5 { right: 41.66666667%; } .am-u-md-pull-6 { right: 50%; } .am-u-md-pull-7 { right: 58.33333333%; } .am-u-md-pull-8 { right: 66.66666667%; } .am-u-md-pull-9 { right: 75%; } .am-u-md-pull-10 { right: 83.33333333%; } .am-u-md-pull-11 { right: 91.66666667%; } .am-u-md-push-0 { left: 0; } .am-u-md-push-1 { left: 8.33333333%; } .am-u-md-push-2 { left: 16.66666667%; } .am-u-md-push-3 { left: 25%; } .am-u-md-push-4 { left: 33.33333333%; } .am-u-md-push-5 { left: 41.66666667%; } .am-u-md-push-6 { left: 50%; } .am-u-md-push-7 { left: 58.33333333%; } .am-u-md-push-8 { left: 66.66666667%; } .am-u-md-push-9 { left: 75%; } .am-u-md-push-10 { left: 83.33333333%; } .am-u-md-push-11 { left: 91.66666667%; } .am-u-md-offset-0 { margin-left: 0; } .am-u-md-offset-1 { margin-left: 8.33333333%; } .am-u-md-offset-2 { margin-left: 16.66666667%; } .am-u-md-offset-3 { margin-left: 25%; } .am-u-md-offset-4 { margin-left: 33.33333333%; } .am-u-md-offset-5 { margin-left: 41.66666667%; } .am-u-md-offset-6 { margin-left: 50%; } .am-u-md-offset-7 { margin-left: 58.33333333%; } .am-u-md-offset-8 { margin-left: 66.66666667%; } .am-u-md-offset-9 { margin-left: 75%; } .am-u-md-offset-10 { margin-left: 83.33333333%; } .am-u-md-offset-11 { margin-left: 91.66666667%; } .am-u-md-reset-order { margin-left: 0; margin-right: 0; left: auto; right: auto; float: left; } [class*="am-u-"].am-u-md-centered { margin-left: auto; margin-right: auto; float: none; } [class*="am-u-"].am-u-md-centered:last-child { float: none; } [class*="am-u-"].am-u-md-uncentered { margin-left: 0; margin-right: 0; float: left; } [class*="am-u-"].am-u-md-uncentered:last-child { float: left; } } @media only screen and (min-width:1025px) { .am-u-lg-1 { width: 8.33333333%; } .am-u-lg-2 { width: 16.66666667%; } .am-u-lg-3 { width: 25%; } .am-u-lg-4 { width: 33.33333333%; } .am-u-lg-5 { width: 41.66666667%; } .am-u-lg-6 { width: 50%; } .am-u-lg-7 { width: 58.33333333%; } .am-u-lg-8 { width: 66.66666667%; } .am-u-lg-9 { width: 75%; } .am-u-lg-10 { width: 83.33333333%; } .am-u-lg-11 { width: 91.66666667%; } .am-u-lg-12 { width: 100%; } .am-u-lg-pull-0 { right: 0; } .am-u-lg-pull-1 { right: 8.33333333%; } .am-u-lg-pull-2 { right: 16.66666667%; } .am-u-lg-pull-3 { right: 25%; } .am-u-lg-pull-4 { right: 33.33333333%; } .am-u-lg-pull-5 { right: 41.66666667%; } .am-u-lg-pull-6 { right: 50%; } .am-u-lg-pull-7 { right: 58.33333333%; } .am-u-lg-pull-8 { right: 66.66666667%; } .am-u-lg-pull-9 { right: 75%; } .am-u-lg-pull-10 { right: 83.33333333%; } .am-u-lg-pull-11 { right: 91.66666667%; } .am-u-lg-push-0 { left: 0; } .am-u-lg-push-1 { left: 8.33333333%; } .am-u-lg-push-2 { left: 16.66666667%; } .am-u-lg-push-3 { left: 25%; } .am-u-lg-push-4 { left: 33.33333333%; } .am-u-lg-push-5 { left: 41.66666667%; } .am-u-lg-push-6 { left: 50%; } .am-u-lg-push-7 { left: 58.33333333%; } .am-u-lg-push-8 { left: 66.66666667%; } .am-u-lg-push-9 { left: 75%; } .am-u-lg-push-10 { left: 83.33333333%; } .am-u-lg-push-11 { left: 91.66666667%; } .am-u-lg-offset-0 { margin-left: 0; } .am-u-lg-offset-1 { margin-left: 8.33333333%; } .am-u-lg-offset-2 { margin-left: 16.66666667%; } .am-u-lg-offset-3 { margin-left: 25%; } .am-u-lg-offset-4 { margin-left: 33.33333333%; } .am-u-lg-offset-5 { margin-left: 41.66666667%; } .am-u-lg-offset-6 { margin-left: 50%; } .am-u-lg-offset-7 { margin-left: 58.33333333%; } .am-u-lg-offset-8 { margin-left: 66.66666667%; } .am-u-lg-offset-9 { margin-left: 75%; } .am-u-lg-offset-10 { margin-left: 83.33333333%; } .am-u-lg-offset-11 { margin-left: 91.66666667%; } .am-u-lg-reset-order { margin-left: 0; margin-right: 0; left: auto; right: auto; float: left; } [class*="am-u-"].am-u-lg-centered { margin-left: auto; margin-right: auto; float: none; } [class*="am-u-"].am-u-lg-centered:last-child { float: none; } [class*="am-u-"].am-u-lg-uncentered { margin-left: 0; margin-right: 0; float: left; } [class*="am-u-"].am-u-lg-uncentered:last-child { float: left; } } /* ========================================================================== Component: AVG Grid ============================================================================ */ [class*="am-avg-"] { display: block; padding: 0; margin: 0; list-style: none; } [class*="am-avg-"]:before, [class*="am-avg-"]:after { content: " "; display: table; } [class*="am-avg-"]:after { clear: both; } [class*="am-avg-"] > li { display: block; height: auto; float: left; } @media only screen { .am-avg-sm-1 > li { width: 100%; } .am-avg-sm-1 > li:nth-of-type(n) { clear: none; } .am-avg-sm-1 > li:nth-of-type(1n + 1) { clear: both; } .am-avg-sm-2 > li { width: 50%; } .am-avg-sm-2 > li:nth-of-type(n) { clear: none; } .am-avg-sm-2 > li:nth-of-type(2n + 1) { clear: both; } .am-avg-sm-3 > li { width: 33.33333333%; } .am-avg-sm-3 > li:nth-of-type(n) { clear: none; } .am-avg-sm-3 > li:nth-of-type(3n + 1) { clear: both; } .am-avg-sm-4 > li { width: 25%; } .am-avg-sm-4 > li:nth-of-type(n) { clear: none; } .am-avg-sm-4 > li:nth-of-type(4n + 1) { clear: both; } .am-avg-sm-5 > li { width: 20%; } .am-avg-sm-5 > li:nth-of-type(n) { clear: none; } .am-avg-sm-5 > li:nth-of-type(5n + 1) { clear: both; } .am-avg-sm-6 > li { width: 16.66666667%; } .am-avg-sm-6 > li:nth-of-type(n) { clear: none; } .am-avg-sm-6 > li:nth-of-type(6n + 1) { clear: both; } .am-avg-sm-7 > li { width: 14.28571429%; } .am-avg-sm-7 > li:nth-of-type(n) { clear: none; } .am-avg-sm-7 > li:nth-of-type(7n + 1) { clear: both; } .am-avg-sm-8 > li { width: 12.5%; } .am-avg-sm-8 > li:nth-of-type(n) { clear: none; } .am-avg-sm-8 > li:nth-of-type(8n + 1) { clear: both; } .am-avg-sm-9 > li { width: 11.11111111%; } .am-avg-sm-9 > li:nth-of-type(n) { clear: none; } .am-avg-sm-9 > li:nth-of-type(9n + 1) { clear: both; } .am-avg-sm-10 > li { width: 10%; } .am-avg-sm-10 > li:nth-of-type(n) { clear: none; } .am-avg-sm-10 > li:nth-of-type(10n + 1) { clear: both; } .am-avg-sm-11 > li { width: 9.09090909%; } .am-avg-sm-11 > li:nth-of-type(n) { clear: none; } .am-avg-sm-11 > li:nth-of-type(11n + 1) { clear: both; } .am-avg-sm-12 > li { width: 8.33333333%; } .am-avg-sm-12 > li:nth-of-type(n) { clear: none; } .am-avg-sm-12 > li:nth-of-type(12n + 1) { clear: both; } } @media only screen and (min-width:641px) { .am-avg-md-1 > li { width: 100%; } .am-avg-md-1 > li:nth-of-type(n) { clear: none; } .am-avg-md-1 > li:nth-of-type(1n + 1) { clear: both; } .am-avg-md-2 > li { width: 50%; } .am-avg-md-2 > li:nth-of-type(n) { clear: none; } .am-avg-md-2 > li:nth-of-type(2n + 1) { clear: both; } .am-avg-md-3 > li { width: 33.33333333%; } .am-avg-md-3 > li:nth-of-type(n) { clear: none; } .am-avg-md-3 > li:nth-of-type(3n + 1) { clear: both; } .am-avg-md-4 > li { width: 25%; } .am-avg-md-4 > li:nth-of-type(n) { clear: none; } .am-avg-md-4 > li:nth-of-type(4n + 1) { clear: both; } .am-avg-md-5 > li { width: 20%; } .am-avg-md-5 > li:nth-of-type(n) { clear: none; } .am-avg-md-5 > li:nth-of-type(5n + 1) { clear: both; } .am-avg-md-6 > li { width: 16.66666667%; } .am-avg-md-6 > li:nth-of-type(n) { clear: none; } .am-avg-md-6 > li:nth-of-type(6n + 1) { clear: both; } .am-avg-md-7 > li { width: 14.28571429%; } .am-avg-md-7 > li:nth-of-type(n) { clear: none; } .am-avg-md-7 > li:nth-of-type(7n + 1) { clear: both; } .am-avg-md-8 > li { width: 12.5%; } .am-avg-md-8 > li:nth-of-type(n) { clear: none; } .am-avg-md-8 > li:nth-of-type(8n + 1) { clear: both; } .am-avg-md-9 > li { width: 11.11111111%; } .am-avg-md-9 > li:nth-of-type(n) { clear: none; } .am-avg-md-9 > li:nth-of-type(9n + 1) { clear: both; } .am-avg-md-10 > li { width: 10%; } .am-avg-md-10 > li:nth-of-type(n) { clear: none; } .am-avg-md-10 > li:nth-of-type(10n + 1) { clear: both; } .am-avg-md-11 > li { width: 9.09090909%; } .am-avg-md-11 > li:nth-of-type(n) { clear: none; } .am-avg-md-11 > li:nth-of-type(11n + 1) { clear: both; } .am-avg-md-12 > li { width: 8.33333333%; } .am-avg-md-12 > li:nth-of-type(n) { clear: none; } .am-avg-md-12 > li:nth-of-type(12n + 1) { clear: both; } } @media only screen and (min-width:1025px) { .am-avg-lg-1 > li { width: 100%; } .am-avg-lg-1 > li:nth-of-type(n) { clear: none; } .am-avg-lg-1 > li:nth-of-type(1n + 1) { clear: both; } .am-avg-lg-2 > li { width: 50%; } .am-avg-lg-2 > li:nth-of-type(n) { clear: none; } .am-avg-lg-2 > li:nth-of-type(2n + 1) { clear: both; } .am-avg-lg-3 > li { width: 33.33333333%; } .am-avg-lg-3 > li:nth-of-type(n) { clear: none; } .am-avg-lg-3 > li:nth-of-type(3n + 1) { clear: both; } .am-avg-lg-4 > li { width: 25%; } .am-avg-lg-4 > li:nth-of-type(n) { clear: none; } .am-avg-lg-4 > li:nth-of-type(4n + 1) { clear: both; } .am-avg-lg-5 > li { width: 20%; } .am-avg-lg-5 > li:nth-of-type(n) { clear: none; } .am-avg-lg-5 > li:nth-of-type(5n + 1) { clear: both; } .am-avg-lg-6 > li { width: 16.66666667%; } .am-avg-lg-6 > li:nth-of-type(n) { clear: none; } .am-avg-lg-6 > li:nth-of-type(6n + 1) { clear: both; } .am-avg-lg-7 > li { width: 14.28571429%; } .am-avg-lg-7 > li:nth-of-type(n) { clear: none; } .am-avg-lg-7 > li:nth-of-type(7n + 1) { clear: both; } .am-avg-lg-8 > li { width: 12.5%; } .am-avg-lg-8 > li:nth-of-type(n) { clear: none; } .am-avg-lg-8 > li:nth-of-type(8n + 1) { clear: both; } .am-avg-lg-9 > li { width: 11.11111111%; } .am-avg-lg-9 > li:nth-of-type(n) { clear: none; } .am-avg-lg-9 > li:nth-of-type(9n + 1) { clear: both; } .am-avg-lg-10 > li { width: 10%; } .am-avg-lg-10 > li:nth-of-type(n) { clear: none; } .am-avg-lg-10 > li:nth-of-type(10n + 1) { clear: both; } .am-avg-lg-11 > li { width: 9.09090909%; } .am-avg-lg-11 > li:nth-of-type(n) { clear: none; } .am-avg-lg-11 > li:nth-of-type(11n + 1) { clear: both; } .am-avg-lg-12 > li { width: 8.33333333%; } .am-avg-lg-12 > li:nth-of-type(n) { clear: none; } .am-avg-lg-12 > li:nth-of-type(12n + 1) { clear: both; } } /* ========================================================================== Component: Code ============================================================================ */ /* Inline and block code styles */ code, kbd, pre, samp { font-family: Monaco, Menlo, Consolas, "Courier New", "FontAwesome", monospace; } /* Inline code */ code { padding: 2px 4px; font-size: 1.3rem; color: #c7254e; background-color: #f8f8f8; white-space: nowrap; border-radius: 0; } /* Code block */ pre { display: block; padding: 1rem; margin: 1rem 0; font-size: 1.3rem; line-height: 1.6; word-break: break-all; word-wrap: break-word; color: #555555; background-color: #f8f8f8; border: 1px solid #dedede; border-radius: 0; } pre code { padding: 0; font-size: inherit; color: inherit; white-space: pre-wrap; background-color: transparent; border-radius: 0; } /* Enable scrollable blocks of code */ .am-pre-scrollable { max-height: 24rem; overflow-y: scroll; } /* ========================================================================== Component: Button ============================================================================ */ .am-btn { display: inline-block; margin-bottom: 0; padding: 0.5em 1em; vertical-align: middle; font-size: 1.6rem; font-weight: normal; line-height: 1.2; text-align: center; white-space: nowrap; background-image: none; border: 1px solid transparent; border-radius: 0; cursor: pointer; outline: none; -webkit-appearance: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-transition: background-color 300ms ease-out, border-color 300ms ease-out; transition: background-color 300ms ease-out, border-color 300ms ease-out; } .am-btn:focus, .am-btn:active:focus { outline: thin dotted; outline: 1px auto -webkit-focus-ring-color; outline-offset: -2px; } .am-btn:hover, .am-btn:focus { color: #444; text-decoration: none; } .am-btn:active, .am-btn.am-active { background-image: none; -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15); } .am-btn.am-disabled, .am-btn[disabled], fieldset[disabled] .am-btn { pointer-events: none; border-color: transparent; cursor: not-allowed; opacity: 0.45; -webkit-box-shadow: none; box-shadow: none; } .am-btn.am-round { border-radius: 1000px; } .am-btn.am-radius { border-radius: 2px; } .am-btn-default { color: #444; background-color: #e6e6e6; border-color: #e6e6e6; } a.am-btn-default:visited { color: #444; } .am-btn-default:hover, .am-btn-default:focus, .am-btn-default:active, .am-btn-default.am-active, .am-active .am-btn-default.am-dropdown-toggle { color: #444; border-color: #c7c7c7; } .am-btn-default:hover, .am-btn-default:focus { background-color: #d4d4d4; } .am-btn-default:active, .am-btn-default.am-active, .am-active .am-btn-default.am-dropdown-toggle { background-image: none; background-color: #c2c2c2; } .am-btn-default.am-disabled, .am-btn-default[disabled], fieldset[disabled] .am-btn-default, .am-btn-default.am-disabled:hover, .am-btn-default[disabled]:hover, fieldset[disabled] .am-btn-default:hover, .am-btn-default.am-disabled:focus, .am-btn-default[disabled]:focus, fieldset[disabled] .am-btn-default:focus, .am-btn-default.am-disabled:active, .am-btn-default[disabled]:active, fieldset[disabled] .am-btn-default:active, .am-btn-default.am-disabled.am-active, .am-btn-default[disabled].am-active, fieldset[disabled] .am-btn-default.am-active { background-color: #e6e6e6; border-color: #e6e6e6; } .am-btn-group .am-btn-default, .am-btn-group-stacked .am-btn-default { border-color: #d9d9d9; } .am-btn-primary { color: #fff; background-color: #0e90d2; border-color: #0e90d2; } a.am-btn-primary:visited { color: #fff; } .am-btn-primary:hover, .am-btn-primary:focus, .am-btn-primary:active, .am-btn-primary.am-active, .am-active .am-btn-primary.am-dropdown-toggle { color: #fff; border-color: #0a6999; } .am-btn-primary:hover, .am-btn-primary:focus { background-color: #0c79b1; } .am-btn-primary:active, .am-btn-primary.am-active, .am-active .am-btn-primary.am-dropdown-toggle { background-image: none; background-color: #0a628f; } .am-btn-primary.am-disabled, .am-btn-primary[disabled], fieldset[disabled] .am-btn-primary, .am-btn-primary.am-disabled:hover, .am-btn-primary[disabled]:hover, fieldset[disabled] .am-btn-primary:hover, .am-btn-primary.am-disabled:focus, .am-btn-primary[disabled]:focus, fieldset[disabled] .am-btn-primary:focus, .am-btn-primary.am-disabled:active, .am-btn-primary[disabled]:active, fieldset[disabled] .am-btn-primary:active, .am-btn-primary.am-disabled.am-active, .am-btn-primary[disabled].am-active, fieldset[disabled] .am-btn-primary.am-active { background-color: #0e90d2; border-color: #0e90d2; } .am-btn-group .am-btn-primary, .am-btn-group-stacked .am-btn-primary { border-color: #0c80ba; } .am-btn-warning { color: #fff; background-color: #F37B1D; border-color: #F37B1D; } a.am-btn-warning:visited { color: #fff; } .am-btn-warning:hover, .am-btn-warning:focus, .am-btn-warning:active, .am-btn-warning.am-active, .am-active .am-btn-warning.am-dropdown-toggle { color: #fff; border-color: #c85e0b; } .am-btn-warning:hover, .am-btn-warning:focus { background-color: #e0690c; } .am-btn-warning:active, .am-btn-warning.am-active, .am-active .am-btn-warning.am-dropdown-toggle { background-image: none; background-color: #be590a; } .am-btn-warning.am-disabled, .am-btn-warning[disabled], fieldset[disabled] .am-btn-warning, .am-btn-warning.am-disabled:hover, .am-btn-warning[disabled]:hover, fieldset[disabled] .am-btn-warning:hover, .am-btn-warning.am-disabled:focus, .am-btn-warning[disabled]:focus, fieldset[disabled] .am-btn-warning:focus, .am-btn-warning.am-disabled:active, .am-btn-warning[disabled]:active, fieldset[disabled] .am-btn-warning:active, .am-btn-warning.am-disabled.am-active, .am-btn-warning[disabled].am-active, fieldset[disabled] .am-btn-warning.am-active { background-color: #F37B1D; border-color: #F37B1D; } .am-btn-group .am-btn-warning, .am-btn-group-stacked .am-btn-warning { border-color: #ea6e0c; } .am-btn-danger { color: #fff; background-color: #dd514c; border-color: #dd514c; } a.am-btn-danger:visited { color: #fff; } .am-btn-danger:hover, .am-btn-danger:focus, .am-btn-danger:active, .am-btn-danger.am-active, .am-active .am-btn-danger.am-dropdown-toggle { color: #fff; border-color: #c62b26; } .am-btn-danger:hover, .am-btn-danger:focus { background-color: #d7342e; } .am-btn-danger:active, .am-btn-danger.am-active, .am-active .am-btn-danger.am-dropdown-toggle { background-image: none; background-color: #be2924; } .am-btn-danger.am-disabled, .am-btn-danger[disabled], fieldset[disabled] .am-btn-danger, .am-btn-danger.am-disabled:hover, .am-btn-danger[disabled]:hover, fieldset[disabled] .am-btn-danger:hover, .am-btn-danger.am-disabled:focus, .am-btn-danger[disabled]:focus, fieldset[disabled] .am-btn-danger:focus, .am-btn-danger.am-disabled:active, .am-btn-danger[disabled]:active, fieldset[disabled] .am-btn-danger:active, .am-btn-danger.am-disabled.am-active, .am-btn-danger[disabled].am-active, fieldset[disabled] .am-btn-danger.am-active { background-color: #dd514c; border-color: #dd514c; } .am-btn-group .am-btn-danger, .am-btn-group-stacked .am-btn-danger { border-color: #d93c37; } .am-btn-success { color: #fff; background-color: #5eb95e; border-color: #5eb95e; } a.am-btn-success:visited { color: #fff; } .am-btn-success:hover, .am-btn-success:focus, .am-btn-success:active, .am-btn-success.am-active, .am-active .am-btn-success.am-dropdown-toggle { color: #fff; border-color: #429842; } .am-btn-success:hover, .am-btn-success:focus { background-color: #4aaa4a; } .am-btn-success:active, .am-btn-success.am-active, .am-active .am-btn-success.am-dropdown-toggle { background-image: none; background-color: #3f913f; } .am-btn-success.am-disabled, .am-btn-success[disabled], fieldset[disabled] .am-btn-success, .am-btn-success.am-disabled:hover, .am-btn-success[disabled]:hover, fieldset[disabled] .am-btn-success:hover, .am-btn-success.am-disabled:focus, .am-btn-success[disabled]:focus, fieldset[disabled] .am-btn-success:focus, .am-btn-success.am-disabled:active, .am-btn-success[disabled]:active, fieldset[disabled] .am-btn-success:active, .am-btn-success.am-disabled.am-active, .am-btn-success[disabled].am-active, fieldset[disabled] .am-btn-success.am-active { background-color: #5eb95e; border-color: #5eb95e; } .am-btn-group .am-btn-success, .am-btn-group-stacked .am-btn-success { border-color: #4db14d; } .am-btn-secondary { color: #fff; background-color: #3bb4f2; border-color: #3bb4f2; } a.am-btn-secondary:visited { color: #fff; } .am-btn-secondary:hover, .am-btn-secondary:focus, .am-btn-secondary:active, .am-btn-secondary.am-active, .am-active .am-btn-secondary.am-dropdown-toggle { color: #fff; border-color: #0f9ae0; } .am-btn-secondary:hover, .am-btn-secondary:focus { background-color: #19a7f0; } .am-btn-secondary:active, .am-btn-secondary.am-active, .am-active .am-btn-secondary.am-dropdown-toggle { background-image: none; background-color: #0e93d7; } .am-btn-secondary.am-disabled, .am-btn-secondary[disabled], fieldset[disabled] .am-btn-secondary, .am-btn-secondary.am-disabled:hover, .am-btn-secondary[disabled]:hover, fieldset[disabled] .am-btn-secondary:hover, .am-btn-secondary.am-disabled:focus, .am-btn-secondary[disabled]:focus, fieldset[disabled] .am-btn-secondary:focus, .am-btn-secondary.am-disabled:active, .am-btn-secondary[disabled]:active, fieldset[disabled] .am-btn-secondary:active, .am-btn-secondary.am-disabled.am-active, .am-btn-secondary[disabled].am-active, fieldset[disabled] .am-btn-secondary.am-active { background-color: #3bb4f2; border-color: #3bb4f2; } .am-btn-group .am-btn-secondary, .am-btn-group-stacked .am-btn-secondary { border-color: #23abf0; } /* Style links like a button */ .am-btn-link { color: #0e90d2; font-weight: normal; cursor: pointer; border-radius: 0; } .am-btn-link, .am-btn-link:active, .am-btn-link[disabled], fieldset[disabled] .am-btn-link { background-color: transparent; -webkit-box-shadow: none; box-shadow: none; } .am-btn-link, .am-btn-link:hover, .am-btn-link:focus, .am-btn-link:active { border-color: transparent; } .am-btn-link:hover, .am-btn-link:focus { color: #095f8a; text-decoration: underline; background-color: transparent; } .am-btn-link[disabled]:hover, fieldset[disabled] .am-btn-link:hover, .am-btn-link[disabled]:focus, fieldset[disabled] .am-btn-link:focus { color: #999999; text-decoration: none; } /* button size */ .am-btn-xs { font-size: 1.2rem; } .am-btn-sm { font-size: 1.4rem; } .am-btn-lg { font-size: 1.8rem; } .am-btn-xl { font-size: 2rem; } /* Block button */ .am-btn-block { display: block; width: 100%; padding-left: 0; padding-right: 0; } /* Multiple block buttons vertically space */ .am-btn-block + .am-btn-block { margin-top: 5px; } /* Specificity overrides */ input[type="submit"].am-btn-block, input[type="reset"].am-btn-block, input[type="button"].am-btn-block { width: 100%; } /* Button with loading spinner */ .am-btn.am-btn-loading .am-icon-spin { margin-right: 5px; } /* ========================================================================== Component: Table ============================================================================ */ table { max-width: 100%; background-color: transparent; empty-cells: show; } table code { white-space: normal; } th { text-align: left; } .am-table { width: 100%; margin-bottom: 1.6rem; border-spacing: 0; border-collapse: separate; } .am-table > thead > tr > th, .am-table > tbody > tr > th, .am-table > tfoot > tr > th, .am-table > thead > tr > td, .am-table > tbody > tr > td, .am-table > tfoot > tr > td { padding: 0.7rem; line-height: 1.6; vertical-align: top; border-top: 1px solid #ddd; } .am-table > thead > tr > th { vertical-align: bottom; border-bottom: 1px solid #ddd; } .am-table > caption + thead > tr:first-child > th, .am-table > colgroup + thead > tr:first-child > th, .am-table > thead:first-child > tr:first-child > th, .am-table > caption + thead > tr:first-child > td, .am-table > colgroup + thead > tr:first-child > td, .am-table > thead:first-child > tr:first-child > td { border-top: 0; } .am-table > tbody + tbody tr:first-child td { border-top: 2px solid #ddd; } /* Bordered version */ .am-table-bordered { border: 1px solid #ddd; border-left: none; } .am-table-bordered > thead > tr > th, .am-table-bordered > tbody > tr > th, .am-table-bordered > tfoot > tr > th, .am-table-bordered > thead > tr > td, .am-table-bordered > tbody > tr > td, .am-table-bordered > tfoot > tr > td { border-left: 1px solid #ddd; /*&:first-child { border-left: none; }*/ } .am-table-bordered > tbody > tr:first-child > th, .am-table-bordered > tbody > tr:first-child > td { border-top: none; } .am-table-bordered > thead + tbody > tr:first-child > th, .am-table-bordered > thead + tbody > tr:first-child > td { border-top: 1px solid #ddd; } /* Border-radius version */ .am-table-radius { border: 1px solid #ddd; border-radius: 2px; } .am-table-radius > thead > tr:first-child > th:first-child, .am-table-radius > thead > tr:first-child > td:first-child { border-top-left-radius: 2px; border-left: none; } .am-table-radius > thead > tr:first-child > th:last-child, .am-table-radius > thead > tr:first-child > td:last-child { border-top-right-radius: 2px; border-right: none; } .am-table-radius > tbody > tr > th:first-child, .am-table-radius > tbody > tr > td:first-child { border-left: none; } .am-table-radius > tbody > tr > th:last-child, .am-table-radius > tbody > tr > td:last-child { border-right: none; } .am-table-radius > tbody > tr:last-child > th, .am-table-radius > tbody > tr:last-child > td { border-bottom: none; } .am-table-radius > tbody > tr:last-child > th:first-child, .am-table-radius > tbody > tr:last-child > td:first-child { border-bottom-left-radius: 2px; } .am-table-radius > tbody > tr:last-child > th:last-child, .am-table-radius > tbody > tr:last-child > td:last-child { border-bottom-right-radius: 2px; } /* Zebra-striping */ .am-table-striped > tbody > tr:nth-child(odd) > td, .am-table-striped > tbody > tr:nth-child(odd) > th { background-color: #f9f9f9; } /* Hover effect */ .am-table-hover > tbody > tr:hover > td, .am-table-hover > tbody > tr:hover > th { background-color: #e9e9e9; } .am-table-compact > thead > tr > th, .am-table-compact > tbody > tr > th, .am-table-compact > tfoot > tr > th, .am-table-compact > thead > tr > td, .am-table-compact > tbody > tr > td, .am-table-compact > tfoot > tr > td { padding: 0.4rem; } .am-table-centered > thead > tr > th, .am-table-centered > tbody > tr > th, .am-table-centered > tfoot > tr > th, .am-table-centered > thead > tr > td, .am-table-centered > tbody > tr > td, .am-table-centered > tfoot > tr > td { text-align: center; } .am-table > thead > tr > td.am-active, .am-table > tbody > tr > td.am-active, .am-table > tfoot > tr > td.am-active, .am-table > thead > tr > th.am-active, .am-table > tbody > tr > th.am-active, .am-table > tfoot > tr > th.am-active, .am-table > thead > tr.am-active > td, .am-table > tbody > tr.am-active > td, .am-table > tfoot > tr.am-active > td, .am-table > thead > tr.am-active > th, .am-table > tbody > tr.am-active > th, .am-table > tfoot > tr.am-active > th { background-color: #ffd; } .am-table > thead > tr > td.am-disabled, .am-table > tbody > tr > td.am-disabled, .am-table > tfoot > tr > td.am-disabled, .am-table > thead > tr > th.am-disabled, .am-table > tbody > tr > th.am-disabled, .am-table > tfoot > tr > th.am-disabled, .am-table > thead > tr.am-disabled > td, .am-table > tbody > tr.am-disabled > td, .am-table > tfoot > tr.am-disabled > td, .am-table > thead > tr.am-disabled > th, .am-table > tbody > tr.am-disabled > th, .am-table > tfoot > tr.am-disabled > th { color: #999999; } .am-table > thead > tr > td.am-primary, .am-table > tbody > tr > td.am-primary, .am-table > tfoot > tr > td.am-primary, .am-table > thead > tr > th.am-primary, .am-table > tbody > tr > th.am-primary, .am-table > tfoot > tr > th.am-primary, .am-table > thead > tr.am-primary > td, .am-table > tbody > tr.am-primary > td, .am-table > tfoot > tr.am-primary > td, .am-table > thead > tr.am-primary > th, .am-table > tbody > tr.am-primary > th, .am-table > tfoot > tr.am-primary > th { color: #0b76ac; background-color: rgba(14, 144, 210, 0.115); } .am-table > thead > tr > td.am-success, .am-table > tbody > tr > td.am-success, .am-table > tfoot > tr > td.am-success, .am-table > thead > tr > th.am-success, .am-table > tbody > tr > th.am-success, .am-table > tfoot > tr > th.am-success, .am-table > thead > tr.am-success > td, .am-table > tbody > tr.am-success > td, .am-table > tfoot > tr.am-success > td, .am-table > thead > tr.am-success > th, .am-table > tbody > tr.am-success > th, .am-table > tfoot > tr.am-success > th { color: #5eb95e; background-color: rgba(94, 185, 94, 0.115); } .am-table > thead > tr > td.am-warning, .am-table > tbody > tr > td.am-warning, .am-table > tfoot > tr > td.am-warning, .am-table > thead > tr > th.am-warning, .am-table > tbody > tr > th.am-warning, .am-table > tfoot > tr > th.am-warning, .am-table > thead > tr.am-warning > td, .am-table > tbody > tr.am-warning > td, .am-table > tfoot > tr.am-warning > td, .am-table > thead > tr.am-warning > th, .am-table > tbody > tr.am-warning > th, .am-table > tfoot > tr.am-warning > th { color: #F37B1D; background-color: rgba(243, 123, 29, 0.115); } .am-table > thead > tr > td.am-danger, .am-table > tbody > tr > td.am-danger, .am-table > tfoot > tr > td.am-danger, .am-table > thead > tr > th.am-danger, .am-table > tbody > tr > th.am-danger, .am-table > tfoot > tr > th.am-danger, .am-table > thead > tr.am-danger > td, .am-table > tbody > tr.am-danger > td, .am-table > tfoot > tr.am-danger > td, .am-table > thead > tr.am-danger > th, .am-table > tbody > tr.am-danger > th, .am-table > tfoot > tr.am-danger > th { color: #dd514c; background-color: rgba(221, 81, 76, 0.115); } /* ========================================================================== Component: Form ============================================================================ */ /* Normalize */ fieldset { border: none; } legend { display: block; width: 100%; margin-bottom: 2rem; font-size: 2rem; line-height: inherit; color: #333333; border-bottom: 1px solid #e5e5e5; padding-bottom: 0.5rem; } label { display: inline-block; margin-bottom: 5px; font-weight: bold; } input[type="search"] { -webkit-box-sizing: border-box; box-sizing: border-box; } input[type="radio"], input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; /* IE8-9 */ line-height: normal; } input[type="file"] { display: block; } select[multiple], select[size] { height: auto; } select optgroup { font-size: inherit; font-style: inherit; font-family: inherit; } input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: thin dotted; outline: 1px auto -webkit-focus-ring-color; outline-offset: -2px; } input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button { height: auto; } output { display: block; padding-top: 1.6rem; font-size: 1.6rem; line-height: 1.6; color: #555555; vertical-align: middle; } /* Common form controls */ .am-form select, .am-form textarea, .am-form input[type="text"], .am-form input[type="password"], .am-form input[type="datetime"], .am-form input[type="datetime-local"], .am-form input[type="date"], .am-form input[type="month"], .am-form input[type="time"], .am-form input[type="week"], .am-form input[type="number"], .am-form input[type="email"], .am-form input[type="url"], .am-form input[type="search"], .am-form input[type="tel"], .am-form input[type="color"], .am-form-field { display: block; width: 100%; padding: 0.5em; font-size: 1.6rem; line-height: 1.2; color: #555555; vertical-align: middle; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 0; -webkit-appearance: none; -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; } .am-form select:focus, .am-form textarea:focus, .am-form input[type="text"]:focus, .am-form input[type="password"]:focus, .am-form input[type="datetime"]:focus, .am-form input[type="datetime-local"]:focus, .am-form input[type="date"]:focus, .am-form input[type="month"]:focus, .am-form input[type="time"]:focus, .am-form input[type="week"]:focus, .am-form input[type="number"]:focus, .am-form input[type="email"]:focus, .am-form input[type="url"]:focus, .am-form input[type="search"]:focus, .am-form input[type="tel"]:focus, .am-form input[type="color"]:focus, .am-form-field:focus { outline: 0; } .am-form select:focus, .am-form textarea:focus, .am-form input[type="text"]:focus, .am-form input[type="password"]:focus, .am-form input[type="datetime"]:focus, .am-form input[type="datetime-local"]:focus, .am-form input[type="date"]:focus, .am-form input[type="month"]:focus, .am-form input[type="time"]:focus, .am-form input[type="week"]:focus, .am-form input[type="number"]:focus, .am-form input[type="email"]:focus, .am-form input[type="url"]:focus, .am-form input[type="search"]:focus, .am-form input[type="tel"]:focus, .am-form input[type="color"]:focus, .am-form-field:focus { background-color: #fefffe; border-color: #3bb4f2; outline: 0; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3); box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3); } .am-form select::-webkit-input-placeholder, .am-form textarea::-webkit-input-placeholder, .am-form input[type="text"]::-webkit-input-placeholder, .am-form input[type="password"]::-webkit-input-placeholder, .am-form input[type="datetime"]::-webkit-input-placeholder, .am-form input[type="datetime-local"]::-webkit-input-placeholder, .am-form input[type="date"]::-webkit-input-placeholder, .am-form input[type="month"]::-webkit-input-placeholder, .am-form input[type="time"]::-webkit-input-placeholder, .am-form input[type="week"]::-webkit-input-placeholder, .am-form input[type="number"]::-webkit-input-placeholder, .am-form input[type="email"]::-webkit-input-placeholder, .am-form input[type="url"]::-webkit-input-placeholder, .am-form input[type="search"]::-webkit-input-placeholder, .am-form input[type="tel"]::-webkit-input-placeholder, .am-form input[type="color"]::-webkit-input-placeholder, .am-form-field::-webkit-input-placeholder { color: #999999; } .am-form select::-moz-placeholder, .am-form textarea::-moz-placeholder, .am-form input[type="text"]::-moz-placeholder, .am-form input[type="password"]::-moz-placeholder, .am-form input[type="datetime"]::-moz-placeholder, .am-form input[type="datetime-local"]::-moz-placeholder, .am-form input[type="date"]::-moz-placeholder, .am-form input[type="month"]::-moz-placeholder, .am-form input[type="time"]::-moz-placeholder, .am-form input[type="week"]::-moz-placeholder, .am-form input[type="number"]::-moz-placeholder, .am-form input[type="email"]::-moz-placeholder, .am-form input[type="url"]::-moz-placeholder, .am-form input[type="search"]::-moz-placeholder, .am-form input[type="tel"]::-moz-placeholder, .am-form input[type="color"]::-moz-placeholder, .am-form-field::-moz-placeholder { color: #999999; } .am-form select:-ms-input-placeholder, .am-form textarea:-ms-input-placeholder, .am-form input[type="text"]:-ms-input-placeholder, .am-form input[type="password"]:-ms-input-placeholder, .am-form input[type="datetime"]:-ms-input-placeholder, .am-form input[type="datetime-local"]:-ms-input-placeholder, .am-form input[type="date"]:-ms-input-placeholder, .am-form input[type="month"]:-ms-input-placeholder, .am-form input[type="time"]:-ms-input-placeholder, .am-form input[type="week"]:-ms-input-placeholder, .am-form input[type="number"]:-ms-input-placeholder, .am-form input[type="email"]:-ms-input-placeholder, .am-form input[type="url"]:-ms-input-placeholder, .am-form input[type="search"]:-ms-input-placeholder, .am-form input[type="tel"]:-ms-input-placeholder, .am-form input[type="color"]:-ms-input-placeholder, .am-form-field:-ms-input-placeholder { color: #999999; } .am-form select::placeholder, .am-form textarea::placeholder, .am-form input[type="text"]::placeholder, .am-form input[type="password"]::placeholder, .am-form input[type="datetime"]::placeholder, .am-form input[type="datetime-local"]::placeholder, .am-form input[type="date"]::placeholder, .am-form input[type="month"]::placeholder, .am-form input[type="time"]::placeholder, .am-form input[type="week"]::placeholder, .am-form input[type="number"]::placeholder, .am-form input[type="email"]::placeholder, .am-form input[type="url"]::placeholder, .am-form input[type="search"]::placeholder, .am-form input[type="tel"]::placeholder, .am-form input[type="color"]::placeholder, .am-form-field::placeholder { color: #999999; } .am-form select::-moz-placeholder, .am-form textarea::-moz-placeholder, .am-form input[type="text"]::-moz-placeholder, .am-form input[type="password"]::-moz-placeholder, .am-form input[type="datetime"]::-moz-placeholder, .am-form input[type="datetime-local"]::-moz-placeholder, .am-form input[type="date"]::-moz-placeholder, .am-form input[type="month"]::-moz-placeholder, .am-form input[type="time"]::-moz-placeholder, .am-form input[type="week"]::-moz-placeholder, .am-form input[type="number"]::-moz-placeholder, .am-form input[type="email"]::-moz-placeholder, .am-form input[type="url"]::-moz-placeholder, .am-form input[type="search"]::-moz-placeholder, .am-form input[type="tel"]::-moz-placeholder, .am-form input[type="color"]::-moz-placeholder, .am-form-field::-moz-placeholder { opacity: 1; } .am-form select[disabled], .am-form textarea[disabled], .am-form input[type="text"][disabled], .am-form input[type="password"][disabled], .am-form input[type="datetime"][disabled], .am-form input[type="datetime-local"][disabled], .am-form input[type="date"][disabled], .am-form input[type="month"][disabled], .am-form input[type="time"][disabled], .am-form input[type="week"][disabled], .am-form input[type="number"][disabled], .am-form input[type="email"][disabled], .am-form input[type="url"][disabled], .am-form input[type="search"][disabled], .am-form input[type="tel"][disabled], .am-form input[type="color"][disabled], .am-form-field[disabled], .am-form select[readonly], .am-form textarea[readonly], .am-form input[type="text"][readonly], .am-form input[type="password"][readonly], .am-form input[type="datetime"][readonly], .am-form input[type="datetime-local"][readonly], .am-form input[type="date"][readonly], .am-form input[type="month"][readonly], .am-form input[type="time"][readonly], .am-form input[type="week"][readonly], .am-form input[type="number"][readonly], .am-form input[type="email"][readonly], .am-form input[type="url"][readonly], .am-form input[type="search"][readonly], .am-form input[type="tel"][readonly], .am-form input[type="color"][readonly], .am-form-field[readonly], fieldset[disabled] .am-form select, fieldset[disabled] .am-form textarea, fieldset[disabled] .am-form input[type="text"], fieldset[disabled] .am-form input[type="password"], fieldset[disabled] .am-form input[type="datetime"], fieldset[disabled] .am-form input[type="datetime-local"], fieldset[disabled] .am-form input[type="date"], fieldset[disabled] .am-form input[type="month"], fieldset[disabled] .am-form input[type="time"], fieldset[disabled] .am-form input[type="week"], fieldset[disabled] .am-form input[type="number"], fieldset[disabled] .am-form input[type="email"], fieldset[disabled] .am-form input[type="url"], fieldset[disabled] .am-form input[type="search"], fieldset[disabled] .am-form input[type="tel"], fieldset[disabled] .am-form input[type="color"], fieldset[disabled] .am-form-field { cursor: not-allowed; background-color: #eeeeee; } .am-form select.am-radius, .am-form textarea.am-radius, .am-form input[type="text"].am-radius, .am-form input[type="password"].am-radius, .am-form input[type="datetime"].am-radius, .am-form input[type="datetime-local"].am-radius, .am-form input[type="date"].am-radius, .am-form input[type="month"].am-radius, .am-form input[type="time"].am-radius, .am-form input[type="week"].am-radius, .am-form input[type="number"].am-radius, .am-form input[type="email"].am-radius, .am-form input[type="url"].am-radius, .am-form input[type="search"].am-radius, .am-form input[type="tel"].am-radius, .am-form input[type="color"].am-radius, .am-form-field.am-radius { border-radius: 2px; } .am-form select.am-round, .am-form textarea.am-round, .am-form input[type="text"].am-round, .am-form input[type="password"].am-round, .am-form input[type="datetime"].am-round, .am-form input[type="datetime-local"].am-round, .am-form input[type="date"].am-round, .am-form input[type="month"].am-round, .am-form input[type="time"].am-round, .am-form input[type="week"].am-round, .am-form input[type="number"].am-round, .am-form input[type="email"].am-round, .am-form input[type="url"].am-round, .am-form input[type="search"].am-round, .am-form input[type="tel"].am-round, .am-form input[type="color"].am-round, .am-form-field.am-round { border-radius: 1000px; } .am-form textarea, .am-form select[multiple], .am-form select[size] { height: auto; } .am-form select { -webkit-appearance: none !important; -moz-appearance: none !important; -webkit-border-radius: 0; background: #fff url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+') no-repeat 100% center; } .am-form select[multiple="multiple"] { background-image: none; } /* help text */ .am-form-help { display: block; margin-top: 5px; margin-bottom: 10px; color: #999999; font-size: 1.3rem; } /* form group */ .am-form-group { margin-bottom: 1.5rem; } /* file field */ .am-form-file { position: relative; overflow: hidden; } .am-form-file input[type="file"] { position: absolute; left: 0; top: 0; z-index: 1; width: 100%; opacity: 0; cursor: pointer; font-size: 50rem; } /** * Checkboxes and radios * Indent the labels to position radios/checkboxes as hanging controls. */ .am-radio, .am-checkbox { display: block; min-height: 1.92rem; margin-top: 10px; margin-bottom: 10px; padding-left: 20px; vertical-align: middle; } .am-radio label, .am-checkbox label { display: inline; margin-bottom: 0; font-weight: normal; cursor: pointer; } .am-radio input[type="radio"], .am-radio-inline input[type="radio"], .am-checkbox input[type="checkbox"], .am-checkbox-inline input[type="checkbox"] { float: left; margin-left: -20px; outline: none; } .am-radio + .am-radio, .am-checkbox + .am-checkbox { margin-top: -5px; } /* Radios and checkboxes inline */ .am-radio-inline, .am-checkbox-inline { display: inline-block; padding-left: 20px; margin-bottom: 0; vertical-align: middle; font-weight: normal; cursor: pointer; } .am-radio-inline + .am-radio-inline, .am-checkbox-inline + .am-checkbox-inline { margin-top: 0; margin-left: 10px; } input[type="radio"][disabled], input[type="checkbox"][disabled], .am-radio[disabled], .am-radio-inline[disabled], .am-checkbox[disabled], .am-checkbox-inline[disabled], fieldset[disabled] input[type="radio"], fieldset[disabled] input[type="checkbox"], fieldset[disabled] .am-radio, fieldset[disabled] .am-radio-inline, fieldset[disabled] .am-checkbox, fieldset[disabled] .am-checkbox-inline { cursor: not-allowed; } /* Form field feedback states */ .am-form-warning .am-form-help, .am-form-warning .am-form-label, .am-form-warning .am-radio, .am-form-warning .am-checkbox, .am-form-warning .am-radio-inline, .am-form-warning .am-checkbox-inline, .am-form-warning label { color: #F37B1D; } .am-form-warning [class*="icon-"] { color: #F37B1D; } .am-form-warning .am-form-field { border-color: #F37B1D !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .am-form-warning .am-form-field:focus { background-color: #fefffe; border-color: #d2620b; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important; } .am-form-error .am-form-help, .am-form-error .am-form-label, .am-form-error .am-radio, .am-form-error .am-checkbox, .am-form-error .am-radio-inline, .am-form-error .am-checkbox-inline, .am-form-error label { color: #dd514c; } .am-form-error [class*="icon-"] { color: #dd514c; } .am-form-error .am-form-field, .am-field-error { border-color: #dd514c !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .am-form-error .am-form-field:focus, .am-field-error:focus { background-color: #fefffe; border-color: #cf2d27; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important; } .am-form-success .am-form-help, .am-form-success .am-form-label, .am-form-success .am-radio, .am-form-success .am-checkbox, .am-form-success .am-radio-inline, .am-form-success .am-checkbox-inline, .am-form-success label { color: #5eb95e; } .am-form-success [class*="icon-"] { color: #5eb95e; } .am-form-success .am-form-field, .am-field-valid { border-color: #5eb95e !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .am-form-success .am-form-field:focus, .am-field-valid:focus { background-color: #fefffe; border-color: #459f45; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important; } /* Horizontal forms */ .am-form-horizontal .am-form-label, .am-form-horizontal .am-radio, .am-form-horizontal .am-checkbox, .am-form-horizontal .am-radio-inline, .am-form-horizontal .am-checkbox-inline { margin-top: 0; margin-bottom: 0; padding-top: 0.6em; } .am-form-horizontal .am-form-group:before, .am-form-horizontal .am-form-group:after { content: " "; display: table; } .am-form-horizontal .am-form-group:after { clear: both; } @media only screen and (min-width:641px) { .am-form-horizontal .am-form-label { text-align: right; } } /* Inline form elements */ @media only screen and (min-width:641px) { .am-form-inline .am-form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .am-form-inline .am-form-field { display: inline-block; width: auto; vertical-align: middle; } .am-form-inline .am-input-group { display: inline-table; vertical-align: middle; } .am-form-inline .am-input-group .am-input-group-label, .am-form-inline .am-input-group .am-input-group-btn, .am-form-inline .am-input-group .am-form-label { width: auto; } .am-form-inline .am-input-group > .am-form-field { width: 100%; } .am-form-inline .am-form-label { margin-bottom: 0; vertical-align: middle; } .am-form-inline .am-radio, .am-form-inline .am-checkbox { display: inline-block; margin-top: 0; margin-bottom: 0; padding-left: 0; vertical-align: middle; } .am-form-inline .am-radio input[type="radio"], .am-form-inline .am-checkbox input[type="checkbox"] { float: none; margin-left: 0; } } /* Form field size */ .am-input-sm { font-size: 1.4rem !important; } .am-input-lg { font-size: 1.8rem !important; } .am-form-group-sm .am-checkbox, .am-form-group-sm .am-radio, .am-form-group-sm .am-form-label, .am-form-group-sm .am-form-field { font-size: 1.4rem !important; } .am-form-group-lg .am-checkbox, .am-form-group-lg .am-radio, .am-form-group-lg .am-form-label, .am-form-group-lg .am-form-field { font-size: 1.8rem !important; } .am-form-group-lg input[type="radio"], .am-form-group-lg input[type="checkbox"] { margin-top: 7px; } /* Form field feedback states */ .am-form-icon { position: relative; } .am-form-icon .am-form-field { padding-left: 1.75em !important; } .am-form-icon [class*='am-icon-'] { position: absolute; left: 0.5em; top: 50%; display: block; margin-top: -0.5em; line-height: 1; z-index: 2; } .am-form-icon label ~ [class*='am-icon-'] { top: 70%; } /* Feedback Icon */ .am-form-feedback { position: relative; } .am-form-feedback .am-form-field { padding-left: 0.5em !important; padding-right: 1.75em !important; } .am-form-feedback [class*='am-icon-'] { right: 0.5em; left: auto; } .am-form-horizontal .am-form-feedback [class*='am-icon-'] { right: 1.6em; } /* Form set */ .am-form-set { margin-bottom: 1.5rem; padding: 0; } .am-form-set > input { position: relative; top: -1px; border-radius: 0 !important; } .am-form-set > input:focus { z-index: 2; } .am-form-set > input:first-child { top: 1px; border-top-right-radius: 0 !important; border-top-left-radius: 0 !important; } .am-form-set > input:last-child { top: -2px; border-bottom-right-radius: 0 !important; border-bottom-left-radius: 0 !important; } /* ========================================================================== Component: Image ============================================================================ */ /* Image thumbnails */ .am-img-thumbnail { display: inline-block; max-width: 100%; height: auto; padding: 2px; line-height: 1.6; background-color: #fff; border: 1px solid #ddd; border-radius: 0; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; } .am-img-thumbnail.am-radius { border-radius: 2px; } .am-img-responsive { display: block; max-width: 100%; height: auto; } /* ========================================================================== Component: Nav ============================================================================ */ .am-nav { margin-bottom: 0; padding: 0; list-style: none; } .am-nav:before, .am-nav:after { content: " "; display: table; } .am-nav:after { clear: both; } .am-nav > li { position: relative; display: block; } .am-nav > li + li { margin-top: 5px; } .am-nav > li + .am-nav-header { margin-top: 1em; } .am-nav > li > a { position: relative; display: block; padding: 0.4em 1em; border-radius: 0; } .am-nav > li > a:hover, .am-nav > li > a:focus { text-decoration: none; background-color: #eeeeee; } .am-nav > li.am-active > a, .am-nav > li.am-active > a:hover, .am-nav > li.am-active > a:focus { color: #fff; background-color: #0e90d2; cursor: default; } .am-nav > li.am-disabled > a { color: #999999; } .am-nav > li.am-disabled > a:hover, .am-nav > li.am-disabled > a:focus { color: #999999; text-decoration: none; background-color: transparent; cursor: not-allowed; } .am-nav-header { padding: 0.4em 1em; text-transform: uppercase; font-weight: bold; font-size: 100%; color: #555555; } .am-nav-divider { margin: 15px 1em !important; border-top: 1px solid #ddd; -webkit-box-shadow: 0 1px 0 #fff; box-shadow: 0 1px 0 #fff; } .am-nav-pills > li { float: left; } .am-nav-pills > li + li { margin-left: 5px; margin-top: 0; } .am-nav-tabs { border-bottom: 1px solid #ddd; } .am-nav-tabs > li { float: left; margin-bottom: -1px; } .am-nav-tabs > li + li { margin-top: 0; } .am-nav-tabs > li > a { margin-right: 5px; line-height: 1.6; border: 1px solid transparent; border-radius: 0 0 0 0; } .am-nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #ddd; } .am-nav-tabs > li.am-active > a, .am-nav-tabs > li.am-active > a:hover, .am-nav-tabs > li.am-active > a:focus { color: #555555; background-color: #fff; border: 1px solid #ddd; border-bottom-color: transparent; cursor: default; } .am-nav-tabs.am-nav-justify { border-bottom: 0; /* > li > a { margin-right: 0; border-radius: @global-radius; } > .am-active > a { &, &:hover, &:focus { border: 1px solid @nav-tabs-justify-link-border-color; } }*/ } .am-nav-tabs.am-nav-justify > li > a { margin-right: 0; border-bottom: 1px solid #ddd; border-radius: 0 0 0 0; } .am-nav-tabs.am-nav-justify > .am-active > a, .am-nav-tabs.am-nav-justify > .am-active > a:hover, .am-nav-tabs.am-nav-justify > .am-active > a:focus { border-bottom-color: #fff; } .am-nav-justify { width: 100%; display: table; } .am-nav-justify > li { float: none; display: table-cell; width: 1%; } .am-nav-justify > li > a { text-align: center; margin-bottom: 0; } .lte9 .am-nav-justify > li { display: table-cell; width: 1%; } /* ========================================================================== Component: Topbar ============================================================================ */ .am-topbar { position: relative; min-height: 50px; margin-bottom: 1.6rem; background: #f8f8f8; border-width: 0 0 1px; border-style: solid; border-color: #ddd; color: #666; } .am-topbar:before, .am-topbar:after { content: " "; display: table; } .am-topbar:after { clear: both; } .am-topbar a { color: #666; } .am-topbar-brand { margin: 0; } @media only screen and (min-width:641px) { .am-topbar-brand { float: left; } } .am-topbar-brand a:hover { color: #4d4d4d; } .am-topbar-collapse { width: 100%; overflow-x: visible; padding: 10px; clear: both; -webkit-overflow-scrolling: touch; } .am-topbar-collapse:before, .am-topbar-collapse:after { content: " "; display: table; } .am-topbar-collapse:after { clear: both; } .am-topbar-collapse.am-in { overflow-y: auto; } @media only screen and (min-width:641px) { .am-topbar-collapse { margin-top: 0; padding: 0; width: auto; clear: none; } .am-topbar-collapse.am-collapse { display: block !important; height: auto !important; padding: 0; overflow: visible !important; } .am-topbar-collapse.am-in { overflow-y: visible; } } .am-topbar-brand { padding: 0 10px; float: left; font-size: 1.8rem; height: 50px; line-height: 50px; } .am-topbar-toggle { position: relative; float: right; margin-right: 10px; } @media only screen and (min-width:641px) { .am-topbar-toggle { display: none; } } @media only screen and (max-width: 640px) { .am-topbar-nav { margin-bottom: 8px; } .am-topbar-nav > li { float: none; } } @media only screen and (max-width: 640px) { .am-topbar-nav > li + li { margin-left: 0; margin-top: 5px; } } @media only screen and (min-width:641px) { .am-topbar-nav { float: left; } .am-topbar-nav > li > a { position: relative; line-height: 50px; padding: 0 10px; } .am-topbar-nav > li > a:after { position: absolute; left: 50%; margin-left: -7px; bottom: -1px; content: ""; display: inline-block; width: 0; height: 0; vertical-align: middle; border-bottom: 7px solid #f8f8f8; border-right: 7px solid transparent; border-left: 7px solid transparent; border-top: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); opacity: 0; -webkit-transition: opacity .1s; transition: opacity .1s; } .am-topbar-nav > li > a:hover:after { opacity: 1; border-bottom-color: #666; } .am-topbar-nav > li.am-dropdown > a:after { display: none; } .am-topbar-nav > li.am-active > a, .am-topbar-nav > li.am-active > a:hover, .am-topbar-nav > li.am-active > a:focus { border-radius: 0; color: #0e90d2; background: none; } .am-topbar-nav > li.am-active > a:after { opacity: 1; border-bottom-color: #0e90d2; } } @media only screen and (max-width: 640px) { .am-topbar-collapse .am-dropdown.am-active .am-dropdown-content { float: none; position: relative; width: 100%; } } @media only screen and (min-width:641px) { .am-topbar-left { float: left; } .am-topbar-right { float: right; margin-right: 10px; } } @media only screen and (max-width: 640px) { .am-topbar-form .am-form-group { margin-bottom: 5px; } } @media only screen and (min-width:641px) { .am-topbar-form { padding: 0 10px; margin-top: 8px; } .am-topbar-form .am-form-group + .am-btn { margin-left: 5px; } } .am-topbar-btn { margin-top: 8px; } @media only screen and (max-width: 640px) { .am-topbar-collapse .am-topbar-btn, .am-topbar-collapse .am-btn { display: block; width: 100%; } } .am-topbar-inverse { background-color: #0e90d2; border-color: #0b6fa2; color: #eeeeee; } .am-topbar-inverse a { color: #eeeeee; } .am-topbar-inverse .am-topbar-brand a { color: #fff; } .am-topbar-inverse .am-topbar-brand a:hover, .am-topbar-inverse .am-topbar-brand a:focus { color: #fff; background-color: transparent; } .am-topbar-inverse .am-topbar-nav > li > a { color: #eeeeee; } .am-topbar-inverse .am-topbar-nav > li > a:hover, .am-topbar-inverse .am-topbar-nav > li > a:focus { color: #fff; background-color: rgba(0, 0, 0, 0.05); } .am-topbar-inverse .am-topbar-nav > li > a:hover:after, .am-topbar-inverse .am-topbar-nav > li > a:focus:after { border-bottom-color: #0b6fa2; } .am-topbar-inverse .am-topbar-nav > li > a:after { border-bottom-color: #0e90d2; } .am-topbar-inverse .am-topbar-nav > li.am-active > a, .am-topbar-inverse .am-topbar-nav > li.am-active > a:hover, .am-topbar-inverse .am-topbar-nav > li.am-active > a:focus { color: #fff; background-color: rgba(0, 0, 0, 0.1); } .am-topbar-inverse .am-topbar-nav > li.am-active > a:after, .am-topbar-inverse .am-topbar-nav > li.am-active > a:hover:after, .am-topbar-inverse .am-topbar-nav > li.am-active > a:focus:after { border-bottom-color: #fff; } .am-topbar-inverse .am-topbar-nav > li .disabled > a, .am-topbar-inverse .am-topbar-nav > li .disabled > a:hover, .am-topbar-inverse .am-topbar-nav > li .disabled > a:focus { color: #444; background-color: transparent; } .am-topbar-fixed-top, .am-topbar-fixed-bottom { position: fixed; right: 0; left: 0; z-index: 1000; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } .am-topbar-fixed-top { top: 0; } .am-topbar-fixed-bottom { bottom: 0; margin-bottom: 0; border-width: 1px 0 0; } .am-with-topbar-fixed-top { padding-top: 51px; } .am-with-topbar-fixed-bottom { padding-bottom: 51px; } @media only screen and (max-width: 640px) { .am-topbar-fixed-bottom .am-topbar-collapse { position: absolute; bottom: 100%; margin-bottom: 1px; background-color: #f8f8f8; } .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:before, .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:after { display: none; } .am-topbar-fixed-bottom.am-topbar-inverse .am-topbar-collapse { background-color: #0e90d2; } } /* ========================================================================== Component: Breadcrumb ============================================================================ */ .am-breadcrumb { padding: .7em .5em; margin-bottom: 2rem; list-style: none; background-color: transparent; border-radius: 0; font-size: 85%; } .am-breadcrumb > li { display: inline-block; } .am-breadcrumb > li [class*="am-icon-"]:before { color: #999999; margin-right: 5px; } .am-breadcrumb > li + li:before { content: "»\00a0"; padding: 0 8px; color: #ccc; } .am-breadcrumb > .am-active { color: #999999; } .am-breadcrumb-slash > li + li:before { content: "/\00a0"; } /* ========================================================================== Component: Pagination ============================================================================ */ .am-pagination { padding-left: 0; margin: 1.5rem 0; list-style: none; color: #999999; text-align: left; } .am-pagination:before, .am-pagination:after { content: " "; display: table; } .am-pagination:after { clear: both; } .am-pagination > li { display: inline-block; } .am-pagination > li > a, .am-pagination > li > span { position: relative; display: block; padding: 0.5em 1em; text-decoration: none; line-height: 1.2; background-color: #fff; border: 1px solid #ddd; border-radius: 0; margin-bottom: 5px; margin-right: 5px; } .am-pagination > li:last-child > a, .am-pagination > li:last-child > span { margin-right: 0; } .am-pagination > li > a:hover, .am-pagination > li > span:hover, .am-pagination > li > a:focus, .am-pagination > li > span:focus { background-color: #eeeeee; } .am-pagination > .am-active > a, .am-pagination > .am-active > span, .am-pagination > .am-active > a:hover, .am-pagination > .am-active > span:hover, .am-pagination > .am-active > a:focus, .am-pagination > .am-active > span:focus { z-index: 2; color: #fff; background-color: #0e90d2; border-color: #0e90d2; cursor: default; } .am-pagination > .am-disabled > span, .am-pagination > .am-disabled > span:hover, .am-pagination > .am-disabled > span:focus, .am-pagination > .am-disabled > a, .am-pagination > .am-disabled > a:hover, .am-pagination > .am-disabled > a:focus { color: #999999; background-color: #fff; border-color: #ddd; cursor: not-allowed; pointer-events: none; } .am-pagination .am-pagination-prev { float: left; } .am-pagination .am-pagination-prev a { border-radius: 0; } .am-pagination .am-pagination-next { float: right; } .am-pagination .am-pagination-next a { border-radius: 0; } .am-pagination-centered { text-align: center; } .am-pagination-right { text-align: right; } /* ========================================================================== Component: Aniamtion ============================================================================ */ [class*="am-animation-"] { -webkit-animation-duration: 0.5s; animation-duration: 0.5s; -webkit-animation-timing-function: ease-out; animation-timing-function: ease-out; -webkit-animation-fill-mode: both; animation-fill-mode: both; } /* Hide animated element if scrollSpy is used */ @media screen { .cssanimations [data-am-scrollspy*="animation"] { opacity: 0; } } /* Fade */ .am-animation-fade { -webkit-animation-name: am-fade; animation-name: am-fade; -webkit-animation-duration: 0.8s; animation-duration: 0.8s; -webkit-animation-timing-function: linear; animation-timing-function: linear; } /* Scale */ .am-animation-scale-up { -webkit-animation-name: am-scale-up; animation-name: am-scale-up; } .am-animation-scale-down { -webkit-animation-name: am-scale-down; animation-name: am-scale-down; } /* Slide */ .am-animation-slide-top { -webkit-animation-name: am-slide-top; animation-name: am-slide-top; } .am-animation-slide-bottom { -webkit-animation-name: am-slide-bottom; animation-name: am-slide-bottom; } .am-animation-slide-left { -webkit-animation-name: am-slide-left; animation-name: am-slide-left; } .am-animation-slide-right { -webkit-animation-name: am-slide-right; animation-name: am-slide-right; } .am-animation-slide-top-fixed { -webkit-animation-name: am-slide-top-fixed; animation-name: am-slide-top-fixed; } /* Shake */ .am-animation-shake { -webkit-animation-name: am-shake; animation-name: am-shake; } /* Spin */ .am-animation-spin { -webkit-animation: am-spin 2s infinite linear; animation: am-spin 2s infinite linear; } /* Spring */ .am-animation-left-spring { -webkit-animation: am-left-spring 0.3s ease-in-out; animation: am-left-spring 0.3s ease-in-out; } .am-animation-right-spring { -webkit-animation: am-right-spring 0.3s ease-in-out; animation: am-right-spring 0.3s ease-in-out; } .am-animation-reverse { -webkit-animation-direction: reverse; animation-direction: reverse; } .am-animation-paused { -webkit-animation-play-state: paused !important; animation-play-state: paused !important; } .am-animation-delay-1 { -webkit-animation-delay: 1s; animation-delay: 1s; } .am-animation-delay-2 { -webkit-animation-delay: 2s; animation-delay: 2s; } .am-animation-delay-3 { -webkit-animation-delay: 3s; animation-delay: 3s; } .am-animation-delay-4 { -webkit-animation-delay: 4s; animation-delay: 4s; } .am-animation-delay-5 { -webkit-animation-delay: 5s; animation-delay: 5s; } .am-animation-delay-6 { -webkit-animation-delay: 6s; animation-delay: 6s; } /* Keyframes ============================================================================ */ /* Fade */ @-webkit-keyframes am-fade { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes am-fade { 0% { opacity: 0; } 100% { opacity: 1; } } /* Scale up */ @-webkit-keyframes am-scale-up { 0% { opacity: 0; -webkit-transform: scale(0.2); transform: scale(0.2); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } @keyframes am-scale-up { 0% { opacity: 0; -webkit-transform: scale(0.2); transform: scale(0.2); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } /* Scale down */ @-webkit-keyframes am-scale-down { 0% { opacity: 0; -webkit-transform: scale(1.8); transform: scale(1.8); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } @keyframes am-scale-down { 0% { opacity: 0; -webkit-transform: scale(1.8); transform: scale(1.8); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } /* Slide top */ @-webkit-keyframes am-slide-top { 0% { opacity: 0; -webkit-transform: translateY(-100%); transform: translateY(-100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-top { 0% { opacity: 0; -webkit-transform: translateY(-100%); transform: translateY(-100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Slide bottom */ @-webkit-keyframes am-slide-bottom { 0% { opacity: 0; -webkit-transform: translateY(100%); transform: translateY(100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-bottom { 0% { opacity: 0; -webkit-transform: translateY(100%); transform: translateY(100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Slide left */ @-webkit-keyframes am-slide-left { 0% { opacity: 0; -webkit-transform: translateX(-100%); transform: translateX(-100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-slide-left { 0% { opacity: 0; -webkit-transform: translateX(-100%); transform: translateX(-100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } /* Slide right */ @-webkit-keyframes am-slide-right { 0% { opacity: 0; -webkit-transform: translateX(100%); transform: translateX(100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-slide-right { 0% { opacity: 0; -webkit-transform: translateX(100%); transform: translateX(100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } /* Shake */ @-webkit-keyframes am-shake { 0%, 100% { -webkit-transform: translateX(0); transform: translateX(0); } 10% { -webkit-transform: translateX(-9px); transform: translateX(-9px); } 20% { -webkit-transform: translateX(8px); transform: translateX(8px); } 30% { -webkit-transform: translateX(-7px); transform: translateX(-7px); } 40% { -webkit-transform: translateX(6px); transform: translateX(6px); } 50% { -webkit-transform: translateX(-5px); transform: translateX(-5px); } 60% { -webkit-transform: translateX(4px); transform: translateX(4px); } 70% { -webkit-transform: translateX(-3px); transform: translateX(-3px); } 80% { -webkit-transform: translateX(2px); transform: translateX(2px); } 90% { -webkit-transform: translateX(-1px); transform: translateX(-1px); } } @keyframes am-shake { 0%, 100% { -webkit-transform: translateX(0); transform: translateX(0); } 10% { -webkit-transform: translateX(-9px); transform: translateX(-9px); } 20% { -webkit-transform: translateX(8px); transform: translateX(8px); } 30% { -webkit-transform: translateX(-7px); transform: translateX(-7px); } 40% { -webkit-transform: translateX(6px); transform: translateX(6px); } 50% { -webkit-transform: translateX(-5px); transform: translateX(-5px); } 60% { -webkit-transform: translateX(4px); transform: translateX(4px); } 70% { -webkit-transform: translateX(-3px); transform: translateX(-3px); } 80% { -webkit-transform: translateX(2px); transform: translateX(2px); } 90% { -webkit-transform: translateX(-1px); transform: translateX(-1px); } } /* Slide top fixed */ @-webkit-keyframes am-slide-top-fixed { 0% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-top-fixed { 0% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Slide bottom fixed */ @-webkit-keyframes am-slide-bottom-fixed { 0% { opacity: 0; -webkit-transform: translateY(10px); transform: translateY(10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-bottom-fixed { 0% { opacity: 0; -webkit-transform: translateY(10px); transform: translateY(10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Spin */ @-webkit-keyframes am-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } @keyframes am-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } /* Spring */ @-webkit-keyframes am-right-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(-20%); transform: translateX(-20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-right-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(-20%); transform: translateX(-20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } @-webkit-keyframes am-left-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(20%); transform: translateX(20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-left-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(20%); transform: translateX(20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } /* ========================================================================== Component: Article ============================================================================ */ .am-article:before, .am-article:after { content: " "; display: table; } .am-article:after { clear: both; } .am-article > :last-child { margin-bottom: 0; } .am-article + .am-article { margin-top: 2.4rem; } /* Sub-object `.@{ns}article-title` */ .am-article-title { font-size: 2.8rem; line-height: 1.15; font-weight: normal; } .am-article-title a { color: inherit; text-decoration: none; } /* Sub-object `.@{ns}article-meta` */ .am-article-meta { font-size: 1.2rem; line-height: 1.5; color: #999999; } /* Sub-object `.@{ns}article-lead` */ .am-article-lead { color: #666; font-size: 1.4rem; line-height: 1.5; border: 1px solid #dedede; border-radius: 2px; background: #f9f9f9; padding: 10px; } /* Sub-object `.@{ns}article-divider` */ .am-article-divider { margin-bottom: 2.4rem; border-color: #eeeeee; } * + .am-article-divider { margin-top: 2.4rem; } /* Sub-object `.@{ns}article-bd` */ .am-article-bd blockquote { font-family: Georgia, "Times New Roman", Times, Kai, "Kaiti SC", KaiTi, BiauKai, "FontAwesome", serif; } .am-article-bd img { display: block; max-width: 100%; } /* ========================================================================== Component: Badge ============================================================================ */ .am-badge { display: inline-block; min-width: 10px; padding: 0.25em 0.625em; font-size: 1.2rem; font-weight: bold; color: #fff; line-height: 1; vertical-align: baseline; white-space: nowrap; text-align: center; background-color: #999999; border-radius: 0; } .am-badge:empty { display: none; } .am-badge.am-square { border-radius: 0; } .am-badge.am-radius { border-radius: 2px; } .am-badge.am-round { border-radius: 1000px; } a.am-badge:hover, a.am-badge:focus { color: #fff; text-decoration: none; cursor: pointer; } .am-badge-primary { background-color: #0e90d2; } .am-badge-secondary { background-color: #3bb4f2; } .am-badge-success { background-color: #5eb95e; } .am-badge-warning { background-color: #F37B1D; } .am-badge-danger { background-color: #dd514c; } /* ========================================================================== Component: Comment ============================================================================ */ .am-comment:before, .am-comment:after { content: " "; display: table; } .am-comment:after { clear: both; } .am-comment-avatar { float: left; width: 32px; height: 32px; border-radius: 50%; border: 1px solid transparent; } @media only screen and (min-width:641px) { .am-comment-avatar { width: 48px; height: 48px; } } .am-comment-main { position: relative; margin-left: 42px; border: 1px solid #dedede; border-radius: 0; } .am-comment-main:before, .am-comment-main:after { position: absolute; top: 10px; left: -8px; right: 100%; width: 0; height: 0; display: block; content: " "; border-color: transparent; border-style: solid solid outset; border-width: 8px 8px 8px 0; pointer-events: none; } .am-comment-main:before { border-right-color: #dedede; z-index: 1; } .am-comment-main:after { border-right-color: #f8f8f8; margin-left: 1px; z-index: 2; } @media only screen and (min-width:641px) { .am-comment-main { margin-left: 63px; } } .am-comment-hd { background: #f8f8f8; border-bottom: 1px solid #eee; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } .am-comment-title { margin: 0 0 8px 0; font-size: 1.6rem; line-height: 1.2; } .am-comment-meta { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; padding: 10px 15px; font-size: 13px; color: #999999; line-height: 1.2; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .am-comment-meta a { color: #999999; } .am-comment-author { font-weight: bold; color: #999999; } .am-comment-bd { padding: 15px; overflow: hidden; } .am-comment-bd > :last-child { margin-bottom: 0; } .am-comment-footer { padding: 0 15px 5px; } .am-comment-footer .am-comment-actions a + a { margin-left: 5px; } .am-comment-actions { font-size: 13px; color: #999999; } .am-comment-actions a { display: inline-block; padding: 10px 5px; line-height: 1; color: #999999; opacity: .7; } .am-comment-actions a:hover { color: #0e90d2; opacity: 1; } .am-comment-hd .am-comment-actions { padding-right: .5rem; } .am-comment-flip .am-comment-avatar { float: right; } .am-comment-flip .am-comment-main { margin-left: auto; margin-right: 42px; } @media only screen and (min-width:641px) { .am-comment-flip .am-comment-main { margin-right: 63px; } } .am-comment-flip .am-comment-main:before, .am-comment-flip .am-comment-main:after { left: auto; right: -8px; border-width: 8px 0 8px 8px; } .am-comment-flip .am-comment-main:before { border-left-color: #dedede; } .am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; margin-right: 1px; margin-left: auto; } .am-comment-primary .am-comment-avatar { border-color: #0e90d2; } .am-comment-primary .am-comment-main { border-color: #0e90d2; } .am-comment-primary .am-comment-main:before { border-right-color: #0e90d2; } .am-comment-primary.am-comment-flip .am-comment-main:before { border-left-color: #0e90d2; border-right-color: transparent; } .am-comment-primary.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-secondary .am-comment-avatar, .am-comment-highlight .am-comment-avatar { border-color: #3bb4f2; } .am-comment-secondary .am-comment-main, .am-comment-highlight .am-comment-main { border-color: #3bb4f2; } .am-comment-secondary .am-comment-main:before, .am-comment-highlight .am-comment-main:before { border-right-color: #3bb4f2; } .am-comment-secondary.am-comment-flip .am-comment-main:before, .am-comment-highlight.am-comment-flip .am-comment-main:before { border-left-color: #3bb4f2; border-right-color: transparent; } .am-comment-secondary.am-comment-flip .am-comment-main:after, .am-comment-highlight.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-success .am-comment-avatar { border-color: #5eb95e; } .am-comment-success .am-comment-main { border-color: #5eb95e; } .am-comment-success .am-comment-main:before { border-right-color: #5eb95e; } .am-comment-success.am-comment-flip .am-comment-main:before { border-left-color: #5eb95e; border-right-color: transparent; } .am-comment-success.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-warning .am-comment-avatar { border-color: #F37B1D; } .am-comment-warning .am-comment-main { border-color: #F37B1D; } .am-comment-warning .am-comment-main:before { border-right-color: #F37B1D; } .am-comment-warning.am-comment-flip .am-comment-main:before { border-left-color: #F37B1D; border-right-color: transparent; } .am-comment-warning.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-danger .am-comment-avatar { border-color: #dd514c; } .am-comment-danger .am-comment-main { border-color: #dd514c; } .am-comment-danger .am-comment-main:before { border-right-color: #dd514c; } .am-comment-danger.am-comment-flip .am-comment-main:before { border-left-color: #dd514c; border-right-color: transparent; } .am-comment-danger.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comments-list { padding: 0; list-style: none; } .am-comments-list .am-comment { margin: 1.6rem 0 0 0; list-style: none; } @media only screen and (min-width:641px) { .am-comments-list-flip .am-comment-main { margin-right: 64px; } .am-comments-list-flip .am-comment-flip .am-comment-main { margin-left: 64px; } } /* ========================================================================== Component: Button Group ============================================================================ */ .am-btn-group, .am-btn-group-stacked { position: relative; display: inline-block; vertical-align: middle; } .am-btn-group > .am-btn, .am-btn-group-stacked > .am-btn { position: relative; float: left; } .am-btn-group > .am-btn:hover, .am-btn-group-stacked > .am-btn:hover, .am-btn-group > .am-btn:focus, .am-btn-group-stacked > .am-btn:focus, .am-btn-group > .am-btn:active, .am-btn-group-stacked > .am-btn:active, .am-btn-group > .am-btn.active, .am-btn-group-stacked > .am-btn.active { z-index: 2; } .am-btn-group > .am-btn:focus, .am-btn-group-stacked > .am-btn:focus { outline: 0; } .am-btn-group .am-btn + .am-btn, .am-btn-group .am-btn + .am-btn-group, .am-btn-group .am-btn-group + .am-btn, .am-btn-group .am-btn-group + .am-btn-group { margin-left: -1px; } .am-btn-toolbar { margin-left: -5px; } .am-btn-toolbar:before, .am-btn-toolbar:after { content: " "; display: table; } .am-btn-toolbar:after { clear: both; } .am-btn-toolbar .am-btn-group, .am-btn-toolbar .am-input-group { float: left; } .am-btn-toolbar > .am-btn, .am-btn-toolbar > .am-btn-group, .am-btn-toolbar > .am-input-group { margin-left: 5px; } .am-btn-group > .am-btn:not(:first-child):not(:last-child):not(.am-dropdown-toggle) { border-radius: 0; } .am-btn-group > .am-btn:first-child { margin-left: 0; } .am-btn-group > .am-btn:first-child:not(:last-child):not(.am-dropdown-toggle) { border-bottom-right-radius: 0; border-top-right-radius: 0; } .am-btn-group > .am-btn:last-child:not(:first-child), .am-btn-group > .am-dropdown-toggle:not(:first-child) { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-btn-group > .am-btn-group { float: left; } .am-btn-group > .am-btn-group:not(:first-child):not(:last-child) > .am-btn { border-radius: 0; } .am-btn-group > .am-btn-group:first-child > .am-btn:last-child, .am-btn-group > .am-btn-group:first-child > .am-dropdown-toggle { border-bottom-right-radius: 0; border-top-right-radius: 0; } .am-btn-group > .am-btn-group:last-child > .am-btn:first-child { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-btn-group-xs > .am-btn { font-size: 1.2rem; } .am-btn-group-sm > .am-btn { font-size: 1.4rem; } .am-btn-group-lg > .am-btn { font-size: 1.8rem; } .am-btn-group-stacked > .am-btn, .am-btn-group-stacked > .am-btn-group, .am-btn-group-stacked > .am-btn-group > .am-btn { display: block; float: none; width: 100%; max-width: 100%; } .am-btn-group-stacked > .am-btn-group:before, .am-btn-group-stacked > .am-btn-group:after { content: " "; display: table; } .am-btn-group-stacked > .am-btn-group:after { clear: both; } .am-btn-group-stacked > .am-btn-group > .am-btn { float: none; } .am-btn-group-stacked > .am-btn + .am-btn, .am-btn-group-stacked > .am-btn + .am-btn-group, .am-btn-group-stacked > .am-btn-group + .am-btn, .am-btn-group-stacked > .am-btn-group + .am-btn-group { margin-top: -1px; margin-left: 0; } .am-btn-group-stacked > .am-btn:not(:first-child):not(:last-child) { border-radius: 0; } .am-btn-group-stacked > .am-btn:first-child:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-btn-group-stacked > .am-btn:last-child:not(:first-child) { border-bottom-left-radius: 0; border-top-right-radius: 0; border-top-left-radius: 0; } .am-btn-group-stacked > .am-btn-group:not(:first-child):not(:last-child) > .am-btn { border-radius: 0; } .am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-btn:last-child, .am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-dropdown-toggle { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-btn-group-stacked > .am-btn-group:last-child:not(:first-child) > .am-btn:first-child { border-top-right-radius: 0; border-top-left-radius: 0; } .am-btn-group-justify { display: table; table-layout: fixed; border-collapse: separate; width: 100%; } .am-btn-group-justify > .am-btn, .am-btn-group-justify > .am-btn-group { float: none; display: table-cell; width: 1%; } .am-btn-group-justify > .am-btn-group .am-btn { width: 100%; } .lte9 .am-btn-group-justify { display: table; table-layout: fixed; border-collapse: separate; } .lte9 .am-btn-group-justify > .am-btn, .lte9 .am-btn-group-justify > .am-btn-group { float: none; display: table-cell; width: 1%; } .am-btn-group .am-dropdown { float: left; margin-left: -1px; } .am-btn-group .am-dropdown > .am-btn { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-btn-group .am-active .am-dropdown-toggle { -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .am-btn-group .am-active .am-dropdown-toggle.am-btn-link { -webkit-box-shadow: none; box-shadow: none; } .am-btn-group .am-dropdown-toggle:active, .am-btn-group .am-active .am-dropdown-toggle { outline: 0; } [data-am-button] > .am-btn > input[type="radio"], [data-am-button] > .am-btn > input[type="checkbox"], .am-btn-group-check > .am-btn > input[type="radio"], .am-btn-group-check > .am-btn > input[type="checkbox"] { position: absolute; z-index: -1; opacity: 0; } /* ========================================================================== Component: Close ============================================================================ */ .am-close { display: inline-block; text-align: center; width: 24px; font-size: 20px; font-weight: bold; line-height: 24px; color: #000; text-shadow: 0 1px 0 #fff; opacity: .2; -webkit-transition: all .3s; transition: all .3s; } .am-close:hover, .am-close:focus { color: #000; text-decoration: none; cursor: pointer; opacity: .5; outline: none; } .am-close[class*="am-icon-"] { font-size: 16px; } button.am-close { padding: 0; cursor: pointer; background: transparent; /* Needed for Sarari */ border: 0; -webkit-appearance: none; } a.am-close:hover { color: inherit; text-decoration: none; cursor: pointer; } /* Modifiers ============================================================================ */ .am-close-alt { border-radius: 50%; background: #eee; opacity: 0.7; -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); /* Hover */ } .am-close-alt:hover, .am-close-alt:focus { opacity: 1; } .am-close-spin:hover { -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } /* ========================================================================== Component: Icon ============================================================================ */ /* Font-face ============================================================================= */ @font-face { font-family: 'FontAwesome'; src: url('../fonts/fontawesome-webfont.eot?v=4.5.0'); src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } /* Component ============================================================================= */ [class*="am-icon-"] { display: inline-block; font-style: normal; } [class*="am-icon-"]:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-icon-border { padding: .2em .25em .15em; border: solid 0.08em #eee; border-radius: .1em; } [class*="am-icon-"].am-fl { margin-right: .3em; } [class*="am-icon-"].am-fr { margin-left: .3em; } .am-icon-sm:before { font-size: 150%; vertical-align: -10%; } .am-icon-md:before { font-size: 200%; vertical-align: -16%; } .am-icon-lg:before { font-size: 250%; vertical-align: -22%; } /* Modifier: `.am-icon-btn` ============================================================================= */ .am-icon-btn { -webkit-box-sizing: border-box; box-sizing: border-box; display: inline-block; width: 48px; height: 48px; font-size: 24px; line-height: 48px; border-radius: 50%; background-color: #eee; color: #555555; text-align: center; /** * Hover * 1. Apply hover style also to focus state * 2. Remove default focus style */ /* Active */ } .am-icon-btn:hover, .am-icon-btn:focus { /* 1 */ background-color: #f5f5f5; color: #333333; text-decoration: none; outline: none; /* 2 */ } .am-icon-btn:active { background-color: #ddd; color: #333333; } .am-icon-btn.am-primary, .am-icon-btn.am-secondary, .am-icon-btn.am-success, .am-icon-btn.am-warning, .am-icon-btn.am-danger { color: #fff; } .am-icon-btn.am-primary { background-color: #0e90d2; } .am-icon-btn.am-secondary { background-color: #3bb4f2; } .am-icon-btn.am-success { background-color: #5eb95e; } .am-icon-btn.am-warning { background-color: #F37B1D; } .am-icon-btn.am-danger { background-color: #dd514c; } .am-icon-btn-sm { width: 32px; height: 32px; font-size: 16px; line-height: 32px; } .am-icon-btn-lg { width: 64px; height: 64px; font-size: 28px; line-height: 64px; } /* Modifier: `.am-icon-fw` Fixed width ============================================================================= */ .am-icon-fw { width: 1.25em; text-align: center; } /* Icon mapping ============================================================================= */ .am-icon-glass:before { content: "\f000"; } .am-icon-music:before { content: "\f001"; } .am-icon-search:before { content: "\f002"; } .am-icon-envelope-o:before { content: "\f003"; } .am-icon-heart:before { content: "\f004"; } .am-icon-star:before { content: "\f005"; } .am-icon-star-o:before { content: "\f006"; } .am-icon-user:before { content: "\f007"; } .am-icon-film:before { content: "\f008"; } .am-icon-th-large:before { content: "\f009"; } .am-icon-th:before { content: "\f00a"; } .am-icon-th-list:before { content: "\f00b"; } .am-icon-check:before { content: "\f00c"; } .am-icon-remove:before, .am-icon-close:before, .am-icon-times:before { content: "\f00d"; } .am-icon-search-plus:before { content: "\f00e"; } .am-icon-search-minus:before { content: "\f010"; } .am-icon-power-off:before { content: "\f011"; } .am-icon-signal:before { content: "\f012"; } .am-icon-gear:before, .am-icon-cog:before { content: "\f013"; } .am-icon-trash-o:before { content: "\f014"; } .am-icon-home:before { content: "\f015"; } .am-icon-file-o:before { content: "\f016"; } .am-icon-clock-o:before { content: "\f017"; } .am-icon-road:before { content: "\f018"; } .am-icon-download:before { content: "\f019"; } .am-icon-arrow-circle-o-down:before { content: "\f01a"; } .am-icon-arrow-circle-o-up:before { content: "\f01b"; } .am-icon-inbox:before { content: "\f01c"; } .am-icon-play-circle-o:before { content: "\f01d"; } .am-icon-rotate-right:before, .am-icon-repeat:before { content: "\f01e"; } .am-icon-refresh:before { content: "\f021"; } .am-icon-list-alt:before { content: "\f022"; } .am-icon-lock:before { content: "\f023"; } .am-icon-flag:before { content: "\f024"; } .am-icon-headphones:before { content: "\f025"; } .am-icon-volume-off:before { content: "\f026"; } .am-icon-volume-down:before { content: "\f027"; } .am-icon-volume-up:before { content: "\f028"; } .am-icon-qrcode:before { content: "\f029"; } .am-icon-barcode:before { content: "\f02a"; } .am-icon-tag:before { content: "\f02b"; } .am-icon-tags:before { content: "\f02c"; } .am-icon-book:before { content: "\f02d"; } .am-icon-bookmark:before { content: "\f02e"; } .am-icon-print:before { content: "\f02f"; } .am-icon-camera:before { content: "\f030"; } .am-icon-font:before { content: "\f031"; } .am-icon-bold:before { content: "\f032"; } .am-icon-italic:before { content: "\f033"; } .am-icon-text-height:before { content: "\f034"; } .am-icon-text-width:before { content: "\f035"; } .am-icon-align-left:before { content: "\f036"; } .am-icon-align-center:before { content: "\f037"; } .am-icon-align-right:before { content: "\f038"; } .am-icon-align-justify:before { content: "\f039"; } .am-icon-list:before { content: "\f03a"; } .am-icon-dedent:before, .am-icon-outdent:before { content: "\f03b"; } .am-icon-indent:before { content: "\f03c"; } .am-icon-video-camera:before { content: "\f03d"; } .am-icon-photo:before, .am-icon-image:before, .am-icon-picture-o:before { content: "\f03e"; } .am-icon-pencil:before { content: "\f040"; } .am-icon-map-marker:before { content: "\f041"; } .am-icon-adjust:before { content: "\f042"; } .am-icon-tint:before { content: "\f043"; } .am-icon-edit:before, .am-icon-pencil-square-o:before { content: "\f044"; } .am-icon-share-square-o:before { content: "\f045"; } .am-icon-check-square-o:before { content: "\f046"; } .am-icon-arrows:before { content: "\f047"; } .am-icon-step-backward:before { content: "\f048"; } .am-icon-fast-backward:before { content: "\f049"; } .am-icon-backward:before { content: "\f04a"; } .am-icon-play:before { content: "\f04b"; } .am-icon-pause:before { content: "\f04c"; } .am-icon-stop:before { content: "\f04d"; } .am-icon-forward:before { content: "\f04e"; } .am-icon-fast-forward:before { content: "\f050"; } .am-icon-step-forward:before { content: "\f051"; } .am-icon-eject:before { content: "\f052"; } .am-icon-chevron-left:before { content: "\f053"; } .am-icon-chevron-right:before { content: "\f054"; } .am-icon-plus-circle:before { content: "\f055"; } .am-icon-minus-circle:before { content: "\f056"; } .am-icon-times-circle:before { content: "\f057"; } .am-icon-check-circle:before { content: "\f058"; } .am-icon-question-circle:before { content: "\f059"; } .am-icon-info-circle:before { content: "\f05a"; } .am-icon-crosshairs:before { content: "\f05b"; } .am-icon-times-circle-o:before { content: "\f05c"; } .am-icon-check-circle-o:before { content: "\f05d"; } .am-icon-ban:before { content: "\f05e"; } .am-icon-arrow-left:before { content: "\f060"; } .am-icon-arrow-right:before { content: "\f061"; } .am-icon-arrow-up:before { content: "\f062"; } .am-icon-arrow-down:before { content: "\f063"; } .am-icon-mail-forward:before, .am-icon-share:before { content: "\f064"; } .am-icon-expand:before { content: "\f065"; } .am-icon-compress:before { content: "\f066"; } .am-icon-plus:before { content: "\f067"; } .am-icon-minus:before { content: "\f068"; } .am-icon-asterisk:before { content: "\f069"; } .am-icon-exclamation-circle:before { content: "\f06a"; } .am-icon-gift:before { content: "\f06b"; } .am-icon-leaf:before { content: "\f06c"; } .am-icon-fire:before { content: "\f06d"; } .am-icon-eye:before { content: "\f06e"; } .am-icon-eye-slash:before { content: "\f070"; } .am-icon-warning:before, .am-icon-exclamation-triangle:before { content: "\f071"; } .am-icon-plane:before { content: "\f072"; } .am-icon-calendar:before { content: "\f073"; } .am-icon-random:before { content: "\f074"; } .am-icon-comment:before { content: "\f075"; } .am-icon-magnet:before { content: "\f076"; } .am-icon-chevron-up:before { content: "\f077"; } .am-icon-chevron-down:before { content: "\f078"; } .am-icon-retweet:before { content: "\f079"; } .am-icon-shopping-cart:before { content: "\f07a"; } .am-icon-folder:before { content: "\f07b"; } .am-icon-folder-open:before { content: "\f07c"; } .am-icon-arrows-v:before { content: "\f07d"; } .am-icon-arrows-h:before { content: "\f07e"; } .am-icon-bar-chart-o:before, .am-icon-bar-chart:before { content: "\f080"; } .am-icon-twitter-square:before { content: "\f081"; } .am-icon-facebook-square:before { content: "\f082"; } .am-icon-camera-retro:before { content: "\f083"; } .am-icon-key:before { content: "\f084"; } .am-icon-gears:before, .am-icon-cogs:before { content: "\f085"; } .am-icon-comments:before { content: "\f086"; } .am-icon-thumbs-o-up:before { content: "\f087"; } .am-icon-thumbs-o-down:before { content: "\f088"; } .am-icon-star-half:before { content: "\f089"; } .am-icon-heart-o:before { content: "\f08a"; } .am-icon-sign-out:before { content: "\f08b"; } .am-icon-linkedin-square:before { content: "\f08c"; } .am-icon-thumb-tack:before { content: "\f08d"; } .am-icon-external-link:before { content: "\f08e"; } .am-icon-sign-in:before { content: "\f090"; } .am-icon-trophy:before { content: "\f091"; } .am-icon-github-square:before { content: "\f092"; } .am-icon-upload:before { content: "\f093"; } .am-icon-lemon-o:before { content: "\f094"; } .am-icon-phone:before { content: "\f095"; } .am-icon-square-o:before { content: "\f096"; } .am-icon-bookmark-o:before { content: "\f097"; } .am-icon-phone-square:before { content: "\f098"; } .am-icon-twitter:before { content: "\f099"; } .am-icon-facebook-f:before, .am-icon-facebook:before { content: "\f09a"; } .am-icon-github:before { content: "\f09b"; } .am-icon-unlock:before { content: "\f09c"; } .am-icon-credit-card:before { content: "\f09d"; } .am-icon-feed:before, .am-icon-rss:before { content: "\f09e"; } .am-icon-hdd-o:before { content: "\f0a0"; } .am-icon-bullhorn:before { content: "\f0a1"; } .am-icon-bell:before { content: "\f0f3"; } .am-icon-certificate:before { content: "\f0a3"; } .am-icon-hand-o-right:before { content: "\f0a4"; } .am-icon-hand-o-left:before { content: "\f0a5"; } .am-icon-hand-o-up:before { content: "\f0a6"; } .am-icon-hand-o-down:before { content: "\f0a7"; } .am-icon-arrow-circle-left:before { content: "\f0a8"; } .am-icon-arrow-circle-right:before { content: "\f0a9"; } .am-icon-arrow-circle-up:before { content: "\f0aa"; } .am-icon-arrow-circle-down:before { content: "\f0ab"; } .am-icon-globe:before { content: "\f0ac"; } .am-icon-wrench:before { content: "\f0ad"; } .am-icon-tasks:before { content: "\f0ae"; } .am-icon-filter:before { content: "\f0b0"; } .am-icon-briefcase:before { content: "\f0b1"; } .am-icon-arrows-alt:before { content: "\f0b2"; } .am-icon-group:before, .am-icon-users:before { content: "\f0c0"; } .am-icon-chain:before, .am-icon-link:before { content: "\f0c1"; } .am-icon-cloud:before { content: "\f0c2"; } .am-icon-flask:before { content: "\f0c3"; } .am-icon-cut:before, .am-icon-scissors:before { content: "\f0c4"; } .am-icon-copy:before, .am-icon-files-o:before { content: "\f0c5"; } .am-icon-paperclip:before { content: "\f0c6"; } .am-icon-save:before, .am-icon-floppy-o:before { content: "\f0c7"; } .am-icon-square:before { content: "\f0c8"; } .am-icon-navicon:before, .am-icon-reorder:before, .am-icon-bars:before { content: "\f0c9"; } .am-icon-list-ul:before { content: "\f0ca"; } .am-icon-list-ol:before { content: "\f0cb"; } .am-icon-strikethrough:before { content: "\f0cc"; } .am-icon-underline:before { content: "\f0cd"; } .am-icon-table:before { content: "\f0ce"; } .am-icon-magic:before { content: "\f0d0"; } .am-icon-truck:before { content: "\f0d1"; } .am-icon-pinterest:before { content: "\f0d2"; } .am-icon-pinterest-square:before { content: "\f0d3"; } .am-icon-google-plus-square:before { content: "\f0d4"; } .am-icon-google-plus:before { content: "\f0d5"; } .am-icon-money:before { content: "\f0d6"; } .am-icon-caret-down:before { content: "\f0d7"; } .am-icon-caret-up:before { content: "\f0d8"; } .am-icon-caret-left:before { content: "\f0d9"; } .am-icon-caret-right:before { content: "\f0da"; } .am-icon-columns:before { content: "\f0db"; } .am-icon-unsorted:before, .am-icon-sort:before { content: "\f0dc"; } .am-icon-sort-down:before, .am-icon-sort-desc:before { content: "\f0dd"; } .am-icon-sort-up:before, .am-icon-sort-asc:before { content: "\f0de"; } .am-icon-envelope:before { content: "\f0e0"; } .am-icon-linkedin:before { content: "\f0e1"; } .am-icon-rotate-left:before, .am-icon-undo:before { content: "\f0e2"; } .am-icon-legal:before, .am-icon-gavel:before { content: "\f0e3"; } .am-icon-dashboard:before, .am-icon-tachometer:before { content: "\f0e4"; } .am-icon-comment-o:before { content: "\f0e5"; } .am-icon-comments-o:before { content: "\f0e6"; } .am-icon-flash:before, .am-icon-bolt:before { content: "\f0e7"; } .am-icon-sitemap:before { content: "\f0e8"; } .am-icon-umbrella:before { content: "\f0e9"; } .am-icon-paste:before, .am-icon-clipboard:before { content: "\f0ea"; } .am-icon-lightbulb-o:before { content: "\f0eb"; } .am-icon-exchange:before { content: "\f0ec"; } .am-icon-cloud-download:before { content: "\f0ed"; } .am-icon-cloud-upload:before { content: "\f0ee"; } .am-icon-user-md:before { content: "\f0f0"; } .am-icon-stethoscope:before { content: "\f0f1"; } .am-icon-suitcase:before { content: "\f0f2"; } .am-icon-bell-o:before { content: "\f0a2"; } .am-icon-coffee:before { content: "\f0f4"; } .am-icon-cutlery:before { content: "\f0f5"; } .am-icon-file-text-o:before { content: "\f0f6"; } .am-icon-building-o:before { content: "\f0f7"; } .am-icon-hospital-o:before { content: "\f0f8"; } .am-icon-ambulance:before { content: "\f0f9"; } .am-icon-medkit:before { content: "\f0fa"; } .am-icon-fighter-jet:before { content: "\f0fb"; } .am-icon-beer:before { content: "\f0fc"; } .am-icon-h-square:before { content: "\f0fd"; } .am-icon-plus-square:before { content: "\f0fe"; } .am-icon-angle-double-left:before { content: "\f100"; } .am-icon-angle-double-right:before { content: "\f101"; } .am-icon-angle-double-up:before { content: "\f102"; } .am-icon-angle-double-down:before { content: "\f103"; } .am-icon-angle-left:before { content: "\f104"; } .am-icon-angle-right:before { content: "\f105"; } .am-icon-angle-up:before { content: "\f106"; } .am-icon-angle-down:before { content: "\f107"; } .am-icon-desktop:before { content: "\f108"; } .am-icon-laptop:before { content: "\f109"; } .am-icon-tablet:before { content: "\f10a"; } .am-icon-mobile-phone:before, .am-icon-mobile:before { content: "\f10b"; } .am-icon-circle-o:before { content: "\f10c"; } .am-icon-quote-left:before { content: "\f10d"; } .am-icon-quote-right:before { content: "\f10e"; } .am-icon-spinner:before { content: "\f110"; } .am-icon-circle:before { content: "\f111"; } .am-icon-mail-reply:before, .am-icon-reply:before { content: "\f112"; } .am-icon-github-alt:before { content: "\f113"; } .am-icon-folder-o:before { content: "\f114"; } .am-icon-folder-open-o:before { content: "\f115"; } .am-icon-smile-o:before { content: "\f118"; } .am-icon-frown-o:before { content: "\f119"; } .am-icon-meh-o:before { content: "\f11a"; } .am-icon-gamepad:before { content: "\f11b"; } .am-icon-keyboard-o:before { content: "\f11c"; } .am-icon-flag-o:before { content: "\f11d"; } .am-icon-flag-checkered:before { content: "\f11e"; } .am-icon-terminal:before { content: "\f120"; } .am-icon-code:before { content: "\f121"; } .am-icon-mail-reply-all:before, .am-icon-reply-all:before { content: "\f122"; } .am-icon-star-half-empty:before, .am-icon-star-half-full:before, .am-icon-star-half-o:before { content: "\f123"; } .am-icon-location-arrow:before { content: "\f124"; } .am-icon-crop:before { content: "\f125"; } .am-icon-code-fork:before { content: "\f126"; } .am-icon-unlink:before, .am-icon-chain-broken:before { content: "\f127"; } .am-icon-question:before { content: "\f128"; } .am-icon-info:before { content: "\f129"; } .am-icon-exclamation:before { content: "\f12a"; } .am-icon-superscript:before { content: "\f12b"; } .am-icon-subscript:before { content: "\f12c"; } .am-icon-eraser:before { content: "\f12d"; } .am-icon-puzzle-piece:before { content: "\f12e"; } .am-icon-microphone:before { content: "\f130"; } .am-icon-microphone-slash:before { content: "\f131"; } .am-icon-shield:before { content: "\f132"; } .am-icon-calendar-o:before { content: "\f133"; } .am-icon-fire-extinguisher:before { content: "\f134"; } .am-icon-rocket:before { content: "\f135"; } .am-icon-maxcdn:before { content: "\f136"; } .am-icon-chevron-circle-left:before { content: "\f137"; } .am-icon-chevron-circle-right:before { content: "\f138"; } .am-icon-chevron-circle-up:before { content: "\f139"; } .am-icon-chevron-circle-down:before { content: "\f13a"; } .am-icon-html5:before { content: "\f13b"; } .am-icon-css3:before { content: "\f13c"; } .am-icon-anchor:before { content: "\f13d"; } .am-icon-unlock-alt:before { content: "\f13e"; } .am-icon-bullseye:before { content: "\f140"; } .am-icon-ellipsis-h:before { content: "\f141"; } .am-icon-ellipsis-v:before { content: "\f142"; } .am-icon-rss-square:before { content: "\f143"; } .am-icon-play-circle:before { content: "\f144"; } .am-icon-ticket:before { content: "\f145"; } .am-icon-minus-square:before { content: "\f146"; } .am-icon-minus-square-o:before { content: "\f147"; } .am-icon-level-up:before { content: "\f148"; } .am-icon-level-down:before { content: "\f149"; } .am-icon-check-square:before { content: "\f14a"; } .am-icon-pencil-square:before { content: "\f14b"; } .am-icon-external-link-square:before { content: "\f14c"; } .am-icon-share-square:before { content: "\f14d"; } .am-icon-compass:before { content: "\f14e"; } .am-icon-toggle-down:before, .am-icon-caret-square-o-down:before { content: "\f150"; } .am-icon-toggle-up:before, .am-icon-caret-square-o-up:before { content: "\f151"; } .am-icon-toggle-right:before, .am-icon-caret-square-o-right:before { content: "\f152"; } .am-icon-euro:before, .am-icon-eur:before { content: "\f153"; } .am-icon-gbp:before { content: "\f154"; } .am-icon-dollar:before, .am-icon-usd:before { content: "\f155"; } .am-icon-rupee:before, .am-icon-inr:before { content: "\f156"; } .am-icon-cny:before, .am-icon-rmb:before, .am-icon-yen:before, .am-icon-jpy:before { content: "\f157"; } .am-icon-ruble:before, .am-icon-rouble:before, .am-icon-rub:before { content: "\f158"; } .am-icon-won:before, .am-icon-krw:before { content: "\f159"; } .am-icon-bitcoin:before, .am-icon-btc:before { content: "\f15a"; } .am-icon-file:before { content: "\f15b"; } .am-icon-file-text:before { content: "\f15c"; } .am-icon-sort-alpha-asc:before { content: "\f15d"; } .am-icon-sort-alpha-desc:before { content: "\f15e"; } .am-icon-sort-amount-asc:before { content: "\f160"; } .am-icon-sort-amount-desc:before { content: "\f161"; } .am-icon-sort-numeric-asc:before { content: "\f162"; } .am-icon-sort-numeric-desc:before { content: "\f163"; } .am-icon-thumbs-up:before { content: "\f164"; } .am-icon-thumbs-down:before { content: "\f165"; } .am-icon-youtube-square:before { content: "\f166"; } .am-icon-youtube:before { content: "\f167"; } .am-icon-xing:before { content: "\f168"; } .am-icon-xing-square:before { content: "\f169"; } .am-icon-youtube-play:before { content: "\f16a"; } .am-icon-dropbox:before { content: "\f16b"; } .am-icon-stack-overflow:before { content: "\f16c"; } .am-icon-instagram:before { content: "\f16d"; } .am-icon-flickr:before { content: "\f16e"; } .am-icon-adn:before { content: "\f170"; } .am-icon-bitbucket:before { content: "\f171"; } .am-icon-bitbucket-square:before { content: "\f172"; } .am-icon-tumblr:before { content: "\f173"; } .am-icon-tumblr-square:before { content: "\f174"; } .am-icon-long-arrow-down:before { content: "\f175"; } .am-icon-long-arrow-up:before { content: "\f176"; } .am-icon-long-arrow-left:before { content: "\f177"; } .am-icon-long-arrow-right:before { content: "\f178"; } .am-icon-apple:before { content: "\f179"; } .am-icon-windows:before { content: "\f17a"; } .am-icon-android:before { content: "\f17b"; } .am-icon-linux:before { content: "\f17c"; } .am-icon-dribbble:before { content: "\f17d"; } .am-icon-skype:before { content: "\f17e"; } .am-icon-foursquare:before { content: "\f180"; } .am-icon-trello:before { content: "\f181"; } .am-icon-female:before { content: "\f182"; } .am-icon-male:before { content: "\f183"; } .am-icon-gittip:before, .am-icon-gratipay:before { content: "\f184"; } .am-icon-sun-o:before { content: "\f185"; } .am-icon-moon-o:before { content: "\f186"; } .am-icon-archive:before { content: "\f187"; } .am-icon-bug:before { content: "\f188"; } .am-icon-vk:before { content: "\f189"; } .am-icon-weibo:before { content: "\f18a"; } .am-icon-renren:before { content: "\f18b"; } .am-icon-pagelines:before { content: "\f18c"; } .am-icon-stack-exchange:before { content: "\f18d"; } .am-icon-arrow-circle-o-right:before { content: "\f18e"; } .am-icon-arrow-circle-o-left:before { content: "\f190"; } .am-icon-toggle-left:before, .am-icon-caret-square-o-left:before { content: "\f191"; } .am-icon-dot-circle-o:before { content: "\f192"; } .am-icon-wheelchair:before { content: "\f193"; } .am-icon-vimeo-square:before { content: "\f194"; } .am-icon-turkish-lira:before, .am-icon-try:before { content: "\f195"; } .am-icon-plus-square-o:before { content: "\f196"; } .am-icon-space-shuttle:before { content: "\f197"; } .am-icon-slack:before { content: "\f198"; } .am-icon-envelope-square:before { content: "\f199"; } .am-icon-wordpress:before { content: "\f19a"; } .am-icon-openid:before { content: "\f19b"; } .am-icon-institution:before, .am-icon-bank:before, .am-icon-university:before { content: "\f19c"; } .am-icon-mortar-board:before, .am-icon-graduation-cap:before { content: "\f19d"; } .am-icon-yahoo:before { content: "\f19e"; } .am-icon-google:before { content: "\f1a0"; } .am-icon-reddit:before { content: "\f1a1"; } .am-icon-reddit-square:before { content: "\f1a2"; } .am-icon-stumbleupon-circle:before { content: "\f1a3"; } .am-icon-stumbleupon:before { content: "\f1a4"; } .am-icon-delicious:before { content: "\f1a5"; } .am-icon-digg:before { content: "\f1a6"; } .am-icon-pied-piper:before { content: "\f1a7"; } .am-icon-pied-piper-alt:before { content: "\f1a8"; } .am-icon-drupal:before { content: "\f1a9"; } .am-icon-joomla:before { content: "\f1aa"; } .am-icon-language:before { content: "\f1ab"; } .am-icon-fax:before { content: "\f1ac"; } .am-icon-building:before { content: "\f1ad"; } .am-icon-child:before { content: "\f1ae"; } .am-icon-paw:before { content: "\f1b0"; } .am-icon-spoon:before { content: "\f1b1"; } .am-icon-cube:before { content: "\f1b2"; } .am-icon-cubes:before { content: "\f1b3"; } .am-icon-behance:before { content: "\f1b4"; } .am-icon-behance-square:before { content: "\f1b5"; } .am-icon-steam:before { content: "\f1b6"; } .am-icon-steam-square:before { content: "\f1b7"; } .am-icon-recycle:before { content: "\f1b8"; } .am-icon-automobile:before, .am-icon-car:before { content: "\f1b9"; } .am-icon-cab:before, .am-icon-taxi:before { content: "\f1ba"; } .am-icon-tree:before { content: "\f1bb"; } .am-icon-spotify:before { content: "\f1bc"; } .am-icon-deviantart:before { content: "\f1bd"; } .am-icon-soundcloud:before { content: "\f1be"; } .am-icon-database:before { content: "\f1c0"; } .am-icon-file-pdf-o:before { content: "\f1c1"; } .am-icon-file-word-o:before { content: "\f1c2"; } .am-icon-file-excel-o:before { content: "\f1c3"; } .am-icon-file-powerpoint-o:before { content: "\f1c4"; } .am-icon-file-photo-o:before, .am-icon-file-picture-o:before, .am-icon-file-image-o:before { content: "\f1c5"; } .am-icon-file-zip-o:before, .am-icon-file-archive-o:before { content: "\f1c6"; } .am-icon-file-sound-o:before, .am-icon-file-audio-o:before { content: "\f1c7"; } .am-icon-file-movie-o:before, .am-icon-file-video-o:before { content: "\f1c8"; } .am-icon-file-code-o:before { content: "\f1c9"; } .am-icon-vine:before { content: "\f1ca"; } .am-icon-codepen:before { content: "\f1cb"; } .am-icon-jsfiddle:before { content: "\f1cc"; } .am-icon-life-bouy:before, .am-icon-life-buoy:before, .am-icon-life-saver:before, .am-icon-support:before, .am-icon-life-ring:before { content: "\f1cd"; } .am-icon-circle-o-notch:before { content: "\f1ce"; } .am-icon-ra:before, .am-icon-rebel:before { content: "\f1d0"; } .am-icon-ge:before, .am-icon-empire:before { content: "\f1d1"; } .am-icon-git-square:before { content: "\f1d2"; } .am-icon-git:before { content: "\f1d3"; } .am-icon-y-combinator-square:before, .am-icon-yc-square:before, .am-icon-hacker-news:before { content: "\f1d4"; } .am-icon-tencent-weibo:before { content: "\f1d5"; } .am-icon-qq:before { content: "\f1d6"; } .am-icon-wechat:before, .am-icon-weixin:before { content: "\f1d7"; } .am-icon-send:before, .am-icon-paper-plane:before { content: "\f1d8"; } .am-icon-send-o:before, .am-icon-paper-plane-o:before { content: "\f1d9"; } .am-icon-history:before { content: "\f1da"; } .am-icon-circle-thin:before { content: "\f1db"; } .am-icon-header:before { content: "\f1dc"; } .am-icon-paragraph:before { content: "\f1dd"; } .am-icon-sliders:before { content: "\f1de"; } .am-icon-share-alt:before { content: "\f1e0"; } .am-icon-share-alt-square:before { content: "\f1e1"; } .am-icon-bomb:before { content: "\f1e2"; } .am-icon-soccer-ball-o:before, .am-icon-futbol-o:before { content: "\f1e3"; } .am-icon-tty:before { content: "\f1e4"; } .am-icon-binoculars:before { content: "\f1e5"; } .am-icon-plug:before { content: "\f1e6"; } .am-icon-slideshare:before { content: "\f1e7"; } .am-icon-twitch:before { content: "\f1e8"; } .am-icon-yelp:before { content: "\f1e9"; } .am-icon-newspaper-o:before { content: "\f1ea"; } .am-icon-wifi:before { content: "\f1eb"; } .am-icon-calculator:before { content: "\f1ec"; } .am-icon-paypal:before { content: "\f1ed"; } .am-icon-google-wallet:before { content: "\f1ee"; } .am-icon-cc-visa:before { content: "\f1f0"; } .am-icon-cc-mastercard:before { content: "\f1f1"; } .am-icon-cc-discover:before { content: "\f1f2"; } .am-icon-cc-amex:before { content: "\f1f3"; } .am-icon-cc-paypal:before { content: "\f1f4"; } .am-icon-cc-stripe:before { content: "\f1f5"; } .am-icon-bell-slash:before { content: "\f1f6"; } .am-icon-bell-slash-o:before { content: "\f1f7"; } .am-icon-trash:before { content: "\f1f8"; } .am-icon-copyright:before { content: "\f1f9"; } .am-icon-at:before { content: "\f1fa"; } .am-icon-eyedropper:before { content: "\f1fb"; } .am-icon-paint-brush:before { content: "\f1fc"; } .am-icon-birthday-cake:before { content: "\f1fd"; } .am-icon-area-chart:before { content: "\f1fe"; } .am-icon-pie-chart:before { content: "\f200"; } .am-icon-line-chart:before { content: "\f201"; } .am-icon-lastfm:before { content: "\f202"; } .am-icon-lastfm-square:before { content: "\f203"; } .am-icon-toggle-off:before { content: "\f204"; } .am-icon-toggle-on:before { content: "\f205"; } .am-icon-bicycle:before { content: "\f206"; } .am-icon-bus:before { content: "\f207"; } .am-icon-ioxhost:before { content: "\f208"; } .am-icon-angellist:before { content: "\f209"; } .am-icon-cc:before { content: "\f20a"; } .am-icon-shekel:before, .am-icon-sheqel:before, .am-icon-ils:before { content: "\f20b"; } .am-icon-meanpath:before { content: "\f20c"; } .am-icon-buysellads:before { content: "\f20d"; } .am-icon-connectdevelop:before { content: "\f20e"; } .am-icon-dashcube:before { content: "\f210"; } .am-icon-forumbee:before { content: "\f211"; } .am-icon-leanpub:before { content: "\f212"; } .am-icon-sellsy:before { content: "\f213"; } .am-icon-shirtsinbulk:before { content: "\f214"; } .am-icon-simplybuilt:before { content: "\f215"; } .am-icon-skyatlas:before { content: "\f216"; } .am-icon-cart-plus:before { content: "\f217"; } .am-icon-cart-arrow-down:before { content: "\f218"; } .am-icon-diamond:before { content: "\f219"; } .am-icon-ship:before { content: "\f21a"; } .am-icon-user-secret:before { content: "\f21b"; } .am-icon-motorcycle:before { content: "\f21c"; } .am-icon-street-view:before { content: "\f21d"; } .am-icon-heartbeat:before { content: "\f21e"; } .am-icon-venus:before { content: "\f221"; } .am-icon-mars:before { content: "\f222"; } .am-icon-mercury:before { content: "\f223"; } .am-icon-intersex:before, .am-icon-transgender:before { content: "\f224"; } .am-icon-transgender-alt:before { content: "\f225"; } .am-icon-venus-double:before { content: "\f226"; } .am-icon-mars-double:before { content: "\f227"; } .am-icon-venus-mars:before { content: "\f228"; } .am-icon-mars-stroke:before { content: "\f229"; } .am-icon-mars-stroke-v:before { content: "\f22a"; } .am-icon-mars-stroke-h:before { content: "\f22b"; } .am-icon-neuter:before { content: "\f22c"; } .am-icon-genderless:before { content: "\f22d"; } .am-icon-facebook-official:before { content: "\f230"; } .am-icon-pinterest-p:before { content: "\f231"; } .am-icon-whatsapp:before { content: "\f232"; } .am-icon-server:before { content: "\f233"; } .am-icon-user-plus:before { content: "\f234"; } .am-icon-user-times:before { content: "\f235"; } .am-icon-hotel:before, .am-icon-bed:before { content: "\f236"; } .am-icon-viacoin:before { content: "\f237"; } .am-icon-train:before { content: "\f238"; } .am-icon-subway:before { content: "\f239"; } .am-icon-medium:before { content: "\f23a"; } .am-icon-yc:before, .am-icon-y-combinator:before { content: "\f23b"; } .am-icon-optin-monster:before { content: "\f23c"; } .am-icon-opencart:before { content: "\f23d"; } .am-icon-expeditedssl:before { content: "\f23e"; } .am-icon-battery-4:before, .am-icon-battery-full:before { content: "\f240"; } .am-icon-battery-3:before, .am-icon-battery-three-quarters:before { content: "\f241"; } .am-icon-battery-2:before, .am-icon-battery-half:before { content: "\f242"; } .am-icon-battery-1:before, .am-icon-battery-quarter:before { content: "\f243"; } .am-icon-battery-0:before, .am-icon-battery-empty:before { content: "\f244"; } .am-icon-mouse-pointer:before { content: "\f245"; } .am-icon-i-cursor:before { content: "\f246"; } .am-icon-object-group:before { content: "\f247"; } .am-icon-object-ungroup:before { content: "\f248"; } .am-icon-sticky-note:before { content: "\f249"; } .am-icon-sticky-note-o:before { content: "\f24a"; } .am-icon-cc-jcb:before { content: "\f24b"; } .am-icon-cc-diners-club:before { content: "\f24c"; } .am-icon-clone:before { content: "\f24d"; } .am-icon-balance-scale:before { content: "\f24e"; } .am-icon-hourglass-o:before { content: "\f250"; } .am-icon-hourglass-1:before, .am-icon-hourglass-start:before { content: "\f251"; } .am-icon-hourglass-2:before, .am-icon-hourglass-half:before { content: "\f252"; } .am-icon-hourglass-3:before, .am-icon-hourglass-end:before { content: "\f253"; } .am-icon-hourglass:before { content: "\f254"; } .am-icon-hand-grab-o:before, .am-icon-hand-rock-o:before { content: "\f255"; } .am-icon-hand-stop-o:before, .am-icon-hand-paper-o:before { content: "\f256"; } .am-icon-hand-scissors-o:before { content: "\f257"; } .am-icon-hand-lizard-o:before { content: "\f258"; } .am-icon-hand-spock-o:before { content: "\f259"; } .am-icon-hand-pointer-o:before { content: "\f25a"; } .am-icon-hand-peace-o:before { content: "\f25b"; } .am-icon-trademark:before { content: "\f25c"; } .am-icon-registered:before { content: "\f25d"; } .am-icon-creative-commons:before { content: "\f25e"; } .am-icon-gg:before { content: "\f260"; } .am-icon-gg-circle:before { content: "\f261"; } .am-icon-tripadvisor:before { content: "\f262"; } .am-icon-odnoklassniki:before { content: "\f263"; } .am-icon-odnoklassniki-square:before { content: "\f264"; } .am-icon-get-pocket:before { content: "\f265"; } .am-icon-wikipedia-w:before { content: "\f266"; } .am-icon-safari:before { content: "\f267"; } .am-icon-chrome:before { content: "\f268"; } .am-icon-firefox:before { content: "\f269"; } .am-icon-opera:before { content: "\f26a"; } .am-icon-internet-explorer:before { content: "\f26b"; } .am-icon-tv:before, .am-icon-television:before { content: "\f26c"; } .am-icon-contao:before { content: "\f26d"; } .am-icon-500px:before { content: "\f26e"; } .am-icon-amazon:before { content: "\f270"; } .am-icon-calendar-plus-o:before { content: "\f271"; } .am-icon-calendar-minus-o:before { content: "\f272"; } .am-icon-calendar-times-o:before { content: "\f273"; } .am-icon-calendar-check-o:before { content: "\f274"; } .am-icon-industry:before { content: "\f275"; } .am-icon-map-pin:before { content: "\f276"; } .am-icon-map-signs:before { content: "\f277"; } .am-icon-map-o:before { content: "\f278"; } .am-icon-map:before { content: "\f279"; } .am-icon-commenting:before { content: "\f27a"; } .am-icon-commenting-o:before { content: "\f27b"; } .am-icon-houzz:before { content: "\f27c"; } .am-icon-vimeo:before { content: "\f27d"; } .am-icon-black-tie:before { content: "\f27e"; } .am-icon-fonticons:before { content: "\f280"; } .am-icon-reddit-alien:before { content: "\f281"; } .am-icon-edge:before { content: "\f282"; } .am-icon-credit-card-alt:before { content: "\f283"; } .am-icon-codiepie:before { content: "\f284"; } .am-icon-modx:before { content: "\f285"; } .am-icon-fort-awesome:before { content: "\f286"; } .am-icon-usb:before { content: "\f287"; } .am-icon-product-hunt:before { content: "\f288"; } .am-icon-mixcloud:before { content: "\f289"; } .am-icon-scribd:before { content: "\f28a"; } .am-icon-pause-circle:before { content: "\f28b"; } .am-icon-pause-circle-o:before { content: "\f28c"; } .am-icon-stop-circle:before { content: "\f28d"; } .am-icon-stop-circle-o:before { content: "\f28e"; } .am-icon-shopping-bag:before { content: "\f290"; } .am-icon-shopping-basket:before { content: "\f291"; } .am-icon-hashtag:before { content: "\f292"; } .am-icon-bluetooth:before { content: "\f293"; } .am-icon-bluetooth-b:before { content: "\f294"; } .am-icon-percent:before { content: "\f295"; } /* Modifier: `am-icon-spin` ============================================================================= */ @-webkit-keyframes icon-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } @keyframes icon-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } .am-icon-spin { -webkit-animation: icon-spin 2s infinite linear; animation: icon-spin 2s infinite linear; } .am-icon-pulse { -webkit-animation: icon-spin 1s infinite steps(8); animation: icon-spin 1s infinite steps(8); } .am-icon-ul { padding-left: 0; margin-left: 2.14285714em; list-style-type: none; } .am-icon-ul > li { position: relative; } .am-icon-li { position: absolute; left: -2.14285714em; width: 2.14285714em; top: 0.14285714em; text-align: center; } /* ========================================================================== Component: Input group ============================================================================ */ .am-input-group { position: relative; display: table; border-collapse: separate; } .am-input-group .am-form-field { position: relative; z-index: 2; float: left; width: 100%; margin-bottom: 0; } .am-input-group-label, .am-input-group-btn, .am-input-group .am-form-field { display: table-cell; } .am-input-group-label:not(:first-child):not(:last-child), .am-input-group-btn:not(:first-child):not(:last-child), .am-input-group .am-form-field:not(:first-child):not(:last-child) { border-radius: 0; } .am-input-group-label, .am-input-group-btn { width: 1%; white-space: nowrap; vertical-align: middle; } .am-input-group-label { height: 38px; padding: 0 1em; font-size: 1.6rem; font-weight: normal; line-height: 36px; color: #555555; text-align: center; background-color: #eeeeee; border: 1px solid #ccc; border-radius: 0; } .am-input-group-label input[type="radio"], .am-input-group-label input[type="checkbox"] { margin-top: 0; } .am-input-group .am-form-field:first-child, .am-input-group-label:first-child, .am-input-group-btn:first-child > .am-btn, .am-input-group-btn:first-child > .am-btn-group > .am-btn, .am-input-group-btn:first-child > .am-dropdown-toggle, .am-input-group-btn:last-child > .am-btn:not(:last-child):not(.dropdown-toggle), .am-input-group-btn:last-child > .am-btn-group:not(:last-child) > .am-btn { border-bottom-right-radius: 0; border-top-right-radius: 0; } .am-input-group-label:first-child { border-right: 0; } .am-input-group .am-form-field:last-child, .am-input-group-label:last-child, .am-input-group-btn:last-child > .am-btn, .am-input-group-btn:last-child > .am-btn-group > .am-btn, .am-input-group-btn:last-child > .am-dropdown-toggle, .am-input-group-btn:first-child > .am-btn:not(:first-child), .am-input-group-btn:first-child > .am-btn-group:not(:first-child) > .am-btn { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-input-group-label:last-child { border-left: 0; } .am-input-group-btn { position: relative; font-size: 0; white-space: nowrap; } .am-input-group-btn > .am-btn { position: relative; border-color: #ccc; } .am-input-group-btn > .am-btn + .am-btn { margin-left: -1px; } .am-input-group-btn > .am-btn:hover, .am-input-group-btn > .am-btn:focus, .am-input-group-btn > .am-btn:active { z-index: 2; } .am-input-group-btn:first-child > .am-btn, .am-input-group-btn:first-child > .am-btn-group { margin-right: -2px; } .am-input-group-btn:last-child > .am-btn, .am-input-group-btn:last-child > .am-btn-group { margin-left: -1px; } .am-input-group .am-form-field, .am-input-group-btn > .am-btn { height: 38px; padding-bottom: auto; } .am-input-group-lg > .am-form-field, .am-input-group-lg > .am-input-group-label, .am-input-group-lg > .am-input-group-btn > .am-btn { height: 42px; font-size: 1.8rem !important; } .am-input-group-lg > .am-input-group-label { line-height: 40px; } .am-input-group-sm > .am-form-field, .am-input-group-sm > .am-input-group-label, .am-input-group-sm > .am-input-group-btn > .am-btn { height: 33px; font-size: 1.4rem !important; } .am-input-group-sm > .am-input-group-label { line-height: 31px; } .am-input-group-primary .am-input-group-label { background: #0e90d2; color: #fff; } .am-input-group-primary .am-input-group-label, .am-input-group-primary .am-input-group-btn > .am-btn, .am-input-group-primary.am-input-group .am-form-field { border-color: #0e90d2; } .am-input-group-secondary .am-input-group-label { background: #3bb4f2; color: #fff; } .am-input-group-secondary .am-input-group-label, .am-input-group-secondary .am-input-group-btn > .am-btn, .am-input-group-secondary.am-input-group .am-form-field { border-color: #3bb4f2; } .am-input-group-success .am-input-group-label { background: #5eb95e; color: #fff; } .am-input-group-success .am-input-group-label, .am-input-group-success .am-input-group-btn > .am-btn, .am-input-group-success.am-input-group .am-form-field { border-color: #5eb95e; } .am-input-group-warning .am-input-group-label { background: #F37B1D; color: #fff; } .am-input-group-warning .am-input-group-label, .am-input-group-warning .am-input-group-btn > .am-btn, .am-input-group-warning.am-input-group .am-form-field { border-color: #F37B1D; } .am-input-group-danger .am-input-group-label { background: #dd514c; color: #fff; } .am-input-group-danger .am-input-group-label, .am-input-group-danger .am-input-group-btn > .am-btn, .am-input-group-danger.am-input-group .am-form-field { border-color: #dd514c; } /* ========================================================================== Component: List ============================================================================ */ .am-list { margin-bottom: 1.6rem; padding-left: 0; } .am-list > li { position: relative; display: block; margin-bottom: -1px; background-color: #fff; border: 1px solid #dedede; border-width: 1px 0; } .am-list > li > a { display: block; padding: 1rem 0; } .am-list > li > a.am-active, .am-list > li > a.am-active:hover, .am-list > li > a.am-active:focus { z-index: 2; color: #fff; background-color: #0e90d2; border-color: #0e90d2; } .am-list > li > a.am-active .am-list-item-heading, .am-list > li > a.am-active:hover .am-list-item-heading, .am-list > li > a.am-active:focus .am-list-item-heading { color: inherit; } .am-list > li > a.am-active .am-list-item-text, .am-list > li > a.am-active:hover .am-list-item-text, .am-list > li > a.am-active:focus .am-list-item-text { color: #b2e2fa; } .am-list > li > .am-badge { float: right; } .am-list > li > .am-badge + .am-badge { margin-right: 5px; } /* Pure text list */ .am-list-static > li { padding: .8rem .2rem; } .am-list-static.am-list-border > li { padding: 1rem; } /* with border */ .am-list-border > li, .am-list-bordered > li { border-width: 1px; } .am-list-border > li:first-child, .am-list-bordered > li:first-child, .am-list-border > li:first-child > a, .am-list-bordered > li:first-child > a { border-top-right-radius: 0; border-top-left-radius: 0; } .am-list-border > li:last-child, .am-list-bordered > li:last-child, .am-list-border > li:last-child > a, .am-list-bordered > li:last-child > a { margin-bottom: 0; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-list-border > li > a, .am-list-bordered > li > a { padding: 1rem; } .am-list-border > li > a:hover, .am-list-bordered > li > a:hover, .am-list-border > li > a:focus, .am-list-bordered > li > a:focus { background-color: #f5f5f5; } /* Striped */ .am-list-striped > li:nth-of-type(even) { background: #f5f5f5; } .am-list-item-hd { margin-top: 0; } .am-list-item-text { line-height: 1.4; font-size: 1.3rem; color: #999999; margin: 0; } /* ========================================================================== Component: Panel ============================================================================ */ .am-panel { margin-bottom: 20px; background-color: #fff; border: 1px solid transparent; border-radius: 0; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); } /* Panel header */ .am-panel-hd { padding: 0.6rem 1.25rem; border-bottom: 1px solid transparent; border-top-right-radius: 0; border-top-left-radius: 0; } /* Panel content */ .am-panel-bd { padding: 1.25rem; } .am-panel-title { margin: 0; font-size: 100%; color: inherit; } .am-panel-title > a { color: inherit; } /* Panel footer */ .am-panel-footer { padding: 0.6rem 1.25rem; background-color: #f5f5f5; border-top: 1px solid #ddd; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-panel-default { border-color: #ddd; } .am-panel-default > .am-panel-hd { color: #444; background-color: #f5f5f5; border-color: #ddd; } .am-panel-default > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #ddd; } .am-panel-default > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #ddd; } .am-panel-primary { border-color: #10a0ea; } .am-panel-primary > .am-panel-hd { color: #fff; background-color: #0e90d2; border-color: #10a0ea; } .am-panel-primary > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #10a0ea; } .am-panel-primary > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #10a0ea; } .am-panel-secondary { border-color: #caebfb; } .am-panel-secondary > .am-panel-hd { color: #14a6ef; background-color: rgba(59, 180, 242, 0.15); border-color: #caebfb; } .am-panel-secondary > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #caebfb; } .am-panel-secondary > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #caebfb; } .am-panel-success { border-color: #c9e7c9; } .am-panel-success > .am-panel-hd { color: #5eb95e; background-color: rgba(94, 185, 94, 0.15); border-color: #c9e7c9; } .am-panel-success > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #c9e7c9; } .am-panel-success > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #c9e7c9; } .am-panel-warning { border-color: #fbd0ae; } .am-panel-warning > .am-panel-hd { color: #F37B1D; background-color: rgba(243, 123, 29, 0.15); border-color: #fbd0ae; } .am-panel-warning > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #fbd0ae; } .am-panel-warning > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #fbd0ae; } .am-panel-danger { border-color: #f5cecd; } .am-panel-danger > .am-panel-hd { color: #dd514c; background-color: rgba(221, 81, 76, 0.15); border-color: #f5cecd; } .am-panel-danger > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #f5cecd; } .am-panel-danger > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #f5cecd; } .am-panel > .am-table { margin-bottom: 0; } .am-panel > .am-table:first-child { border-top-right-radius: 0; border-top-left-radius: 0; } .am-panel > .am-table:first-child > thead:first-child > tr:first-child td:first-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:first-child, .am-panel > .am-table:first-child > thead:first-child > tr:first-child th:first-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:first-child { border-top-left-radius: 0; } .am-panel > .am-table:first-child > thead:first-child > tr:first-child td:last-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:last-child, .am-panel > .am-table:first-child > thead:first-child > tr:first-child th:last-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:last-child { border-top-right-radius: 0; } .am-panel > .am-table:last-child { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:first-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:first-child, .am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:first-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:first-child { border-bottom-left-radius: 0; } .am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:last-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:last-child, .am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:last-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:last-child { border-bottom-right-radius: 0; } .am-panel > .am-panel-bd + .am-table { border-top: 1px solid #ddd; } .am-panel > .am-table > tbody:first-child > tr:first-child th, .am-panel > .am-table > tbody:first-child > tr:first-child td { border-top: 0; } .am-panel > .am-table-bd { border: 0; } .am-panel > .am-table-bd > thead > tr > th:first-child, .am-panel > .am-table-bd > tbody > tr > th:first-child, .am-panel > .am-table-bd > tfoot > tr > th:first-child, .am-panel > .am-table-bd > thead > tr > td:first-child, .am-panel > .am-table-bd > tbody > tr > td:first-child, .am-panel > .am-table-bd > tfoot > tr > td:first-child { border-left: 0; } .am-panel > .am-table-bd > thead > tr > th:last-child, .am-panel > .am-table-bd > tbody > tr > th:last-child, .am-panel > .am-table-bd > tfoot > tr > th:last-child, .am-panel > .am-table-bd > thead > tr > td:last-child, .am-panel > .am-table-bd > tbody > tr > td:last-child, .am-panel > .am-table-bd > tfoot > tr > td:last-child { border-right: 0; } .am-panel > .am-table-bd > thead > tr:first-child > td, .am-panel > .am-table-bd > tbody > tr:first-child > td, .am-panel > .am-table-bd > thead > tr:first-child > th, .am-panel > .am-table-bd > tbody > tr:first-child > th { border-bottom: 0; } .am-panel > .am-table-bd > tbody > tr:last-child > td, .am-panel > .am-table-bd > tfoot > tr:last-child > td, .am-panel > .am-table-bd > tbody > tr:last-child > th, .am-panel > .am-table-bd > tfoot > tr:last-child > th { border-bottom: 0; } /* Wrap list */ .am-panel > .am-list { margin: 0; } .am-panel > .am-list > li > a { padding-left: 1rem; padding-right: 1rem; } .am-panel > .am-list-static li { padding-left: 1rem; padding-right: 1rem; } /* Panel group */ .am-panel-group { margin-bottom: 2rem; } .am-panel-group .am-panel { margin-bottom: 0; border-radius: 0; } .am-panel-group .am-panel + .am-panel { margin-top: 6px; } .am-panel-group .am-panel-hd { border-bottom: 0; } .am-panel-group .am-panel-hd + .am-panel-collapse .am-panel-bd { border-top: 1px solid #ddd; } .am-panel-group .am-panel-footer { border-top: 0; } .am-panel-group .am-panel-footer + .am-panel-collapse .am-panel-bd { border-bottom: 1px solid #ddd; } /* ========================================================================== Component: Progress ============================================================================ */ /* Progress bar animation */ @-webkit-keyframes progress-bar-stripes { from { background-position: 36px 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 36px 0; } to { background-position: 0 0; } } /* Progress container */ .am-progress { overflow: hidden; height: 2rem; margin-bottom: 2rem; background-color: #f5f5f5; border-radius: 0; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } /* Progress bar */ .am-progress-bar { float: left; width: 0; height: 100%; font-size: 1.2rem; line-height: 2rem; color: #fff; text-align: center; background-color: #0e90d2; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-transition: width .6s ease; transition: width .6s ease; } .am-progress-striped .am-progress-bar { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 36px 36px; background-size: 36px 36px; } .am-progress.am-active .am-progress-bar { -webkit-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .am-progress-bar[aria-valuenow="1"], .am-progress-bar[aria-valuenow="2"] { min-width: 30px; } .am-progress-bar[aria-valuenow="0"] { color: #999999; min-width: 30px; background: none; -webkit-box-shadow: none; box-shadow: none; } .am-progress-bar-secondary { background-color: #3bb4f2; } .am-progress-striped .am-progress-bar-secondary { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-bar-success { background-color: #5eb95e; } .am-progress-striped .am-progress-bar-success { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-bar-warning { background-color: #F37B1D; } .am-progress-striped .am-progress-bar-warning { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-bar-danger { background-color: #dd514c; } .am-progress-striped .am-progress-bar-danger { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-xs { height: 0.6rem; } .am-progress-sm { height: 1.2rem; } /* ========================================================================== Component: Thumbnail ============================================================================ */ .am-thumbnail { display: block; padding: 2px; margin-bottom: 2rem; background-color: #fff; border: 1px solid #ddd; border-radius: 0; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; } .am-thumbnail > img, .am-thumbnail a > img { margin-left: auto; margin-right: auto; display: block; } .am-thumbnail a.am-thumbnail:hover, .am-thumbnail a.am-thumbnail:focus, .am-thumbnail a.am-thumbnail.active { border-color: #0e90d2; background-color: #fff; } img.am-thumbnail, .am-thumbnail > img, .am-thumbnail a > img { max-width: 100%; height: auto; } /* Image caption */ .am-thumbnail-caption { margin: 0; padding: 0.8rem; color: #333; font-weight: normal; } .am-thumbnail-caption *:last-child { margin-bottom: 0; } .am-thumbnails { margin-left: -0.5rem; margin-right: -0.5rem; } .am-thumbnails > li { padding: 0 .5rem 1rem .5rem; } /* ========================================================================== Component: Utility ============================================================================ */ .am-scrollable-horizontal { width: 100%; overflow-y: hidden; overflow-x: auto; -ms-overflow-style: -ms-autohiding-scrollbar; -webkit-overflow-scrolling: touch; } .am-scrollable-vertical { height: 240px; overflow-y: scroll; -webkit-overflow-scrolling: touch; resize: vertical; } /* Border-radius*/ .am-square { border-radius: 0; } .am-radius { border-radius: 2px; } .am-round { border-radius: 1000px; } .am-circle { border-radius: 50%; } /* Float blocks*/ .am-cf:before, .am-cf:after { content: " "; display: table; } .am-cf:after { clear: both; } .am-fl { float: left; } .am-fr { float: right; } .am-nbfc { overflow: hidden; } .am-center { display: block; margin-left: auto; margin-right: auto; } /* Display */ .am-block { display: block !important; } .am-inline { display: inline !important; } .am-inline-block { display: inline-block !important; } .am-hide { display: none !important; visibility: hidden !important; } /* * Remove whitespace between child elements when using `inline-block` */ .am-vertical-align { font-size: 0.001px; } /* * The `@{ns}vertical-align` container needs a specific height */ .am-vertical-align:before { content: ''; display: inline-block; height: 100%; vertical-align: middle; } /* * Sub-object which can have any height * 1. Reset whitespace hack */ .am-vertical-align-middle, .am-vertical-align-bottom { display: inline-block; font-size: 1.6rem; /* 1 */ max-width: 100%; } .am-vertical-align-middle { vertical-align: middle; } .am-vertical-align-bottom { vertical-align: bottom; } .am-responsive-width { -webkit-box-sizing: border-box; box-sizing: border-box; max-width: 100%; height: auto; } /* Margin helpers */ .am-margin { margin: 1.6rem; } .am-margin-0 { margin: 0!important; } .am-margin-xs { margin: 0.5rem; } .am-margin-sm { margin: 1rem; } .am-margin-lg { margin: 2.4rem; } .am-margin-xl { margin: 3.2rem; } .am-margin-horizontal { margin-left: 1.6rem; margin-right: 1.6rem; } .am-margin-horizontal-0 { margin-left: 0!important; margin-right: 0!important; } .am-margin-horizontal-xs { margin-left: 0.5rem; margin-right: 0.5rem; } .am-margin-horizontal-sm { margin-left: 1rem; margin-right: 1rem; } .am-margin-horizontal-lg { margin-left: 2.4rem; margin-right: 2.4rem; } .am-margin-horizontal-xl { margin-left: 3.2rem; margin-right: 3.2rem; } .am-margin-vertical { margin-top: 1.6rem; margin-bottom: 1.6rem; } .am-margin-vertical-0 { margin-top: 0!important; margin-bottom: 0!important; } .am-margin-vertical-xs { margin-top: 0.5rem; margin-bottom: 0.5rem; } .am-margin-vertical-sm { margin-top: 1rem; margin-bottom: 1rem; } .am-margin-vertical-lg { margin-top: 2.4rem; margin-bottom: 2.4rem; } .am-margin-vertical-xl { margin-top: 3.2rem; margin-bottom: 3.2rem; } .am-margin-top { margin-top: 1.6rem; } .am-margin-top-0 { margin-top: 0!important; } .am-margin-top-xs { margin-top: 0.5rem; } .am-margin-top-sm { margin-top: 1rem; } .am-margin-top-lg { margin-top: 2.4rem; } .am-margin-top-xl { margin-top: 3.2rem; } .am-margin-bottom { margin-bottom: 1.6rem; } .am-margin-bottom-0 { margin-bottom: 0!important; } .am-margin-bottom-xs { margin-bottom: 0.5rem; } .am-margin-bottom-sm { margin-bottom: 1rem; } .am-margin-bottom-lg { margin-bottom: 2.4rem; } .am-margin-bottom-xl { margin-bottom: 3.2rem; } .am-margin-left { margin-left: 1.6rem; } .am-margin-left-0 { margin-left: 0!important; } .am-margin-left-xs { margin-left: 0.5rem; } .am-margin-left-sm { margin-left: 1rem; } .am-margin-left-lg { margin-left: 2.4rem; } .am-margin-left-xl { margin-left: 3.2rem; } .am-margin-right { margin-right: 1.6rem; } .am-margin-right-0 { margin-right: 0!important; } .am-margin-right-xs { margin-right: 0.5rem; } .am-margin-right-sm { margin-right: 1rem; } .am-margin-right-lg { margin-right: 2.4rem; } .am-margin-right-xl { margin-right: 3.2rem; } /* Padding helpers */ .am-padding { padding: 1.6rem; } .am-padding-0 { padding: 0!important; } .am-padding-xs { padding: 0.5rem; } .am-padding-sm { padding: 1rem; } .am-padding-lg { padding: 2.4rem; } .am-padding-xl { padding: 3.2rem; } .am-padding-horizontal { padding-left: 1.6rem; padding-right: 1.6rem; } .am-padding-horizontal-0 { padding-left: 0!important; padding-right: 0!important; } .am-padding-horizontal-xs { padding-left: 0.5rem; padding-right: 0.5rem; } .am-padding-horizontal-sm { padding-left: 1rem; padding-right: 1rem; } .am-padding-horizontal-lg { padding-left: 2.4rem; padding-right: 2.4rem; } .am-padding-horizontal-xl { padding-left: 3.2rem; padding-right: 3.2rem; } .am-padding-vertical { padding-top: 1.6rem; padding-bottom: 1.6rem; } .am-padding-vertical-0 { padding-top: 0!important; padding-bottom: 0!important; } .am-padding-vertical-xs { padding-top: 0.5rem; padding-bottom: 0.5rem; } .am-padding-vertical-sm { padding-top: 1rem; padding-bottom: 1rem; } .am-padding-vertical-lg { padding-top: 2.4rem; padding-bottom: 2.4rem; } .am-padding-vertical-xl { padding-top: 3.2rem; padding-bottom: 3.2rem; } .am-padding-top { padding-top: 1.6rem; } .am-padding-top-0 { padding-top: 0!important; } .am-padding-top-xs { padding-top: 0.5rem; } .am-padding-top-sm { padding-top: 1rem; } .am-padding-top-lg { padding-top: 2.4rem; } .am-padding-top-xl { padding-top: 3.2rem; } .am-padding-bottom { padding-bottom: 1.6rem; } .am-padding-bottom-0 { padding-bottom: 0!important; } .am-padding-bottom-xs { padding-bottom: 0.5rem; } .am-padding-bottom-sm { padding-bottom: 1rem; } .am-padding-bottom-lg { padding-bottom: 2.4rem; } .am-padding-bottom-xl { padding-bottom: 3.2rem; } .am-padding-left { padding-left: 1.6rem; } .am-padding-left-0 { padding-left: 0!important; } .am-padding-left-xs { padding-left: 0.5rem; } .am-padding-left-sm { padding-left: 1rem; } .am-padding-left-lg { padding-left: 2.4rem; } .am-padding-left-xl { padding-left: 3.2rem; } .am-padding-right { padding-right: 1.6rem; } .am-padding-right-0 { padding-right: 0!important; } .am-padding-right-xs { padding-right: 0.5rem; } .am-padding-right-sm { padding-right: 1rem; } .am-padding-right-lg { padding-right: 2.4rem; } .am-padding-right-xl { padding-right: 3.2rem; } /* small displays */ @media only screen { .am-show-sm-only, .am-show-sm-up, .am-show-sm, .am-show-sm-down, .am-hide-md-only, .am-hide-md-up, .am-hide-md, .am-show-md-down, .am-hide-lg-only, .am-hide-lg-up, .am-hide-lg, .am-show-lg-down { display: inherit !important; } .am-hide-sm-only, .am-hide-sm-up, .am-hide-sm, .am-hide-sm-down, .am-show-md-only, .am-show-md-up, .am-show-md, .am-hide-md-down, .am-show-lg-only, .am-show-lg-up, .am-show-lg, .am-hide-lg-down { display: none !important; } /* table */ table.am-show-sm-only, table.am-show-sm-up, table.am-show-sm, table.am-show-sm-down, table.am-hide-md-only, table.am-hide-md-up, table.am-hide-md, table.am-show-md-down, table.am-hide-lg-only, table.am-hide-lg-up, table.am-hide-lg, table.am-show-lg-down { display: table !important; } thead.am-show-sm-only, thead.am-show-sm-up, thead.am-show-sm, thead.am-show-sm-down, thead.am-hide-md-only, thead.am-hide-md-up, thead.am-hide-md, thead.am-show-md-down, thead.am-hide-lg-only, thead.am-hide-lg-up, thead.am-hide-lg, thead.am-show-lg-down { display: table-header-group !important; } tbody.am-show-sm-only, tbody.am-show-sm-up, tbody.am-show-sm, tbody.am-show-sm-down, tbody.am-hide-md-only, tbody.am-hide-md-up, tbody.am-hide-md, tbody.am-show-md-down, tbody.am-hide-lg-only, tbody.am-hide-lg-up, tbody.am-hide-lg, tbody.am-show-lg-down { display: table-row-group !important; } tr.am-show-sm-only, tr.am-show-sm-up, tr.am-show-sm, tr.am-show-sm-down, tr.am-hide-md-only, tr.am-hide-md-up, tr.am-hide-md, tr.am-show-md-down, tr.am-hide-lg-only, tr.am-hide-lg-up, tr.am-hide-lg, tr.am-show-lg-down { display: table-row !important; } th.am-show-sm-only, td.am-show-sm-only, th.am-show-sm-up, td.am-show-sm-up, th.am-show-sm, td.am-show-sm, th.am-show-sm-down, td.am-show-sm-down, th.am-hide-md-only, td.am-hide-md-only, th.am-hide-md-up, td.am-hide-md-up, th.am-hide-md, td.am-hide-md, th.am-show-md-down, td.am-show-md-down, th.am-hide-lg-only, td.am-hide-lg-only, th.am-hide-lg-up, td.am-hide-lg-up, th.am-hide-lg, td.am-hide-lg, th.am-show-lg-down, td.am-show-lg-down { display: table-cell !important; } } /* medium displays */ @media only screen and (min-width:641px) { .am-hide-sm-only, .am-show-sm-up, .am-hide-sm, .am-hide-sm-down, .am-show-md-only, .am-show-md-up, .am-show-md, .am-show-md-down, .am-hide-lg-only, .am-hide-lg-up, .am-hide-lg, .am-show-lg-down { display: inherit !important; } .am-show-sm-only, .am-hide-sm-up, .am-show-sm, .am-show-sm-down, .am-hide-md-only, .am-hide-md-up, .am-hide-md, .am-hide-md-down, .am-show-lg-only, .am-show-lg-up, .am-show-lg, .am-hide-lg-down { display: none !important; } table.am-hide-sm-only, table.am-show-sm-up, table.am-hide-sm, table.am-hide-sm-down, table.am-show-md-only, table.am-show-md-up, table.am-show-md, table.am-show-md-down, table.am-hide-lg-only, table.am-hide-lg-up, table.am-hide-lg, table.am-show-lg-down { display: table !important; } thead.am-hide-sm-only, thead.am-show-sm-up, thead.am-hide-sm, thead.am-hide-sm-down, thead.am-show-md-only, thead.am-show-md-up, thead.am-show-md, thead.am-show-md-down, thead.am-hide-lg-only, thead.am-hide-lg-up, thead.am-hide-lg, thead.am-show-lg-down { display: table-header-group !important; } tbody.am-hide-sm-only, tbody.am-show-sm-up, tbody.am-hide-sm, tbody.am-hide-sm-down, tbody.am-show-md-only, tbody.am-show-md-up, tbody.am-show-md, tbody.am-show-md-down, tbody.am-hide-lg-only, tbody.am-hide-lg-up, tbody.am-hide-lg, tbody.am-show-lg-down { display: table-row-group !important; } tr.am-hide-sm-only, tr.am-show-sm-up, tr.am-hide-sm, tr.am-hide-sm-down, tr.am-show-md-only, tr.am-show-md-up, tr.am-show-md, tr.am-show-md-down, tr.am-hide-lg-only, tr.am-hide-lg-up, tr.am-hide-lg, tr.am-show-lg-down { display: table-row !important; } th.am-hide-sm-only, td.am-hide-sm-only, th.am-show-sm-up, td.am-show-sm-up, th.am-hide-sm, td.am-hide-sm, th.am-hide-sm-down, td.am-hide-sm-down, th.am-show-md-only, td.am-show-md-only, th.am-show-md-up, td.am-show-md-up, th.am-show-md, td.am-show-md, th.am-show-md-down, td.am-show-md-down, th.am-hide-lg-only, td.am-hide-lg-only, th.am-hide-lg-up, td.am-hide-lg-up, th.am-hide-lg, td.am-hide-lg, th.am-show-lg-down, td.am-show-lg-down { display: table-cell !important; } } /* large displays */ @media only screen and (min-width:1025px) { .am-hide-sm-only, .am-show-sm-up, .am-hide-sm, .am-hide-sm-down, .am-hide-md-only, .am-show-md-up, .am-hide-md, .am-hide-md-down, .am-show-lg-only, .am-show-lg-up, .am-show-lg, .am-show-lg-down { display: inherit !important; } .am-show-sm-only, .am-hide-sm-up, .am-show-sm, .am-show-sm-down, .am-show-md-only, .am-hide-md-up, .am-show-md, .am-show-md-down, .am-hide-lg-only, .am-hide-lg-up, .am-hide-lg, .am-hide-lg-down { display: none !important; } table.am-hide-sm-only, table.am-show-sm-up, table.am-hide-sm, table.am-hide-sm-down, table.am-hide-md-only, table.am-show-md-up, table.am-hide-md, table.am-hide-md-down, table.am-show-lg-only, table.am-show-lg-up, table.am-show-lg, table.am-show-lg-down { display: table !important; } thead.am-hide-sm-only, thead.am-show-sm-up, thead.am-hide-sm, thead.am-hide-sm-down, thead.am-hide-md-only, thead.am-show-md-up, thead.am-hide-md, thead.am-hide-md-down, thead.am-show-lg-only, thead.am-show-lg-up, thead.am-show-lg, thead.am-show-lg-down { display: table-header-group !important; } tbody.am-hide-sm-only, tbody.am-show-sm-up, tbody.am-hide-sm, tbody.am-hide-sm-down, tbody.am-hide-md-only, tbody.am-show-md-up, tbody.am-hide-md, tbody.am-hide-md-down, tbody.am-show-lg-only, tbody.am-show-lg-up, tbody.am-show-lg, tbody.am-show-lg-down { display: table-row-group !important; } tr.am-hide-sm-only, tr.am-show-sm-up, tr.am-hide-sm, tr.am-hide-sm-down, tr.am-hide-md-only, tr.am-show-md-up, tr.am-hide-md, tr.am-hide-md-down, tr.am-show-lg-only, tr.am-show-lg-up, tr.am-show-lg, tr.am-show-lg-down { display: table-row !important; } th.am-hide-sm-only, td.am-hide-sm-only, th.am-show-sm-up, td.am-show-sm-up, th.am-hide-sm, td.am-hide-sm, th.am-hide-sm-down, td.am-hide-sm-down, th.am-hide-md-only, td.am-hide-md-only, th.am-show-md-up, td.am-show-md-up, th.am-hide-md, td.am-hide-md, th.am-hide-md-down, td.am-hide-md-down, th.am-show-lg-only, td.am-show-lg-only, th.am-show-lg-up, td.am-show-lg-up, th.am-show-lg, td.am-show-lg, th.am-show-lg-down, td.am-show-lg-down { display: table-cell !important; } } @media only screen and (orientation: landscape) { .am-show-landscape, .am-hide-portrait { display: inherit !important; } .am-hide-landscape, .am-show-portrait { display: none !important; } } @media only screen and (orientation: portrait) { .am-show-portrait, .am-hide-landscape { display: inherit !important; } .am-hide-portrait, .am-show-landscape { display: none !important; } } .am-sans-serif { font-family: "Segoe UI", "Lucida Grande", Helvetica, Arial, "Microsoft YaHei", FreeSans, Arimo, "Droid Sans", "wenquanyi micro hei", "Hiragino Sans GB", "Hiragino Sans GB W3", "FontAwesome", sans-serif; } .am-serif { font-family: Georgia, "Times New Roman", Times, SimSun, "FontAwesome", serif; } .am-kai { font-family: Georgia, "Times New Roman", Times, Kai, "Kaiti SC", KaiTi, BiauKai, "FontAwesome", serif; } .am-monospace { font-family: Monaco, Menlo, Consolas, "Courier New", "FontAwesome", monospace; } .am-text-primary { color: #0e90d2; } .am-text-secondary { color: #3bb4f2; } .am-text-success { color: #5eb95e; } .am-text-warning { color: #F37B1D; } .am-text-danger { color: #dd514c; } .am-link-muted { color: #666; } .am-link-muted a { color: #666; } .am-link-muted:hover, .am-link-muted a:hover { color: #555; } .am-text-default { font-size: 1.6rem; } /* .@{ns}text-xxs { font-size: @font-size-xxs; } */ .am-text-xs { font-size: 1.2rem; } .am-text-sm { font-size: 1.4rem; } .am-text-lg { font-size: 1.8rem; } .am-text-xl { font-size: 2.4rem; } .am-text-xxl { font-size: 3.2rem; } .am-text-xxxl { font-size: 4.2rem; } .am-ellipsis, .am-text-truncate { word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-text-break { word-wrap: break-word; -webkit-hyphens: auto; -ms-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } .am-text-nowrap { white-space: nowrap; } [class*='am-align-'] { margin-bottom: 1rem; } .am-align-left { margin-right: 1rem; float: left; } .am-align-right { margin-left: 1rem; float: right; } /** Only display content to screen readers * See: http://a11yproject.com/posts/how-to-hide-content/ */ .am-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } /* Text Image Replacement */ .am-text-ir { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } /* Text align */ @media only screen { .am-text-left { text-align: left !important; } .am-text-right { text-align: right !important; } .am-text-center { text-align: center !important; } .am-text-justify { text-align: justify !important; } } @media only screen and (max-width: 640px) { .am-sm-only-text-left { text-align: left !important; } .am-sm-only-text-right { text-align: right !important; } .am-sm-only-text-center { text-align: center !important; } .am-sm-only-text-justify { text-align: justify !important; } } @media only screen and (min-width:641px) and (max-width:1024px) { .am-md-only-text-left { text-align: left !important; } .am-md-only-text-right { text-align: right !important; } .am-md-only-text-center { text-align: center !important; } .am-md-only-text-justify { text-align: justify !important; } } @media only screen and (min-width:641px) { .am-md-text-left { text-align: left !important; } .am-md-text-right { text-align: right !important; } .am-md-text-center { text-align: center !important; } .am-md-text-justify { text-align: justify !important; } } @media only screen and (min-width:1025px) { .am-lg-text-left { text-align: left !important; } .am-lg-text-right { text-align: right !important; } .am-lg-text-center { text-align: center !important; } .am-lg-text-justify { text-align: justify !important; } } .am-text-top { vertical-align: top !important; } .am-text-middle { vertical-align: middle !important; } .am-text-bottom { vertical-align: bottom !important; } .am-angle { position: absolute; } .am-angle:before, .am-angle:after { position: absolute; display: block; content: ""; width: 0; height: 0; border: 8px dashed transparent; z-index: 1; } .am-angle-up { top: 0; } .am-angle-up:before, .am-angle-up:after { border-bottom-style: solid; border-width: 0 8px 8px; } .am-angle-up:before { border-bottom-color: #ddd; bottom: 0; } .am-angle-up:after { border-bottom-color: #fff; bottom: -1px; } .am-angle-down { bottom: -9px; } .am-angle-down:before, .am-angle-down:after { border-top-style: solid; border-width: 8px 8px 0; } .am-angle-down:before { border-top-color: #ddd; bottom: 0; } .am-angle-down:after { border-top-color: #fff; bottom: 1px; } .am-angle-left { left: -9px; } .am-angle-left:before, .am-angle-left:after { border-right-style: solid; border-width: 8px 8px 8px 0; } .am-angle-left:before { border-right-color: #ddd; left: 0; } .am-angle-left:after { border-right-color: #fff; left: 1px; } .am-angle-right { right: 0; } .am-angle-right:before, .am-angle-right:after { border-left-style: solid; border-width: 8px 0 8px 8px; } .am-angle-right:before { border-left-color: #ddd; left: 0; } .am-angle-right:after { border-left-color: #fff; left: -1px; } /* ========================================================================== Component: Alert Plugin ============================================================================ */ .am-alert { margin-bottom: 1em; padding: 0.625em; background: #0e90d2; color: #fff; border: 1px solid #0c7cb5; border-radius: 0; } .am-alert a { color: #fff; } .am-alert h1, .am-alert h2, .am-alert h3, .am-alert h4, .am-alert h5, .am-alert h6 { color: inherit; } .am-alert .am-close { opacity: .4; } .am-alert .am-close:hover { opacity: .6; } /* Add margin if adjacent element */ * + .am-alert { margin-top: 1em; } /* Remove margin from the last-child */ .am-alert > :last-child { margin-bottom: 0; } /* within am-form-group */ .am-form-group .am-alert { margin: 5px 0 0; padding: 0.25em 0.625em; font-size: 1.3rem; } /* Close in alert */ .am-alert > .am-close:first-child { float: right; height: auto; margin: -3px -5px auto auto; } /* Remove margin from adjacent element */ .am-alert > .am-close:first-child + * { margin-top: 0; } .am-alert-secondary { background-color: #eeeeee; border-color: #dfdfdf; color: #555555; } .am-alert-success { background-color: #5eb95e; border-color: #4bad4b; color: #fff; } .am-alert-warning { background-color: #F37B1D; border-color: #e56c0c; color: #fff; } .am-alert-danger { background-color: #dd514c; border-color: #d83832; color: #fff; } .am-dropdown { position: relative; display: inline-block; } .am-dropdown-toggle:focus { outline: 0; } .am-dropdown-content { position: absolute; top: 100%; left: 0; z-index: 1020; display: none; float: left; min-width: 160px; padding: 15px; margin: 9px 0 0; text-align: left; line-height: 1.6; background-color: #fff; border: 1px solid #ddd; border-radius: 0; -webkit-background-clip: padding-box; background-clip: padding-box; -webkit-animation-duration: .15s; animation-duration: .15s; } .am-dropdown-content:before, .am-dropdown-content:after { position: absolute; display: block; content: ""; width: 0; height: 0; border: 8px dashed transparent; z-index: 1; } .am-dropdown-content:before, .am-dropdown-content:after { border-bottom-style: solid; border-width: 0 8px 8px; } .am-dropdown-content:before { border-bottom-color: #ddd; bottom: 0; } .am-dropdown-content:after { border-bottom-color: #fff; bottom: -1px; } .am-dropdown-content:before, .am-dropdown-content:after { left: 10px; top: -8px; pointer-events: none; } .am-dropdown-content:after { top: -7px; } .am-active > .am-dropdown-content { display: block; } .am-dropdown-content :first-child { margin-top: 0; } .am-dropdown-up .am-dropdown-content { top: auto; bottom: 100%; margin: 0 0 9px; } .am-dropdown-up .am-dropdown-content:before, .am-dropdown-up .am-dropdown-content:after { border-bottom: none; border-top: 8px solid #ddd; top: auto; bottom: -8px; } .am-dropdown-up .am-dropdown-content:after { bottom: -7px; border-top-color: #fff; } .am-dropdown-flip .am-dropdown-content { left: auto; right: 0; } .am-dropdown-flip .am-dropdown-content:before, .am-dropdown-flip .am-dropdown-content:after { left: auto; right: 10px; } ul.am-dropdown-content { list-style: none; padding: 5px 0; } ul.am-dropdown-content.am-fr { right: 0; left: auto; } ul.am-dropdown-content .am-divider { height: 1px; margin: 0rem 0; overflow: hidden; background-color: #e5e5e5; } ul.am-dropdown-content > li > a { display: block; padding: 6px 20px; clear: both; font-weight: normal; color: #333333; white-space: nowrap; } ul.am-dropdown-content > li > a:hover, ul.am-dropdown-content > li > a:focus { text-decoration: none; color: #262626; background-color: #f5f5f5; } ul.am-dropdown-content > .am-active > a, ul.am-dropdown-content > .am-active > a:hover, ul.am-dropdown-content > .am-active > a:focus { color: #fff; text-decoration: none; outline: 0; background-color: #0e90d2; } ul.am-dropdown-content > .am-disabled > a, ul.am-dropdown-content > .am-disabled > a:hover, ul.am-dropdown-content > .am-disabled > a:focus { color: #999999; } ul.am-dropdown-content > .am-disabled > a:hover, ul.am-dropdown-content > .am-disabled > a:focus { text-decoration: none; background-color: transparent; background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); cursor: not-allowed; } .am-dropdown-header { display: block; padding: 6px 20px; font-size: 1.2rem; color: #999999; } .am-fr > .am-dropdown-content { right: 0; left: auto; } .am-fr > .am-dropdown-content:before { right: 10px; left: auto; } .am-dropdown-animation { -webkit-animation: am-dropdown-animation 0.15s ease-out; animation: am-dropdown-animation 0.15s ease-out; } @-webkit-keyframes am-dropdown-animation { 0% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } 100% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } } @keyframes am-dropdown-animation { 0% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } 100% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } } /* ========================================================================== Component: Flex Slider Plugin ============================================================================ */ .am-slider a:hover, .am-slider a:focus { outline: none; } .am-slides, .am-control-nav, .am-direction-nav { margin: 0; padding: 0; list-style: none; } .am-slider { margin: 0; padding: 0; } .am-slider .am-slides:before, .am-slider .am-slides:after { content: " "; display: table; } .am-slider .am-slides:after { clear: both; } .am-slider .am-slides > li { display: none; -webkit-backface-visibility: hidden; position: relative; } .no-js .am-slider .am-slides > li:first-child { display: block; } .am-slider .am-slides img { width: 100%; display: block; } .am-pauseplay span { text-transform: capitalize; } .am-slider { position: relative; } .am-viewport { -webkit-transition: all 1s ease; transition: all 1s ease; } .am-slider-carousel li { margin-right: 5px; } .am-control-nav { position: absolute; } .am-control-nav li { display: inline-block; } .am-control-thumbs { position: static; overflow: hidden; } .am-control-thumbs img { -webkit-transition: all 1s ease; transition: all 1s ease; } .am-slider-slide .am-slides > li { display: none; position: relative; } @media all and (transform-3d), (-webkit-transform-3d) { .am-slider-slide .am-slides > li { -webkit-transition: -webkit-transform 0.6s ease-in-out; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .am-slider-slide .am-slides > li.next, .am-slider-slide .am-slides > li.active.right { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); left: 0; } .am-slider-slide .am-slides > li.prev, .am-slider-slide .am-slides > li.active.left { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); left: 0; } .am-slider-slide .am-slides > li.next.left, .am-slider-slide .am-slides > li.prev.right, .am-slider-slide .am-slides > li.active { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); left: 0; } } .am-slider-slide .am-slides > .active, .am-slider-slide .am-slides > .next, .am-slider-slide .am-slides > .prev { display: block; } .am-slider-slide .am-slides > .active { left: 0; } .am-slider-slide .am-slides > .next, .am-slider-slide .am-slides > .prev { position: absolute; top: 0; width: 100%; } .am-slider-slide .am-slides > .next { left: 100%; } .am-slider-slide .am-slides > .prev { left: -100%; } .am-slider-slide .am-slides > .next.left, .am-slider-slide .am-slides > .prev.right { left: 0; } .am-slider-slide .am-slides > .active.left { left: -100%; } .am-slider-slide .am-slides > .active.right { left: 100%; } /** * Slider Theme: Default */ .am-slider-default { margin: 0 0 20px; background-color: #fff; border-radius: 2px; -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15); box-shadow: 0 0 2px rgba(0, 0, 0, 0.15); /* Direction Nav */ /* Pause/Play */ /* Control Nav */ } .am-slider-default .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-default .am-viewport { max-height: 300px; } .am-slider-default .carousel li { margin-right: 5px; } .am-slider-default .am-direction-nav a { position: absolute; top: 50%; z-index: 10; display: block; width: 36px; height: 36px; margin: -18px 0 0; overflow: hidden; opacity: 0.45; cursor: pointer; color: rgba(0, 0, 0, 0.65); -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-default .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); width: 100%; color: #333333; content: "\f137"; font-size: 24px!important; text-align: center; line-height: 36px!important; height: 36px; } .am-slider-default .am-direction-nav a.am-next:before { content: "\f138"; } .am-slider-default .am-direction-nav .am-prev { left: 10px; } .am-slider-default .am-direction-nav .am-next { right: 10px; text-align: right; } .am-slider-default .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-default:hover .am-prev { opacity: 0.7; left: 10px; } .am-slider-default:hover .am-prev:hover { opacity: 1; } .am-slider-default:hover .am-next { opacity: 0.7; right: 10px; } .am-slider-default:hover .am-next:hover { opacity: 1; } .am-slider-default .am-pauseplay a { display: block; width: 20px; height: 20px; position: absolute; bottom: 5px; left: 10px; opacity: 0.8; z-index: 10; overflow: hidden; cursor: pointer; color: #000; } .am-slider-default .am-pauseplay a::before { font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); font-size: 20px; display: inline-block; content: "\f04c"; } .am-slider-default .am-pauseplay a:hover { opacity: 1; } .am-slider-default .am-pauseplay a.am-play::before { content: "\f04b"; } .am-slider-default .am-slider-desc { background-color: rgba(0, 0, 0, 0.7); position: absolute; bottom: 0; padding: 10px; width: 100%; color: #fff; } .am-slider-default .am-control-nav { width: 100%; position: absolute; bottom: -15px; text-align: center; } .am-slider-default .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-default .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: #666; background-color: rgba(0, 0, 0, 0.5); line-height: 0; font-size: 0; cursor: pointer; text-indent: -9999px; border-radius: 20px; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-default .am-control-nav li a:hover { background-color: #333; background-color: rgba(0, 0, 0, 0.7); } .am-slider-default .am-control-nav li a.am-active { background-color: #000; background-color: #0e90d2; cursor: default; } .am-slider-default .am-control-thumbs { margin: 5px 0 0; position: static; overflow: hidden; } .am-slider-default .am-control-thumbs li { width: 25%; float: left; margin: 0; } .am-slider-default .am-control-thumbs img { width: 100%; height: auto; display: block; opacity: .7; cursor: pointer; } .am-slider-default .am-control-thumbs img:hover { opacity: 1; } .am-slider-default .am-control-thumbs .am-active { opacity: 1; cursor: default; } .am-slider-default .am-control-thumbs i { position: absolute; } /* TODO: 1. 动画应该放在 dialog 上,不再是整个 modal,涉及 JS 逻辑,需要统筹修改 2. modal 滚动条处理,是否需要添加一个滚动条宽度的水平 padding? */ /* ========================================================================== Component: Modal Plugin ============================================================================ */ .am-modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1110; display: none; opacity: 0; outline: 0; text-align: center; -webkit-transform: scale(1.185); -ms-transform: scale(1.185); transform: scale(1.185); -webkit-transition-property: opacity, -webkit-transform; transition-property: opacity, -webkit-transform; transition-property: transform, opacity; transition-property: transform, opacity, -webkit-transform; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .am-modal:focus { outline: 0; } .am-modal.am-modal-active { opacity: 1; -webkit-transition-duration: 300ms; transition-duration: 300ms; -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1); overflow-x: hidden; overflow-y: auto; } .am-modal.am-modal-out { opacity: 0; z-index: 1109; -webkit-transition-duration: 300ms; transition-duration: 300ms; -webkit-transform: scale(0.815); -ms-transform: scale(0.815); transform: scale(0.815); } .am-modal:before { content: "\200B"; display: inline-block; height: 100%; vertical-align: middle; } .am-modal-dialog { position: relative; display: inline-block; vertical-align: middle; margin-left: auto; margin-right: auto; width: 270px; max-width: 100%; border-radius: 0; background: #f8f8f8; /*@media @large-up { width: @modal-lg; margin-left: -@modal-lg/2; }*/ } @media only screen and (min-width:641px) { .am-modal-dialog { width: 540px; } } .am-modal-hd { padding: 15px 10px 5px 10px; font-size: 1.8rem; font-weight: 500; } .am-modal-hd + .am-modal-bd { padding-top: 0; } .am-modal-hd .am-close { position: absolute; top: 4px; right: 4px; } .am-modal-bd { padding: 15px 10px; text-align: center; border-bottom: 1px solid #dedede; border-radius: 2px 2px 0 0; } .am-modal-bd + .am-modal-bd { margin-top: 5px; } .am-modal-prompt-input { display: block; margin: 5px auto 0 auto; border-radius: 0; padding: 5px; line-height: 1.8rem; width: 80%; border: 1px solid #dedede; -webkit-appearance: none; -moz-appearance: none; -ms-appearance: none; appearance: none; } .am-modal-prompt-input:focus { outline: none; border-color: #d6d6d6; } .am-modal-footer { height: 44px; overflow: hidden; display: table; width: 100%; border-collapse: collapse; } .am-modal-btn { display: table-cell !important; padding: 0 5px; height: 44px; -webkit-box-sizing: border-box !important; box-sizing: border-box !important; font-size: 1.6rem; line-height: 44px; text-align: center; color: #0e90d2; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; cursor: pointer; border-right: 1px solid #dedede; } .am-modal-btn:first-child { border-radius: 0 0 0 0; } .am-modal-btn:last-child { border-right: none; border-radius: 0 0 0 0; } .am-modal-btn:first-child:last-child { border-radius: 0 0 0 0; } .am-modal-btn.am-modal-btn-bold { font-weight: 500; } .am-modal-btn:active { background: #d4d4d4; } .am-modal-btn + .am-modal-btn { border-left: 1px solid #dedede; } .am-modal-no-btn .am-modal-dialog { border-radius: 0; border-bottom: none; } .am-modal-no-btn .am-modal-bd { border-bottom: none; } .am-modal-no-btn .am-modal-footer { display: none; } .am-modal-loading .am-modal-bd { border-bottom: none; } .am-modal-loading .am-icon-spin { display: inline-block; font-size: 2.4rem; } .am-modal-loading .am-modal-footer { display: none; } .am-modal-actions { position: fixed; left: 0; bottom: 0; z-index: 1110; width: 100%; max-height: 100%; overflow-x: hidden; overflow-y: auto; text-align: center; border-radius: 0; -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); -webkit-transition: -webkit-transform 300ms; transition: -webkit-transform 300ms; transition: transform 300ms; transition: transform 300ms, -webkit-transform 300ms; } .am-modal-actions.am-modal-active { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); } .am-modal-actions.am-modal-out { z-index: 1109; -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); } .am-modal-actions-group { margin: 10px; } .am-modal-actions-group .am-list { margin: 0; border-radius: 0; } .am-modal-actions-group .am-list > li { margin-bottom: 0; border-bottom: none; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015); box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015); } .am-modal-actions-group .am-list > li > a { padding: 1rem; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-modal-actions-group .am-list > li:first-child { border-top: none; border-top-right-radius: 0; border-top-left-radius: 0; } .am-modal-actions-group .am-list > li:last-child { border-bottom: none; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-modal-actions-header { padding: 1rem; color: #999999; font-size: 1.4rem; } .am-modal-actions-danger { color: #dd514c; } .am-modal-actions-danger a { color: inherit; } .am-popup { position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 1110; background: #fff; display: none; overflow: hidden; -webkit-transition-property: -webkit-transform; transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); } .am-popup.am-modal-active, .am-popup.am-modal-out { -webkit-transition-duration: 300ms; transition-duration: 300ms; } .am-popup.am-modal-active { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); } .am-popup.am-modal-out { -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); } @media all and (min-width: 630px) and (min-height: 630px) { .am-popup { width: 630px; height: 630px; left: 50%; top: 50%; margin-left: -315px; margin-top: -315px; -webkit-transform: translateY(1024px); -ms-transform: translateY(1024px); transform: translateY(1024px); } .am-popup.am-modal-active { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); } .am-popup.am-modal-out { -webkit-transform: translateY(1024px); -ms-transform: translateY(1024px); transform: translateY(1024px); } } .am-popup-inner { padding-top: 44px; height: 100%; overflow: auto; -webkit-overflow-scrolling: touch; } .am-popup-hd { position: absolute; top: 0; z-index: 1000; width: 100%; height: 43px; border-bottom: 1px solid #dedede; background-color: #fff; } .am-popup-hd .am-popup-title { font-size: 1.8rem; font-weight: bold; line-height: 43px; text-align: center; margin: 0 30px; color: #333333; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-popup-hd .am-close { position: absolute; right: 10px; top: 8px; cursor: pointer; -webkit-transition: all 0.3s; transition: all 0.3s; color: #999999; } .am-popup-hd .am-close:hover { -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); color: #555555; } .am-popup-bd { padding: 15px; background: #f8f8f8; color: #555555; } /* ========================================================================== Component: OffCanvas Plugin ============================================================================ */ /* Off-canvas overlay and bar container */ .am-offcanvas { display: none; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1090; background: rgba(0, 0, 0, 0.15); } .am-offcanvas.am-active { display: block; } /** * .@{ns}offcanvas-page * * Prepares the whole HTML page to slide-out * 1. Fix the main page and disallow scrolling * 2. Side-out transition */ .am-offcanvas-page { position: fixed; /* 1 */ -webkit-transition: margin-left 0.3s ease-in-out; transition: margin-left 0.3s ease-in-out; /* 2 */ } /* Sub-object .@{ns}offcanvas-bar */ .am-offcanvas-bar { position: fixed; top: 0; bottom: 0; left: 0; z-index: 1091; width: 270px; max-width: 100%; background: #333; overflow-y: auto; /* scrollable */ -webkit-overflow-scrolling: touch; /* scrollable */ -webkit-transition: -webkit-transform 0.3s ease-in-out; transition: -webkit-transform 0.3s ease-in-out; transition: transform 0.3s ease-in-out; transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; -webkit-transform: translateX(-100%); -ms-transform: translateX(-100%); transform: translateX(-100%); } .am-offcanvas-bar:after { content: ""; display: block; position: absolute; top: 0; bottom: 0; right: 0; width: 1px; background: #262626; } .am-offcanvas.am-active .am-offcanvas-bar.am-offcanvas-bar-active { -webkit-transform: translateX(0); -ms-transform: translateX(0); transform: translateX(0); } /* .@{ns}offcanvas-bar-flip */ .am-offcanvas-bar-flip { left: auto; right: 0; -webkit-transform: translateX(100%); -ms-transform: translateX(100%); transform: translateX(100%); } .am-offcanvas-bar-flip:after { right: auto; left: 0; } .am-offcanvas-content { padding: 15px; color: #999; } .am-offcanvas-content a { color: #ccc; } /* ========================================================================== Component: Popover Plugin ============================================================================ */ .am-popover { position: absolute; top: 0; left: 0; margin: 0; border-radius: 0; background: #333333; color: #fff; border: 1px solid #333333; display: none; font-size: 1.6rem; z-index: 1030; opacity: 0; -webkit-transition: opacity 300ms; transition: opacity 300ms; } .am-popover.am-active { display: block !important; opacity: 1; } .am-popover-inner { position: relative; background: #333333; padding: 8px; z-index: 110; } .am-popover-caret { position: absolute; top: 0; z-index: 100; display: inline-block; width: 0; height: 0; vertical-align: middle; border-bottom: 8px solid #333333; border-right: 8px solid transparent; border-left: 8px solid transparent; border-top: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); overflow: hidden; } .am-popover-top .am-popover-caret { top: auto; bottom: -8px; -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } .am-popover-bottom .am-popover-caret { top: -8px; } .am-popover-top .am-popover-caret, .am-popover-bottom .am-popover-caret { left: 50%; margin-left: -8px; } .am-popover-left .am-popover-caret { top: auto; left: auto; right: -12px; -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .am-popover-right .am-popover-caret { right: auto; left: -12px; -webkit-transform: rotate(-90deg); -ms-transform: rotate(-90deg); transform: rotate(-90deg); } .am-popover-left .am-popover-caret, .am-popover-right .am-popover-caret { top: 50%; margin-top: -4px; } .am-popover-sm { font-size: 1.4rem; } .am-popover-sm .am-popover-inner { padding: 5px; } .am-popover-lg { font-size: 1.8rem; } .am-popover-primary { border-color: #0e90d2; } .am-popover-primary .am-popover-inner { background: #0e90d2; } .am-popover-primary .am-popover-caret { border-bottom-color: #0e90d2; } .am-popover-secondary { border-color: #3bb4f2; } .am-popover-secondary .am-popover-inner { background: #3bb4f2; } .am-popover-secondary .am-popover-caret { border-bottom-color: #3bb4f2; } .am-popover-success { border-color: #5eb95e; } .am-popover-success .am-popover-inner { background: #5eb95e; } .am-popover-success .am-popover-caret { border-bottom-color: #5eb95e; } .am-popover-warning { border-color: #F37B1D; } .am-popover-warning .am-popover-inner { background: #F37B1D; } .am-popover-warning .am-popover-caret { border-bottom-color: #F37B1D; } .am-popover-danger { border-color: #dd514c; } .am-popover-danger .am-popover-inner { background: #dd514c; } .am-popover-danger .am-popover-caret { border-bottom-color: #dd514c; } /* ========================================================================== Component: Progress Plugin ============================================================================ */ #nprogress { /* Make clicks pass-through */ pointer-events: none; /* Fancy blur effect */ } #nprogress .nprogress-bar { position: fixed; top: 0; left: 0; z-index: 2000; width: 100%; height: 2px; background: #5eb95e; } #nprogress .nprogress-peg { display: block; position: absolute; right: 0; width: 100px; height: 100%; -webkit-box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e; box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e; opacity: 1; -webkit-transform: rotate(3deg) translate(0px, -4px); -ms-transform: rotate(3deg) translate(0px, -4px); transform: rotate(3deg) translate(0px, -4px); } #nprogress .nprogress-spinner { position: fixed; top: 15px; right: 15px; z-index: 2000; display: block; } #nprogress .nprogress-spinner-icon { width: 18px; height: 18px; -webkit-box-sizing: border-box; box-sizing: border-box; border: solid 2px transparent; border-top-color: #5eb95e; border-left-color: #5eb95e; border-radius: 50%; -webkit-animation: nprogress-spinner 400ms linear infinite; animation: nprogress-spinner 400ms linear infinite; } @-webkit-keyframes nprogress-spinner { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes nprogress-spinner { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } /* ========================================================================== Component: Tabs Plugin ============================================================================ */ .am-tabs-bd { position: relative; overflow: hidden; border: 1px solid #ddd; border-top: none; z-index: 100; -webkit-transition: height .3s; transition: height .3s; } .am-tabs-bd:before, .am-tabs-bd:after { content: " "; display: table; } .am-tabs-bd:after { clear: both; } .am-tabs-bd .am-tab-panel { position: absolute; top: 0; z-index: 99; float: left; width: 100%; padding: 10px 10px 15px; visibility: hidden; -webkit-transition: -webkit-transform 0.3s; transition: -webkit-transform 0.3s; transition: transform 0.3s; transition: transform 0.3s, -webkit-transform 0.3s; -webkit-transform: translateX(-100%); -ms-transform: translateX(-100%); transform: translateX(-100%); } .am-tabs-bd .am-tab-panel * { -webkit-user-drag: none; } .am-tabs-bd .am-tab-panel.am-active { position: relative; z-index: 100; visibility: visible; -webkit-transform: translateX(0); -ms-transform: translateX(0); transform: translateX(0); } .am-tabs-bd .am-tab-panel.am-active ~ .am-tab-panel { -webkit-transform: translateX(100%); -ms-transform: translateX(100%); transform: translateX(100%); } .am-tabs-bd .am-tabs-bd { border: none; } .am-tabs-bd-ofv { overflow: visible; } .am-tabs-fade .am-tab-panel { opacity: 0; -webkit-transition: opacity .25s linear; transition: opacity .25s linear; } .am-tabs-fade .am-tab-panel.am-in { opacity: 1; } /* ========================================================================== Component: Share Plugin ============================================================================ */ .am-share { font-size: 14px; } .am-share-title { padding: 10px 0 0; margin: 0 10px; font-weight: normal; text-align: center; color: #555555; background-color: #f8f8f8; border-bottom: 1px solid #fff; border-top-right-radius: 2px; border-top-left-radius: 2px; } .am-share-title:after { content: ""; display: block; width: 100%; height: 0; margin-top: 10px; border-bottom: 1px solid #dfdfdf; } .am-share-sns { margin: 0 10px; padding-top: 15px; background-color: #f8f8f8; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } .am-share-sns li { margin-bottom: 15px; } .am-share-sns a { display: block; color: #555555; } .am-share-sns span { display: block; } .am-share-sns [class*='am-icon'] { background-color: #3bb4f2; border-radius: 50%; width: 36px; height: 36px; line-height: 36px; color: #fff; margin-bottom: 5px; font-size: 18px; } .am-share-sns .am-icon-weibo { background-color: #ea1328; } .am-share-sns .am-icon-qq { background-color: #009cda; } .am-share-sns .am-icon-star { background-color: #ffc028; } .am-share-sns .am-icon-tencent-weibo { background-color: #23ccfe; } .am-share-sns .am-icon-wechat, .am-share-sns .am-icon-weixin { background-color: #44b549; } .am-share-sns .am-icon-renren { background-color: #105ba3; } .am-share-sns .am-icon-comment { background-color: #5eb95e; } .am-share-footer { margin: 10px; } .am-share-footer .am-btn { color: #555555; } .am-share-wechat-qr { font-size: 14px; color: #777; } .am-share-wechat-qr .am-modal-dialog { background-color: #fff; border: 1px solid #dedede; } .am-share-wechat-qr .am-modal-hd { padding-top: 10px; text-align: left; margin-bottom: 10px; } .am-share-wechat-qr .am-share-wx-qr { margin-bottom: 10px; } .am-share-wechat-qr .am-share-wechat-tip { text-align: left; } .am-share-wechat-qr .am-share-wechat-tip em { color: #dd514c; font-weight: bold; font-style: normal; margin-left: 3px; margin-right: 3px; } /* ========================================================================== Component: PureView Plugin ============================================================================ */ .am-pureview { position: fixed; left: 0; top: 0; bottom: 0; right: 0; z-index: 1120; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.95); display: none; overflow: hidden; -webkit-transition: -webkit-transform .3s; transition: -webkit-transform .3s; transition: transform .3s; transition: transform .3s, -webkit-transform .3s; -webkit-transform: translate(0, 100%); -ms-transform: translate(0, 100%); transform: translate(0, 100%); } .am-pureview.am-active { -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-pureview ul, .am-pureview ol { list-style: none; padding: 0; margin: 0; width: 100%; } .am-pureview-slider { overflow: hidden; height: 100%; } .am-pureview-slider li { position: absolute; width: 100%; height: 100%; top: 0; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; vertical-align: middle; -webkit-transition: all .3s linear; transition: all .3s linear; z-index: 100; visibility: hidden; } .am-pureview-slider li.am-pureview-slide-prev { -webkit-transform: translate(-100%, 0); -ms-transform: translate(-100%, 0); transform: translate(-100%, 0); z-index: 109; } .am-pureview-slider li.am-pureview-slide-next { -webkit-transform: translate(100%, 0); -ms-transform: translate(100%, 0); transform: translate(100%, 0); z-index: 109; } .am-pureview-slider li.am-active { position: relative; z-index: 110; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); visibility: visible; } .am-pureview-slider .pinch-zoom-container { width: 100%; z-index: 1121; } .am-pureview-slider .am-pinch-zoom { position: relative; width: 100%; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; } .am-pureview-slider .am-pinch-zoom:after { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f110"; -webkit-animation: icon-spin 2s infinite linear; animation: icon-spin 2s infinite linear; font-size: 24px; line-height: 24px; color: #eee; position: absolute; top: 50%; left: 50%; margin-left: -12px; margin-top: -12px; z-index: 1; } .am-pureview-slider .am-pinch-zoom.am-pureview-loaded:after { display: none; } .am-pureview-slider img { position: relative; display: block; max-width: 100%; max-height: 100%; opacity: 0; z-index: 200; -webkit-user-drag: none; -webkit-transition: opacity 0.2s ease-in; transition: opacity 0.2s ease-in; } .am-pureview-slider img.am-img-loaded { opacity: 1; } .am-pureview-direction { position: absolute; top: 50%; width: 100%; margin-top: -18px !important; z-index: 1122; } .am-touch .am-pureview-direction, .am-pureview-only .am-pureview-direction { display: none; } .am-pureview-direction li { position: absolute; width: 36px; height: 36px; } .am-pureview-direction a { display: block; height: 36px; border: none; color: #ccc; opacity: 0.5; cursor: pointer; text-align: center; z-index: 1125; } .am-pureview-direction a:before { content: "\f137"; line-height: 36px; font-size: 24px; } .am-pureview-direction a:hover { opacity: 1; } .am-pureview-direction .am-pureview-prev { left: 15px; } .am-pureview-direction .am-pureview-next { right: 15px; } .am-pureview-direction .am-pureview-next a:before { content: "\f138"; } .am-pureview-bar { position: absolute; bottom: 0; height: 45px; width: 100%; background-color: rgba(0, 0, 0, 0.35); color: #eeeeee; line-height: 45px; padding: 0 10px; font-size: 14px; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } .am-pureview-bar .am-pureview-title { display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; margin-left: 6px; -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; } .am-pureview-bar .am-pureview-total { font-size: 10px; line-height: 48px; } .am-pureview-actions { position: absolute; z-index: 1130; left: 0; right: 0; top: 0; height: 45px; background-color: rgba(0, 0, 0, 0.35); } .am-pureview-actions a { position: absolute; left: 10px; color: #ccc; display: block; width: 45px; line-height: 45px; text-align: left; font-size: 16px; } .am-pureview-actions a:hover { color: #fff; } .am-pureview-actions [data-am-toggle="share"] { left: auto; right: 10px; } .am-pureview-bar, .am-pureview-actions { opacity: 0; -webkit-transition: all .15s; transition: all .15s; z-index: 1130; } .am-pureview-bar-active .am-pureview-bar, .am-pureview-bar-active .am-pureview-actions { opacity: 1; } .am-pureview-nav { position: absolute; bottom: 15px; left: 0; right: 0; text-align: center; z-index: 1131; } .am-pureview-bar-active .am-pureview-nav { display: none; } .am-pureview-nav li { display: inline-block; background: #ccc; background: rgba(255, 255, 255, 0.5); width: 8px; height: 8px; margin: 0 3px; border-radius: 50%; text-indent: -9999px; overflow: hidden; cursor: pointer; } .am-pureview-nav .am-active { background: #fff; background: rgba(255, 255, 255, 0.9); } [data-am-pureview] img { cursor: pointer; } .am-pureview-active { overflow: hidden; } .ath-viewport * { -webkit-box-sizing: border-box; box-sizing: border-box; } .ath-viewport { position: relative; z-index: 2147483641; pointer-events: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-text-size-adjust: none; -ms-text-size-adjust: none; text-size-adjust: none; } .ath-modal { pointer-events: auto !important; background: rgba(0, 0, 0, 0.6); } .ath-mandatory { background: #000; } .ath-container { pointer-events: auto !important; position: absolute; z-index: 2147483641; padding: 0.7em 0.6em; width: 18em; background: #eee; -webkit-background-size: 100% auto; background-size: 100% auto; -webkit-box-shadow: 0 0.2em 0 #d1d1d1; box-shadow: 0 0.2em 0 #d1d1d1; font-family: sans-serif; font-size: 15px; line-height: 1.5em; text-align: center; } .ath-container small { font-size: 0.8em; line-height: 1.3em; display: block; margin-top: 0.5em; } .ath-ios.ath-phone { bottom: 1.8em; left: 50%; margin-left: -9em; } .ath-ios6.ath-tablet { left: 5em; top: 1.8em; } .ath-ios7.ath-tablet { left: 0.7em; top: 1.8em; } .ath-ios8.ath-tablet { right: 0.4em; top: 1.8em; } .ath-android { bottom: 1.8em; left: 50%; margin-left: -9em; } /* close icon */ .ath-container:before { content: ''; position: relative; display: block; float: right; margin: -0.7em -0.6em 0 0.5em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAAAdVBMVEUAAAA5OTkzMzM7Ozs3NzdBQUFAQEA/Pz8+Pj5BQUFAQEA/Pz8+Pj5BQUFAQEA/Pz9BQUE+Pj4/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8+Pj4/Pz8+Pj4/Pz8/Pz8/Pz8/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8/Pz9AQEA/Pz+fdCaPAAAAJnRSTlMACQoNDjM4OTo7PEFCQ0RFS6ytsbS1tru8vcTFxu7x8vX19vf4+C5yomAAAAJESURBVHgBvdzLTsJAGEfxr4C2KBcVkQsIDsK8/yPaqIsPzVlyzrKrX/5p0kkXEz81L23otc9NpIbbWia2YVLqdnhlqFlhGWpSDHe1aopsSIpRb8gK0dC3G30b9rVmhWZIimTICsvQtx/FsuYOrWHoDjX3Gu31gzJxdki934WrAIOsAIOsAIOiAMPhPsJTgKGN0BVsYIVsYIVpYIVpYIVpYIVpYIVpYIVpYIVpYIVlAIVgEBRs8BRs8BRs8BRs8BRs8BRs8BRs8BRTNmgKNngKNngKNngKNngKNhiKGxgiOlZoBlaYBlaYBlaYBlaYBlaYBlaYBlaYBlZIBlBMfQMrVAMr2KAqBENSHFHhGEABhi5CV6gGUKgGUKgGUKgGUFwuqgEUvoEVsoEVpoEUpgEUggF+gKTKY+h1fxSlC7/Z+RrxOQ3fcEoAPPHZBlaYBlaYBlaYBlZYBlYIhvLBCstw7PgM7hkiWOEZWGEaWGEaWGEaIsakEAysmHkGVpxmvoEVqoEVpoEVpoEVpoEVpoEVpoEVkoEVgkFQsEFSsEFQsGEcoSvY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnmbNAUT2c2WAo2eAo2eAo2eAo2eAo2eArNEPFACjZ4CjZ4CjZ4CjaIird/rBvFH6llNCvewdli1URWCIakSIZesUaDoFg36dKFWk9zCZDei3TtwmCj7pC22AwikiIZPEU29IpFNliKxa/hC9DFITjQPYhcAAAAAElFTkSuQmCC); background-color: rgba(255, 255, 255, 0.8); -webkit-background-size: 50% 50%; background-size: 50%; background-repeat: no-repeat; background-position: 50%; width: 2.7em; height: 2.7em; text-align: center; overflow: hidden; color: #a33; z-index: 2147483642; } .ath-container.ath-icon:before { position: absolute; top: 0; right: 0; margin: 0; float: none; } .ath-mandatory .ath-container:before { display: none; } .ath-container.ath-android:before { float: left; margin: -0.7em 0.5em 0 -0.6em; } .ath-container.ath-android.ath-icon:before { position: absolute; right: auto; left: 0; margin: 0; float: none; } /* applied only if the application icon is shown */ .ath-action-icon { display: inline-block; vertical-align: middle; background-position: 50%; background-repeat: no-repeat; text-indent: -9999em; overflow: hidden; } .ath-ios7 .ath-action-icon, .ath-ios8 .ath-action-icon { width: 1.6em; height: 1.6em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAACtCAYAAAB7l7tOAAAF6UlEQVR4AezZWWxUZRiH8VcQEdxZEFFiUZBFUCIa1ABBDARDcCciYGKMqTEGww3SOcNSAwQTjOBiiIpEhRjAhRgXRC8MFxojEhAFZUGttVhaoSxlaW3n8W3yXZxm6vTrOMM5Q98n+V9MMu1pvl++uZhKuypghu49KaaTWGdZSYoVN6VD95nMpLNYZ9XNbdQR2od2k88O3Gm6Bh0t7H0p5Vwp2Ax3ajpu2tYbciFWwkTFO63DY6+JcI4USFaSyYpWp8N7SVZJKR3EinkBk9JxvZFXxhnZSjBaoWp1ZL0ES8WKYXMZp0AndORgy8WKFe5Yf1zvvSBWDEpys2LU6MjD5kmEWQlGKsJRHXlcqUSQVcItEnDEA6gAb7LhjvD9WO6yIEfICQI5A1nzGCYB1T4og5bBiFcyv2f6ujYhl4iVxwKG6qp8MK55HsqPwK0rMr9v/yEo3uCPrJstVh5KMER30Aeh31Ioq0FrHfjXw9CYghnrvYFTuqfEymFzGSwBlT4ARYr7u+K6GLmCVGvAGg2NMG0d/sgJnpScZLjXSkC5z8H3eQ72/k24Q8NfzvwFyK4qtuJSZKaubRPyE/K/Mtx+EvCHL+7uasId1t10w0scz/RzSzYzAfgKV30D3LPaG7lRkR8RK4tKKJKAMp+D7r0EfmmOe0x3m2itAc/ZxBjgAt1mXHWKPPkdb+QGSTJdrDaU5EoJ2OtzwD0WwY7KNNzbRfMFFg24WPdtGHnS221Cflgsj56hjwTs8TnY7oq7/QDhjutGicsb2AVcovsO18l6uPPNNiE/JFaGAq7Q7fY50G4LYVtz3FrdaNGyBXbIl+q24DqhyHes9EaulwR3SwtZs+ktAT/7HORliru1gnCndONFyx44Dfn7MPLYN7yR6yTJZAllJeguAT/4HOBFz8I3ZWm4E0TLFbBD7qn7EVdtHYx53R9ZN0ksrZRuErDN5+AuLIWvm+Oe1k0ULdfADrmX7idcR0/DyBXeyCdlLuMMOGCBz4F1ng+f7yFcve5e0fIFHELeiav6BAx70Rt5p0yhY3u/wR0kyarW/uX35b403PtFyzewQ75ctwtXzSkY8WqruHslSV8RscrL6TJ1bcvfWJ0/HzbtIdw/ugdFyzdwOOAq3T6fmzxwGQ3vbmO8iFioIWqYSsHMj9M/ljfuTsOdItoZBXYBfXX7cVXVwvXLm/8+fU3lcdCqdEMNGBbgUmRmfQISQKd5sGEn4VK6YtEiAXYBA3QVuA4q8hCHrDcafR1ul65jewfuovsCl7vJrNlOuEbdo6JFCuwCrtb9hqusBu56Cw4cI1y1briIWEBn3Ue0XKPuMdGiBg4H9NdV0HJ/6QZLOEPmPN0GmpfSPS5arIBdwHUtIFfoBsl/ZsgfhHCfFi2WwC5goO4AmvanbqBkzJA76tboZokWa2AXMEi3RTdAvDLkDqJFAhzB32xFD2wZsGXA0WfAlgFbBmwZsGXAlgFbBpzk04JaKb0iA9ZnF9x5SQAFtRKKIgPWZxfaeRmwAZ/BGbAB37eaG6MCbnq2Aed5czYyKirgpmcbsAHHZAZswN0Wwo7KeG1fFf2jAm56dtzOQ42yB+65mDhWFBUwUETMUiMDNmADbp/APRaTAh6I2bpGCNw1bufRZJQ1cPdF/NueHZsgDEBBGLbMGoIu4AZu5gLOZeEaYmEXeznF3jRPyEv4frgJvvJe3qTefY0AAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwb8rwADBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgz4/sz1Nia/9hizA7zgklwy3RYwYMBzBRjw4bPjxAbAAizAAtwgwAIswAIswAIMGDBgARZgARZgAS4FWIAFWIAFWIABAwYswAIswAIswIUAC7AAC7AACzBgwIAFWIAFWIAFuBBgARZgARZgAQYMGPApQ99ZCdgWtzqwATbABtgAG2DbnxNb7zbRimsMLMACrDf2wMWI/WasfQAAAABJRU5ErkJggg==); margin-top: -0.3em; -webkit-background-size: auto 100%; background-size: auto 100%; } .ath-ios6 .ath-action-icon { width: 1.8em; height: 1.8em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAB0CAQAAADAmnOnAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAWwEAAFsBAXkZiFwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAF4klEQVR4Ae3a/a+XdR3H8ec5HM45HDmKICoVohkZsxESRRCzcZM/2JKkdGR5MrSkleA0Pd00O4u5IVuNM2yYc6XSzCExU4oUNRPCJFdMUAhsYZpUGhscOHA4N8/WZzsL6HBxvofvdV3fa3yer//gsV3vH659KHzncBsJxUYhDzOEhCKQbORs+ip2wzgM+wvj+P9i35qAGLaHGcQSgKSTrxBLABJppZpYApCspoFYApBsZjSxBCD5OxOJJQBJG1cQSwCSLpqJJQCJ3MvgCGTinuSMCJS8LZwfgZL3FtMiUPIOcU0ESl4PLRHoRPsJtREoeRsYGYGS9yrvo6RmpbLaigWSfzOdErLs6+bLUMFA0sF1+QF1cz1UNlBYK9V5AHXyWSgEkKyiIWOgGh829Ki1lLcaxjCVK7mJRSxjBY+zgRf/u9pXcMB7jhEZAg32EUP3O6hMKOP5Iq2sZQeHMZXt5KKMgOpcY+iHVnFyjeQKlrCBdsxge5ieAVC9vzLUelI8H+A7bKIHM10H81IGGuKvDf1ggDxVTKOV1zG3/Yia1ICG+ltD32MgNTKfP2HuW0VDKkCNrjfUTOm9i6XswwrZJkaVHeh0f2fodkrtfO6jAytqrzG+rEDDfVG1x1sprZEs5RBW4PZxeT+Bbrf5hPu9arfzKaU6WjiAFbseWvoF1GW/6vYGSmkyW7Dit4xB5QHq9Br6Xx2t9GAhtp6zkoHsfNp1J9wX6H+jeR4LtJc4LxGopZZyNpN/YcG2mw9nBTSPLizgOmjKAujGgvJID3ekD7QYi7nGzkvmQtpA38Vi7iJf0TedlC7QTVjMfcY2QyvSBPpUMW/PIBfbo9pls1XpAX2EdizeznStob3OJpQO0DB2YfE21q2GtnghpAm0Gou3T9tm6BGHQppA12HRVt17eboNlydNoLHsx2JtmL801OYcQmkC/QKLtQt9ydBW3wNpA30ci7Ur3WdolUMhbaBqNhf/8qQJ9Hkszs5wjaH9XkUobaAqtmFRdoGbDb3sWMgG6DIs5852knO82RaXer+P+qyb3eWeo7ZNBrRZvm1otY2QFdBjeHIb6hTne49Put12+9ObMoDdYmfy5UkF6AK6cCCr9aM2u9IddptcOYCG+FNDB5xLKCugO7G01TndFp/xgAntdYvrfdwVLnORt3q9Vx25F27DUjbGPxr6qxMgW6Cd2N+d6wLXedA+6nKbK73Lr/pJxzusvE/wZrvX0FOOgGyBxmF/dprXutYOj6nNdS6xyYnWp/dGcaGdhr5vDWQN9E1MXrUzfcA2j2qPj/l1J1uT9iPOeh8w1O7nCGUN9HzyGZ7ndo9qp0ucanU2r1xH+wdDu5wIeQDVVx0+/kd1i697RNv8thdn+Qz4Uv9p6DeOhHyApmBfq3OBu+3Nfd7nVELZAX3Nw4ZarYG8gG7GY1dlk6/Zm3/2Rk8jlB1QvT82dNAmQjkBVf8Mj957fdrefM7ZVhPKEuidvmDob06CXIGGbsX/bZDf8KAhfdbJhLIGmuZuQ084HHIGatiLvRvrRkP6qldbBXkAzbfD0N0OhryBGqrEMOd50FC7d1hPKGugBh8ydMh5hPIGGouI1d5lj6F1vptQ9kDvcKOhN5wMlQH0QcRGnzC03yZCeQDN9G1D6xwBFQI07FI8x02GdjgB8gJqttPQcmuhYoAumzvG7YZWejrkA1TrPYYO+SVCFQO0aM4bqj0uJJQH0LluSP7PkyeQU9QOmyAvoBm+Zegpz4LKA/qYB/wE5AXUe3m81zqoRKAPOYWcuvP9dxvqcD6h7IAKkaNU3eUlHLcI9EzS5YlAi62h/zUy89QCqqKUmvgHywsJlEHnsQYxAvXVIJo5gIhnPhiBju1iNmLvLn85Ah1ZPYs5jBGo72awEzEC9dVwHqQHI9DxWoAYgSLQQKteGIESu/qhCJTYtT+PQBEoAkWgCBSBkotAEehUWwSKQBEoAkWg/BeBIlAEikARKAJFoFmealu4gVLy1Gt5dkARKAL9BzujPSurTmu/AAAAAElFTkSuQmCC); margin-bottom: 0.4em; -webkit-background-size: 100% auto; background-size: 100% auto; } .ath-android .ath-action-icon { width: 1.4em; height: 1.4em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVmZmb///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZW6fJrAAAAEXRSTlMAAAYHG21ub8fLz9DR8/T4+RrZ9owAAAB3SURBVHja7dNLDoAgDATQWv4gKve/rEajJOJiWLgg6WzpSyB0aHqHiNj6nL1lovb4C+hYzkSNAT7mryQFAVOeGAj4CjwEtgrWXpD/uZKtwEJApXt+Vn0flzRhgNiFZQkOXY0aADQZCOCPlsZJ46Rx0jhp3IiN2wGDHhxtldrlwQAAAABJRU5ErkJggg==); -webkit-background-size: 100% auto; background-size: 100% auto; } .ath-container p { margin: 0; padding: 0; position: relative; z-index: 2147483642; text-shadow: 0 0.1em 0 #fff; font-size: 1.1em; } .ath-ios.ath-phone:after { content: ''; background: #eee; position: absolute; width: 2em; height: 2em; bottom: -0.9em; left: 50%; margin-left: -1em; -webkit-transform: scaleX(0.9) rotate(45deg); -ms-transform: scaleX(0.9) rotate(45deg); transform: scaleX(0.9) rotate(45deg); -webkit-box-shadow: 0.2em 0.2em 0 #d1d1d1; box-shadow: 0.2em 0.2em 0 #d1d1d1; } .ath-ios.ath-tablet:after { content: ''; background: #eee; position: absolute; width: 2em; height: 2em; top: -0.9em; left: 50%; margin-left: -1em; -webkit-transform: scaleX(0.9) rotate(45deg); -ms-transform: scaleX(0.9) rotate(45deg); transform: scaleX(0.9) rotate(45deg); z-index: 2147483641; } .ath-application-icon { position: relative; padding: 0; border: 0; margin: 0 auto 0.2em auto; height: 6em; width: 6em; z-index: 2147483642; } .ath-container.ath-ios .ath-application-icon { border-radius: 1em; -webkit-box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5); box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5); margin: 0 auto 0.4em auto; } @media only screen and (orientation: landscape) { .ath-container.ath-phone { width: 24em; } .ath-android.ath-phone { margin-left: -12em; } .ath-ios.ath-phone { margin-left: -12em; } .ath-ios6:after { left: 39%; } .ath-ios8.ath-phone { left: auto; bottom: auto; right: 0.4em; top: 1.8em; } .ath-ios8.ath-phone:after { bottom: auto; top: -0.9em; left: 68%; z-index: 2147483641; -webkit-box-shadow: none; box-shadow: none; } } /* ========================================================================== Component: uCheck Plugin ============================================================================ */ .am-checkbox, .am-radio, .am-checkbox-inline, .am-radio-inline { padding-left: 22px; position: relative; -webkit-transition: color .25s linear; transition: color .25s linear; font-size: 14px; line-height: 1.5; } label.am-checkbox, label.am-radio { font-weight: normal; } .am-ucheck-icons { color: #999999; display: block; height: 20px; top: 0; left: 0; position: absolute; width: 20px; text-align: center; line-height: 21px; font-size: 18px; cursor: pointer; } .am-checkbox .am-icon-checked, .am-radio .am-icon-checked, .am-checkbox-inline .am-icon-checked, .am-radio-inline .am-icon-checked, .am-checkbox .am-icon-unchecked, .am-radio .am-icon-unchecked, .am-checkbox-inline .am-icon-unchecked, .am-radio-inline .am-icon-unchecked { position: absolute; left: 0; top: 0; display: inline-table; margin: 0; background-color: transparent; -webkit-transition: color .25s linear; transition: color .25s linear; } .am-checkbox .am-icon-checked:before, .am-radio .am-icon-checked:before, .am-checkbox-inline .am-icon-checked:before, .am-radio-inline .am-icon-checked:before, .am-checkbox .am-icon-unchecked:before, .am-radio .am-icon-unchecked:before, .am-checkbox-inline .am-icon-unchecked:before, .am-radio-inline .am-icon-unchecked:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-checkbox .am-icon-checked, .am-radio .am-icon-checked, .am-checkbox-inline .am-icon-checked, .am-radio-inline .am-icon-checked { opacity: 0; } .am-checkbox .am-icon-checked:before, .am-checkbox-inline .am-icon-checked:before { content: "\f046"; } .am-checkbox .am-icon-unchecked:before, .am-checkbox-inline .am-icon-unchecked:before { content: "\f096"; } .am-radio .am-icon-checked:before, .am-radio-inline .am-icon-checked:before { content: "\f192"; } .am-radio .am-icon-unchecked:before, .am-radio-inline .am-icon-unchecked:before { content: "\f10c"; } .am-ucheck-checkbox, .am-ucheck-radio { position: absolute; left: 0; top: 0; margin: 0; padding: 0; width: 20px; height: 20px; opacity: 0; outline: none !important; } .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #0e90d2; } .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-ucheck-radio:checked + .am-ucheck-icons { color: #0e90d2; } .am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-unchecked, .am-ucheck-radio:checked + .am-ucheck-icons .am-icon-unchecked { opacity: 0; } .am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-checked, .am-ucheck-radio:checked + .am-ucheck-icons .am-icon-checked { opacity: 1; } .am-ucheck-checkbox:disabled + .am-ucheck-icons, .am-ucheck-radio:disabled + .am-ucheck-icons { cursor: default; color: #d8d8d8; } .am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-unchecked, .am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-unchecked { opacity: 0; } .am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-checked, .am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-checked { opacity: 1; color: #d8d8d8; } .am-checkbox.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #3bb4f2; } .am-checkbox.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons { color: #3bb4f2; } .am-checkbox.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #5eb95e; } .am-checkbox.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-success .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-success .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons { color: #5eb95e; } .am-checkbox.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #F37B1D; } .am-checkbox.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-warning .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons { color: #F37B1D; } .am-checkbox.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #dd514c; } .am-checkbox.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-danger .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons { color: #dd514c; } .am-field-error + .am-ucheck-icons { color: #dd514c; } .am-field-valid + .am-ucheck-icons { color: #5eb95e; } /* // Group Addon .@{ns}input-group-label { .@{ns}radio, .@{ns}checkbox { margin: -2px 0; padding-left: 15px; } } // Form inline style .@{ns}form-inline .@{ns}checkbox, .@{ns}form-inline .@{ns}radio { padding-left: 24px; } */ /* ========================================================================== Component: Selected Plugin ============================================================================ */ .am-selected { width: 200px; } .am-selected-btn { width: 100%; padding-left: 10px; text-align: right; } .am-selected-btn.am-btn-default { background: none; } .am-invalid .am-selected-btn { border-color: #dd514c; } .am-selected-header { height: 45px; background-color: #f2f2f2; border-bottom: 1px solid #ddd; display: none; } .am-selected-status { text-align: left; width: 100%; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-selected-content { padding: 10px 0; } .am-selected-search { padding: 0 10px 10px; } .am-selected-search .am-form-field { padding: .5em; } .am-selected-list { margin: 0; padding: 0; list-style: none; font-size: 1.5rem; } .am-selected-list li { position: relative; cursor: pointer; padding: 5px 10px; -webkit-transition: background-color 0.15s; transition: background-color 0.15s; } .am-selected-list li:hover { background-color: #f8f8f8; } .am-selected-list li:hover .am-icon-check { opacity: .6; } .am-selected-list li.am-checked .am-icon-check { opacity: 1; color: #0e90d2; } .am-selected-list li.am-disabled { opacity: .5; pointer-events: none; cursor: not-allowed; } .am-selected-list .am-selected-list-header { margin-top: 8px; font-size: 1.3rem; color: #999999; border-bottom: 1px solid #e5e5e5; cursor: default; } .am-selected-list .am-selected-list-header:hover { background: none; } .am-selected-list .am-selected-list-header:first-child { margin-top: 0; } .am-selected-list .am-selected-text { display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; margin-right: 30px; } .am-selected-list .am-icon-check { position: absolute; right: 8px; top: 5px; color: #999999; opacity: 0; -webkit-transition: opacity .15s; transition: opacity .15s; } .am-selected-hint { line-height: 1.2; color: #dd514c; } .am-selected-hint:not(:empty) { margin-top: 10px; border-top: 1px solid #e5e5e5; padding: 10px 10px 0; } .am-selected-placeholder { opacity: .65; } /* ========================================================================== Component: JS Plugins helpers ============================================================================ */ .am-fade { opacity: 0; -webkit-transition: opacity .2s linear; transition: opacity .2s linear; } .am-fade.am-in { opacity: 1; } .am-collapse { display: none; } .am-collapse.am-in { display: block; } tr.am-collapse.am-in { display: table-row; } tbody.am-collapse.am-in { display: table-row-group; } .am-collapsing { position: relative; height: 0; overflow: hidden; -webkit-transition: height .3s ease; transition: height .3s ease; } .am-sticky { position: fixed !important; z-index: 1010; -webkit-transform-origin: 0 0; -ms-transform-origin: 0 0; transform-origin: 0 0; } [data-am-sticky][class*="am-animation-"] { -webkit-animation-duration: .2s; animation-duration: .2s; } .am-dimmer-active { overflow: hidden; } .am-dimmer { position: fixed; top: 0; right: 0; bottom: 0; left: 0; display: none; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); z-index: 1100; opacity: 0; } .am-dimmer.am-active { opacity: 1; } [data-am-collapse] { cursor: pointer; } .am-datepicker { top: 0; left: 0; border-radius: 0; background: #fff; -webkit-box-shadow: 0 0 10px #ccc; box-shadow: 0 0 10px #ccc; padding-bottom: 10px; margin-top: 10px; width: 238px; color: #555; display: none; } .am-datepicker > div { display: none; } .am-datepicker table { width: 100%; } .am-datepicker tr.am-datepicker-header { font-size: 1.6rem; color: #fff; background: #3bb4f2; } .am-datepicker td, .am-datepicker th { text-align: center; font-weight: normal; cursor: pointer; } .am-datepicker th { height: 48px; } .am-datepicker td { font-size: 1.4rem; } .am-datepicker td.am-datepicker-day { height: 34px; width: 34px; } .am-datepicker td.am-datepicker-day:hover { background: #F0F0F0; height: 34px; width: 34px; } .am-datepicker td.am-datepicker-day.am-disabled { cursor: no-drop; color: #999; background: #fafafa; } .am-datepicker td.am-datepicker-old, .am-datepicker td.am-datepicker-new { color: #89d7ff; } .am-datepicker td.am-active, .am-datepicker td.am-active:hover { border-radius: 0; color: #0084c7; background: #F0F0F0; } .am-datepicker td span { display: block; width: 79.33333333px; height: 40px; line-height: 40px; float: left; cursor: pointer; } .am-datepicker td span:hover { background: #F0F0F0; } .am-datepicker td span.am-active { color: #0084c7; background: #F0F0F0; } .am-datepicker td span.am-disabled { cursor: no-drop; color: #999; background: #fafafa; } .am-datepicker td span.am-datepicker-old { color: #89d7ff; } .am-datepicker .am-datepicker-dow { height: 40px; color: #0c80ba; } .am-datepicker-caret { display: block!important; display: inline-block; width: 0; height: 0; vertical-align: middle; border-bottom: 7px solid #3bb4f2; border-right: 7px solid transparent; border-left: 7px solid transparent; border-top: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); position: absolute; top: -7px; left: 6px; } .am-datepicker-right .am-datepicker-caret { left: auto; right: 7px; } .am-datepicker-up .am-datepicker-caret { top: auto; bottom: -7px; display: inline-block; width: 0; height: 0; vertical-align: middle; border-top: 7px solid #fff; border-right: 7px solid transparent; border-left: 7px solid transparent; border-bottom: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } .am-datepicker-select { height: 34px; line-height: 34px; text-align: center; -webkit-transition: background-color 300ms ease-out; transition: background-color 300ms ease-out; } .am-datepicker-select:hover { background: rgba(154, 217, 248, 0.5); color: #0c80ba; } .am-datepicker-prev, .am-datepicker-next { width: 34px; height: 34px; } .am-datepicker-prev-icon, .am-datepicker-next-icon { width: 34px; height: 34px; line-height: 34px; display: inline-block; -webkit-transition: background-color 300ms ease-out; transition: background-color 300ms ease-out; } .am-datepicker-prev-icon:hover, .am-datepicker-next-icon:hover { background: rgba(154, 217, 248, 0.5); color: #0c80ba; } .am-datepicker-prev-icon:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; } .am-datepicker-next-icon:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f054"; } .am-datepicker-dropdown { position: absolute; z-index: 1120; } @media only screen and (max-width: 640px) { .am-datepicker { width: 100%; } .am-datepicker td span { width: 33.33%; } .am-datepicker-caret { display: none!important; } .am-datepicker-prev, .am-datepicker-next { width: 44px; height: 44px; } } .am-datepicker-success tr.am-datepicker-header { background: #5eb95e; } .am-datepicker-success td.am-datepicker-day.am-disabled { color: #999; } .am-datepicker-success td.am-datepicker-old, .am-datepicker-success td.am-datepicker-new { color: #94df94; } .am-datepicker-success td.am-active, .am-datepicker-success td.am-active:hover { color: #1b961b; } .am-datepicker-success td span.am-datepicker-old { color: #94df94; } .am-datepicker-success td span.am-active { color: #1b961b; } .am-datepicker-success .am-datepicker-caret { border-bottom-color: #5eb95e; } .am-datepicker-success .am-datepicker-dow { color: #367b36; } .am-datepicker-success .am-datepicker-select:hover, .am-datepicker-success .am-datepicker-prev-icon:hover, .am-datepicker-success .am-datepicker-next-icon:hover { background: rgba(165, 216, 165, 0.5); color: #367b36; } .am-datepicker-danger tr.am-datepicker-header { background: #dd514c; } .am-datepicker-danger td.am-datepicker-day.am-disabled { color: #999; } .am-datepicker-danger td.am-datepicker-old, .am-datepicker-danger td.am-datepicker-new { color: #f59490; } .am-datepicker-danger td.am-active, .am-datepicker-danger td.am-active:hover { color: #c10802; } .am-datepicker-danger td span.am-datepicker-old { color: #f59490; } .am-datepicker-danger td span.am-active { color: #c10802; } .am-datepicker-danger .am-datepicker-caret { border-bottom-color: #dd514c; } .am-datepicker-danger .am-datepicker-dow { color: #a4241f; } .am-datepicker-danger .am-datepicker-select:hover, .am-datepicker-danger .am-datepicker-prev-icon:hover, .am-datepicker-danger .am-datepicker-next-icon:hover { background: rgba(237, 164, 162, 0.5); color: #a4241f; } .am-datepicker-warning tr.am-datepicker-header { background: #F37B1D; } .am-datepicker-warning td.am-datepicker-day.am-disabled { color: #999; } .am-datepicker-warning td.am-datepicker-old, .am-datepicker-warning td.am-datepicker-new { color: #ffad6d; } .am-datepicker-warning td.am-active, .am-datepicker-warning td.am-active:hover { color: #aa4b00; } .am-datepicker-warning td span.am-datepicker-old { color: #ffad6d; } .am-datepicker-warning td span.am-active { color: #aa4b00; } .am-datepicker-warning .am-datepicker-caret { border-bottom-color: #F37B1D; } .am-datepicker-warning .am-datepicker-dow { color: #a14c09; } .am-datepicker-warning .am-datepicker-select:hover, .am-datepicker-warning .am-datepicker-prev-icon:hover, .am-datepicker-warning .am-datepicker-next-icon:hover { background: rgba(248, 180, 126, 0.5); color: #a14c09; } .am-datepicker > div { display: block; } .am-datepicker > div span.am-datepicker-hour { width: 59.5px; } .am-datepicker-date { display: block; } .am-datepicker-date.am-input-group { display: table; } .am-datepicker-time-box { padding: 30px 0 30px 0; } .am-datepicker-time-box strong { font-size: 5.2rem; display: inline-block; height: 70px; width: 70px; line-height: 70px; font-weight: normal; } .am-datepicker-time-box strong:hover { border-radius: 4px; background: #ECECEC; } .am-datepicker-time-box em { display: inline-block; height: 70px; width: 20px; line-height: 70px; font-size: 5.2rem; font-style: normal; } .am-datepicker-toggle { text-align: center; cursor: pointer; padding: 10px 0; } .am-datepicker-toggle:hover { background: #f0f0f0; } /* ========================================================================== Component: Print ============================================================================ */ @media print { *, *:before, *:after { background: transparent !important; color: #000 !important; /* Black prints faster: h5bp.com/s */ -webkit-box-shadow: none !important; box-shadow: none !important; text-shadow: none !important; } a, a:visited { text-decoration: underline; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " [" attr(title) "] "; } /** * Don't show links that are fragment identifiers, * or use the `javascript:` pseudo protocol */ a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; /* h5bp.com/t */ } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } @page { margin: 0.5cm; } select { background: #fff !important; } .am-topbar { display: none; } .am-table td, .am-table th { background-color: #fff !important; } .am-table { border-collapse: collapse !important; } .am-table-bordered th, .am-table-bordered td { border: 1px solid #ddd !important; } } /* print helper classes */ .am-print-block { display: none !important; } @media print { .am-print-block { display: block !important; } } .am-print-inline { display: none !important; } @media print { .am-print-inline { display: inline !important; } } .am-print-inline-block { display: none !important; } @media print { .am-print-inline-block { display: inline-block !important; } } @media print { .am-print-hide { display: none !important; } } .lte9 #nprogress .nprogress-spinner { display: none !important; } .lte8 .am-dimmer { background-color: #000; filter: alpha(opacity=60); } .lte8 .am-modal-actions { display: none; } .lte8 .am-modal-actions.am-modal-active { display: block; } .lte8 .am-offcanvas.am-active { background: #000; } .lte8 .am-popover .am-popover-caret { border: 8px solid transparent; } .lte8 .am-popover-top .am-popover-caret { border-top: 8px solid #333333; border-bottom: none; } .lte8 .am-popover-left .am-popover-caret { right: -8px; margin-top: -6px; border-left: 8px solid #333333; border-right: none; } .lte8 .am-popover-right .am-popover-caret { left: -8px; margin-top: -6px; border-right: 8px solid #333333; border-left: none; } .am-accordion-item { margin: 0; } .am-accordion-title { font-weight: normal; cursor: pointer; } .am-accordion-item.am-disabled .am-accordion-title { cursor: default; pointer-events: none; } .am-accordion-bd { margin: 0 !important; padding: 0 !important; border: none !important; } .am-accordion-content { margin-top: 0; padding: 0.8rem 1rem 1.2rem; font-size: 1.4rem; } /** * Accordion Theme: default * Author: Minwe (minwe@yunshipei.com) */ .am-accordion-default { margin: 1rem; border-radius: 2px; -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); } .am-accordion-default .am-accordion-item { border-top: 1px solid rgba(0, 0, 0, 0.05); } .am-accordion-default .am-accordion-item:first-child { border-top: none; } .am-accordion-default .am-accordion-title { color: rgba(0, 0, 0, 0.6); -webkit-transition: background-color 0.2s ease-out; transition: background-color 0.2s ease-out; padding: .8rem 1rem; } .am-accordion-default .am-accordion-title:before { content: "\f0da"; display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); -webkit-transition: -webkit-transform .2s ease; transition: -webkit-transform .2s ease; transition: transform .2s ease; transition: transform .2s ease, -webkit-transform .2s ease; -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); margin-right: 5px; } .am-accordion-default .am-accordion-title:hover { color: #0e90d2; } .am-accordion-default .am-accordion-content { color: #666; } .am-accordion-default .am-active .am-accordion-title { background-color: #eeeeee; color: #0e90d2; } .am-accordion-default .am-active .am-accordion-title:before { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } /** * Accordion Theme: basic * Author: Minwe (minwe@yunshipei.com) */ .am-accordion-basic { margin: 1rem; } .am-accordion-basic .am-accordion-title { color: #333333; -webkit-transition: background-color 0.2s ease-out; transition: background-color 0.2s ease-out; padding: .8rem 0 0; } .am-accordion-basic .am-accordion-title:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f0da"; -webkit-transition: -webkit-transform .2s ease; transition: -webkit-transform .2s ease; transition: transform .2s ease; transition: transform .2s ease, -webkit-transform .2s ease; -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); margin-right: .5rem; } .am-accordion-basic .am-accordion-content { color: #666; } .am-accordion-basic .am-active .am-accordion-title { color: #0e90d2; } .am-accordion-basic .am-active .am-accordion-title:before { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } /** * Accordion Theme: gapped * Author: Minwe (minwe@yunshipei.com) */ .am-accordion-gapped { margin: .5rem 1rem; } .am-accordion-gapped .am-accordion-item { border: 1px solid #dedede; border-bottom: none; margin: .5rem 0; } .am-accordion-gapped .am-accordion-item.am-active { border-bottom: 1px solid #dedede; } .am-accordion-gapped .am-accordion-title { color: rgba(0, 0, 0, 0.6); -webkit-transition: background-color 0.15s ease-out; transition: background-color 0.15s ease-out; border-bottom: 1px solid #dedede; padding: 0.8rem 2rem 0.8rem 1rem; position: relative; } .am-accordion-gapped .am-accordion-title:after { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f105"; -webkit-transition: -webkit-transform .2s linear; transition: -webkit-transform .2s linear; transition: transform .2s linear; transition: transform .2s linear, -webkit-transform .2s linear; position: absolute; right: 10px; top: 50%; margin-top: -0.8rem; } .am-accordion-gapped .am-accordion-title:hover { color: rgba(0, 0, 0, 0.8); } .am-accordion-gapped .am-accordion-content { color: #666; } .am-accordion-gapped .am-active .am-accordion-title { background-color: #f5f5f5; color: rgba(0, 0, 0, 0.8); } .am-accordion-gapped .am-active .am-accordion-title:after { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .am-divider { height: 0; margin: 1.5rem auto; overflow: hidden; clear: both; } /** * Divider Theme: default */ .am-divider-default { border-top: 1px solid #ddd; } /** * Divider Theme: dotted */ .am-divider-dotted { border-top: 1px dotted #ccc; } /** * Divider Theme: dashed */ .am-divider-dashed { border-top: 1px dashed #ccc; } .am-figure-zoomable { position: relative; cursor: pointer; } .am-figure-zoomable:after { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f00e"; position: absolute; top: 1rem; right: 1rem; color: #999999; font-size: 1.6rem; -webkit-transition: all 0.2s; transition: all 0.2s; pointer-events: none; } .am-figure-zoomable:hover:after { color: #eeeeee; } .am-figure-default { margin: 10px; } .am-figure-default img { display: block; max-width: 100%; height: auto; padding: 2px; border: 1px solid #eeeeee; margin: 10px auto; } .am-figure-default figcaption { text-align: center; font-size: 1.4rem; margin-bottom: 15px; color: #333333; } .am-footer { text-align: center; padding: 1em 0; font-size: 1.6rem; } .am-footer .am-switch-mode-ysp { cursor: pointer; } .am-footer .am-footer-text { margin-top: 10px; font-size: 14px; } .am-footer .am-footer-text-left { text-align: left; padding-left: 10px; } .am-modal-footer-hd { padding-bottom: 10px; } /** * Footer Theme: default */ .am-footer-default { background-color: #fff; } .am-footer-default a { color: #555555; } .am-footer-default .am-footer-switch { margin-bottom: 10px; font-weight: bold; } .am-footer-default .am-footer-ysp { color: #555555; cursor: pointer; } .am-footer-default .am-footer-divider { color: #ccc; } .am-footer-default .am-footer-desktop { color: #0e90d2; } .am-footer-default .am-footer-miscs { color: #999999; font-size: 13px; } .am-footer-default .am-footer-miscs p { margin: 5px 0; } @media only screen and (min-width:641px) { .am-footer-default .am-footer-miscs p { display: inline-block; margin: 5px; } } .am-gallery { padding: 5px 5px 0 5px; list-style: none; } .am-gallery h3 { margin: 0; } [data-am-gallery*='pureview'] img { cursor: pointer; } /** * Gallery Theme: default * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-default > li { padding: 5px; } .am-gallery-default .am-gallery-item img { width: 100%; height: auto; } .am-gallery-default .am-gallery-title { margin-top: 10px; font-weight: normal; font-size: 1.4rem; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; color: #555555; } .am-gallery-default .am-gallery-desc { color: #999999; font-size: 1.2rem; } /** * Gallery Theme: overlay * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-overlay > li { padding: 5px; } .am-gallery-overlay .am-gallery-item { position: relative; } .am-gallery-overlay .am-gallery-item img { width: 100%; height: auto; } .am-gallery-overlay .am-gallery-title { font-weight: normal; font-size: 1.4rem; color: #FFF; position: absolute; bottom: 0; width: 100%; background-color: rgba(0, 0, 0, 0.5); text-indent: 5px; height: 30px; line-height: 30px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-gallery-overlay .am-gallery-desc { display: none; } /** * Accordion Theme: bordered * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-bordered > li { padding: 5px; } .am-gallery-bordered .am-gallery-item { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); padding: 5px; } .am-gallery-bordered .am-gallery-item img { width: 100%; height: auto; } .am-gallery-bordered .am-gallery-title { margin-top: 10px; font-weight: normal; font-size: 1.4rem; color: #555555; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-gallery-bordered .am-gallery-desc { color: #999999; font-size: 1.2rem; } /** * Gallery Theme: imgbordered * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-imgbordered > li { padding: 5px; } .am-gallery-imgbordered .am-gallery-item img { width: 100%; height: auto; border: 3px solid #FFF; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); } .am-gallery-imgbordered .am-gallery-title { margin-top: 10px; font-weight: normal; font-size: 1.4rem; color: #555555; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-gallery-imgbordered .am-gallery-desc { color: #999999; font-size: 1.2rem; } .am-gotop a { display: inline-block; text-decoration: none; } /** * Gotop Theme: default */ .am-gotop-default { text-align: center; margin: 10px 0; } .am-gotop-default a { background-color: #0e90d2; padding: .5em 1.5em; border-radius: 0; color: #fff; } .am-gotop-default a img { display: none; } /** * Gotop Theme: fixed */ .am-gotop-fixed { position: fixed; right: 10px; bottom: 10px; z-index: 1010; opacity: 0; width: 32px; min-height: 32px; overflow: hidden; border-radius: 0; text-align: center; } .am-gotop-fixed.am-active { opacity: .9; } .am-gotop-fixed.am-active:hover { opacity: 1; } .am-gotop-fixed a { display: block; } .am-gotop-fixed .am-gotop-title { display: none; } .am-gotop-fixed .am-gotop-icon-custom { display: inline-block; max-width: 30px; vertical-align: middle; } .am-gotop-fixed .am-gotop-icon { width: 100%; line-height: 32px; background-color: #555555; vertical-align: middle; color: #ddd; } .am-gotop-fixed .am-gotop-icon:hover { color: #fff; } .am-with-fixed-navbar .am-gotop-fixed { bottom: 60px; } .am-header { position: relative; width: 100%; height: 49px; line-height: 49px; padding: 0 10px; } .am-header h1 { margin-top: 0; margin-bottom: 0; } .am-header .am-header-title { margin: 0 30%; font-size: 2rem; font-weight: normal; text-align: center; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-header .am-header-title img { margin-top: 12px; height: 25px; vertical-align: top; } .am-header .am-header-nav { position: absolute; top: 0; } .am-header .am-header-nav img { height: 16px; width: auto; vertical-align: middle; } .am-header .am-header-left { left: 10px; } .am-header .am-header-right { right: 10px; } .am-header-fixed { position: fixed; top: 0; left: 0; right: 0; width: 100%; z-index: 1010; } .am-with-fixed-header { padding-top: 49px; } /** * Header Theme: default */ .am-header-default { background-color: #0e90d2; } .am-header-default .am-header-title { color: #fff; } .am-header-default .am-header-title a { color: #fff; } .am-header-default .am-header-icon { font-size: 20px; } .am-header-default .am-header-nav { color: #eeeeee; } .am-header-default .am-header-nav > a { display: inline-block; min-width: 36px; text-align: center; color: #eeeeee; } .am-header-default .am-header-nav > a + a { margin-left: 5px; } .am-header-default .am-header-nav .am-btn { margin-top: 9px; height: 31px; padding: 0 0.5em; line-height: 30px; font-size: 14px; vertical-align: top; } .am-header-default .am-header-nav .am-btn .am-header-icon { font-size: inherit; } .am-header-default .am-header-nav .am-btn-default { color: #999999; } .am-header-default .am-header-nav-title, .am-header-default .am-header-nav-title + .am-header-icon { font-size: 14px; } .am-intro { position: relative; } .am-intro img { max-width: 100%; } .am-intro-hd { position: relative; height: 45px; line-height: 45px; } .am-intro-title { font-size: 18px; margin: 0; font-weight: bold; } .am-intro-more-top { position: absolute; right: 10px; top: 0; font-size: 1.4rem; } .am-intro-bd { padding-top: 15px; padding-bottom: 15px; font-size: 1.4rem; } .am-intro-bd p:last-child { margin-bottom: 0; } .am-intro-more-bottom { clear: both; text-align: center; } .am-intro-more-bottom .am-btn { font-size: 14px; } /** * Intro Theme: default */ .am-intro-default .am-intro-hd { background-color: #0e90d2; color: #fff; padding: 0 10px; } .am-intro-default .am-intro-hd a { color: #eee; } .am-intro-default .am-intro-right { padding-left: 0; } .am-list-news-hd { padding-top: 1.2rem; padding-bottom: 0.8rem; } .am-list-news-hd a { display: block; } .am-list-news-hd h2 { font-size: 1.6rem; float: left; margin: 0; height: 2rem; line-height: 2rem; } .am-list-news-hd h3 { margin: 0; } .am-list-news-hd .am-list-news-more { font-size: 1.3rem; height: 2rem; line-height: 2rem; } .am-list .am-list-item-dated a { padding-right: 80px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-list .am-list-item-dated a::after { display: none; } .am-list .am-list-item-desced a, .am-list .am-list-item-thumbed a { padding-right: 0; } .am-list-news .am-list-item-hd { margin: 0; } .am-list-date { position: absolute; right: 5px; font-size: 1.3rem; top: 1.3rem; } .am-list-item-desced { padding-bottom: 1rem; } .am-list-item-desced > a { padding: 1rem 0; } .am-list-item-desced .am-list-date { position: static; } .am-list-item-thumbed { padding-top: 1em; } .am-list-news-ft { text-align: center; } .am-list-news .am-titlebar { margin-left: 0; margin-right: 0; } .am-list-news .am-titlebar ~ .am-list-news-bd .am-list > li:first-child { border-top: none; } /** * list_news Theme: default */ .am-list-news-default { margin: 10px; } .am-list-news-default .am-g { margin-left: auto; margin-right: auto; } .am-list-news-default .am-list-item-hd { font-weight: normal; } .am-list-news-default .am-list-date { color: #999999; } .am-list-news-default .am-list > li { border-color: #dedede; } .am-list-news-default .am-list .am-list-item-desced { padding-top: 1rem; padding-bottom: 1rem; } .am-list-news-default .am-list .am-list-item-desced > a { padding: 0; } .am-list-news-default .am-list .am-list-item-desced .am-list-item-text { margin-top: 0.5rem; color: #757575; } .am-list-news-default .am-list .am-list-item-text { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; line-height: 1.3em; -webkit-line-clamp: 2; /* number of lines to show */ max-height: 2.6em; } .am-list-news-default .am-list .am-list-item-thumb-top .am-list-thumb { padding: 0; margin-bottom: 0.8rem; } .am-list-news-default .am-list .am-list-item-thumb-top .am-list-main { padding: 0; } .am-list-news-default .am-list .am-list-item-thumb-left .am-list-thumb { padding-left: 0; } .am-list-news-default .am-list .am-list-item-desced .am-list-main { padding: 0; } .am-list-news-default .am-list .am-list-item-thumb-right .am-list-thumb { padding-right: 0; } .am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-item-hd { clear: both; padding-bottom: 0.5rem; } .am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-thumb { padding-left: 0; } .am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-item-hd { clear: both; padding-bottom: 0.5rem; } .am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-thumb { padding-right: 0; } .am-list-news-default .am-list .am-list-thumb img { width: 100%; display: block; } @media only screen and (max-width: 640px) { .am-list-news-default .am-list-item-thumb-left .am-list-thumb, .am-list-news-default .am-list-item-thumb-right .am-list-thumb { max-height: 80px; overflow: hidden; } .am-list-news-default .am-list-item-thumb-bottom-left .am-list-item-text, .am-list-news-default .am-list-item-thumb-bottom-right .am-list-item-text { -webkit-line-clamp: 3; /* number of lines to show */ max-height: 3.9em; } .am-list-news-default .am-list-item-thumb-bottom-left .am-list-thumb, .am-list-news-default .am-list-item-thumb-bottom-right .am-list-thumb { max-height: 60px; overflow: hidden; } } .am-map { width: 100%; height: 300px; } /** * Accordion Theme: default * Author: Hzp (hzp@yunshipei.com) */ .am-map-default #bd-map { width: 100%; height: 100%; overflow: hidden; margin: 0; font-size: 14px; line-height: 1.4!important; } .am-map-default .BMap_bubble_title { font-weight: bold; } .am-map-default #BMap_mask { width: 100%; } .am-mechat { margin: 1rem; } .am-mechat .section-cbox-wap .cbox-post-wap .post-action-wap .action-function-wap .function-list-wap .list-upload-wap .upload-mutual-wap { -webkit-box-sizing: content-box; box-sizing: content-box; } .am-menu { position: relative; padding: 0; margin: 0; } .am-menu ul { padding: 0; margin: 0; } .am-menu li { list-style: none; } .am-menu a:after, .am-menu a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-menu-sub { z-index: 1050; } .am-menu-toggle { display: none; z-index: 1015; } .am-menu-toggle img { display: inline-block; height: 16px; width: auto; vertical-align: middle; } .am-menu-nav a { display: block; padding: 0.8rem 0; -webkit-transition: all 0.45s; transition: all 0.45s; } /** * Menu Theme: default * Author: Minwe (minwe@yunshipei.com) */ .am-menu-default .am-menu-nav { padding-top: 8px; padding-bottom: 8px; } .am-menu-default .am-menu-nav a { text-align: center; height: 36px; line-height: 36px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; padding: 0; color: #0e90d2; } .am-menu-default .am-menu-nav > .am-parent > a { position: relative; -webkit-transition: .15s; transition: .15s; } .am-menu-default .am-menu-nav > .am-parent > a:after { content: "\f107"; margin-left: 5px; -webkit-transition: .15s; transition: .15s; } .am-menu-default .am-menu-nav > .am-parent > a:before { position: absolute; top: 100%; margin-top: -16px; left: 50%; margin-left: -12px; content: "\f0d8"; display: none; color: #f1f1f1; font-size: 24px; } .am-menu-default .am-menu-nav > .am-parent.am-open > a { color: #095f8a; } .am-menu-default .am-menu-nav > .am-parent.am-open > a:before { display: block; } .am-menu-default .am-menu-nav > .am-parent.am-open > a:after { -webkit-transform: rotate(-180deg); -ms-transform: rotate(-180deg); transform: rotate(-180deg); } .am-menu-default .am-menu-sub { position: absolute; left: 5px; right: 5px; background-color: #f1f1f1; border-radius: 0; padding-top: 8px; padding-bottom: 8px; } .am-menu-default .am-menu-sub > li > a { color: #555555; } @media only screen and (min-width:641px) { .am-menu-default .am-menu-nav li { width: auto; float: left; clear: none; display: inline; } .am-menu-default .am-menu-nav a { padding-left: 1.5rem; padding-right: .5rem; } } /** /** * Menu Theme: dropdown1 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-dropdown1 { position: relative; /*@media @medium-up { .am-menu-toggle { display: none!important; } .am-menu-nav { &.am-collapse { display: block; } .am-menu-sub { background-color: ;//@menu-sub-bg; display: block; & > li { clear: none; } } .am-menu-lv2 { & > li { clear: none; width: auto; } } } }*/ } .am-menu-dropdown1 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-dropdown1 a { -webkit-transition: all .4s; transition: all .4s; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-menu-dropdown1 .am-menu-nav { position: absolute; left: 0; right: 0; z-index: 1050; } .am-menu-dropdown1 .am-menu-nav a { padding: 0.8rem; } .am-menu-dropdown1 .am-menu-nav > li { width: 100%; } .am-menu-dropdown1 .am-menu-nav > li.am-parent > a { position: relative; } .am-menu-dropdown1 .am-menu-nav > li.am-parent > a::before { content: "\f067"; position: absolute; right: 1rem; top: 1.4rem; } .am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a { background-color: #0c80ba; border-bottom: none; color: #fff; } .am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:before { content: "\f068"; } .am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:after { content: ""; display: inline-block; width: 0; height: 0; vertical-align: middle; border-top: 8px solid #0c80ba; border-right: 8px solid transparent; border-left: 8px solid transparent; border-bottom: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); position: absolute; top: 100%; left: 50%; margin-left: -4px; } .am-menu-dropdown1 .am-menu-nav > li > a { border-bottom: 1px solid #0b76ac; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); background-color: #0e90d2; color: #fff; height: 49px; line-height: 49px; padding: 0; text-indent: 10px; } .am-menu-dropdown1 .am-menu-sub { background-color: #fff; } .am-menu-dropdown1 .am-menu-sub a { color: #555; height: 44px; line-height: 44px; text-indent: 5px; padding: 0; } .am-menu-dropdown1 .am-menu-sub a:before { content: "\f105"; color: #aaa; font-size: 16px; margin-right: 5px; } /** * Menu Theme: dropdown2 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-dropdown2 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-dropdown2 .am-menu-nav { position: absolute; left: 0; right: 0; background-color: #f5f5f5; -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); z-index: 1050; padding-top: 8px; padding-bottom: 8px; } .am-menu-dropdown2 .am-menu-nav a { height: 38px; line-height: 38px; padding: 0; text-align: center; } .am-menu-dropdown2 .am-menu-nav > li > a { color: #333333; } .am-menu-dropdown2 .am-menu-nav > li.am-parent > a { position: relative; } .am-menu-dropdown2 .am-menu-nav > li.am-parent > a:after { content: "\f107"; margin-left: 5px; -webkit-transition: -webkit-transform .2s; transition: -webkit-transform .2s; transition: transform .2s; transition: transform .2s, -webkit-transform .2s; } .am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a { position: relative; } .am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:after { color: #0e90d2; -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } .am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:before { position: absolute; top: 100%; margin-top: -16px; left: 50%; margin-left: -12px; font-size: 24px; content: "\f0d8"; color: rgba(0, 0, 0, 0.2); } .am-menu-dropdown2 .am-menu-sub { position: absolute; left: 5px; right: 5px; padding: 8px 0; border-radius: 2px; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); background-color: #fff; z-index: 1055; } .am-menu-dropdown2 .am-menu-sub a { padding: 0; height: 35px; color: #555555; line-height: 35px; } @media only screen and (min-width:641px) { .am-menu-dropdown2 .am-menu-toggle { display: none !important; } .am-menu-dropdown2 .am-menu-nav { position: static; display: block; } .am-menu-dropdown2 .am-menu-nav > li { float: none; width: auto; display: inline-block; } .am-menu-dropdown2 .am-menu-nav > li a { padding-left: 1.5rem; padding-right: 1.5rem; } .am-menu-dropdown2 .am-menu-sub { left: auto; right: auto; } .am-menu-dropdown2 .am-menu-sub > li { float: none; width: auto; } .am-menu-dropdown2 .am-menu-sub a { padding-left: 2rem; padding-right: 2rem; } } /** * Menu Theme: slide1 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-slide1 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-slide1 .am-menu-nav { background-color: #f5f5f5; padding-top: 8px; padding-bottom: 8px; } .am-menu-slide1 .am-menu-nav.am-in:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f0d8"; font-size: 24px; color: #f5f5f5; position: absolute; right: 16px; top: -16px; } .am-menu-slide1 .am-menu-nav a { line-height: 38px; height: 38px; display: block; padding: 0; text-align: center; } .am-menu-slide1 .am-menu-nav > li > a { color: #333333; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-menu-slide1 .am-menu-nav > .am-parent > a { position: relative; -webkit-transition: .15s; transition: .15s; } .am-menu-slide1 .am-menu-nav > .am-parent > a:after { content: "\f107"; margin-left: 5px; -webkit-transition: .15s; transition: .15s; } .am-menu-slide1 .am-menu-nav > .am-parent > a:before { position: absolute; top: 100%; margin-top: -16px; left: 50%; margin-left: -12px; content: "\f0d8"; display: none; color: #0e90d2; font-size: 24px; } .am-menu-slide1 .am-menu-nav > .am-parent.am-open > a { color: #0e90d2; } .am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:before { display: block; } .am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:after { -webkit-transform: rotate(-180deg); -ms-transform: rotate(-180deg); transform: rotate(-180deg); } .am-menu-slide1 .am-menu-sub { position: absolute; left: 5px; right: 5px; background-color: #0e90d2; border-radius: 0; padding-top: 8px; padding-bottom: 8px; } .am-menu-slide1 .am-menu-sub > li > a { color: #fff; } @media only screen and (min-width:641px) { .am-menu-slide1 .am-menu-toggle { display: none !important; } .am-menu-slide1 .am-menu-nav { background-color: #f5f5f5; display: block; } .am-menu-slide1 .am-menu-nav.am-in:before { display: none; } .am-menu-slide1 .am-menu-nav li { width: auto; clear: none; } .am-menu-slide1 .am-menu-nav li a { padding-left: 1.5rem; padding-right: 1.5rem; } } /** * Menu Theme: offcanvas1 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-offcanvas1 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-offcanvas1 .am-menu-nav { border-bottom: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); } .am-menu-offcanvas1 .am-menu-nav > li > a { height: 44px; line-height: 44px; text-indent: 15px; padding: 0; position: relative; color: #ccc; border-top: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); } .am-menu-offcanvas1 .am-menu-nav > .am-open > a, .am-menu-offcanvas1 .am-menu-nav > li > a:hover, .am-menu-offcanvas1 .am-menu-nav > li > a:focus { background-color: #474747; color: #fff; outline: none; } .am-menu-offcanvas1 .am-menu-nav > .am-active > a { background-color: #1a1a1a; color: #fff; } .am-menu-offcanvas1 .am-menu-nav > .am-parent > a { -webkit-transition: all .3s; transition: all .3s; } .am-menu-offcanvas1 .am-menu-nav > .am-parent > a:after { content: "\f104"; position: absolute; right: 1.5rem; top: 1.3rem; } .am-menu-offcanvas1 .am-menu-nav > .am-parent.am-open > a:after { content: "\f107"; } .am-menu-offcanvas1 .am-menu-sub { border-top: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); padding: 5px 0 5px 15px; background-color: #1a1a1a; font-size: 1.4rem; } .am-menu-offcanvas1 .am-menu-sub a { color: #eee; } .am-menu-offcanvas1 .am-menu-sub a:hover { color: #fff; } .am-menu-offcanvas1 .am-nav-divider { border-top: 1px solid #1a1a1a; } /** * Menu Theme: offcanvas2 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-offcanvas2 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-offcanvas2 .am-menu-nav { padding: 10px 5px; } .am-menu-offcanvas2 .am-menu-nav > li { padding: 5px; } .am-menu-offcanvas2 .am-menu-nav > li > a { -webkit-transition: all 0.3s; transition: all 0.3s; background-color: #404040; color: #ccc; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; border: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); height: 44px; line-height: 44px; padding: 0; text-align: center; } .am-menu-offcanvas2 .am-menu-nav > li > a:hover, .am-menu-offcanvas2 .am-menu-nav > li > a:focus { background-color: #262626; color: #fff; outline: none; } .am-menu-offcanvas2 .am-menu-nav > .am-active > a { background-color: #262626; color: #fff; } /** * Menu Theme: stack * Author: Minwe (minwe@yunshipei.com) */ .am-menu-stack .am-menu-nav { border-bottom: 1px solid #dedede; -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); } .am-menu-stack .am-menu-nav > .am-parent > a { -webkit-transition: all .3s; transition: all .3s; } .am-menu-stack .am-menu-nav > .am-parent > a:after { content: "\f105"; position: absolute; right: 1.5rem; top: 1.3rem; -webkit-transition: all .15s; transition: all .15s; } .am-menu-stack .am-menu-nav > .am-parent.am-open > a:after { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .am-menu-stack .am-menu-nav > li > a { position: relative; color: #333; background-color: #f5f5f5; border-top: 1px solid #dedede; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); height: 49px; line-height: 49px; text-indent: 10px; padding: 0; } .am-menu-stack .am-menu-nav > .am-open > a, .am-menu-stack .am-menu-nav > li > a:hover, .am-menu-stack .am-menu-nav > li > a:focus { background-color: #e5e5e5; color: #222; outline: none; } .am-menu-stack .am-menu-sub { padding: 0; font-size: 1.4rem; border-top: 1px solid #dedede; } .am-menu-stack .am-menu-sub a { border-bottom: 1px solid #dedede; padding-left: 2rem; color: #444; } .am-menu-stack .am-menu-sub a:hover { color: #333; } .am-menu-stack .am-menu-sub li:last-child a { border-bottom: none; } .am-menu-stack .am-menu-sub > li > a { height: 44px; line-height: 44px; text-indent: 15px; padding: 0; } @media only screen and (min-width:641px) { .am-menu-stack .am-menu-nav { background-color: #f5f5f5; } .am-menu-stack .am-menu-nav > li { float: left; width: auto; clear: none !important; display: inline-block; } .am-menu-stack .am-menu-nav > li a { padding-left: 1.5rem; padding-right: 1.5rem; } .am-menu-stack .am-menu-nav > li.am-parent > a:after { position: static; content: "\f107"; } .am-menu-stack .am-menu-nav > li.am-parent.am-open a { border-bottom: none; } .am-menu-stack .am-menu-nav > li.am-parent.am-open a:after { -webkit-transform: rotateX(-180deg); transform: rotateX(-180deg); } .am-menu-stack .am-menu-nav > li.am-parent.am-open .am-menu-sub { background-color: #e5e5e5; } .am-menu-stack .am-menu-sub { position: absolute; left: 0; right: 0; background-color: #ddd; border-top: none; } .am-menu-stack .am-menu-sub li { width: auto; float: left; clear: none; } } .am-navbar { position: fixed; left: 0; bottom: 0; width: 100%; height: 49px; line-height: 49px; z-index: 1010; } .am-navbar ul { padding-left: 0; margin: 0; list-style: none; width: 100%; } .am-navbar .am-navbar-nav { padding-left: 8px; padding-right: 8px; text-align: center; overflow: hidden; display: table; } .am-navbar .am-navbar-nav li { display: table-cell; width: 1%; float: none; } .am-navbar-nav { position: relative; z-index: 1015; } .am-navbar-nav a { display: inline-block; width: 100%; height: 49px; line-height: 20px; } .am-navbar-nav a img { display: block; vertical-align: middle; height: 24px; width: 24px; margin: 4px auto 0; } .am-navbar-nav a [class*="am-icon"] { width: 24px; height: 24px; margin: 4px auto 0; display: block; line-height: 24px; } .am-navbar-nav a [class*="am-icon"]:before { font-size: 22px; vertical-align: middle; } .am-navbar-nav a .am-navbar-label { padding-top: 2px; line-height: 1; font-size: 12px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-navbar-more [class*="am-icon-"] { -webkit-transition: 0.15s; transition: 0.15s; } .am-navbar-more.am-active [class*="am-icon-"] { -webkit-transform: rotateX(-180deg); transform: rotateX(-180deg); } .am-navbar-actions { position: absolute; bottom: 49px; right: 0; left: 0; z-index: 1009; opacity: 0; -webkit-transition: .3s; transition: .3s; -webkit-transform: translate(0, 100%); -ms-transform: translate(0, 100%); transform: translate(0, 100%); } .am-navbar-actions.am-active { opacity: 1; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-navbar-actions li { line-height: 42px; position: relative; } .am-navbar-actions li a { display: block; width: 100%; height: 40px; -webkit-box-shadow: inset 0 1px rgba(220, 220, 220, 0.25); box-shadow: inset 0 1px rgba(220, 220, 220, 0.25); padding-left: 20px; padding-right: 36px; } .am-navbar-actions li a :after { font-family: "FontAwesome", sans-serif; content: "\f105"; display: inline-block; position: absolute; top: 0; right: 20px; } .am-navbar-actions li a img { vertical-align: middle; height: 20px; width: 20px; display: inline; } #am-navbar-qrcode { width: 220px; height: 220px; margin-left: -110px; } #am-navbar-qrcode .am-modal-bd { padding: 10px; } #am-navbar-qrcode canvas { display: block; width: 200px; height: 200px; } .am-with-fixed-navbar { padding-bottom: 54px; } /** * Navbar Theme: default * Author: hzp (hzp@yunshipei.com) */ .am-navbar-default a { color: #fff; } .am-navbar-default .am-navbar-nav { background-color: #0e90d2; } .am-navbar-default .am-navbar-actions { background-color: #0d86c4; } .am-navbar-default .am-navbar-actions a { border-bottom: 1px solid #0b6fa2; } .am-pagination { position: relative; } /** * Pagination Theme: default */ .am-pagination-default { margin-left: 10px; margin-right: 10px; font-size: 1.6rem; } .am-pagination-default .am-pagination-prev, .am-pagination-default .am-pagination-next { float: none; } /** * Pagination Theme: select */ .am-pagination-select { margin-left: 10px; margin-right: 10px; font-size: 1.6rem; } .am-pagination-select > li > a { line-height: 36px; background-color: #eeeeee; padding: 0 15px; border: 0; color: #555555; } .am-pagination-select .am-pagination-select { position: absolute; top: 0; left: 50%; margin-left: -35px; width: 70px; height: 36px; text-align: center; border-radius: 0; } .am-pagination-select .am-pagination-select select { display: block; border: 0; line-height: 36px; width: 70px; height: 36px; border-radius: 0; color: #555555; background-color: #eeeeee; -webkit-appearance: none; -moz-appearance: none; appearance: none; padding-left: 18px; } .am-paragraph p { margin: 10px 0; } .am-paragraph img { max-width: 100%; } .am-paragraph h1, .am-paragraph h2, .am-paragraph h3, .am-paragraph h4, .am-paragraph h5, .am-paragraph h6 { color: #222222; } .am-paragraph table { max-width: none; } .am-paragraph-table-container { overflow: hidden; background: #eeeeee; max-width: none; } .am-paragraph-table-container table { width: 100%; max-width: none; } .am-paragraph-table-container table th { background: #bce5fb; height: 40px; border: 1px solid #999999; text-align: center; } .am-paragraph-table-container table td { border: 1px solid #999999; text-align: center; vertical-align: middle; background: #fff; } .am-paragraph-table-container table td p { text-indent: 0; font-size: 1.4rem; } .am-paragraph-table-container table td a { font-size: 1.4rem; } /** * Paragraph Theme: default */ .am-paragraph-default { margin: 0 10px; color: #333333; background-color: transparent; } .am-paragraph-default p { font-size: 1.4rem; } .am-paragraph-default img { max-width: 98%; display: block; margin: 5px auto; border: 1px solid #eeeeee; padding: 2px; } .am-paragraph-default a { color: #0e90d2; } /** * Slider Theme: a1 */ .am-slider-a1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a1 .am-viewport { max-height: 300px; } .am-slider-a1 .am-control-nav { width: 100%; position: absolute; bottom: 5px; text-align: center; line-height: 0; } .am-slider-a1 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a1 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-a1 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a1 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-a1 .am-direction-nav, .am-slider-a1 .am-pauseplay { display: none; } /** * Slider Theme: a2 */ .am-slider-a2 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a2 .am-viewport { max-height: 300px; } .am-slider-a2 .am-control-nav { width: 100%; position: absolute; bottom: 5px; text-align: center; line-height: 0; } .am-slider-a2 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a2 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-a2 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a2 .am-control-nav li a.am-active { background: #0e93d7; cursor: default; } .am-slider-a2 .am-direction-nav, .am-slider-a2 .am-pauseplay { display: none; } /** * Slider Theme: a3 */ .am-slider-a3 { margin-bottom: 20px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a3 .am-viewport { max-height: 300px; } .am-slider-a3 .am-control-nav { width: 100%; position: absolute; bottom: -20px; text-align: center; height: 20px; background-color: #000; padding-top: 5px; line-height: 0; } .am-slider-a3 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a3 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; -webkit-box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3); box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3); } .am-slider-a3 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a3 .am-control-nav li a.am-active { background: #0e90d2; cursor: default; } .am-slider-a3 .am-direction-nav, .am-slider-a3 .am-pauseplay { display: none; } /** * Slider Theme: a4 */ .am-slider-a4 { margin-bottom: 30px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a4 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a4 .am-viewport { max-height: 300px; } .am-slider-a4 .am-control-nav { width: 100%; position: absolute; bottom: -15px; text-align: center; line-height: 0; } .am-slider-a4 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a4 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-a4 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a4 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-a4 .am-direction-nav, .am-slider-a4 .am-pauseplay { display: none; } /** * Slider Theme: a5 */ .am-slider-a5 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a5 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a5 .am-viewport { max-height: 300px; } .am-slider-a5 .am-control-nav { width: 100%; position: absolute; text-align: center; height: 6px; display: table; bottom: 0; font-size: 0; line-height: 0; } .am-slider-a5 .am-control-nav li { display: table-cell; } .am-slider-a5 .am-control-nav li a { width: 100%; height: 6px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; } .am-slider-a5 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a5 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-a5 .am-direction-nav, .am-slider-a5 .am-pauseplay { display: none; } /** * Slider Theme: b1 */ .am-slider-b1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b1 .am-viewport { max-height: 300px; } .am-slider-b1 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 8px 0; margin: -20px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #fff; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); background-color: rgba(0, 0, 0, 0.5); font-size: 0; text-align: center; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b1 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 24px; } .am-slider-b1 .am-direction-nav a.am-prev { left: 0; padding-right: 5px; border-bottom-right-radius: 5px; border-top-right-radius: 5px; } .am-slider-b1 .am-direction-nav a.am-next { right: 0; padding-left: 5px; border-bottom-left-radius: 5px; border-top-left-radius: 5px; } .am-slider-b1 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b1 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b1:hover .am-prev { opacity: 0.7; } .am-slider-b1:hover .am-prev:hover { opacity: 1; } .am-slider-b1:hover .am-next { opacity: 0.7; } .am-slider-b1:hover .am-next:hover { opacity: 1; } .am-slider-b1 .am-control-nav, .am-slider-b1 .am-pauseplay { display: none; } /** * Slider Theme: b2 */ .am-slider-b2 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b2 .am-viewport { max-height: 300px; } .am-slider-b2 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px; margin: -16px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #fff; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); background-color: rgba(0, 0, 0, 0.5); font-size: 0; text-align: center; border-radius: 50%; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b2 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 16px; line-height: 24px; } .am-slider-b2 .am-direction-nav a.am-prev { left: 5px; } .am-slider-b2 .am-direction-nav a.am-next { right: 5px; } .am-slider-b2 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b2 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b2:hover .am-prev { opacity: 0.7; } .am-slider-b2:hover .am-prev:hover { opacity: 1; } .am-slider-b2:hover .am-next { opacity: 0.7; } .am-slider-b2:hover .am-next:hover { opacity: 1; } .am-slider-b2 .am-control-nav, .am-slider-b2 .am-pauseplay { display: none; } /** * Slider Theme: b3 */ .am-slider-b3 { margin: 15px 30px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b3 .am-viewport { max-height: 300px; } .am-slider-b3 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px; margin: -16px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #333333; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b3 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 24px; } .am-slider-b3 .am-direction-nav a.am-prev { left: -25px; } .am-slider-b3 .am-direction-nav a.am-next { right: -25px; text-align: right; } .am-slider-b3 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b3 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b3:hover .am-prev { opacity: 0.7; } .am-slider-b3:hover .am-prev:hover { opacity: 1; } .am-slider-b3:hover .am-next { opacity: 0.7; } .am-slider-b3:hover .am-next:hover { opacity: 1; } .am-slider-b3 .am-control-nav, .am-slider-b3 .am-pauseplay { display: none; } /** * Slider Theme: b4 */ .am-slider-b4 { margin: 15px 20px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b4 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b4 .am-viewport { max-height: 300px; } .am-slider-b4 .am-direction-nav a { position: absolute; top: 50%; z-index: 10; display: block; -webkit-box-sizing: content-box; box-sizing: content-box; width: 24px; height: 24px; margin: -16px 0 0; padding: 4px; overflow: hidden; opacity: 0.45; background-color: rgba(0, 0, 0, 0.8); cursor: pointer; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; border-radius: 50%; text-align: center; color: #fff; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b4 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 20px; line-height: 24px; } .am-slider-b4 .am-direction-nav a.am-prev { left: -15px; } .am-slider-b4 .am-direction-nav a.am-next { right: -15px; } .am-slider-b4 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b4 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b4:hover .am-prev { opacity: 0.7; } .am-slider-b4:hover .am-prev:hover { opacity: 0.9; } .am-slider-b4:hover .am-next { opacity: 0.7; } .am-slider-b4:hover .am-next:hover { opacity: 0.9; } .am-slider-b4 .am-control-nav, .am-slider-b4 .am-pauseplay { display: none; } /** * Slider Theme: c1 */ .am-slider-c1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-c1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c1 .am-viewport { max-height: 300px; } .am-slider-c1 .am-control-nav { position: absolute; bottom: 0; display: table; width: 100%; height: 6px; font-size: 0; line-height: 0; text-align: center; } .am-slider-c1 .am-control-nav li { display: table-cell; width: 1%; } .am-slider-c1 .am-control-nav li a { width: 100%; height: 6px; display: block; background-color: rgba(0, 0, 0, 0.7); cursor: pointer; text-indent: -9999px; } .am-slider-c1 .am-control-nav li a:hover { background: rgba(0, 0, 0, 0.8); } .am-slider-c1 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-c1 .am-slider-desc { background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 6px; padding: 8px; width: 100%; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c1 .am-direction-nav, .am-slider-c1 .am-pauseplay { display: none; } /** * Slider Theme: c2 */ .am-slider-c2 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-c2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c2 .am-viewport { max-height: 300px; } .am-slider-c2 .am-control-nav { position: absolute; bottom: 15px; right: 0; height: 6px; text-align: center; font-size: 0; line-height: 0; } .am-slider-c2 .am-control-nav li { display: inline-block; margin-right: 6px; } .am-slider-c2 .am-control-nav li a { width: 6px; height: 6px; display: block; background-color: rgba(255, 255, 255, 0.4); cursor: pointer; text-indent: -9999px; } .am-slider-c2 .am-control-nav li a:hover { background: rgba(230, 230, 230, 0.4); } .am-slider-c2 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-c2 .am-slider-desc { background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 0; padding: 8px 60px 8px 8px; width: 100%; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c2 .am-direction-nav, .am-slider-c2 .am-pauseplay { display: none; } /** * Slider Theme: c3 */ .am-slider-c3 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-c3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c3 .am-viewport { max-height: 300px; } .am-slider-c3 .am-slider-desc { background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 10px; right: 60px; height: 30px; left: 0; padding-right: 5px; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c3 .am-slider-counter { margin-right: 5px; display: inline-block; height: 30px; background-color: #0e90d2; width: 40px; text-align: center; line-height: 30px; color: #eee; font-size: 1rem; } .am-slider-c3 .am-slider-counter .am-active { font-size: 1.8rem; font-weight: bold; color: #fff; } .am-slider-c3 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px 0; margin: -16px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #fff; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); background-color: rgba(0, 0, 0, 0.5); font-size: 0; text-align: center; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-c3 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 16px; line-height: 24px; } .am-slider-c3 .am-direction-nav a.am-prev { left: 0; padding-right: 5px; } .am-slider-c3 .am-direction-nav a.am-next { right: 0; padding-left: 5px; } .am-slider-c3 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-c3 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-c3:hover .am-prev { opacity: 0.7; } .am-slider-c3:hover .am-prev:hover { opacity: 1; } .am-slider-c3:hover .am-next { opacity: 0.7; } .am-slider-c3:hover .am-next:hover { opacity: 1; } .am-slider-c3 .am-control-nav, .am-slider-c3 .am-pauseplay { display: none; } /** * Slider Theme: c4 */ .am-slider-c4 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-c4 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c4 .am-viewport { max-height: 300px; } .am-slider-c4 .am-slider-desc { width: 100%; background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 0; right: 0; left: 0; padding: 8px 40px; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c4 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px 0; margin: 0; position: absolute; bottom: 4px; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; text-align: center; color: rgba(0, 0, 0, 0.7); -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-c4 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 24px; } .am-slider-c4 .am-direction-nav a.am-prev { left: 0; padding-right: 5px; } .am-slider-c4 .am-direction-nav a.am-next { right: 0; padding-left: 5px; } .am-slider-c4 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-c4 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-c4:hover .am-prev { opacity: 0.7; } .am-slider-c4:hover .am-prev:hover { opacity: 1; } .am-slider-c4:hover .am-next { opacity: 0.7; } .am-slider-c4:hover .am-next:hover { opacity: 1; } .am-slider-c4 .am-control-nav, .am-slider-c4 .am-pauseplay { display: none; } /** * Slider Theme: d1 */ .am-slider-d1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-d1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-d1 .am-viewport { max-height: 300px; } .am-slider-d1 .am-slider-desc { padding: 8px 35px; width: 100%; color: #fff; background-color: #0e90d2; } .am-slider-d1 .am-slider-title { font-weight: normal; margin-bottom: 2px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d1 .am-slider-more { color: #eeeeee; font-size: 1.3rem; } .am-slider-d1 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; margin: 0; position: absolute; bottom: 18px; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; text-align: center; border: 1px solid rgba(255, 255, 255, 0.9); color: rgba(255, 255, 255, 0.9); border-radius: 50%; -webkit-transition: all 03s ease; transition: all 03s ease; } .am-slider-d1 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 16px; line-height: 24px; } .am-slider-d1 .am-direction-nav a.am-prev { left: 5px; } .am-slider-d1 .am-direction-nav a.am-next { right: 5px; } .am-slider-d1 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-d1 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-d1:hover .am-prev { opacity: 0.7; } .am-slider-d1:hover .am-prev:hover { opacity: 1; } .am-slider-d1:hover .am-next { opacity: 0.7; } .am-slider-d1:hover .am-next:hover { opacity: 1; } .am-slider-d1 .am-control-nav, .am-slider-d1 .am-pauseplay { display: none; } /** * Slider Theme: d2 */ .am-slider-d2 { margin-bottom: 20px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-d2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-d2 .am-viewport { max-height: 300px; } .am-slider-d2 .am-slider-desc { position: absolute; left: 10px; bottom: 20px; right: 50px; color: #fff; } .am-slider-d2 .am-slider-content { background-color: rgba(0, 0, 0, 0.7); padding: 10px 6px; margin-bottom: 10px; } .am-slider-d2 .am-slider-content p { margin: 0; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; font-size: 1.4rem; } .am-slider-d2 .am-slider-title { font-weight: normal; margin-bottom: 5px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d2 .am-slider-more { color: #eeeeee; font-size: 1.3rem; background-color: #0e90d2; padding: 2px 10px; } .am-slider-d2 .am-control-nav { width: 100%; position: absolute; bottom: -15px; text-align: center; } .am-slider-d2 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-d2 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; font-size: 0; line-height: 0; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-d2 .am-control-nav li a:hover { background: rgba(0, 0, 0, 0.5); } .am-slider-d2 .am-control-nav li a.am-active { background: #0e90d2; cursor: default; } .am-slider-d2 .am-direction-nav, .am-slider-d2 .am-pauseplay { display: none; } /** * Slider Theme: d3 */ .am-slider-d3 { margin-bottom: 10px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-d3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-d3 .am-viewport { max-height: 300px; } .am-slider-d3 .am-slider-desc { position: absolute; bottom: 0; color: #fff; width: 100%; background-color: rgba(0, 0, 0, 0.7); padding: 8px 5px; } .am-slider-d3 .am-slider-desc p { margin: 0; font-size: 1.3rem; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d3 .am-slider-title { font-weight: normal; margin-bottom: 5px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d3 .am-control-thumbs { position: static; overflow: hidden; } .am-slider-d3 .am-control-thumbs li { padding: 12px 4px 4px; position: relative; } .am-slider-d3 .am-control-thumbs img { width: 100%; display: block; opacity: .85; cursor: pointer; } .am-slider-d3 .am-control-thumbs img:hover { opacity: 1; } .am-slider-d3 .am-control-thumbs .am-active { opacity: 1; cursor: default; } .am-slider-d3 .am-control-thumbs .am-active + i { position: absolute; top: 0; left: 50%; content: ""; display: inline-block; width: 0; height: 0; vertical-align: middle; border-top: 8px solid rgba(0, 0, 0, 0.7); border-right: 8px solid transparent; border-left: 8px solid transparent; border-bottom: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); margin-left: -4px; -webkit-transition: all 0.2s; transition: all 0.2s; } .am-slider-d3 .am-direction-nav, .am-slider-d3 .am-pauseplay { display: none; } .am-slider-d3 .am-control-thumbs { display: table; } .am-slider-d3 .am-control-thumbs li { display: table-cell; width: 1%; } [data-am-widget='tabs'] { margin: 10px; } [data-am-widget='tabs'] .am-tabs-nav { width: 100%; padding: 0; margin: 0; list-style: none; text-align: center; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } [data-am-widget='tabs'] .am-tabs-nav li { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; } [data-am-widget='tabs'] .am-tabs-nav a { display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } /** * Tabs Theme: default */ .am-tabs-default .am-tabs-nav { line-height: 40px; background-color: #eeeeee; } .am-tabs-default .am-tabs-nav a { color: #222222; line-height: 42px; } .am-tabs-default .am-tabs-nav > .am-active a { background-color: #0e90d2; color: #fff; } /** * Tabs Theme: d2 */ .am-tabs-d2 .am-tabs-nav { background-color: #eeeeee; } .am-tabs-d2 .am-tabs-nav li { height: 42px; } .am-tabs-d2 .am-tabs-nav a { color: #222222; line-height: 42px; } .am-tabs-d2 .am-tabs-nav > .am-active { position: relative; background-color: #fcfcfc; border-bottom: 2px solid #0e90d2; } .am-tabs-d2 .am-tabs-nav > .am-active a { line-height: 40px; color: #0e90d2; } .am-tabs-d2 .am-tabs-nav > .am-active:after { position: absolute; width: 0; height: 0; bottom: 0px; left: 50%; margin-left: -5px; border: 6px rgba(0, 0, 0, 0) solid; content: ""; z-index: 1; border-bottom-color: #0e90d2; } .am-titlebar { margin-top: 20px; height: 45px; font-size: 100%; } .am-titlebar h2 { margin-top: 0; margin-bottom: 0; font-size: 1.6rem; } .am-titlebar .am-titlebar-title img { height: 24px; width: auto; } /** * Titlebar Theme: default */ .am-titlebar-default { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; margin-left: 10px; margin-right: 10px; background-color: transparent; border-bottom: 1px solid #dedede; line-height: 44px; } .am-titlebar-default a { color: #0e90d2; } .am-titlebar-default .am-titlebar-title { position: relative; padding-left: 12px; color: #0e90d2; font-size: 1.8rem; text-align: left; font-weight: bold; } .am-titlebar-default .am-titlebar-title:before { content: ""; position: absolute; left: 2px; top: 8px; bottom: 8px; border-left: 3px solid #0e90d2; } .am-titlebar-default .am-titlebar-nav { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; text-align: right; } .am-titlebar-default .am-titlebar-nav a { margin-right: 10px; } .am-titlebar-default .am-titlebar-nav a:last-child { margin-right: 5px; } /** * Titlebar Theme: multi */ .am-titlebar-multi { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; background-color: #f5f5f5; border-top: 2px solid #3bb4f2; border-bottom: 1px solid #e8e8e8; } .am-titlebar-multi a { color: #0e90d2; } .am-titlebar-multi .am-titlebar-title { padding-left: 10px; color: #0e90d2; font-size: 1.8rem; text-align: left; font-weight: bold; line-height: 42px; } .am-titlebar-multi .am-titlebar-nav { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; text-align: right; line-height: 42px; } .am-titlebar-multi .am-titlebar-nav a { margin-right: 10px; } /** * Titlebar Theme: cols */ .am-titlebar-cols { position: relative; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; padding-left: 10px; background-color: #f5f5f5; color: #555555; font-size: 18px; border-top: 2px solid #e1e1e1; line-height: 41px; } .am-titlebar-cols a { color: #555555; } .am-titlebar-cols .am-titlebar-title { color: #0e90d2; margin-right: 15px; border-bottom: 2px solid #0e90d2; font-weight: bold; } .am-titlebar-cols .am-titlebar-title a { color: #0e90d2; } .am-titlebar-cols .am-titlebar-nav { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; } .am-titlebar-cols .am-titlebar-nav a { display: inline-block; margin-right: 15px; line-height: 41px; border-bottom: 2px solid transparent; } .am-titlebar-cols .am-titlebar-nav a:hover { color: #3c3c3c; border-bottom-color: #0e90d2; } .am-titlebar-cols .am-titlebar-nav a:last-child { margin-right: 10px; } .am-wechatpay .am-wechatpay-btn { margin-top: 1rem; margin-bottom: 1rem; } ================================================ FILE: open-layui-web/src/main/view/static/assets/css/amazeui.flat.css ================================================ /*! Amaze UI v2.6.0 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ /* ========================================================================== Component: Base ============================================================================ */ /** * Fix the flawed CSS box model - Yes, IE6's box model is better * Browser support: IE8+ * via: http://paulirish.com/2012/box-sizing-border-box-ftw/ */ *, *:before, *:after { -webkit-box-sizing: border-box; box-sizing: border-box; } /* normalize.css v3.0.2 | git.io/normalize */ /* Set and to inherit the height of the viewport */ html, body { min-height: 100%; } /** * 1. Prevent iOS text size adjust after orientation change, without disabling * user zoom. * https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust */ html { -ms-text-size-adjust: 100%; /* 1 */ -webkit-text-size-adjust: 100%; /* 1 */ } /** * Remove default margin. */ body { margin: 0; } /* HTML5 display definitions ========================================================================== */ /** * Correct `block` display not defined for any HTML5 element in IE 8/9. * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. * Correct `block` display not defined for `main` in IE 11. * hgroup has been removed from the HTML5 (W3C) specification * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, main, nav, section, summary { display: block; } /** * 1. Correct `inline-block` display not defined in IE 8/9. * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. */ audio, canvas, progress, video { display: inline-block; /* 1 */ vertical-align: baseline; /* 2 */ } /** * Prevent modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */ audio:not([controls]) { display: none; height: 0; } /** * Address `[hidden]` styling not present in IE 8/9/10. * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. */ [hidden], template, script { display: none; } /* Links ========================================================================== */ /** * Remove the gray background color from active links in IE 10. */ a { background-color: transparent; } /** * Address `outline` inconsistency between Chrome and other browsers. */ a:focus { outline: thin dotted; } /** * Improve readability when focused and also mouse hovered in all browsers. */ a:active, a:hover { outline: 0; } /* Text-level semantics ========================================================================== */ /** * Remove text-decoration */ ins, a { text-decoration: none; } /** * Address styling not present in IE 8/9, Safari 5, and Chrome. */ abbr[title] { border-bottom: 1px dotted; } /** * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ b, strong { font-weight: bold; } /** * Improve readability of pre-formatted text in all browsers. */ pre { white-space: pre-wrap; } /** * Set consistent quote types. */ q { quotes: "\201C" "\201D" "\2018" "\2019"; } /** * Address inconsistent and variable font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } /* Embedded content ========================================================================== */ /** * 1. Corrects max-width behavior (2.) if padding and border are used * 2. Responsiveness: Sets a maxium width relative to the parent and auto scales the height * 3. Remove the gap between images and the bottom of their containers * 4. Remove border when inside `a` element in IE 8/9. * remove 2. for Issue #502 */ img { -webkit-box-sizing: border-box; box-sizing: border-box; /* 1 */ vertical-align: middle; /* 3 */ border: 0; /* 4 */ } /** * Correct overflow displayed oddly in IE 9. */ svg:not(:root) { overflow: hidden; } /* Grouping content ========================================================================== */ /** * Address margin not present in IE 8/9 and Safari. */ figure { margin: 0; } /** * Correct font family set oddly in Safari 5 and Chrome. */ code, kbd, pre, samp { font-family: Monaco, Menlo, Consolas, "Courier New", "FontAwesome", monospace; font-size: 1em; } /* Forms ========================================================================== */ /** * Define consistent border, margin, and padding. */ fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } /** * 1. Correct `color` not being inherited in IE 8/9. * 2. Remove padding so people aren't caught out if they zero out fieldsets. */ legend { border: 0; /* 1 */ padding: 0; /* 2 */ } /** * 1. Correct color not being inherited. * Known issue: affects color of disabled elements. * 2. Correct font properties not being inherited. * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */ button, input, optgroup, select, textarea { color: inherit; /* 1 */ font: inherit; /* 2 */ margin: 0; /* 3 */ } /** * Address `overflow` set to `hidden` in IE 8/9/10/11. */ button { overflow: visible; } /** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */ button, input { line-height: normal; } /** * Address inconsistent `text-transform` inheritance for `button` and `select`. * All other form control elements do not inherit `text-transform` values. * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. * Correct `select` style inheritance in Firefox. */ button, select { text-transform: none; } /** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` * and `video` controls. * 2. Correct inability to style clickable `input` types in iOS. * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */ button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } /* * 1. Improves consistency of cursor style for clickable elements * 2. Removes excess padding in IE 8/9. * 3. Address box sizing set to `content-box` in IE 8/9/10. */ input[type="radio"], input[type="checkbox"] { cursor: pointer; /*1*/ padding: 0; /*2*/ -webkit-box-sizing: border-box; box-sizing: border-box; /* 3 */ } /** * Re-set default cursor for disabled elements. */ button[disabled], html input[disabled] { cursor: default; } /** * Remove inner padding and border in Firefox 4+. */ button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } /** * Fix the cursor style for Chrome's increment/decrement buttons. For certain * `font-size` values of the `input`, it causes the cursor style of the * decrement button to change from `default` to `text`. */ input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Address `appearance` set to `searchfield` in Safari and Chrome. * 2. Address `box-sizing` set to `border-box` in Safari and Chrome * (include `-moz` to future-proof). */ input[type="search"] { -webkit-appearance: textfield; /* 1 */ -webkit-box-sizing: content-box; box-sizing: content-box; /* 2 */ } /** * Remove inner padding and search cancel button in Safari 5 and Chrome * on OS X. */ input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * 1. Remove default vertical scrollbar in IE 8/9. * 2. Improve readability and alignment in all browsers. */ textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ resize: vertical; } /** * Don't inherit the `font-weight` (applied by a rule above). * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. */ optgroup { font-weight: bold; } /* Tables ========================================================================== */ /** * Remove most spacing between table cells. */ table { border-collapse: collapse; border-spacing: 0; } td, th { padding: 0; } /* AMUI Base ========================================================================== */ /** * `font-size` is set in `html` element to support the `rem` unit for font-sizes * NOTE: IE9 & IE10 do not recognize `rem` units when used with the `font` shorthand property. */ html { font-size: 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { position: relative; background: #fff; font-family: "Segoe UI", "Lucida Grande", Helvetica, Arial, "Microsoft YaHei", FreeSans, Arimo, "Droid Sans", "wenquanyi micro hei", "Hiragino Sans GB", "Hiragino Sans GB W3", "FontAwesome", sans-serif; font-weight: normal; line-height: 1.6; color: #333333; font-size: 1.6rem; } /** * 1. http://usabilitypost.com/2012/11/15/w-optimizelegibility-on-mobile-devices/ * 2. http://maxvoltar.com/archive/-webkit-font-smoothing * NOTE: http://usabilitypost.com/2012/11/05/stop-fixing-font-smoothing/ * 3. http://maximilianhoffmann.com/posts/better-font-rendering-on-osx * http://jaydenseric.com/blog/css-font-smoothing-for-firefox-mac */ body, input, textarea, select, button { text-rendering: optimizeLegibility; /* 1 */ -webkit-font-smoothing: antialiased; /* 2 */ -moz-osx-font-smoothing: grayscale; /* 3 Default: auto */ -moz-font-feature-settings: "liga", "kern"; } /*Only phones */ @media only screen and (max-width: 640px) { /** * Break strings if their length exceeds the width of their container */ body { word-wrap: break-word; -webkit-hyphens: auto; -ms-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } } /** * links */ a { color: #0e90d2; } a:hover, a:focus { color: #095f8a; } a:focus { outline: thin dotted; outline: 1px auto -webkit-focus-ring-color; outline-offset: -2px; } /* Insert */ ins { background: #ffa; color: #333333; } /** * Mark * Note: Addresses styling not present in IE 8/9. */ mark { background: #ffa; color: #333333; } /** * Abbreviation and definition */ abbr[title], dfn[title] { cursor: help; } dfn[title] { border-bottom: 1px dotted; font-style: normal; } /* Spacing for block elements */ p, hr, ul, ol, dl, blockquote, pre, address, fieldset, figure { margin: 0 0 1.6rem 0; } * + p, * + hr, * + ul, * + ol, * + dl, * + blockquote, * + pre, * + address, * + fieldset, * + figure { margin-top: 1.6rem; } /* Headings ========================================================================== */ h1, h2, h3, h4, h5, h6 { margin: 0 0 1.6rem 0; font-weight: 600; font-size: 100%; } h1 { font-size: 1.5em; } h2 { font-size: 1.25em; } * + h1, * + h2, * + h3, * + h4, * + h5, * + h6 { margin-top: 2em; } /* Ordered and unordered lists */ ul, ol { padding-left: 2em; } /* Reset margin for nested lists */ ul > li > ul, ul > li > ol, ol > li > ol, ol > li > ul { margin: 1em 0; } /* Description lists */ dt { font-weight: bold; } dt + dd { margin-top: .5em; } dd { margin-left: 0; } dd + dt { margin-top: 1em; } /** * Horizontal rule * 1. Address differences between Firefox and other browsers. */ hr { display: block; padding: 0; border: 0; height: 0; border-top: 1px solid #eeeeee; /* 1 */ -webkit-box-sizing: content-box; box-sizing: content-box; /* 1 */ } /* Address */ address { font-style: normal; } /* Quotes */ blockquote { padding-top: 5px; padding-bottom: 5px; padding-left: 15px; border-left: 4px solid #ddd; font-family: Georgia, "Times New Roman", Times, Kai, "Kaiti SC", KaiTi, BiauKai, "FontAwesome", serif; /* Small print for identifying the source */ /* Smaller margin if `small` follows */ } blockquote small { display: block; color: #999999; font-family: "Segoe UI", "Lucida Grande", Helvetica, Arial, "Microsoft YaHei", FreeSans, Arimo, "Droid Sans", "wenquanyi micro hei", "Hiragino Sans GB", "Hiragino Sans GB W3", "FontAwesome", sans-serif; text-align: right; } blockquote p:last-of-type { margin-bottom: 0; } /* iframe */ iframe { border: 0; } /* Forms ========================================================================== */ /** * Vertical alignment * Exclude `radio` and `checkbox` elements because the default `baseline` value aligns better with text */ button, input:not([type="radio"]):not([type="checkbox"]), select { vertical-align: middle; } /** * Fix viewport for IE10 snap mode * http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ * http://msdn.microsoft.com/en-us/library/ie/hh869615%28v=vs.85%29.aspx * http://msdn.microsoft.com/zh-cn/library/ie/hh708740(v=vs.85).aspx * @2014.01.20: 设置一下属性以后,windows Phone 8 上显示的字体过小,暂时注释掉 * ========================================================================== */ /* @-ms-viewport { width: device-width; } */ .am-scrollbar-measure { width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px; } /* ========================================================================== Component: Grid ============================================================================ */ .am-container { -webkit-box-sizing: border-box; box-sizing: border-box; margin-left: auto; margin-right: auto; padding-left: 1rem; padding-right: 1rem; width: 100%; max-width: 1000px; } .am-container:before, .am-container:after { content: " "; display: table; } .am-container:after { clear: both; } @media only screen and (min-width:641px) { .am-container { padding-left: 1.5rem; padding-right: 1.5rem; } } .am-container > .am-g { width: auto; margin-left: -1rem; margin-right: -1rem; } @media only screen and (min-width:641px) { .am-container > .am-g { margin-left: -1.5rem; margin-right: -1.5rem; } } .am-g { margin: 0 auto; width: 100%; } .am-g:before, .am-g:after { content: " "; display: table; } .am-g:after { clear: both; } .am-g .am-g { margin-left: -1rem; margin-right: -1rem; width: auto; } .am-g .am-g.am-g-collapse { margin-left: 0; margin-right: 0; width: auto; } @media only screen and (min-width:641px) { .am-g .am-g { margin-left: -1.5rem; margin-right: -1.5rem; } } .am-g.am-g-collapse .am-g { margin-left: 0; margin-right: 0; } .am-g-collapse [class*="am-u-"] { padding-left: 0; padding-right: 0; } .am-g-fixed { max-width: 1000px; } [class*="am-u-"] { width: 100%; padding-left: 1rem; padding-right: 1rem; float: left; position: relative; } [class*="am-u-"] + [class*="am-u-"]:last-child { float: right; } [class*="am-u-"] + [class*="am-u-"].am-u-end { float: left; } @media only screen and (min-width:641px) { [class*="am-u-"] { padding-left: 1.5rem; padding-right: 1.5rem; } } [class*="am-u-pull-"] { left: auto; } [class*="am-u-push-"] { right: auto; } @media only screen { .am-u-sm-1 { width: 8.33333333%; } .am-u-sm-2 { width: 16.66666667%; } .am-u-sm-3 { width: 25%; } .am-u-sm-4 { width: 33.33333333%; } .am-u-sm-5 { width: 41.66666667%; } .am-u-sm-6 { width: 50%; } .am-u-sm-7 { width: 58.33333333%; } .am-u-sm-8 { width: 66.66666667%; } .am-u-sm-9 { width: 75%; } .am-u-sm-10 { width: 83.33333333%; } .am-u-sm-11 { width: 91.66666667%; } .am-u-sm-12 { width: 100%; } .am-u-sm-pull-0 { right: 0; } .am-u-sm-pull-1 { right: 8.33333333%; } .am-u-sm-pull-2 { right: 16.66666667%; } .am-u-sm-pull-3 { right: 25%; } .am-u-sm-pull-4 { right: 33.33333333%; } .am-u-sm-pull-5 { right: 41.66666667%; } .am-u-sm-pull-6 { right: 50%; } .am-u-sm-pull-7 { right: 58.33333333%; } .am-u-sm-pull-8 { right: 66.66666667%; } .am-u-sm-pull-9 { right: 75%; } .am-u-sm-pull-10 { right: 83.33333333%; } .am-u-sm-pull-11 { right: 91.66666667%; } .am-u-sm-push-0 { left: 0; } .am-u-sm-push-1 { left: 8.33333333%; } .am-u-sm-push-2 { left: 16.66666667%; } .am-u-sm-push-3 { left: 25%; } .am-u-sm-push-4 { left: 33.33333333%; } .am-u-sm-push-5 { left: 41.66666667%; } .am-u-sm-push-6 { left: 50%; } .am-u-sm-push-7 { left: 58.33333333%; } .am-u-sm-push-8 { left: 66.66666667%; } .am-u-sm-push-9 { left: 75%; } .am-u-sm-push-10 { left: 83.33333333%; } .am-u-sm-push-11 { left: 91.66666667%; } .am-u-sm-offset-0 { margin-left: 0; } .am-u-sm-offset-1 { margin-left: 8.33333333%; } .am-u-sm-offset-2 { margin-left: 16.66666667%; } .am-u-sm-offset-3 { margin-left: 25%; } .am-u-sm-offset-4 { margin-left: 33.33333333%; } .am-u-sm-offset-5 { margin-left: 41.66666667%; } .am-u-sm-offset-6 { margin-left: 50%; } .am-u-sm-offset-7 { margin-left: 58.33333333%; } .am-u-sm-offset-8 { margin-left: 66.66666667%; } .am-u-sm-offset-9 { margin-left: 75%; } .am-u-sm-offset-10 { margin-left: 83.33333333%; } .am-u-sm-offset-11 { margin-left: 91.66666667%; } .am-u-sm-reset-order { margin-left: 0; margin-right: 0; left: auto; right: auto; float: left; } [class*="am-u-"].am-u-sm-centered { margin-left: auto; margin-right: auto; float: none; } [class*="am-u-"].am-u-sm-centered:last-child { float: none; } [class*="am-u-"].am-u-sm-uncentered { margin-left: 0; margin-right: 0; float: left; } [class*="am-u-"].am-u-sm-uncentered:last-child { float: left; } } @media only screen and (min-width:641px) { .am-u-md-1 { width: 8.33333333%; } .am-u-md-2 { width: 16.66666667%; } .am-u-md-3 { width: 25%; } .am-u-md-4 { width: 33.33333333%; } .am-u-md-5 { width: 41.66666667%; } .am-u-md-6 { width: 50%; } .am-u-md-7 { width: 58.33333333%; } .am-u-md-8 { width: 66.66666667%; } .am-u-md-9 { width: 75%; } .am-u-md-10 { width: 83.33333333%; } .am-u-md-11 { width: 91.66666667%; } .am-u-md-12 { width: 100%; } .am-u-md-pull-0 { right: 0; } .am-u-md-pull-1 { right: 8.33333333%; } .am-u-md-pull-2 { right: 16.66666667%; } .am-u-md-pull-3 { right: 25%; } .am-u-md-pull-4 { right: 33.33333333%; } .am-u-md-pull-5 { right: 41.66666667%; } .am-u-md-pull-6 { right: 50%; } .am-u-md-pull-7 { right: 58.33333333%; } .am-u-md-pull-8 { right: 66.66666667%; } .am-u-md-pull-9 { right: 75%; } .am-u-md-pull-10 { right: 83.33333333%; } .am-u-md-pull-11 { right: 91.66666667%; } .am-u-md-push-0 { left: 0; } .am-u-md-push-1 { left: 8.33333333%; } .am-u-md-push-2 { left: 16.66666667%; } .am-u-md-push-3 { left: 25%; } .am-u-md-push-4 { left: 33.33333333%; } .am-u-md-push-5 { left: 41.66666667%; } .am-u-md-push-6 { left: 50%; } .am-u-md-push-7 { left: 58.33333333%; } .am-u-md-push-8 { left: 66.66666667%; } .am-u-md-push-9 { left: 75%; } .am-u-md-push-10 { left: 83.33333333%; } .am-u-md-push-11 { left: 91.66666667%; } .am-u-md-offset-0 { margin-left: 0; } .am-u-md-offset-1 { margin-left: 8.33333333%; } .am-u-md-offset-2 { margin-left: 16.66666667%; } .am-u-md-offset-3 { margin-left: 25%; } .am-u-md-offset-4 { margin-left: 33.33333333%; } .am-u-md-offset-5 { margin-left: 41.66666667%; } .am-u-md-offset-6 { margin-left: 50%; } .am-u-md-offset-7 { margin-left: 58.33333333%; } .am-u-md-offset-8 { margin-left: 66.66666667%; } .am-u-md-offset-9 { margin-left: 75%; } .am-u-md-offset-10 { margin-left: 83.33333333%; } .am-u-md-offset-11 { margin-left: 91.66666667%; } .am-u-md-reset-order { margin-left: 0; margin-right: 0; left: auto; right: auto; float: left; } [class*="am-u-"].am-u-md-centered { margin-left: auto; margin-right: auto; float: none; } [class*="am-u-"].am-u-md-centered:last-child { float: none; } [class*="am-u-"].am-u-md-uncentered { margin-left: 0; margin-right: 0; float: left; } [class*="am-u-"].am-u-md-uncentered:last-child { float: left; } } @media only screen and (min-width:1025px) { .am-u-lg-1 { width: 8.33333333%; } .am-u-lg-2 { width: 16.66666667%; } .am-u-lg-3 { width: 25%; } .am-u-lg-4 { width: 33.33333333%; } .am-u-lg-5 { width: 41.66666667%; } .am-u-lg-6 { width: 50%; } .am-u-lg-7 { width: 58.33333333%; } .am-u-lg-8 { width: 66.66666667%; } .am-u-lg-9 { width: 75%; } .am-u-lg-10 { width: 83.33333333%; } .am-u-lg-11 { width: 91.66666667%; } .am-u-lg-12 { width: 100%; } .am-u-lg-pull-0 { right: 0; } .am-u-lg-pull-1 { right: 8.33333333%; } .am-u-lg-pull-2 { right: 16.66666667%; } .am-u-lg-pull-3 { right: 25%; } .am-u-lg-pull-4 { right: 33.33333333%; } .am-u-lg-pull-5 { right: 41.66666667%; } .am-u-lg-pull-6 { right: 50%; } .am-u-lg-pull-7 { right: 58.33333333%; } .am-u-lg-pull-8 { right: 66.66666667%; } .am-u-lg-pull-9 { right: 75%; } .am-u-lg-pull-10 { right: 83.33333333%; } .am-u-lg-pull-11 { right: 91.66666667%; } .am-u-lg-push-0 { left: 0; } .am-u-lg-push-1 { left: 8.33333333%; } .am-u-lg-push-2 { left: 16.66666667%; } .am-u-lg-push-3 { left: 25%; } .am-u-lg-push-4 { left: 33.33333333%; } .am-u-lg-push-5 { left: 41.66666667%; } .am-u-lg-push-6 { left: 50%; } .am-u-lg-push-7 { left: 58.33333333%; } .am-u-lg-push-8 { left: 66.66666667%; } .am-u-lg-push-9 { left: 75%; } .am-u-lg-push-10 { left: 83.33333333%; } .am-u-lg-push-11 { left: 91.66666667%; } .am-u-lg-offset-0 { margin-left: 0; } .am-u-lg-offset-1 { margin-left: 8.33333333%; } .am-u-lg-offset-2 { margin-left: 16.66666667%; } .am-u-lg-offset-3 { margin-left: 25%; } .am-u-lg-offset-4 { margin-left: 33.33333333%; } .am-u-lg-offset-5 { margin-left: 41.66666667%; } .am-u-lg-offset-6 { margin-left: 50%; } .am-u-lg-offset-7 { margin-left: 58.33333333%; } .am-u-lg-offset-8 { margin-left: 66.66666667%; } .am-u-lg-offset-9 { margin-left: 75%; } .am-u-lg-offset-10 { margin-left: 83.33333333%; } .am-u-lg-offset-11 { margin-left: 91.66666667%; } .am-u-lg-reset-order { margin-left: 0; margin-right: 0; left: auto; right: auto; float: left; } [class*="am-u-"].am-u-lg-centered { margin-left: auto; margin-right: auto; float: none; } [class*="am-u-"].am-u-lg-centered:last-child { float: none; } [class*="am-u-"].am-u-lg-uncentered { margin-left: 0; margin-right: 0; float: left; } [class*="am-u-"].am-u-lg-uncentered:last-child { float: left; } } /* ========================================================================== Component: AVG Grid ============================================================================ */ [class*="am-avg-"] { display: block; padding: 0; margin: 0; list-style: none; } [class*="am-avg-"]:before, [class*="am-avg-"]:after { content: " "; display: table; } [class*="am-avg-"]:after { clear: both; } [class*="am-avg-"] > li { display: block; height: auto; float: left; } @media only screen { .am-avg-sm-1 > li { width: 100%; } .am-avg-sm-1 > li:nth-of-type(n) { clear: none; } .am-avg-sm-1 > li:nth-of-type(1n + 1) { clear: both; } .am-avg-sm-2 > li { width: 50%; } .am-avg-sm-2 > li:nth-of-type(n) { clear: none; } .am-avg-sm-2 > li:nth-of-type(2n + 1) { clear: both; } .am-avg-sm-3 > li { width: 33.33333333%; } .am-avg-sm-3 > li:nth-of-type(n) { clear: none; } .am-avg-sm-3 > li:nth-of-type(3n + 1) { clear: both; } .am-avg-sm-4 > li { width: 25%; } .am-avg-sm-4 > li:nth-of-type(n) { clear: none; } .am-avg-sm-4 > li:nth-of-type(4n + 1) { clear: both; } .am-avg-sm-5 > li { width: 20%; } .am-avg-sm-5 > li:nth-of-type(n) { clear: none; } .am-avg-sm-5 > li:nth-of-type(5n + 1) { clear: both; } .am-avg-sm-6 > li { width: 16.66666667%; } .am-avg-sm-6 > li:nth-of-type(n) { clear: none; } .am-avg-sm-6 > li:nth-of-type(6n + 1) { clear: both; } .am-avg-sm-7 > li { width: 14.28571429%; } .am-avg-sm-7 > li:nth-of-type(n) { clear: none; } .am-avg-sm-7 > li:nth-of-type(7n + 1) { clear: both; } .am-avg-sm-8 > li { width: 12.5%; } .am-avg-sm-8 > li:nth-of-type(n) { clear: none; } .am-avg-sm-8 > li:nth-of-type(8n + 1) { clear: both; } .am-avg-sm-9 > li { width: 11.11111111%; } .am-avg-sm-9 > li:nth-of-type(n) { clear: none; } .am-avg-sm-9 > li:nth-of-type(9n + 1) { clear: both; } .am-avg-sm-10 > li { width: 10%; } .am-avg-sm-10 > li:nth-of-type(n) { clear: none; } .am-avg-sm-10 > li:nth-of-type(10n + 1) { clear: both; } .am-avg-sm-11 > li { width: 9.09090909%; } .am-avg-sm-11 > li:nth-of-type(n) { clear: none; } .am-avg-sm-11 > li:nth-of-type(11n + 1) { clear: both; } .am-avg-sm-12 > li { width: 8.33333333%; } .am-avg-sm-12 > li:nth-of-type(n) { clear: none; } .am-avg-sm-12 > li:nth-of-type(12n + 1) { clear: both; } } @media only screen and (min-width:641px) { .am-avg-md-1 > li { width: 100%; } .am-avg-md-1 > li:nth-of-type(n) { clear: none; } .am-avg-md-1 > li:nth-of-type(1n + 1) { clear: both; } .am-avg-md-2 > li { width: 50%; } .am-avg-md-2 > li:nth-of-type(n) { clear: none; } .am-avg-md-2 > li:nth-of-type(2n + 1) { clear: both; } .am-avg-md-3 > li { width: 33.33333333%; } .am-avg-md-3 > li:nth-of-type(n) { clear: none; } .am-avg-md-3 > li:nth-of-type(3n + 1) { clear: both; } .am-avg-md-4 > li { width: 25%; } .am-avg-md-4 > li:nth-of-type(n) { clear: none; } .am-avg-md-4 > li:nth-of-type(4n + 1) { clear: both; } .am-avg-md-5 > li { width: 20%; } .am-avg-md-5 > li:nth-of-type(n) { clear: none; } .am-avg-md-5 > li:nth-of-type(5n + 1) { clear: both; } .am-avg-md-6 > li { width: 16.66666667%; } .am-avg-md-6 > li:nth-of-type(n) { clear: none; } .am-avg-md-6 > li:nth-of-type(6n + 1) { clear: both; } .am-avg-md-7 > li { width: 14.28571429%; } .am-avg-md-7 > li:nth-of-type(n) { clear: none; } .am-avg-md-7 > li:nth-of-type(7n + 1) { clear: both; } .am-avg-md-8 > li { width: 12.5%; } .am-avg-md-8 > li:nth-of-type(n) { clear: none; } .am-avg-md-8 > li:nth-of-type(8n + 1) { clear: both; } .am-avg-md-9 > li { width: 11.11111111%; } .am-avg-md-9 > li:nth-of-type(n) { clear: none; } .am-avg-md-9 > li:nth-of-type(9n + 1) { clear: both; } .am-avg-md-10 > li { width: 10%; } .am-avg-md-10 > li:nth-of-type(n) { clear: none; } .am-avg-md-10 > li:nth-of-type(10n + 1) { clear: both; } .am-avg-md-11 > li { width: 9.09090909%; } .am-avg-md-11 > li:nth-of-type(n) { clear: none; } .am-avg-md-11 > li:nth-of-type(11n + 1) { clear: both; } .am-avg-md-12 > li { width: 8.33333333%; } .am-avg-md-12 > li:nth-of-type(n) { clear: none; } .am-avg-md-12 > li:nth-of-type(12n + 1) { clear: both; } } @media only screen and (min-width:1025px) { .am-avg-lg-1 > li { width: 100%; } .am-avg-lg-1 > li:nth-of-type(n) { clear: none; } .am-avg-lg-1 > li:nth-of-type(1n + 1) { clear: both; } .am-avg-lg-2 > li { width: 50%; } .am-avg-lg-2 > li:nth-of-type(n) { clear: none; } .am-avg-lg-2 > li:nth-of-type(2n + 1) { clear: both; } .am-avg-lg-3 > li { width: 33.33333333%; } .am-avg-lg-3 > li:nth-of-type(n) { clear: none; } .am-avg-lg-3 > li:nth-of-type(3n + 1) { clear: both; } .am-avg-lg-4 > li { width: 25%; } .am-avg-lg-4 > li:nth-of-type(n) { clear: none; } .am-avg-lg-4 > li:nth-of-type(4n + 1) { clear: both; } .am-avg-lg-5 > li { width: 20%; } .am-avg-lg-5 > li:nth-of-type(n) { clear: none; } .am-avg-lg-5 > li:nth-of-type(5n + 1) { clear: both; } .am-avg-lg-6 > li { width: 16.66666667%; } .am-avg-lg-6 > li:nth-of-type(n) { clear: none; } .am-avg-lg-6 > li:nth-of-type(6n + 1) { clear: both; } .am-avg-lg-7 > li { width: 14.28571429%; } .am-avg-lg-7 > li:nth-of-type(n) { clear: none; } .am-avg-lg-7 > li:nth-of-type(7n + 1) { clear: both; } .am-avg-lg-8 > li { width: 12.5%; } .am-avg-lg-8 > li:nth-of-type(n) { clear: none; } .am-avg-lg-8 > li:nth-of-type(8n + 1) { clear: both; } .am-avg-lg-9 > li { width: 11.11111111%; } .am-avg-lg-9 > li:nth-of-type(n) { clear: none; } .am-avg-lg-9 > li:nth-of-type(9n + 1) { clear: both; } .am-avg-lg-10 > li { width: 10%; } .am-avg-lg-10 > li:nth-of-type(n) { clear: none; } .am-avg-lg-10 > li:nth-of-type(10n + 1) { clear: both; } .am-avg-lg-11 > li { width: 9.09090909%; } .am-avg-lg-11 > li:nth-of-type(n) { clear: none; } .am-avg-lg-11 > li:nth-of-type(11n + 1) { clear: both; } .am-avg-lg-12 > li { width: 8.33333333%; } .am-avg-lg-12 > li:nth-of-type(n) { clear: none; } .am-avg-lg-12 > li:nth-of-type(12n + 1) { clear: both; } } /* ========================================================================== Component: Code ============================================================================ */ /* Inline and block code styles */ code, kbd, pre, samp { font-family: Monaco, Menlo, Consolas, "Courier New", "FontAwesome", monospace; } /* Inline code */ code { padding: 2px 4px; font-size: 1.3rem; color: #c7254e; background-color: #f8f8f8; white-space: nowrap; border-radius: 2px; } /* Code block */ pre { display: block; padding: 1rem; margin: 1rem 0; font-size: 1.3rem; line-height: 1.6; word-break: break-all; word-wrap: break-word; color: #555555; background-color: #f8f8f8; border: 1px solid #dedede; border-radius: 2px; } pre code { padding: 0; font-size: inherit; color: inherit; white-space: pre-wrap; background-color: transparent; border-radius: 0; } /* Enable scrollable blocks of code */ .am-pre-scrollable { max-height: 24rem; overflow-y: scroll; } /* ========================================================================== Component: Button ============================================================================ */ .am-btn { display: inline-block; margin-bottom: 0; padding: 0.5em 1em; vertical-align: middle; font-size: 1.6rem; font-weight: normal; line-height: 1.2; text-align: center; white-space: nowrap; background-image: none; border: 1px solid transparent; border-radius: 2px; cursor: pointer; outline: none; -webkit-appearance: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-transition: background-color 300ms ease-out, border-color 300ms ease-out; transition: background-color 300ms ease-out, border-color 300ms ease-out; } .am-btn.am-square { border-radius: 0; } .am-btn:focus, .am-btn:active:focus { outline: thin dotted; outline: 1px auto -webkit-focus-ring-color; outline-offset: -2px; } .am-btn:hover, .am-btn:focus { color: #444; text-decoration: none; } .am-btn:active, .am-btn.am-active { background-image: none; -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.15); } .am-btn.am-disabled, .am-btn[disabled], fieldset[disabled] .am-btn { pointer-events: none; border-color: transparent; cursor: not-allowed; opacity: 0.45; -webkit-box-shadow: none; box-shadow: none; } .am-btn.am-round { border-radius: 1000px; } .am-btn.am-radius { border-radius: 2px; } .am-btn-default { color: #444; background-color: #e6e6e6; border-color: #e6e6e6; } a.am-btn-default:visited { color: #444; } .am-btn-default:hover, .am-btn-default:focus, .am-btn-default:active, .am-btn-default.am-active, .am-active .am-btn-default.am-dropdown-toggle { color: #444; border-color: #c7c7c7; } .am-btn-default:hover, .am-btn-default:focus { background-color: #d4d4d4; } .am-btn-default:active, .am-btn-default.am-active, .am-active .am-btn-default.am-dropdown-toggle { background-image: none; background-color: #c2c2c2; } .am-btn-default.am-disabled, .am-btn-default[disabled], fieldset[disabled] .am-btn-default, .am-btn-default.am-disabled:hover, .am-btn-default[disabled]:hover, fieldset[disabled] .am-btn-default:hover, .am-btn-default.am-disabled:focus, .am-btn-default[disabled]:focus, fieldset[disabled] .am-btn-default:focus, .am-btn-default.am-disabled:active, .am-btn-default[disabled]:active, fieldset[disabled] .am-btn-default:active, .am-btn-default.am-disabled.am-active, .am-btn-default[disabled].am-active, fieldset[disabled] .am-btn-default.am-active { background-color: #e6e6e6; border-color: #e6e6e6; } .am-btn-group .am-btn-default, .am-btn-group-stacked .am-btn-default { border-color: #d9d9d9; } .am-btn-primary { color: #fff; background-color: #0e90d2; border-color: #0e90d2; } a.am-btn-primary:visited { color: #fff; } .am-btn-primary:hover, .am-btn-primary:focus, .am-btn-primary:active, .am-btn-primary.am-active, .am-active .am-btn-primary.am-dropdown-toggle { color: #fff; border-color: #0a6999; } .am-btn-primary:hover, .am-btn-primary:focus { background-color: #0c79b1; } .am-btn-primary:active, .am-btn-primary.am-active, .am-active .am-btn-primary.am-dropdown-toggle { background-image: none; background-color: #0a628f; } .am-btn-primary.am-disabled, .am-btn-primary[disabled], fieldset[disabled] .am-btn-primary, .am-btn-primary.am-disabled:hover, .am-btn-primary[disabled]:hover, fieldset[disabled] .am-btn-primary:hover, .am-btn-primary.am-disabled:focus, .am-btn-primary[disabled]:focus, fieldset[disabled] .am-btn-primary:focus, .am-btn-primary.am-disabled:active, .am-btn-primary[disabled]:active, fieldset[disabled] .am-btn-primary:active, .am-btn-primary.am-disabled.am-active, .am-btn-primary[disabled].am-active, fieldset[disabled] .am-btn-primary.am-active { background-color: #0e90d2; border-color: #0e90d2; } .am-btn-group .am-btn-primary, .am-btn-group-stacked .am-btn-primary { border-color: #0c80ba; } .am-btn-warning { color: #fff; background-color: #F37B1D; border-color: #F37B1D; } a.am-btn-warning:visited { color: #fff; } .am-btn-warning:hover, .am-btn-warning:focus, .am-btn-warning:active, .am-btn-warning.am-active, .am-active .am-btn-warning.am-dropdown-toggle { color: #fff; border-color: #c85e0b; } .am-btn-warning:hover, .am-btn-warning:focus { background-color: #e0690c; } .am-btn-warning:active, .am-btn-warning.am-active, .am-active .am-btn-warning.am-dropdown-toggle { background-image: none; background-color: #be590a; } .am-btn-warning.am-disabled, .am-btn-warning[disabled], fieldset[disabled] .am-btn-warning, .am-btn-warning.am-disabled:hover, .am-btn-warning[disabled]:hover, fieldset[disabled] .am-btn-warning:hover, .am-btn-warning.am-disabled:focus, .am-btn-warning[disabled]:focus, fieldset[disabled] .am-btn-warning:focus, .am-btn-warning.am-disabled:active, .am-btn-warning[disabled]:active, fieldset[disabled] .am-btn-warning:active, .am-btn-warning.am-disabled.am-active, .am-btn-warning[disabled].am-active, fieldset[disabled] .am-btn-warning.am-active { background-color: #F37B1D; border-color: #F37B1D; } .am-btn-group .am-btn-warning, .am-btn-group-stacked .am-btn-warning { border-color: #ea6e0c; } .am-btn-danger { color: #fff; background-color: #dd514c; border-color: #dd514c; } a.am-btn-danger:visited { color: #fff; } .am-btn-danger:hover, .am-btn-danger:focus, .am-btn-danger:active, .am-btn-danger.am-active, .am-active .am-btn-danger.am-dropdown-toggle { color: #fff; border-color: #c62b26; } .am-btn-danger:hover, .am-btn-danger:focus { background-color: #d7342e; } .am-btn-danger:active, .am-btn-danger.am-active, .am-active .am-btn-danger.am-dropdown-toggle { background-image: none; background-color: #be2924; } .am-btn-danger.am-disabled, .am-btn-danger[disabled], fieldset[disabled] .am-btn-danger, .am-btn-danger.am-disabled:hover, .am-btn-danger[disabled]:hover, fieldset[disabled] .am-btn-danger:hover, .am-btn-danger.am-disabled:focus, .am-btn-danger[disabled]:focus, fieldset[disabled] .am-btn-danger:focus, .am-btn-danger.am-disabled:active, .am-btn-danger[disabled]:active, fieldset[disabled] .am-btn-danger:active, .am-btn-danger.am-disabled.am-active, .am-btn-danger[disabled].am-active, fieldset[disabled] .am-btn-danger.am-active { background-color: #dd514c; border-color: #dd514c; } .am-btn-group .am-btn-danger, .am-btn-group-stacked .am-btn-danger { border-color: #d93c37; } .am-btn-success { color: #fff; background-color: #5eb95e; border-color: #5eb95e; } a.am-btn-success:visited { color: #fff; } .am-btn-success:hover, .am-btn-success:focus, .am-btn-success:active, .am-btn-success.am-active, .am-active .am-btn-success.am-dropdown-toggle { color: #fff; border-color: #429842; } .am-btn-success:hover, .am-btn-success:focus { background-color: #4aaa4a; } .am-btn-success:active, .am-btn-success.am-active, .am-active .am-btn-success.am-dropdown-toggle { background-image: none; background-color: #3f913f; } .am-btn-success.am-disabled, .am-btn-success[disabled], fieldset[disabled] .am-btn-success, .am-btn-success.am-disabled:hover, .am-btn-success[disabled]:hover, fieldset[disabled] .am-btn-success:hover, .am-btn-success.am-disabled:focus, .am-btn-success[disabled]:focus, fieldset[disabled] .am-btn-success:focus, .am-btn-success.am-disabled:active, .am-btn-success[disabled]:active, fieldset[disabled] .am-btn-success:active, .am-btn-success.am-disabled.am-active, .am-btn-success[disabled].am-active, fieldset[disabled] .am-btn-success.am-active { background-color: #5eb95e; border-color: #5eb95e; } .am-btn-group .am-btn-success, .am-btn-group-stacked .am-btn-success { border-color: #4db14d; } .am-btn-secondary { color: #fff; background-color: #3bb4f2; border-color: #3bb4f2; } a.am-btn-secondary:visited { color: #fff; } .am-btn-secondary:hover, .am-btn-secondary:focus, .am-btn-secondary:active, .am-btn-secondary.am-active, .am-active .am-btn-secondary.am-dropdown-toggle { color: #fff; border-color: #0f9ae0; } .am-btn-secondary:hover, .am-btn-secondary:focus { background-color: #19a7f0; } .am-btn-secondary:active, .am-btn-secondary.am-active, .am-active .am-btn-secondary.am-dropdown-toggle { background-image: none; background-color: #0e93d7; } .am-btn-secondary.am-disabled, .am-btn-secondary[disabled], fieldset[disabled] .am-btn-secondary, .am-btn-secondary.am-disabled:hover, .am-btn-secondary[disabled]:hover, fieldset[disabled] .am-btn-secondary:hover, .am-btn-secondary.am-disabled:focus, .am-btn-secondary[disabled]:focus, fieldset[disabled] .am-btn-secondary:focus, .am-btn-secondary.am-disabled:active, .am-btn-secondary[disabled]:active, fieldset[disabled] .am-btn-secondary:active, .am-btn-secondary.am-disabled.am-active, .am-btn-secondary[disabled].am-active, fieldset[disabled] .am-btn-secondary.am-active { background-color: #3bb4f2; border-color: #3bb4f2; } .am-btn-group .am-btn-secondary, .am-btn-group-stacked .am-btn-secondary { border-color: #23abf0; } /* Style links like a button */ .am-btn-link { color: #0e90d2; font-weight: normal; cursor: pointer; border-radius: 0; } .am-btn-link, .am-btn-link:active, .am-btn-link[disabled], fieldset[disabled] .am-btn-link { background-color: transparent; -webkit-box-shadow: none; box-shadow: none; } .am-btn-link, .am-btn-link:hover, .am-btn-link:focus, .am-btn-link:active { border-color: transparent; } .am-btn-link:hover, .am-btn-link:focus { color: #095f8a; text-decoration: underline; background-color: transparent; } .am-btn-link[disabled]:hover, fieldset[disabled] .am-btn-link:hover, .am-btn-link[disabled]:focus, fieldset[disabled] .am-btn-link:focus { color: #999999; text-decoration: none; } /* button size */ .am-btn-xs { font-size: 1.2rem; } .am-btn-sm { font-size: 1.4rem; } .am-btn-lg { font-size: 1.8rem; } .am-btn-xl { font-size: 2rem; } /* Block button */ .am-btn-block { display: block; width: 100%; padding-left: 0; padding-right: 0; } /* Multiple block buttons vertically space */ .am-btn-block + .am-btn-block { margin-top: 5px; } /* Specificity overrides */ input[type="submit"].am-btn-block, input[type="reset"].am-btn-block, input[type="button"].am-btn-block { width: 100%; } /* Button with loading spinner */ .am-btn.am-btn-loading .am-icon-spin { margin-right: 5px; } /* ========================================================================== Component: Table ============================================================================ */ table { max-width: 100%; background-color: transparent; empty-cells: show; } table code { white-space: normal; } th { text-align: left; } .am-table { width: 100%; margin-bottom: 1.6rem; border-spacing: 0; border-collapse: separate; } .am-table > thead > tr > th, .am-table > tbody > tr > th, .am-table > tfoot > tr > th, .am-table > thead > tr > td, .am-table > tbody > tr > td, .am-table > tfoot > tr > td { padding: 0.7rem; line-height: 1.6; vertical-align: top; border-top: 1px solid #ddd; } .am-table > thead > tr > th { vertical-align: bottom; border-bottom: 1px solid #ddd; } .am-table > caption + thead > tr:first-child > th, .am-table > colgroup + thead > tr:first-child > th, .am-table > thead:first-child > tr:first-child > th, .am-table > caption + thead > tr:first-child > td, .am-table > colgroup + thead > tr:first-child > td, .am-table > thead:first-child > tr:first-child > td { border-top: 0; } .am-table > tbody + tbody tr:first-child td { border-top: 2px solid #ddd; } /* Bordered version */ .am-table-bordered { border: 1px solid #ddd; border-left: none; } .am-table-bordered > thead > tr > th, .am-table-bordered > tbody > tr > th, .am-table-bordered > tfoot > tr > th, .am-table-bordered > thead > tr > td, .am-table-bordered > tbody > tr > td, .am-table-bordered > tfoot > tr > td { border-left: 1px solid #ddd; /*&:first-child { border-left: none; }*/ } .am-table-bordered > tbody > tr:first-child > th, .am-table-bordered > tbody > tr:first-child > td { border-top: none; } .am-table-bordered > thead + tbody > tr:first-child > th, .am-table-bordered > thead + tbody > tr:first-child > td { border-top: 1px solid #ddd; } /* Border-radius version */ .am-table-radius { border: 1px solid #ddd; border-radius: 2px; } .am-table-radius > thead > tr:first-child > th:first-child, .am-table-radius > thead > tr:first-child > td:first-child { border-top-left-radius: 2px; border-left: none; } .am-table-radius > thead > tr:first-child > th:last-child, .am-table-radius > thead > tr:first-child > td:last-child { border-top-right-radius: 2px; border-right: none; } .am-table-radius > tbody > tr > th:first-child, .am-table-radius > tbody > tr > td:first-child { border-left: none; } .am-table-radius > tbody > tr > th:last-child, .am-table-radius > tbody > tr > td:last-child { border-right: none; } .am-table-radius > tbody > tr:last-child > th, .am-table-radius > tbody > tr:last-child > td { border-bottom: none; } .am-table-radius > tbody > tr:last-child > th:first-child, .am-table-radius > tbody > tr:last-child > td:first-child { border-bottom-left-radius: 2px; } .am-table-radius > tbody > tr:last-child > th:last-child, .am-table-radius > tbody > tr:last-child > td:last-child { border-bottom-right-radius: 2px; } /* Zebra-striping */ .am-table-striped > tbody > tr:nth-child(odd) > td, .am-table-striped > tbody > tr:nth-child(odd) > th { background-color: #f9f9f9; } /* Hover effect */ .am-table-hover > tbody > tr:hover > td, .am-table-hover > tbody > tr:hover > th { background-color: #e9e9e9; } .am-table-compact > thead > tr > th, .am-table-compact > tbody > tr > th, .am-table-compact > tfoot > tr > th, .am-table-compact > thead > tr > td, .am-table-compact > tbody > tr > td, .am-table-compact > tfoot > tr > td { padding: 0.4rem; } .am-table-centered > thead > tr > th, .am-table-centered > tbody > tr > th, .am-table-centered > tfoot > tr > th, .am-table-centered > thead > tr > td, .am-table-centered > tbody > tr > td, .am-table-centered > tfoot > tr > td { text-align: center; } .am-table > thead > tr > td.am-active, .am-table > tbody > tr > td.am-active, .am-table > tfoot > tr > td.am-active, .am-table > thead > tr > th.am-active, .am-table > tbody > tr > th.am-active, .am-table > tfoot > tr > th.am-active, .am-table > thead > tr.am-active > td, .am-table > tbody > tr.am-active > td, .am-table > tfoot > tr.am-active > td, .am-table > thead > tr.am-active > th, .am-table > tbody > tr.am-active > th, .am-table > tfoot > tr.am-active > th { background-color: #ffd; } .am-table > thead > tr > td.am-disabled, .am-table > tbody > tr > td.am-disabled, .am-table > tfoot > tr > td.am-disabled, .am-table > thead > tr > th.am-disabled, .am-table > tbody > tr > th.am-disabled, .am-table > tfoot > tr > th.am-disabled, .am-table > thead > tr.am-disabled > td, .am-table > tbody > tr.am-disabled > td, .am-table > tfoot > tr.am-disabled > td, .am-table > thead > tr.am-disabled > th, .am-table > tbody > tr.am-disabled > th, .am-table > tfoot > tr.am-disabled > th { color: #999999; } .am-table > thead > tr > td.am-primary, .am-table > tbody > tr > td.am-primary, .am-table > tfoot > tr > td.am-primary, .am-table > thead > tr > th.am-primary, .am-table > tbody > tr > th.am-primary, .am-table > tfoot > tr > th.am-primary, .am-table > thead > tr.am-primary > td, .am-table > tbody > tr.am-primary > td, .am-table > tfoot > tr.am-primary > td, .am-table > thead > tr.am-primary > th, .am-table > tbody > tr.am-primary > th, .am-table > tfoot > tr.am-primary > th { color: #0b76ac; background-color: rgba(14, 144, 210, 0.115); } .am-table > thead > tr > td.am-success, .am-table > tbody > tr > td.am-success, .am-table > tfoot > tr > td.am-success, .am-table > thead > tr > th.am-success, .am-table > tbody > tr > th.am-success, .am-table > tfoot > tr > th.am-success, .am-table > thead > tr.am-success > td, .am-table > tbody > tr.am-success > td, .am-table > tfoot > tr.am-success > td, .am-table > thead > tr.am-success > th, .am-table > tbody > tr.am-success > th, .am-table > tfoot > tr.am-success > th { color: #5eb95e; background-color: rgba(94, 185, 94, 0.115); } .am-table > thead > tr > td.am-warning, .am-table > tbody > tr > td.am-warning, .am-table > tfoot > tr > td.am-warning, .am-table > thead > tr > th.am-warning, .am-table > tbody > tr > th.am-warning, .am-table > tfoot > tr > th.am-warning, .am-table > thead > tr.am-warning > td, .am-table > tbody > tr.am-warning > td, .am-table > tfoot > tr.am-warning > td, .am-table > thead > tr.am-warning > th, .am-table > tbody > tr.am-warning > th, .am-table > tfoot > tr.am-warning > th { color: #F37B1D; background-color: rgba(243, 123, 29, 0.115); } .am-table > thead > tr > td.am-danger, .am-table > tbody > tr > td.am-danger, .am-table > tfoot > tr > td.am-danger, .am-table > thead > tr > th.am-danger, .am-table > tbody > tr > th.am-danger, .am-table > tfoot > tr > th.am-danger, .am-table > thead > tr.am-danger > td, .am-table > tbody > tr.am-danger > td, .am-table > tfoot > tr.am-danger > td, .am-table > thead > tr.am-danger > th, .am-table > tbody > tr.am-danger > th, .am-table > tfoot > tr.am-danger > th { color: #dd514c; background-color: rgba(221, 81, 76, 0.115); } /* ========================================================================== Component: Form ============================================================================ */ /* Normalize */ fieldset { border: none; } legend { display: block; width: 100%; margin-bottom: 2rem; font-size: 2rem; line-height: inherit; color: #333333; border-bottom: 1px solid #e5e5e5; padding-bottom: 0.5rem; } label { display: inline-block; margin-bottom: 5px; font-weight: bold; } input[type="search"] { -webkit-box-sizing: border-box; box-sizing: border-box; } input[type="radio"], input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; /* IE8-9 */ line-height: normal; } input[type="file"] { display: block; } select[multiple], select[size] { height: auto; } select optgroup { font-size: inherit; font-style: inherit; font-family: inherit; } input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: thin dotted; outline: 1px auto -webkit-focus-ring-color; outline-offset: -2px; } input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button { height: auto; } output { display: block; padding-top: 1.6rem; font-size: 1.6rem; line-height: 1.6; color: #555555; vertical-align: middle; } /* Common form controls */ .am-form select, .am-form textarea, .am-form input[type="text"], .am-form input[type="password"], .am-form input[type="datetime"], .am-form input[type="datetime-local"], .am-form input[type="date"], .am-form input[type="month"], .am-form input[type="time"], .am-form input[type="week"], .am-form input[type="number"], .am-form input[type="email"], .am-form input[type="url"], .am-form input[type="search"], .am-form input[type="tel"], .am-form input[type="color"], .am-form-field { display: block; width: 100%; padding: 0.5em; font-size: 1.6rem; line-height: 1.2; color: #555555; vertical-align: middle; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 2px; -webkit-appearance: none; -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; } .am-form select.am-square, .am-form textarea.am-square, .am-form input[type="text"].am-square, .am-form input[type="password"].am-square, .am-form input[type="datetime"].am-square, .am-form input[type="datetime-local"].am-square, .am-form input[type="date"].am-square, .am-form input[type="month"].am-square, .am-form input[type="time"].am-square, .am-form input[type="week"].am-square, .am-form input[type="number"].am-square, .am-form input[type="email"].am-square, .am-form input[type="url"].am-square, .am-form input[type="search"].am-square, .am-form input[type="tel"].am-square, .am-form input[type="color"].am-square, .am-form-field.am-square { border-radius: 0; } .am-form select:focus, .am-form textarea:focus, .am-form input[type="text"]:focus, .am-form input[type="password"]:focus, .am-form input[type="datetime"]:focus, .am-form input[type="datetime-local"]:focus, .am-form input[type="date"]:focus, .am-form input[type="month"]:focus, .am-form input[type="time"]:focus, .am-form input[type="week"]:focus, .am-form input[type="number"]:focus, .am-form input[type="email"]:focus, .am-form input[type="url"]:focus, .am-form input[type="search"]:focus, .am-form input[type="tel"]:focus, .am-form input[type="color"]:focus, .am-form-field:focus { outline: 0; } .am-form select:focus, .am-form textarea:focus, .am-form input[type="text"]:focus, .am-form input[type="password"]:focus, .am-form input[type="datetime"]:focus, .am-form input[type="datetime-local"]:focus, .am-form input[type="date"]:focus, .am-form input[type="month"]:focus, .am-form input[type="time"]:focus, .am-form input[type="week"]:focus, .am-form input[type="number"]:focus, .am-form input[type="email"]:focus, .am-form input[type="url"]:focus, .am-form input[type="search"]:focus, .am-form input[type="tel"]:focus, .am-form input[type="color"]:focus, .am-form-field:focus { background-color: #fefffe; border-color: #3bb4f2; outline: 0; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3); box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(59, 180, 242, 0.3); } .am-form select::-webkit-input-placeholder, .am-form textarea::-webkit-input-placeholder, .am-form input[type="text"]::-webkit-input-placeholder, .am-form input[type="password"]::-webkit-input-placeholder, .am-form input[type="datetime"]::-webkit-input-placeholder, .am-form input[type="datetime-local"]::-webkit-input-placeholder, .am-form input[type="date"]::-webkit-input-placeholder, .am-form input[type="month"]::-webkit-input-placeholder, .am-form input[type="time"]::-webkit-input-placeholder, .am-form input[type="week"]::-webkit-input-placeholder, .am-form input[type="number"]::-webkit-input-placeholder, .am-form input[type="email"]::-webkit-input-placeholder, .am-form input[type="url"]::-webkit-input-placeholder, .am-form input[type="search"]::-webkit-input-placeholder, .am-form input[type="tel"]::-webkit-input-placeholder, .am-form input[type="color"]::-webkit-input-placeholder, .am-form-field::-webkit-input-placeholder { color: #999999; } .am-form select::-moz-placeholder, .am-form textarea::-moz-placeholder, .am-form input[type="text"]::-moz-placeholder, .am-form input[type="password"]::-moz-placeholder, .am-form input[type="datetime"]::-moz-placeholder, .am-form input[type="datetime-local"]::-moz-placeholder, .am-form input[type="date"]::-moz-placeholder, .am-form input[type="month"]::-moz-placeholder, .am-form input[type="time"]::-moz-placeholder, .am-form input[type="week"]::-moz-placeholder, .am-form input[type="number"]::-moz-placeholder, .am-form input[type="email"]::-moz-placeholder, .am-form input[type="url"]::-moz-placeholder, .am-form input[type="search"]::-moz-placeholder, .am-form input[type="tel"]::-moz-placeholder, .am-form input[type="color"]::-moz-placeholder, .am-form-field::-moz-placeholder { color: #999999; } .am-form select:-ms-input-placeholder, .am-form textarea:-ms-input-placeholder, .am-form input[type="text"]:-ms-input-placeholder, .am-form input[type="password"]:-ms-input-placeholder, .am-form input[type="datetime"]:-ms-input-placeholder, .am-form input[type="datetime-local"]:-ms-input-placeholder, .am-form input[type="date"]:-ms-input-placeholder, .am-form input[type="month"]:-ms-input-placeholder, .am-form input[type="time"]:-ms-input-placeholder, .am-form input[type="week"]:-ms-input-placeholder, .am-form input[type="number"]:-ms-input-placeholder, .am-form input[type="email"]:-ms-input-placeholder, .am-form input[type="url"]:-ms-input-placeholder, .am-form input[type="search"]:-ms-input-placeholder, .am-form input[type="tel"]:-ms-input-placeholder, .am-form input[type="color"]:-ms-input-placeholder, .am-form-field:-ms-input-placeholder { color: #999999; } .am-form select::placeholder, .am-form textarea::placeholder, .am-form input[type="text"]::placeholder, .am-form input[type="password"]::placeholder, .am-form input[type="datetime"]::placeholder, .am-form input[type="datetime-local"]::placeholder, .am-form input[type="date"]::placeholder, .am-form input[type="month"]::placeholder, .am-form input[type="time"]::placeholder, .am-form input[type="week"]::placeholder, .am-form input[type="number"]::placeholder, .am-form input[type="email"]::placeholder, .am-form input[type="url"]::placeholder, .am-form input[type="search"]::placeholder, .am-form input[type="tel"]::placeholder, .am-form input[type="color"]::placeholder, .am-form-field::placeholder { color: #999999; } .am-form select::-moz-placeholder, .am-form textarea::-moz-placeholder, .am-form input[type="text"]::-moz-placeholder, .am-form input[type="password"]::-moz-placeholder, .am-form input[type="datetime"]::-moz-placeholder, .am-form input[type="datetime-local"]::-moz-placeholder, .am-form input[type="date"]::-moz-placeholder, .am-form input[type="month"]::-moz-placeholder, .am-form input[type="time"]::-moz-placeholder, .am-form input[type="week"]::-moz-placeholder, .am-form input[type="number"]::-moz-placeholder, .am-form input[type="email"]::-moz-placeholder, .am-form input[type="url"]::-moz-placeholder, .am-form input[type="search"]::-moz-placeholder, .am-form input[type="tel"]::-moz-placeholder, .am-form input[type="color"]::-moz-placeholder, .am-form-field::-moz-placeholder { opacity: 1; } .am-form select[disabled], .am-form textarea[disabled], .am-form input[type="text"][disabled], .am-form input[type="password"][disabled], .am-form input[type="datetime"][disabled], .am-form input[type="datetime-local"][disabled], .am-form input[type="date"][disabled], .am-form input[type="month"][disabled], .am-form input[type="time"][disabled], .am-form input[type="week"][disabled], .am-form input[type="number"][disabled], .am-form input[type="email"][disabled], .am-form input[type="url"][disabled], .am-form input[type="search"][disabled], .am-form input[type="tel"][disabled], .am-form input[type="color"][disabled], .am-form-field[disabled], .am-form select[readonly], .am-form textarea[readonly], .am-form input[type="text"][readonly], .am-form input[type="password"][readonly], .am-form input[type="datetime"][readonly], .am-form input[type="datetime-local"][readonly], .am-form input[type="date"][readonly], .am-form input[type="month"][readonly], .am-form input[type="time"][readonly], .am-form input[type="week"][readonly], .am-form input[type="number"][readonly], .am-form input[type="email"][readonly], .am-form input[type="url"][readonly], .am-form input[type="search"][readonly], .am-form input[type="tel"][readonly], .am-form input[type="color"][readonly], .am-form-field[readonly], fieldset[disabled] .am-form select, fieldset[disabled] .am-form textarea, fieldset[disabled] .am-form input[type="text"], fieldset[disabled] .am-form input[type="password"], fieldset[disabled] .am-form input[type="datetime"], fieldset[disabled] .am-form input[type="datetime-local"], fieldset[disabled] .am-form input[type="date"], fieldset[disabled] .am-form input[type="month"], fieldset[disabled] .am-form input[type="time"], fieldset[disabled] .am-form input[type="week"], fieldset[disabled] .am-form input[type="number"], fieldset[disabled] .am-form input[type="email"], fieldset[disabled] .am-form input[type="url"], fieldset[disabled] .am-form input[type="search"], fieldset[disabled] .am-form input[type="tel"], fieldset[disabled] .am-form input[type="color"], fieldset[disabled] .am-form-field { cursor: not-allowed; background-color: #eeeeee; } .am-form select.am-radius, .am-form textarea.am-radius, .am-form input[type="text"].am-radius, .am-form input[type="password"].am-radius, .am-form input[type="datetime"].am-radius, .am-form input[type="datetime-local"].am-radius, .am-form input[type="date"].am-radius, .am-form input[type="month"].am-radius, .am-form input[type="time"].am-radius, .am-form input[type="week"].am-radius, .am-form input[type="number"].am-radius, .am-form input[type="email"].am-radius, .am-form input[type="url"].am-radius, .am-form input[type="search"].am-radius, .am-form input[type="tel"].am-radius, .am-form input[type="color"].am-radius, .am-form-field.am-radius { border-radius: 2px; } .am-form select.am-round, .am-form textarea.am-round, .am-form input[type="text"].am-round, .am-form input[type="password"].am-round, .am-form input[type="datetime"].am-round, .am-form input[type="datetime-local"].am-round, .am-form input[type="date"].am-round, .am-form input[type="month"].am-round, .am-form input[type="time"].am-round, .am-form input[type="week"].am-round, .am-form input[type="number"].am-round, .am-form input[type="email"].am-round, .am-form input[type="url"].am-round, .am-form input[type="search"].am-round, .am-form input[type="tel"].am-round, .am-form input[type="color"].am-round, .am-form-field.am-round { border-radius: 1000px; } .am-form textarea, .am-form select[multiple], .am-form select[size] { height: auto; } .am-form select { -webkit-appearance: none !important; -moz-appearance: none !important; -webkit-border-radius: 2px; background: #fff url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+') no-repeat 100% center; } .am-form select[multiple="multiple"] { background-image: none; } /* help text */ .am-form-help { display: block; margin-top: 5px; margin-bottom: 10px; color: #999999; font-size: 1.3rem; } /* form group */ .am-form-group { margin-bottom: 1.5rem; } /* file field */ .am-form-file { position: relative; overflow: hidden; } .am-form-file input[type="file"] { position: absolute; left: 0; top: 0; z-index: 1; width: 100%; opacity: 0; cursor: pointer; font-size: 50rem; } /** * Checkboxes and radios * Indent the labels to position radios/checkboxes as hanging controls. */ .am-radio, .am-checkbox { display: block; min-height: 1.92rem; margin-top: 10px; margin-bottom: 10px; padding-left: 20px; vertical-align: middle; } .am-radio label, .am-checkbox label { display: inline; margin-bottom: 0; font-weight: normal; cursor: pointer; } .am-radio input[type="radio"], .am-radio-inline input[type="radio"], .am-checkbox input[type="checkbox"], .am-checkbox-inline input[type="checkbox"] { float: left; margin-left: -20px; outline: none; } .am-radio + .am-radio, .am-checkbox + .am-checkbox { margin-top: -5px; } /* Radios and checkboxes inline */ .am-radio-inline, .am-checkbox-inline { display: inline-block; padding-left: 20px; margin-bottom: 0; vertical-align: middle; font-weight: normal; cursor: pointer; } .am-radio-inline + .am-radio-inline, .am-checkbox-inline + .am-checkbox-inline { margin-top: 0; margin-left: 10px; } input[type="radio"][disabled], input[type="checkbox"][disabled], .am-radio[disabled], .am-radio-inline[disabled], .am-checkbox[disabled], .am-checkbox-inline[disabled], fieldset[disabled] input[type="radio"], fieldset[disabled] input[type="checkbox"], fieldset[disabled] .am-radio, fieldset[disabled] .am-radio-inline, fieldset[disabled] .am-checkbox, fieldset[disabled] .am-checkbox-inline { cursor: not-allowed; } /* Form field feedback states */ .am-form-warning .am-form-help, .am-form-warning .am-form-label, .am-form-warning .am-radio, .am-form-warning .am-checkbox, .am-form-warning .am-radio-inline, .am-form-warning .am-checkbox-inline, .am-form-warning label { color: #F37B1D; } .am-form-warning [class*="icon-"] { color: #F37B1D; } .am-form-warning .am-form-field { border-color: #F37B1D !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .am-form-warning .am-form-field:focus { background-color: #fefffe; border-color: #d2620b; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #f8b47e !important; } .am-form-error .am-form-help, .am-form-error .am-form-label, .am-form-error .am-radio, .am-form-error .am-checkbox, .am-form-error .am-radio-inline, .am-form-error .am-checkbox-inline, .am-form-error label { color: #dd514c; } .am-form-error [class*="icon-"] { color: #dd514c; } .am-form-error .am-form-field, .am-field-error { border-color: #dd514c !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .am-form-error .am-form-field:focus, .am-field-error:focus { background-color: #fefffe; border-color: #cf2d27; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #eda4a2 !important; } .am-form-success .am-form-help, .am-form-success .am-form-label, .am-form-success .am-radio, .am-form-success .am-checkbox, .am-form-success .am-radio-inline, .am-form-success .am-checkbox-inline, .am-form-success label { color: #5eb95e; } .am-form-success [class*="icon-"] { color: #5eb95e; } .am-form-success .am-form-field, .am-field-valid { border-color: #5eb95e !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .am-form-success .am-form-field:focus, .am-field-valid:focus { background-color: #fefffe; border-color: #459f45; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px #a5d8a5 !important; } /* Horizontal forms */ .am-form-horizontal .am-form-label, .am-form-horizontal .am-radio, .am-form-horizontal .am-checkbox, .am-form-horizontal .am-radio-inline, .am-form-horizontal .am-checkbox-inline { margin-top: 0; margin-bottom: 0; padding-top: 0.6em; } .am-form-horizontal .am-form-group:before, .am-form-horizontal .am-form-group:after { content: " "; display: table; } .am-form-horizontal .am-form-group:after { clear: both; } @media only screen and (min-width:641px) { .am-form-horizontal .am-form-label { text-align: right; } } /* Inline form elements */ @media only screen and (min-width:641px) { .am-form-inline .am-form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .am-form-inline .am-form-field { display: inline-block; width: auto; vertical-align: middle; } .am-form-inline .am-input-group { display: inline-table; vertical-align: middle; } .am-form-inline .am-input-group .am-input-group-label, .am-form-inline .am-input-group .am-input-group-btn, .am-form-inline .am-input-group .am-form-label { width: auto; } .am-form-inline .am-input-group > .am-form-field { width: 100%; } .am-form-inline .am-form-label { margin-bottom: 0; vertical-align: middle; } .am-form-inline .am-radio, .am-form-inline .am-checkbox { display: inline-block; margin-top: 0; margin-bottom: 0; padding-left: 0; vertical-align: middle; } .am-form-inline .am-radio input[type="radio"], .am-form-inline .am-checkbox input[type="checkbox"] { float: none; margin-left: 0; } } /* Form field size */ .am-input-sm { font-size: 1.4rem !important; } .am-input-lg { font-size: 1.8rem !important; } .am-form-group-sm .am-checkbox, .am-form-group-sm .am-radio, .am-form-group-sm .am-form-label, .am-form-group-sm .am-form-field { font-size: 1.4rem !important; } .am-form-group-lg .am-checkbox, .am-form-group-lg .am-radio, .am-form-group-lg .am-form-label, .am-form-group-lg .am-form-field { font-size: 1.8rem !important; } .am-form-group-lg input[type="radio"], .am-form-group-lg input[type="checkbox"] { margin-top: 7px; } /* Form field feedback states */ .am-form-icon { position: relative; } .am-form-icon .am-form-field { padding-left: 1.75em !important; } .am-form-icon [class*='am-icon-'] { position: absolute; left: 0.5em; top: 50%; display: block; margin-top: -0.5em; line-height: 1; z-index: 2; } .am-form-icon label ~ [class*='am-icon-'] { top: 70%; } /* Feedback Icon */ .am-form-feedback { position: relative; } .am-form-feedback .am-form-field { padding-left: 0.5em !important; padding-right: 1.75em !important; } .am-form-feedback [class*='am-icon-'] { right: 0.5em; left: auto; } .am-form-horizontal .am-form-feedback [class*='am-icon-'] { right: 1.6em; } /* Form set */ .am-form-set { margin-bottom: 1.5rem; padding: 0; } .am-form-set > input { position: relative; top: -1px; border-radius: 0 !important; } .am-form-set > input:focus { z-index: 2; } .am-form-set > input:first-child { top: 1px; border-top-right-radius: 2px !important; border-top-left-radius: 2px !important; } .am-form-set > input:last-child { top: -2px; border-bottom-right-radius: 2px !important; border-bottom-left-radius: 2px !important; } /* ========================================================================== Component: Image ============================================================================ */ /* Image thumbnails */ .am-img-thumbnail { display: inline-block; max-width: 100%; height: auto; padding: 2px; line-height: 1.6; background-color: #fff; border: 1px solid #ddd; border-radius: 2px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; } .am-img-thumbnail.am-radius { border-radius: 2px; } .am-img-responsive { display: block; max-width: 100%; height: auto; } /* ========================================================================== Component: Nav ============================================================================ */ .am-nav { margin-bottom: 0; padding: 0; list-style: none; } .am-nav:before, .am-nav:after { content: " "; display: table; } .am-nav:after { clear: both; } .am-nav > li { position: relative; display: block; } .am-nav > li + li { margin-top: 5px; } .am-nav > li + .am-nav-header { margin-top: 1em; } .am-nav > li > a { position: relative; display: block; padding: 0.4em 1em; border-radius: 2px; } .am-nav > li > a:hover, .am-nav > li > a:focus { text-decoration: none; background-color: #eeeeee; } .am-nav > li.am-active > a, .am-nav > li.am-active > a:hover, .am-nav > li.am-active > a:focus { color: #fff; background-color: #0e90d2; cursor: default; } .am-nav > li.am-disabled > a { color: #999999; } .am-nav > li.am-disabled > a:hover, .am-nav > li.am-disabled > a:focus { color: #999999; text-decoration: none; background-color: transparent; cursor: not-allowed; } .am-nav-header { padding: 0.4em 1em; text-transform: uppercase; font-weight: bold; font-size: 100%; color: #555555; } .am-nav-divider { margin: 15px 1em !important; border-top: 1px solid #ddd; -webkit-box-shadow: 0 1px 0 #fff; box-shadow: 0 1px 0 #fff; } .am-nav-pills > li { float: left; } .am-nav-pills > li + li { margin-left: 5px; margin-top: 0; } .am-nav-tabs { border-bottom: 1px solid #ddd; } .am-nav-tabs > li { float: left; margin-bottom: -1px; } .am-nav-tabs > li + li { margin-top: 0; } .am-nav-tabs > li > a { margin-right: 5px; line-height: 1.6; border: 1px solid transparent; border-radius: 2px 2px 0 0; } .am-nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #ddd; } .am-nav-tabs > li.am-active > a, .am-nav-tabs > li.am-active > a:hover, .am-nav-tabs > li.am-active > a:focus { color: #555555; background-color: #fff; border: 1px solid #ddd; border-bottom-color: transparent; cursor: default; } .am-nav-tabs.am-nav-justify { border-bottom: 0; /* > li > a { margin-right: 0; border-radius: @global-radius; } > .am-active > a { &, &:hover, &:focus { border: 1px solid @nav-tabs-justify-link-border-color; } }*/ } .am-nav-tabs.am-nav-justify > li > a { margin-right: 0; border-bottom: 1px solid #ddd; border-radius: 2px 2px 0 0; } .am-nav-tabs.am-nav-justify > .am-active > a, .am-nav-tabs.am-nav-justify > .am-active > a:hover, .am-nav-tabs.am-nav-justify > .am-active > a:focus { border-bottom-color: #fff; } .am-nav-justify { width: 100%; display: table; } .am-nav-justify > li { float: none; display: table-cell; width: 1%; } .am-nav-justify > li > a { text-align: center; margin-bottom: 0; } .lte9 .am-nav-justify > li { display: table-cell; width: 1%; } /* ========================================================================== Component: Topbar ============================================================================ */ .am-topbar { position: relative; min-height: 50px; margin-bottom: 1.6rem; background: #f8f8f8; border-width: 0 0 1px; border-style: solid; border-color: #ddd; color: #666; } .am-topbar:before, .am-topbar:after { content: " "; display: table; } .am-topbar:after { clear: both; } .am-topbar a { color: #666; } .am-topbar-brand { margin: 0; } @media only screen and (min-width:641px) { .am-topbar-brand { float: left; } } .am-topbar-brand a:hover { color: #4d4d4d; } .am-topbar-collapse { width: 100%; overflow-x: visible; padding: 10px; clear: both; -webkit-overflow-scrolling: touch; } .am-topbar-collapse:before, .am-topbar-collapse:after { content: " "; display: table; } .am-topbar-collapse:after { clear: both; } .am-topbar-collapse.am-in { overflow-y: auto; } @media only screen and (min-width:641px) { .am-topbar-collapse { margin-top: 0; padding: 0; width: auto; clear: none; } .am-topbar-collapse.am-collapse { display: block !important; height: auto !important; padding: 0; overflow: visible !important; } .am-topbar-collapse.am-in { overflow-y: visible; } } .am-topbar-brand { padding: 0 10px; float: left; font-size: 1.8rem; height: 50px; line-height: 50px; } .am-topbar-toggle { position: relative; float: right; margin-right: 10px; } @media only screen and (min-width:641px) { .am-topbar-toggle { display: none; } } @media only screen and (max-width: 640px) { .am-topbar-nav { margin-bottom: 8px; } .am-topbar-nav > li { float: none; } } @media only screen and (max-width: 640px) { .am-topbar-nav > li + li { margin-left: 0; margin-top: 5px; } } @media only screen and (min-width:641px) { .am-topbar-nav { float: left; } .am-topbar-nav > li > a { position: relative; line-height: 50px; padding: 0 10px; } .am-topbar-nav > li > a:after { position: absolute; left: 50%; margin-left: -7px; bottom: -1px; content: ""; display: inline-block; width: 0; height: 0; vertical-align: middle; border-bottom: 7px solid #f8f8f8; border-right: 7px solid transparent; border-left: 7px solid transparent; border-top: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); opacity: 0; -webkit-transition: opacity .1s; transition: opacity .1s; } .am-topbar-nav > li > a:hover:after { opacity: 1; border-bottom-color: #666; } .am-topbar-nav > li.am-dropdown > a:after { display: none; } .am-topbar-nav > li.am-active > a, .am-topbar-nav > li.am-active > a:hover, .am-topbar-nav > li.am-active > a:focus { border-radius: 0; color: #0e90d2; background: none; } .am-topbar-nav > li.am-active > a:after { opacity: 1; border-bottom-color: #0e90d2; } } @media only screen and (max-width: 640px) { .am-topbar-collapse .am-dropdown.am-active .am-dropdown-content { float: none; position: relative; width: 100%; } } @media only screen and (min-width:641px) { .am-topbar-left { float: left; } .am-topbar-right { float: right; margin-right: 10px; } } @media only screen and (max-width: 640px) { .am-topbar-form .am-form-group { margin-bottom: 5px; } } @media only screen and (min-width:641px) { .am-topbar-form { padding: 0 10px; margin-top: 8px; } .am-topbar-form .am-form-group + .am-btn { margin-left: 5px; } } .am-topbar-btn { margin-top: 8px; } @media only screen and (max-width: 640px) { .am-topbar-collapse .am-topbar-btn, .am-topbar-collapse .am-btn { display: block; width: 100%; } } .am-topbar-inverse { background-color: #0e90d2; border-color: #0b6fa2; color: #eeeeee; } .am-topbar-inverse a { color: #eeeeee; } .am-topbar-inverse .am-topbar-brand a { color: #fff; } .am-topbar-inverse .am-topbar-brand a:hover, .am-topbar-inverse .am-topbar-brand a:focus { color: #fff; background-color: transparent; } .am-topbar-inverse .am-topbar-nav > li > a { color: #eeeeee; } .am-topbar-inverse .am-topbar-nav > li > a:hover, .am-topbar-inverse .am-topbar-nav > li > a:focus { color: #fff; background-color: rgba(0, 0, 0, 0.05); } .am-topbar-inverse .am-topbar-nav > li > a:hover:after, .am-topbar-inverse .am-topbar-nav > li > a:focus:after { border-bottom-color: #0b6fa2; } .am-topbar-inverse .am-topbar-nav > li > a:after { border-bottom-color: #0e90d2; } .am-topbar-inverse .am-topbar-nav > li.am-active > a, .am-topbar-inverse .am-topbar-nav > li.am-active > a:hover, .am-topbar-inverse .am-topbar-nav > li.am-active > a:focus { color: #fff; background-color: rgba(0, 0, 0, 0.1); } .am-topbar-inverse .am-topbar-nav > li.am-active > a:after, .am-topbar-inverse .am-topbar-nav > li.am-active > a:hover:after, .am-topbar-inverse .am-topbar-nav > li.am-active > a:focus:after { border-bottom-color: #fff; } .am-topbar-inverse .am-topbar-nav > li .disabled > a, .am-topbar-inverse .am-topbar-nav > li .disabled > a:hover, .am-topbar-inverse .am-topbar-nav > li .disabled > a:focus { color: #444; background-color: transparent; } .am-topbar-fixed-top, .am-topbar-fixed-bottom { position: fixed; right: 0; left: 0; z-index: 1000; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } .am-topbar-fixed-top { top: 0; } .am-topbar-fixed-bottom { bottom: 0; margin-bottom: 0; border-width: 1px 0 0; } .am-with-topbar-fixed-top { padding-top: 51px; } .am-with-topbar-fixed-bottom { padding-bottom: 51px; } @media only screen and (max-width: 640px) { .am-topbar-fixed-bottom .am-topbar-collapse { position: absolute; bottom: 100%; margin-bottom: 1px; background-color: #f8f8f8; } .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:before, .am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:after { display: none; } .am-topbar-fixed-bottom.am-topbar-inverse .am-topbar-collapse { background-color: #0e90d2; } } /* ========================================================================== Component: Breadcrumb ============================================================================ */ .am-breadcrumb { padding: .7em .5em; margin-bottom: 2rem; list-style: none; background-color: transparent; border-radius: 2px; font-size: 85%; } .am-breadcrumb > li { display: inline-block; } .am-breadcrumb > li [class*="am-icon-"]:before { color: #999999; margin-right: 5px; } .am-breadcrumb > li + li:before { content: "»\00a0"; padding: 0 8px; color: #ccc; } .am-breadcrumb > .am-active { color: #999999; } .am-breadcrumb-slash > li + li:before { content: "/\00a0"; } /* ========================================================================== Component: Pagination ============================================================================ */ .am-pagination { padding-left: 0; margin: 1.5rem 0; list-style: none; color: #999999; text-align: left; } .am-pagination:before, .am-pagination:after { content: " "; display: table; } .am-pagination:after { clear: both; } .am-pagination > li { display: inline-block; } .am-pagination > li > a, .am-pagination > li > span { position: relative; display: block; padding: 0.5em 1em; text-decoration: none; line-height: 1.2; background-color: #fff; border: 1px solid #ddd; border-radius: 2px; margin-bottom: 5px; margin-right: 5px; } .am-pagination > li:last-child > a, .am-pagination > li:last-child > span { margin-right: 0; } .am-pagination > li > a:hover, .am-pagination > li > span:hover, .am-pagination > li > a:focus, .am-pagination > li > span:focus { background-color: #eeeeee; } .am-pagination > .am-active > a, .am-pagination > .am-active > span, .am-pagination > .am-active > a:hover, .am-pagination > .am-active > span:hover, .am-pagination > .am-active > a:focus, .am-pagination > .am-active > span:focus { z-index: 2; color: #fff; background-color: #0e90d2; border-color: #0e90d2; cursor: default; } .am-pagination > .am-disabled > span, .am-pagination > .am-disabled > span:hover, .am-pagination > .am-disabled > span:focus, .am-pagination > .am-disabled > a, .am-pagination > .am-disabled > a:hover, .am-pagination > .am-disabled > a:focus { color: #999999; background-color: #fff; border-color: #ddd; cursor: not-allowed; pointer-events: none; } .am-pagination .am-pagination-prev { float: left; } .am-pagination .am-pagination-prev a { border-radius: 2px; } .am-pagination .am-pagination-next { float: right; } .am-pagination .am-pagination-next a { border-radius: 2px; } .am-pagination-centered { text-align: center; } .am-pagination-right { text-align: right; } /* ========================================================================== Component: Aniamtion ============================================================================ */ [class*="am-animation-"] { -webkit-animation-duration: 0.5s; animation-duration: 0.5s; -webkit-animation-timing-function: ease-out; animation-timing-function: ease-out; -webkit-animation-fill-mode: both; animation-fill-mode: both; } /* Hide animated element if scrollSpy is used */ @media screen { .cssanimations [data-am-scrollspy*="animation"] { opacity: 0; } } /* Fade */ .am-animation-fade { -webkit-animation-name: am-fade; animation-name: am-fade; -webkit-animation-duration: 0.8s; animation-duration: 0.8s; -webkit-animation-timing-function: linear; animation-timing-function: linear; } /* Scale */ .am-animation-scale-up { -webkit-animation-name: am-scale-up; animation-name: am-scale-up; } .am-animation-scale-down { -webkit-animation-name: am-scale-down; animation-name: am-scale-down; } /* Slide */ .am-animation-slide-top { -webkit-animation-name: am-slide-top; animation-name: am-slide-top; } .am-animation-slide-bottom { -webkit-animation-name: am-slide-bottom; animation-name: am-slide-bottom; } .am-animation-slide-left { -webkit-animation-name: am-slide-left; animation-name: am-slide-left; } .am-animation-slide-right { -webkit-animation-name: am-slide-right; animation-name: am-slide-right; } .am-animation-slide-top-fixed { -webkit-animation-name: am-slide-top-fixed; animation-name: am-slide-top-fixed; } /* Shake */ .am-animation-shake { -webkit-animation-name: am-shake; animation-name: am-shake; } /* Spin */ .am-animation-spin { -webkit-animation: am-spin 2s infinite linear; animation: am-spin 2s infinite linear; } /* Spring */ .am-animation-left-spring { -webkit-animation: am-left-spring 0.3s ease-in-out; animation: am-left-spring 0.3s ease-in-out; } .am-animation-right-spring { -webkit-animation: am-right-spring 0.3s ease-in-out; animation: am-right-spring 0.3s ease-in-out; } .am-animation-reverse { -webkit-animation-direction: reverse; animation-direction: reverse; } .am-animation-paused { -webkit-animation-play-state: paused !important; animation-play-state: paused !important; } .am-animation-delay-1 { -webkit-animation-delay: 1s; animation-delay: 1s; } .am-animation-delay-2 { -webkit-animation-delay: 2s; animation-delay: 2s; } .am-animation-delay-3 { -webkit-animation-delay: 3s; animation-delay: 3s; } .am-animation-delay-4 { -webkit-animation-delay: 4s; animation-delay: 4s; } .am-animation-delay-5 { -webkit-animation-delay: 5s; animation-delay: 5s; } .am-animation-delay-6 { -webkit-animation-delay: 6s; animation-delay: 6s; } /* Keyframes ============================================================================ */ /* Fade */ @-webkit-keyframes am-fade { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes am-fade { 0% { opacity: 0; } 100% { opacity: 1; } } /* Scale up */ @-webkit-keyframes am-scale-up { 0% { opacity: 0; -webkit-transform: scale(0.2); transform: scale(0.2); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } @keyframes am-scale-up { 0% { opacity: 0; -webkit-transform: scale(0.2); transform: scale(0.2); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } /* Scale down */ @-webkit-keyframes am-scale-down { 0% { opacity: 0; -webkit-transform: scale(1.8); transform: scale(1.8); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } @keyframes am-scale-down { 0% { opacity: 0; -webkit-transform: scale(1.8); transform: scale(1.8); } 100% { opacity: 1; -webkit-transform: scale(1); transform: scale(1); } } /* Slide top */ @-webkit-keyframes am-slide-top { 0% { opacity: 0; -webkit-transform: translateY(-100%); transform: translateY(-100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-top { 0% { opacity: 0; -webkit-transform: translateY(-100%); transform: translateY(-100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Slide bottom */ @-webkit-keyframes am-slide-bottom { 0% { opacity: 0; -webkit-transform: translateY(100%); transform: translateY(100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-bottom { 0% { opacity: 0; -webkit-transform: translateY(100%); transform: translateY(100%); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Slide left */ @-webkit-keyframes am-slide-left { 0% { opacity: 0; -webkit-transform: translateX(-100%); transform: translateX(-100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-slide-left { 0% { opacity: 0; -webkit-transform: translateX(-100%); transform: translateX(-100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } /* Slide right */ @-webkit-keyframes am-slide-right { 0% { opacity: 0; -webkit-transform: translateX(100%); transform: translateX(100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-slide-right { 0% { opacity: 0; -webkit-transform: translateX(100%); transform: translateX(100%); } 100% { opacity: 1; -webkit-transform: translateX(0); transform: translateX(0); } } /* Shake */ @-webkit-keyframes am-shake { 0%, 100% { -webkit-transform: translateX(0); transform: translateX(0); } 10% { -webkit-transform: translateX(-9px); transform: translateX(-9px); } 20% { -webkit-transform: translateX(8px); transform: translateX(8px); } 30% { -webkit-transform: translateX(-7px); transform: translateX(-7px); } 40% { -webkit-transform: translateX(6px); transform: translateX(6px); } 50% { -webkit-transform: translateX(-5px); transform: translateX(-5px); } 60% { -webkit-transform: translateX(4px); transform: translateX(4px); } 70% { -webkit-transform: translateX(-3px); transform: translateX(-3px); } 80% { -webkit-transform: translateX(2px); transform: translateX(2px); } 90% { -webkit-transform: translateX(-1px); transform: translateX(-1px); } } @keyframes am-shake { 0%, 100% { -webkit-transform: translateX(0); transform: translateX(0); } 10% { -webkit-transform: translateX(-9px); transform: translateX(-9px); } 20% { -webkit-transform: translateX(8px); transform: translateX(8px); } 30% { -webkit-transform: translateX(-7px); transform: translateX(-7px); } 40% { -webkit-transform: translateX(6px); transform: translateX(6px); } 50% { -webkit-transform: translateX(-5px); transform: translateX(-5px); } 60% { -webkit-transform: translateX(4px); transform: translateX(4px); } 70% { -webkit-transform: translateX(-3px); transform: translateX(-3px); } 80% { -webkit-transform: translateX(2px); transform: translateX(2px); } 90% { -webkit-transform: translateX(-1px); transform: translateX(-1px); } } /* Slide top fixed */ @-webkit-keyframes am-slide-top-fixed { 0% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-top-fixed { 0% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Slide bottom fixed */ @-webkit-keyframes am-slide-bottom-fixed { 0% { opacity: 0; -webkit-transform: translateY(10px); transform: translateY(10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } @keyframes am-slide-bottom-fixed { 0% { opacity: 0; -webkit-transform: translateY(10px); transform: translateY(10px); } 100% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } } /* Spin */ @-webkit-keyframes am-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } @keyframes am-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } /* Spring */ @-webkit-keyframes am-right-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(-20%); transform: translateX(-20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-right-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(-20%); transform: translateX(-20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } @-webkit-keyframes am-left-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(20%); transform: translateX(20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } @keyframes am-left-spring { 0% { -webkit-transform: translateX(0); transform: translateX(0); } 50% { -webkit-transform: translateX(20%); transform: translateX(20%); } 100% { -webkit-transform: translateX(0); transform: translateX(0); } } /* ========================================================================== Component: Article ============================================================================ */ .am-article:before, .am-article:after { content: " "; display: table; } .am-article:after { clear: both; } .am-article > :last-child { margin-bottom: 0; } .am-article + .am-article { margin-top: 2.4rem; } /* Sub-object `.@{ns}article-title` */ .am-article-title { font-size: 2.8rem; line-height: 1.15; font-weight: normal; } .am-article-title a { color: inherit; text-decoration: none; } /* Sub-object `.@{ns}article-meta` */ .am-article-meta { font-size: 1.2rem; line-height: 1.5; color: #999999; } /* Sub-object `.@{ns}article-lead` */ .am-article-lead { color: #666; font-size: 1.4rem; line-height: 1.5; border: 1px solid #dedede; border-radius: 2px; background: #f9f9f9; padding: 10px; } /* Sub-object `.@{ns}article-divider` */ .am-article-divider { margin-bottom: 2.4rem; border-color: #eeeeee; } * + .am-article-divider { margin-top: 2.4rem; } /* Sub-object `.@{ns}article-bd` */ .am-article-bd blockquote { font-family: Georgia, "Times New Roman", Times, Kai, "Kaiti SC", KaiTi, BiauKai, "FontAwesome", serif; } .am-article-bd img { display: block; max-width: 100%; } /* ========================================================================== Component: Badge ============================================================================ */ .am-badge { display: inline-block; min-width: 10px; padding: 0.25em 0.625em; font-size: 1.2rem; font-weight: bold; color: #fff; line-height: 1; vertical-align: baseline; white-space: nowrap; text-align: center; background-color: #999999; border-radius: 0; } .am-badge:empty { display: none; } .am-badge.am-square { border-radius: 0; } .am-badge.am-radius { border-radius: 2px; } .am-badge.am-round { border-radius: 1000px; } a.am-badge:hover, a.am-badge:focus { color: #fff; text-decoration: none; cursor: pointer; } .am-badge-primary { background-color: #0e90d2; } .am-badge-secondary { background-color: #3bb4f2; } .am-badge-success { background-color: #5eb95e; } .am-badge-warning { background-color: #F37B1D; } .am-badge-danger { background-color: #dd514c; } /* ========================================================================== Component: Comment ============================================================================ */ .am-comment:before, .am-comment:after { content: " "; display: table; } .am-comment:after { clear: both; } .am-comment-avatar { float: left; width: 32px; height: 32px; border-radius: 50%; border: 1px solid transparent; } @media only screen and (min-width:641px) { .am-comment-avatar { width: 48px; height: 48px; } } .am-comment-main { position: relative; margin-left: 42px; border: 1px solid #dedede; border-radius: 2px; } .am-comment-main:before, .am-comment-main:after { position: absolute; top: 10px; left: -8px; right: 100%; width: 0; height: 0; display: block; content: " "; border-color: transparent; border-style: solid solid outset; border-width: 8px 8px 8px 0; pointer-events: none; } .am-comment-main:before { border-right-color: #dedede; z-index: 1; } .am-comment-main:after { border-right-color: #f8f8f8; margin-left: 1px; z-index: 2; } @media only screen and (min-width:641px) { .am-comment-main { margin-left: 63px; } } .am-comment-hd { background: #f8f8f8; border-bottom: 1px solid #eee; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } .am-comment-title { margin: 0 0 8px 0; font-size: 1.6rem; line-height: 1.2; } .am-comment-meta { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; padding: 10px 15px; font-size: 13px; color: #999999; line-height: 1.2; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .am-comment-meta a { color: #999999; } .am-comment-author { font-weight: bold; color: #999999; } .am-comment-bd { padding: 15px; overflow: hidden; } .am-comment-bd > :last-child { margin-bottom: 0; } .am-comment-footer { padding: 0 15px 5px; } .am-comment-footer .am-comment-actions a + a { margin-left: 5px; } .am-comment-actions { font-size: 13px; color: #999999; } .am-comment-actions a { display: inline-block; padding: 10px 5px; line-height: 1; color: #999999; opacity: .7; } .am-comment-actions a:hover { color: #0e90d2; opacity: 1; } .am-comment-hd .am-comment-actions { padding-right: .5rem; } .am-comment-flip .am-comment-avatar { float: right; } .am-comment-flip .am-comment-main { margin-left: auto; margin-right: 42px; } @media only screen and (min-width:641px) { .am-comment-flip .am-comment-main { margin-right: 63px; } } .am-comment-flip .am-comment-main:before, .am-comment-flip .am-comment-main:after { left: auto; right: -8px; border-width: 8px 0 8px 8px; } .am-comment-flip .am-comment-main:before { border-left-color: #dedede; } .am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; margin-right: 1px; margin-left: auto; } .am-comment-primary .am-comment-avatar { border-color: #0e90d2; } .am-comment-primary .am-comment-main { border-color: #0e90d2; } .am-comment-primary .am-comment-main:before { border-right-color: #0e90d2; } .am-comment-primary.am-comment-flip .am-comment-main:before { border-left-color: #0e90d2; border-right-color: transparent; } .am-comment-primary.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-secondary .am-comment-avatar, .am-comment-highlight .am-comment-avatar { border-color: #3bb4f2; } .am-comment-secondary .am-comment-main, .am-comment-highlight .am-comment-main { border-color: #3bb4f2; } .am-comment-secondary .am-comment-main:before, .am-comment-highlight .am-comment-main:before { border-right-color: #3bb4f2; } .am-comment-secondary.am-comment-flip .am-comment-main:before, .am-comment-highlight.am-comment-flip .am-comment-main:before { border-left-color: #3bb4f2; border-right-color: transparent; } .am-comment-secondary.am-comment-flip .am-comment-main:after, .am-comment-highlight.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-success .am-comment-avatar { border-color: #5eb95e; } .am-comment-success .am-comment-main { border-color: #5eb95e; } .am-comment-success .am-comment-main:before { border-right-color: #5eb95e; } .am-comment-success.am-comment-flip .am-comment-main:before { border-left-color: #5eb95e; border-right-color: transparent; } .am-comment-success.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-warning .am-comment-avatar { border-color: #F37B1D; } .am-comment-warning .am-comment-main { border-color: #F37B1D; } .am-comment-warning .am-comment-main:before { border-right-color: #F37B1D; } .am-comment-warning.am-comment-flip .am-comment-main:before { border-left-color: #F37B1D; border-right-color: transparent; } .am-comment-warning.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comment-danger .am-comment-avatar { border-color: #dd514c; } .am-comment-danger .am-comment-main { border-color: #dd514c; } .am-comment-danger .am-comment-main:before { border-right-color: #dd514c; } .am-comment-danger.am-comment-flip .am-comment-main:before { border-left-color: #dd514c; border-right-color: transparent; } .am-comment-danger.am-comment-flip .am-comment-main:after { border-left-color: #f8f8f8; } .am-comments-list { padding: 0; list-style: none; } .am-comments-list .am-comment { margin: 1.6rem 0 0 0; list-style: none; } @media only screen and (min-width:641px) { .am-comments-list-flip .am-comment-main { margin-right: 64px; } .am-comments-list-flip .am-comment-flip .am-comment-main { margin-left: 64px; } } /* ========================================================================== Component: Button Group ============================================================================ */ .am-btn-group, .am-btn-group-stacked { position: relative; display: inline-block; vertical-align: middle; } .am-btn-group > .am-btn, .am-btn-group-stacked > .am-btn { position: relative; float: left; } .am-btn-group > .am-btn:hover, .am-btn-group-stacked > .am-btn:hover, .am-btn-group > .am-btn:focus, .am-btn-group-stacked > .am-btn:focus, .am-btn-group > .am-btn:active, .am-btn-group-stacked > .am-btn:active, .am-btn-group > .am-btn.active, .am-btn-group-stacked > .am-btn.active { z-index: 2; } .am-btn-group > .am-btn:focus, .am-btn-group-stacked > .am-btn:focus { outline: 0; } .am-btn-group .am-btn + .am-btn, .am-btn-group .am-btn + .am-btn-group, .am-btn-group .am-btn-group + .am-btn, .am-btn-group .am-btn-group + .am-btn-group { margin-left: -1px; } .am-btn-toolbar { margin-left: -5px; } .am-btn-toolbar:before, .am-btn-toolbar:after { content: " "; display: table; } .am-btn-toolbar:after { clear: both; } .am-btn-toolbar .am-btn-group, .am-btn-toolbar .am-input-group { float: left; } .am-btn-toolbar > .am-btn, .am-btn-toolbar > .am-btn-group, .am-btn-toolbar > .am-input-group { margin-left: 5px; } .am-btn-group > .am-btn:not(:first-child):not(:last-child):not(.am-dropdown-toggle) { border-radius: 0; } .am-btn-group > .am-btn:first-child { margin-left: 0; } .am-btn-group > .am-btn:first-child:not(:last-child):not(.am-dropdown-toggle) { border-bottom-right-radius: 0; border-top-right-radius: 0; } .am-btn-group > .am-btn:last-child:not(:first-child), .am-btn-group > .am-dropdown-toggle:not(:first-child) { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-btn-group > .am-btn-group { float: left; } .am-btn-group > .am-btn-group:not(:first-child):not(:last-child) > .am-btn { border-radius: 0; } .am-btn-group > .am-btn-group:first-child > .am-btn:last-child, .am-btn-group > .am-btn-group:first-child > .am-dropdown-toggle { border-bottom-right-radius: 0; border-top-right-radius: 0; } .am-btn-group > .am-btn-group:last-child > .am-btn:first-child { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-btn-group-xs > .am-btn { font-size: 1.2rem; } .am-btn-group-sm > .am-btn { font-size: 1.4rem; } .am-btn-group-lg > .am-btn { font-size: 1.8rem; } .am-btn-group-stacked > .am-btn, .am-btn-group-stacked > .am-btn-group, .am-btn-group-stacked > .am-btn-group > .am-btn { display: block; float: none; width: 100%; max-width: 100%; } .am-btn-group-stacked > .am-btn-group:before, .am-btn-group-stacked > .am-btn-group:after { content: " "; display: table; } .am-btn-group-stacked > .am-btn-group:after { clear: both; } .am-btn-group-stacked > .am-btn-group > .am-btn { float: none; } .am-btn-group-stacked > .am-btn + .am-btn, .am-btn-group-stacked > .am-btn + .am-btn-group, .am-btn-group-stacked > .am-btn-group + .am-btn, .am-btn-group-stacked > .am-btn-group + .am-btn-group { margin-top: -1px; margin-left: 0; } .am-btn-group-stacked > .am-btn:not(:first-child):not(:last-child) { border-radius: 0; } .am-btn-group-stacked > .am-btn:first-child:not(:last-child) { border-top-right-radius: 2px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-btn-group-stacked > .am-btn:last-child:not(:first-child) { border-bottom-left-radius: 2px; border-top-right-radius: 0; border-top-left-radius: 0; } .am-btn-group-stacked > .am-btn-group:not(:first-child):not(:last-child) > .am-btn { border-radius: 0; } .am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-btn:last-child, .am-btn-group-stacked > .am-btn-group:first-child:not(:last-child) > .am-dropdown-toggle { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .am-btn-group-stacked > .am-btn-group:last-child:not(:first-child) > .am-btn:first-child { border-top-right-radius: 0; border-top-left-radius: 0; } .am-btn-group-justify { display: table; table-layout: fixed; border-collapse: separate; width: 100%; } .am-btn-group-justify > .am-btn, .am-btn-group-justify > .am-btn-group { float: none; display: table-cell; width: 1%; } .am-btn-group-justify > .am-btn-group .am-btn { width: 100%; } .lte9 .am-btn-group-justify { display: table; table-layout: fixed; border-collapse: separate; } .lte9 .am-btn-group-justify > .am-btn, .lte9 .am-btn-group-justify > .am-btn-group { float: none; display: table-cell; width: 1%; } .am-btn-group .am-dropdown { float: left; margin-left: -1px; } .am-btn-group .am-dropdown > .am-btn { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-btn-group .am-active .am-dropdown-toggle { -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .am-btn-group .am-active .am-dropdown-toggle.am-btn-link { -webkit-box-shadow: none; box-shadow: none; } .am-btn-group .am-dropdown-toggle:active, .am-btn-group .am-active .am-dropdown-toggle { outline: 0; } [data-am-button] > .am-btn > input[type="radio"], [data-am-button] > .am-btn > input[type="checkbox"], .am-btn-group-check > .am-btn > input[type="radio"], .am-btn-group-check > .am-btn > input[type="checkbox"] { position: absolute; z-index: -1; opacity: 0; } /* ========================================================================== Component: Close ============================================================================ */ .am-close { display: inline-block; text-align: center; width: 24px; font-size: 20px; font-weight: bold; line-height: 24px; color: #000; text-shadow: 0 1px 0 #fff; opacity: .2; -webkit-transition: all .3s; transition: all .3s; } .am-close:hover, .am-close:focus { color: #000; text-decoration: none; cursor: pointer; opacity: .5; outline: none; } .am-close[class*="am-icon-"] { font-size: 16px; } button.am-close { padding: 0; cursor: pointer; background: transparent; /* Needed for Sarari */ border: 0; -webkit-appearance: none; } a.am-close:hover { color: inherit; text-decoration: none; cursor: pointer; } /* Modifiers ============================================================================ */ .am-close-alt { border-radius: 50%; background: #eee; opacity: 0.7; -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); /* Hover */ } .am-close-alt:hover, .am-close-alt:focus { opacity: 1; } .am-close-spin:hover { -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } /* ========================================================================== Component: Icon ============================================================================ */ /* Font-face ============================================================================= */ @font-face { font-family: 'FontAwesome'; src: url('../fonts/fontawesome-webfont.eot?v=4.5.0'); src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } /* Component ============================================================================= */ [class*="am-icon-"] { display: inline-block; font-style: normal; } [class*="am-icon-"]:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-icon-border { padding: .2em .25em .15em; border: solid 0.08em #eee; border-radius: .1em; } [class*="am-icon-"].am-fl { margin-right: .3em; } [class*="am-icon-"].am-fr { margin-left: .3em; } .am-icon-sm:before { font-size: 150%; vertical-align: -10%; } .am-icon-md:before { font-size: 200%; vertical-align: -16%; } .am-icon-lg:before { font-size: 250%; vertical-align: -22%; } /* Modifier: `.am-icon-btn` ============================================================================= */ .am-icon-btn { -webkit-box-sizing: border-box; box-sizing: border-box; display: inline-block; width: 48px; height: 48px; font-size: 24px; line-height: 48px; border-radius: 50%; background-color: #eee; color: #555555; text-align: center; /** * Hover * 1. Apply hover style also to focus state * 2. Remove default focus style */ /* Active */ } .am-icon-btn:hover, .am-icon-btn:focus { /* 1 */ background-color: #f5f5f5; color: #333333; text-decoration: none; outline: none; /* 2 */ } .am-icon-btn:active { background-color: #ddd; color: #333333; } .am-icon-btn.am-primary, .am-icon-btn.am-secondary, .am-icon-btn.am-success, .am-icon-btn.am-warning, .am-icon-btn.am-danger { color: #fff; } .am-icon-btn.am-primary { background-color: #0e90d2; } .am-icon-btn.am-secondary { background-color: #3bb4f2; } .am-icon-btn.am-success { background-color: #5eb95e; } .am-icon-btn.am-warning { background-color: #F37B1D; } .am-icon-btn.am-danger { background-color: #dd514c; } .am-icon-btn-sm { width: 32px; height: 32px; font-size: 16px; line-height: 32px; } .am-icon-btn-lg { width: 64px; height: 64px; font-size: 28px; line-height: 64px; } /* Modifier: `.am-icon-fw` Fixed width ============================================================================= */ .am-icon-fw { width: 1.25em; text-align: center; } /* Icon mapping ============================================================================= */ .am-icon-glass:before { content: "\f000"; } .am-icon-music:before { content: "\f001"; } .am-icon-search:before { content: "\f002"; } .am-icon-envelope-o:before { content: "\f003"; } .am-icon-heart:before { content: "\f004"; } .am-icon-star:before { content: "\f005"; } .am-icon-star-o:before { content: "\f006"; } .am-icon-user:before { content: "\f007"; } .am-icon-film:before { content: "\f008"; } .am-icon-th-large:before { content: "\f009"; } .am-icon-th:before { content: "\f00a"; } .am-icon-th-list:before { content: "\f00b"; } .am-icon-check:before { content: "\f00c"; } .am-icon-remove:before, .am-icon-close:before, .am-icon-times:before { content: "\f00d"; } .am-icon-search-plus:before { content: "\f00e"; } .am-icon-search-minus:before { content: "\f010"; } .am-icon-power-off:before { content: "\f011"; } .am-icon-signal:before { content: "\f012"; } .am-icon-gear:before, .am-icon-cog:before { content: "\f013"; } .am-icon-trash-o:before { content: "\f014"; } .am-icon-home:before { content: "\f015"; } .am-icon-file-o:before { content: "\f016"; } .am-icon-clock-o:before { content: "\f017"; } .am-icon-road:before { content: "\f018"; } .am-icon-download:before { content: "\f019"; } .am-icon-arrow-circle-o-down:before { content: "\f01a"; } .am-icon-arrow-circle-o-up:before { content: "\f01b"; } .am-icon-inbox:before { content: "\f01c"; } .am-icon-play-circle-o:before { content: "\f01d"; } .am-icon-rotate-right:before, .am-icon-repeat:before { content: "\f01e"; } .am-icon-refresh:before { content: "\f021"; } .am-icon-list-alt:before { content: "\f022"; } .am-icon-lock:before { content: "\f023"; } .am-icon-flag:before { content: "\f024"; } .am-icon-headphones:before { content: "\f025"; } .am-icon-volume-off:before { content: "\f026"; } .am-icon-volume-down:before { content: "\f027"; } .am-icon-volume-up:before { content: "\f028"; } .am-icon-qrcode:before { content: "\f029"; } .am-icon-barcode:before { content: "\f02a"; } .am-icon-tag:before { content: "\f02b"; } .am-icon-tags:before { content: "\f02c"; } .am-icon-book:before { content: "\f02d"; } .am-icon-bookmark:before { content: "\f02e"; } .am-icon-print:before { content: "\f02f"; } .am-icon-camera:before { content: "\f030"; } .am-icon-font:before { content: "\f031"; } .am-icon-bold:before { content: "\f032"; } .am-icon-italic:before { content: "\f033"; } .am-icon-text-height:before { content: "\f034"; } .am-icon-text-width:before { content: "\f035"; } .am-icon-align-left:before { content: "\f036"; } .am-icon-align-center:before { content: "\f037"; } .am-icon-align-right:before { content: "\f038"; } .am-icon-align-justify:before { content: "\f039"; } .am-icon-list:before { content: "\f03a"; } .am-icon-dedent:before, .am-icon-outdent:before { content: "\f03b"; } .am-icon-indent:before { content: "\f03c"; } .am-icon-video-camera:before { content: "\f03d"; } .am-icon-photo:before, .am-icon-image:before, .am-icon-picture-o:before { content: "\f03e"; } .am-icon-pencil:before { content: "\f040"; } .am-icon-map-marker:before { content: "\f041"; } .am-icon-adjust:before { content: "\f042"; } .am-icon-tint:before { content: "\f043"; } .am-icon-edit:before, .am-icon-pencil-square-o:before { content: "\f044"; } .am-icon-share-square-o:before { content: "\f045"; } .am-icon-check-square-o:before { content: "\f046"; } .am-icon-arrows:before { content: "\f047"; } .am-icon-step-backward:before { content: "\f048"; } .am-icon-fast-backward:before { content: "\f049"; } .am-icon-backward:before { content: "\f04a"; } .am-icon-play:before { content: "\f04b"; } .am-icon-pause:before { content: "\f04c"; } .am-icon-stop:before { content: "\f04d"; } .am-icon-forward:before { content: "\f04e"; } .am-icon-fast-forward:before { content: "\f050"; } .am-icon-step-forward:before { content: "\f051"; } .am-icon-eject:before { content: "\f052"; } .am-icon-chevron-left:before { content: "\f053"; } .am-icon-chevron-right:before { content: "\f054"; } .am-icon-plus-circle:before { content: "\f055"; } .am-icon-minus-circle:before { content: "\f056"; } .am-icon-times-circle:before { content: "\f057"; } .am-icon-check-circle:before { content: "\f058"; } .am-icon-question-circle:before { content: "\f059"; } .am-icon-info-circle:before { content: "\f05a"; } .am-icon-crosshairs:before { content: "\f05b"; } .am-icon-times-circle-o:before { content: "\f05c"; } .am-icon-check-circle-o:before { content: "\f05d"; } .am-icon-ban:before { content: "\f05e"; } .am-icon-arrow-left:before { content: "\f060"; } .am-icon-arrow-right:before { content: "\f061"; } .am-icon-arrow-up:before { content: "\f062"; } .am-icon-arrow-down:before { content: "\f063"; } .am-icon-mail-forward:before, .am-icon-share:before { content: "\f064"; } .am-icon-expand:before { content: "\f065"; } .am-icon-compress:before { content: "\f066"; } .am-icon-plus:before { content: "\f067"; } .am-icon-minus:before { content: "\f068"; } .am-icon-asterisk:before { content: "\f069"; } .am-icon-exclamation-circle:before { content: "\f06a"; } .am-icon-gift:before { content: "\f06b"; } .am-icon-leaf:before { content: "\f06c"; } .am-icon-fire:before { content: "\f06d"; } .am-icon-eye:before { content: "\f06e"; } .am-icon-eye-slash:before { content: "\f070"; } .am-icon-warning:before, .am-icon-exclamation-triangle:before { content: "\f071"; } .am-icon-plane:before { content: "\f072"; } .am-icon-calendar:before { content: "\f073"; } .am-icon-random:before { content: "\f074"; } .am-icon-comment:before { content: "\f075"; } .am-icon-magnet:before { content: "\f076"; } .am-icon-chevron-up:before { content: "\f077"; } .am-icon-chevron-down:before { content: "\f078"; } .am-icon-retweet:before { content: "\f079"; } .am-icon-shopping-cart:before { content: "\f07a"; } .am-icon-folder:before { content: "\f07b"; } .am-icon-folder-open:before { content: "\f07c"; } .am-icon-arrows-v:before { content: "\f07d"; } .am-icon-arrows-h:before { content: "\f07e"; } .am-icon-bar-chart-o:before, .am-icon-bar-chart:before { content: "\f080"; } .am-icon-twitter-square:before { content: "\f081"; } .am-icon-facebook-square:before { content: "\f082"; } .am-icon-camera-retro:before { content: "\f083"; } .am-icon-key:before { content: "\f084"; } .am-icon-gears:before, .am-icon-cogs:before { content: "\f085"; } .am-icon-comments:before { content: "\f086"; } .am-icon-thumbs-o-up:before { content: "\f087"; } .am-icon-thumbs-o-down:before { content: "\f088"; } .am-icon-star-half:before { content: "\f089"; } .am-icon-heart-o:before { content: "\f08a"; } .am-icon-sign-out:before { content: "\f08b"; } .am-icon-linkedin-square:before { content: "\f08c"; } .am-icon-thumb-tack:before { content: "\f08d"; } .am-icon-external-link:before { content: "\f08e"; } .am-icon-sign-in:before { content: "\f090"; } .am-icon-trophy:before { content: "\f091"; } .am-icon-github-square:before { content: "\f092"; } .am-icon-upload:before { content: "\f093"; } .am-icon-lemon-o:before { content: "\f094"; } .am-icon-phone:before { content: "\f095"; } .am-icon-square-o:before { content: "\f096"; } .am-icon-bookmark-o:before { content: "\f097"; } .am-icon-phone-square:before { content: "\f098"; } .am-icon-twitter:before { content: "\f099"; } .am-icon-facebook-f:before, .am-icon-facebook:before { content: "\f09a"; } .am-icon-github:before { content: "\f09b"; } .am-icon-unlock:before { content: "\f09c"; } .am-icon-credit-card:before { content: "\f09d"; } .am-icon-feed:before, .am-icon-rss:before { content: "\f09e"; } .am-icon-hdd-o:before { content: "\f0a0"; } .am-icon-bullhorn:before { content: "\f0a1"; } .am-icon-bell:before { content: "\f0f3"; } .am-icon-certificate:before { content: "\f0a3"; } .am-icon-hand-o-right:before { content: "\f0a4"; } .am-icon-hand-o-left:before { content: "\f0a5"; } .am-icon-hand-o-up:before { content: "\f0a6"; } .am-icon-hand-o-down:before { content: "\f0a7"; } .am-icon-arrow-circle-left:before { content: "\f0a8"; } .am-icon-arrow-circle-right:before { content: "\f0a9"; } .am-icon-arrow-circle-up:before { content: "\f0aa"; } .am-icon-arrow-circle-down:before { content: "\f0ab"; } .am-icon-globe:before { content: "\f0ac"; } .am-icon-wrench:before { content: "\f0ad"; } .am-icon-tasks:before { content: "\f0ae"; } .am-icon-filter:before { content: "\f0b0"; } .am-icon-briefcase:before { content: "\f0b1"; } .am-icon-arrows-alt:before { content: "\f0b2"; } .am-icon-group:before, .am-icon-users:before { content: "\f0c0"; } .am-icon-chain:before, .am-icon-link:before { content: "\f0c1"; } .am-icon-cloud:before { content: "\f0c2"; } .am-icon-flask:before { content: "\f0c3"; } .am-icon-cut:before, .am-icon-scissors:before { content: "\f0c4"; } .am-icon-copy:before, .am-icon-files-o:before { content: "\f0c5"; } .am-icon-paperclip:before { content: "\f0c6"; } .am-icon-save:before, .am-icon-floppy-o:before { content: "\f0c7"; } .am-icon-square:before { content: "\f0c8"; } .am-icon-navicon:before, .am-icon-reorder:before, .am-icon-bars:before { content: "\f0c9"; } .am-icon-list-ul:before { content: "\f0ca"; } .am-icon-list-ol:before { content: "\f0cb"; } .am-icon-strikethrough:before { content: "\f0cc"; } .am-icon-underline:before { content: "\f0cd"; } .am-icon-table:before { content: "\f0ce"; } .am-icon-magic:before { content: "\f0d0"; } .am-icon-truck:before { content: "\f0d1"; } .am-icon-pinterest:before { content: "\f0d2"; } .am-icon-pinterest-square:before { content: "\f0d3"; } .am-icon-google-plus-square:before { content: "\f0d4"; } .am-icon-google-plus:before { content: "\f0d5"; } .am-icon-money:before { content: "\f0d6"; } .am-icon-caret-down:before { content: "\f0d7"; } .am-icon-caret-up:before { content: "\f0d8"; } .am-icon-caret-left:before { content: "\f0d9"; } .am-icon-caret-right:before { content: "\f0da"; } .am-icon-columns:before { content: "\f0db"; } .am-icon-unsorted:before, .am-icon-sort:before { content: "\f0dc"; } .am-icon-sort-down:before, .am-icon-sort-desc:before { content: "\f0dd"; } .am-icon-sort-up:before, .am-icon-sort-asc:before { content: "\f0de"; } .am-icon-envelope:before { content: "\f0e0"; } .am-icon-linkedin:before { content: "\f0e1"; } .am-icon-rotate-left:before, .am-icon-undo:before { content: "\f0e2"; } .am-icon-legal:before, .am-icon-gavel:before { content: "\f0e3"; } .am-icon-dashboard:before, .am-icon-tachometer:before { content: "\f0e4"; } .am-icon-comment-o:before { content: "\f0e5"; } .am-icon-comments-o:before { content: "\f0e6"; } .am-icon-flash:before, .am-icon-bolt:before { content: "\f0e7"; } .am-icon-sitemap:before { content: "\f0e8"; } .am-icon-umbrella:before { content: "\f0e9"; } .am-icon-paste:before, .am-icon-clipboard:before { content: "\f0ea"; } .am-icon-lightbulb-o:before { content: "\f0eb"; } .am-icon-exchange:before { content: "\f0ec"; } .am-icon-cloud-download:before { content: "\f0ed"; } .am-icon-cloud-upload:before { content: "\f0ee"; } .am-icon-user-md:before { content: "\f0f0"; } .am-icon-stethoscope:before { content: "\f0f1"; } .am-icon-suitcase:before { content: "\f0f2"; } .am-icon-bell-o:before { content: "\f0a2"; } .am-icon-coffee:before { content: "\f0f4"; } .am-icon-cutlery:before { content: "\f0f5"; } .am-icon-file-text-o:before { content: "\f0f6"; } .am-icon-building-o:before { content: "\f0f7"; } .am-icon-hospital-o:before { content: "\f0f8"; } .am-icon-ambulance:before { content: "\f0f9"; } .am-icon-medkit:before { content: "\f0fa"; } .am-icon-fighter-jet:before { content: "\f0fb"; } .am-icon-beer:before { content: "\f0fc"; } .am-icon-h-square:before { content: "\f0fd"; } .am-icon-plus-square:before { content: "\f0fe"; } .am-icon-angle-double-left:before { content: "\f100"; } .am-icon-angle-double-right:before { content: "\f101"; } .am-icon-angle-double-up:before { content: "\f102"; } .am-icon-angle-double-down:before { content: "\f103"; } .am-icon-angle-left:before { content: "\f104"; } .am-icon-angle-right:before { content: "\f105"; } .am-icon-angle-up:before { content: "\f106"; } .am-icon-angle-down:before { content: "\f107"; } .am-icon-desktop:before { content: "\f108"; } .am-icon-laptop:before { content: "\f109"; } .am-icon-tablet:before { content: "\f10a"; } .am-icon-mobile-phone:before, .am-icon-mobile:before { content: "\f10b"; } .am-icon-circle-o:before { content: "\f10c"; } .am-icon-quote-left:before { content: "\f10d"; } .am-icon-quote-right:before { content: "\f10e"; } .am-icon-spinner:before { content: "\f110"; } .am-icon-circle:before { content: "\f111"; } .am-icon-mail-reply:before, .am-icon-reply:before { content: "\f112"; } .am-icon-github-alt:before { content: "\f113"; } .am-icon-folder-o:before { content: "\f114"; } .am-icon-folder-open-o:before { content: "\f115"; } .am-icon-smile-o:before { content: "\f118"; } .am-icon-frown-o:before { content: "\f119"; } .am-icon-meh-o:before { content: "\f11a"; } .am-icon-gamepad:before { content: "\f11b"; } .am-icon-keyboard-o:before { content: "\f11c"; } .am-icon-flag-o:before { content: "\f11d"; } .am-icon-flag-checkered:before { content: "\f11e"; } .am-icon-terminal:before { content: "\f120"; } .am-icon-code:before { content: "\f121"; } .am-icon-mail-reply-all:before, .am-icon-reply-all:before { content: "\f122"; } .am-icon-star-half-empty:before, .am-icon-star-half-full:before, .am-icon-star-half-o:before { content: "\f123"; } .am-icon-location-arrow:before { content: "\f124"; } .am-icon-crop:before { content: "\f125"; } .am-icon-code-fork:before { content: "\f126"; } .am-icon-unlink:before, .am-icon-chain-broken:before { content: "\f127"; } .am-icon-question:before { content: "\f128"; } .am-icon-info:before { content: "\f129"; } .am-icon-exclamation:before { content: "\f12a"; } .am-icon-superscript:before { content: "\f12b"; } .am-icon-subscript:before { content: "\f12c"; } .am-icon-eraser:before { content: "\f12d"; } .am-icon-puzzle-piece:before { content: "\f12e"; } .am-icon-microphone:before { content: "\f130"; } .am-icon-microphone-slash:before { content: "\f131"; } .am-icon-shield:before { content: "\f132"; } .am-icon-calendar-o:before { content: "\f133"; } .am-icon-fire-extinguisher:before { content: "\f134"; } .am-icon-rocket:before { content: "\f135"; } .am-icon-maxcdn:before { content: "\f136"; } .am-icon-chevron-circle-left:before { content: "\f137"; } .am-icon-chevron-circle-right:before { content: "\f138"; } .am-icon-chevron-circle-up:before { content: "\f139"; } .am-icon-chevron-circle-down:before { content: "\f13a"; } .am-icon-html5:before { content: "\f13b"; } .am-icon-css3:before { content: "\f13c"; } .am-icon-anchor:before { content: "\f13d"; } .am-icon-unlock-alt:before { content: "\f13e"; } .am-icon-bullseye:before { content: "\f140"; } .am-icon-ellipsis-h:before { content: "\f141"; } .am-icon-ellipsis-v:before { content: "\f142"; } .am-icon-rss-square:before { content: "\f143"; } .am-icon-play-circle:before { content: "\f144"; } .am-icon-ticket:before { content: "\f145"; } .am-icon-minus-square:before { content: "\f146"; } .am-icon-minus-square-o:before { content: "\f147"; } .am-icon-level-up:before { content: "\f148"; } .am-icon-level-down:before { content: "\f149"; } .am-icon-check-square:before { content: "\f14a"; } .am-icon-pencil-square:before { content: "\f14b"; } .am-icon-external-link-square:before { content: "\f14c"; } .am-icon-share-square:before { content: "\f14d"; } .am-icon-compass:before { content: "\f14e"; } .am-icon-toggle-down:before, .am-icon-caret-square-o-down:before { content: "\f150"; } .am-icon-toggle-up:before, .am-icon-caret-square-o-up:before { content: "\f151"; } .am-icon-toggle-right:before, .am-icon-caret-square-o-right:before { content: "\f152"; } .am-icon-euro:before, .am-icon-eur:before { content: "\f153"; } .am-icon-gbp:before { content: "\f154"; } .am-icon-dollar:before, .am-icon-usd:before { content: "\f155"; } .am-icon-rupee:before, .am-icon-inr:before { content: "\f156"; } .am-icon-cny:before, .am-icon-rmb:before, .am-icon-yen:before, .am-icon-jpy:before { content: "\f157"; } .am-icon-ruble:before, .am-icon-rouble:before, .am-icon-rub:before { content: "\f158"; } .am-icon-won:before, .am-icon-krw:before { content: "\f159"; } .am-icon-bitcoin:before, .am-icon-btc:before { content: "\f15a"; } .am-icon-file:before { content: "\f15b"; } .am-icon-file-text:before { content: "\f15c"; } .am-icon-sort-alpha-asc:before { content: "\f15d"; } .am-icon-sort-alpha-desc:before { content: "\f15e"; } .am-icon-sort-amount-asc:before { content: "\f160"; } .am-icon-sort-amount-desc:before { content: "\f161"; } .am-icon-sort-numeric-asc:before { content: "\f162"; } .am-icon-sort-numeric-desc:before { content: "\f163"; } .am-icon-thumbs-up:before { content: "\f164"; } .am-icon-thumbs-down:before { content: "\f165"; } .am-icon-youtube-square:before { content: "\f166"; } .am-icon-youtube:before { content: "\f167"; } .am-icon-xing:before { content: "\f168"; } .am-icon-xing-square:before { content: "\f169"; } .am-icon-youtube-play:before { content: "\f16a"; } .am-icon-dropbox:before { content: "\f16b"; } .am-icon-stack-overflow:before { content: "\f16c"; } .am-icon-instagram:before { content: "\f16d"; } .am-icon-flickr:before { content: "\f16e"; } .am-icon-adn:before { content: "\f170"; } .am-icon-bitbucket:before { content: "\f171"; } .am-icon-bitbucket-square:before { content: "\f172"; } .am-icon-tumblr:before { content: "\f173"; } .am-icon-tumblr-square:before { content: "\f174"; } .am-icon-long-arrow-down:before { content: "\f175"; } .am-icon-long-arrow-up:before { content: "\f176"; } .am-icon-long-arrow-left:before { content: "\f177"; } .am-icon-long-arrow-right:before { content: "\f178"; } .am-icon-apple:before { content: "\f179"; } .am-icon-windows:before { content: "\f17a"; } .am-icon-android:before { content: "\f17b"; } .am-icon-linux:before { content: "\f17c"; } .am-icon-dribbble:before { content: "\f17d"; } .am-icon-skype:before { content: "\f17e"; } .am-icon-foursquare:before { content: "\f180"; } .am-icon-trello:before { content: "\f181"; } .am-icon-female:before { content: "\f182"; } .am-icon-male:before { content: "\f183"; } .am-icon-gittip:before, .am-icon-gratipay:before { content: "\f184"; } .am-icon-sun-o:before { content: "\f185"; } .am-icon-moon-o:before { content: "\f186"; } .am-icon-archive:before { content: "\f187"; } .am-icon-bug:before { content: "\f188"; } .am-icon-vk:before { content: "\f189"; } .am-icon-weibo:before { content: "\f18a"; } .am-icon-renren:before { content: "\f18b"; } .am-icon-pagelines:before { content: "\f18c"; } .am-icon-stack-exchange:before { content: "\f18d"; } .am-icon-arrow-circle-o-right:before { content: "\f18e"; } .am-icon-arrow-circle-o-left:before { content: "\f190"; } .am-icon-toggle-left:before, .am-icon-caret-square-o-left:before { content: "\f191"; } .am-icon-dot-circle-o:before { content: "\f192"; } .am-icon-wheelchair:before { content: "\f193"; } .am-icon-vimeo-square:before { content: "\f194"; } .am-icon-turkish-lira:before, .am-icon-try:before { content: "\f195"; } .am-icon-plus-square-o:before { content: "\f196"; } .am-icon-space-shuttle:before { content: "\f197"; } .am-icon-slack:before { content: "\f198"; } .am-icon-envelope-square:before { content: "\f199"; } .am-icon-wordpress:before { content: "\f19a"; } .am-icon-openid:before { content: "\f19b"; } .am-icon-institution:before, .am-icon-bank:before, .am-icon-university:before { content: "\f19c"; } .am-icon-mortar-board:before, .am-icon-graduation-cap:before { content: "\f19d"; } .am-icon-yahoo:before { content: "\f19e"; } .am-icon-google:before { content: "\f1a0"; } .am-icon-reddit:before { content: "\f1a1"; } .am-icon-reddit-square:before { content: "\f1a2"; } .am-icon-stumbleupon-circle:before { content: "\f1a3"; } .am-icon-stumbleupon:before { content: "\f1a4"; } .am-icon-delicious:before { content: "\f1a5"; } .am-icon-digg:before { content: "\f1a6"; } .am-icon-pied-piper:before { content: "\f1a7"; } .am-icon-pied-piper-alt:before { content: "\f1a8"; } .am-icon-drupal:before { content: "\f1a9"; } .am-icon-joomla:before { content: "\f1aa"; } .am-icon-language:before { content: "\f1ab"; } .am-icon-fax:before { content: "\f1ac"; } .am-icon-building:before { content: "\f1ad"; } .am-icon-child:before { content: "\f1ae"; } .am-icon-paw:before { content: "\f1b0"; } .am-icon-spoon:before { content: "\f1b1"; } .am-icon-cube:before { content: "\f1b2"; } .am-icon-cubes:before { content: "\f1b3"; } .am-icon-behance:before { content: "\f1b4"; } .am-icon-behance-square:before { content: "\f1b5"; } .am-icon-steam:before { content: "\f1b6"; } .am-icon-steam-square:before { content: "\f1b7"; } .am-icon-recycle:before { content: "\f1b8"; } .am-icon-automobile:before, .am-icon-car:before { content: "\f1b9"; } .am-icon-cab:before, .am-icon-taxi:before { content: "\f1ba"; } .am-icon-tree:before { content: "\f1bb"; } .am-icon-spotify:before { content: "\f1bc"; } .am-icon-deviantart:before { content: "\f1bd"; } .am-icon-soundcloud:before { content: "\f1be"; } .am-icon-database:before { content: "\f1c0"; } .am-icon-file-pdf-o:before { content: "\f1c1"; } .am-icon-file-word-o:before { content: "\f1c2"; } .am-icon-file-excel-o:before { content: "\f1c3"; } .am-icon-file-powerpoint-o:before { content: "\f1c4"; } .am-icon-file-photo-o:before, .am-icon-file-picture-o:before, .am-icon-file-image-o:before { content: "\f1c5"; } .am-icon-file-zip-o:before, .am-icon-file-archive-o:before { content: "\f1c6"; } .am-icon-file-sound-o:before, .am-icon-file-audio-o:before { content: "\f1c7"; } .am-icon-file-movie-o:before, .am-icon-file-video-o:before { content: "\f1c8"; } .am-icon-file-code-o:before { content: "\f1c9"; } .am-icon-vine:before { content: "\f1ca"; } .am-icon-codepen:before { content: "\f1cb"; } .am-icon-jsfiddle:before { content: "\f1cc"; } .am-icon-life-bouy:before, .am-icon-life-buoy:before, .am-icon-life-saver:before, .am-icon-support:before, .am-icon-life-ring:before { content: "\f1cd"; } .am-icon-circle-o-notch:before { content: "\f1ce"; } .am-icon-ra:before, .am-icon-rebel:before { content: "\f1d0"; } .am-icon-ge:before, .am-icon-empire:before { content: "\f1d1"; } .am-icon-git-square:before { content: "\f1d2"; } .am-icon-git:before { content: "\f1d3"; } .am-icon-y-combinator-square:before, .am-icon-yc-square:before, .am-icon-hacker-news:before { content: "\f1d4"; } .am-icon-tencent-weibo:before { content: "\f1d5"; } .am-icon-qq:before { content: "\f1d6"; } .am-icon-wechat:before, .am-icon-weixin:before { content: "\f1d7"; } .am-icon-send:before, .am-icon-paper-plane:before { content: "\f1d8"; } .am-icon-send-o:before, .am-icon-paper-plane-o:before { content: "\f1d9"; } .am-icon-history:before { content: "\f1da"; } .am-icon-circle-thin:before { content: "\f1db"; } .am-icon-header:before { content: "\f1dc"; } .am-icon-paragraph:before { content: "\f1dd"; } .am-icon-sliders:before { content: "\f1de"; } .am-icon-share-alt:before { content: "\f1e0"; } .am-icon-share-alt-square:before { content: "\f1e1"; } .am-icon-bomb:before { content: "\f1e2"; } .am-icon-soccer-ball-o:before, .am-icon-futbol-o:before { content: "\f1e3"; } .am-icon-tty:before { content: "\f1e4"; } .am-icon-binoculars:before { content: "\f1e5"; } .am-icon-plug:before { content: "\f1e6"; } .am-icon-slideshare:before { content: "\f1e7"; } .am-icon-twitch:before { content: "\f1e8"; } .am-icon-yelp:before { content: "\f1e9"; } .am-icon-newspaper-o:before { content: "\f1ea"; } .am-icon-wifi:before { content: "\f1eb"; } .am-icon-calculator:before { content: "\f1ec"; } .am-icon-paypal:before { content: "\f1ed"; } .am-icon-google-wallet:before { content: "\f1ee"; } .am-icon-cc-visa:before { content: "\f1f0"; } .am-icon-cc-mastercard:before { content: "\f1f1"; } .am-icon-cc-discover:before { content: "\f1f2"; } .am-icon-cc-amex:before { content: "\f1f3"; } .am-icon-cc-paypal:before { content: "\f1f4"; } .am-icon-cc-stripe:before { content: "\f1f5"; } .am-icon-bell-slash:before { content: "\f1f6"; } .am-icon-bell-slash-o:before { content: "\f1f7"; } .am-icon-trash:before { content: "\f1f8"; } .am-icon-copyright:before { content: "\f1f9"; } .am-icon-at:before { content: "\f1fa"; } .am-icon-eyedropper:before { content: "\f1fb"; } .am-icon-paint-brush:before { content: "\f1fc"; } .am-icon-birthday-cake:before { content: "\f1fd"; } .am-icon-area-chart:before { content: "\f1fe"; } .am-icon-pie-chart:before { content: "\f200"; } .am-icon-line-chart:before { content: "\f201"; } .am-icon-lastfm:before { content: "\f202"; } .am-icon-lastfm-square:before { content: "\f203"; } .am-icon-toggle-off:before { content: "\f204"; } .am-icon-toggle-on:before { content: "\f205"; } .am-icon-bicycle:before { content: "\f206"; } .am-icon-bus:before { content: "\f207"; } .am-icon-ioxhost:before { content: "\f208"; } .am-icon-angellist:before { content: "\f209"; } .am-icon-cc:before { content: "\f20a"; } .am-icon-shekel:before, .am-icon-sheqel:before, .am-icon-ils:before { content: "\f20b"; } .am-icon-meanpath:before { content: "\f20c"; } .am-icon-buysellads:before { content: "\f20d"; } .am-icon-connectdevelop:before { content: "\f20e"; } .am-icon-dashcube:before { content: "\f210"; } .am-icon-forumbee:before { content: "\f211"; } .am-icon-leanpub:before { content: "\f212"; } .am-icon-sellsy:before { content: "\f213"; } .am-icon-shirtsinbulk:before { content: "\f214"; } .am-icon-simplybuilt:before { content: "\f215"; } .am-icon-skyatlas:before { content: "\f216"; } .am-icon-cart-plus:before { content: "\f217"; } .am-icon-cart-arrow-down:before { content: "\f218"; } .am-icon-diamond:before { content: "\f219"; } .am-icon-ship:before { content: "\f21a"; } .am-icon-user-secret:before { content: "\f21b"; } .am-icon-motorcycle:before { content: "\f21c"; } .am-icon-street-view:before { content: "\f21d"; } .am-icon-heartbeat:before { content: "\f21e"; } .am-icon-venus:before { content: "\f221"; } .am-icon-mars:before { content: "\f222"; } .am-icon-mercury:before { content: "\f223"; } .am-icon-intersex:before, .am-icon-transgender:before { content: "\f224"; } .am-icon-transgender-alt:before { content: "\f225"; } .am-icon-venus-double:before { content: "\f226"; } .am-icon-mars-double:before { content: "\f227"; } .am-icon-venus-mars:before { content: "\f228"; } .am-icon-mars-stroke:before { content: "\f229"; } .am-icon-mars-stroke-v:before { content: "\f22a"; } .am-icon-mars-stroke-h:before { content: "\f22b"; } .am-icon-neuter:before { content: "\f22c"; } .am-icon-genderless:before { content: "\f22d"; } .am-icon-facebook-official:before { content: "\f230"; } .am-icon-pinterest-p:before { content: "\f231"; } .am-icon-whatsapp:before { content: "\f232"; } .am-icon-server:before { content: "\f233"; } .am-icon-user-plus:before { content: "\f234"; } .am-icon-user-times:before { content: "\f235"; } .am-icon-hotel:before, .am-icon-bed:before { content: "\f236"; } .am-icon-viacoin:before { content: "\f237"; } .am-icon-train:before { content: "\f238"; } .am-icon-subway:before { content: "\f239"; } .am-icon-medium:before { content: "\f23a"; } .am-icon-yc:before, .am-icon-y-combinator:before { content: "\f23b"; } .am-icon-optin-monster:before { content: "\f23c"; } .am-icon-opencart:before { content: "\f23d"; } .am-icon-expeditedssl:before { content: "\f23e"; } .am-icon-battery-4:before, .am-icon-battery-full:before { content: "\f240"; } .am-icon-battery-3:before, .am-icon-battery-three-quarters:before { content: "\f241"; } .am-icon-battery-2:before, .am-icon-battery-half:before { content: "\f242"; } .am-icon-battery-1:before, .am-icon-battery-quarter:before { content: "\f243"; } .am-icon-battery-0:before, .am-icon-battery-empty:before { content: "\f244"; } .am-icon-mouse-pointer:before { content: "\f245"; } .am-icon-i-cursor:before { content: "\f246"; } .am-icon-object-group:before { content: "\f247"; } .am-icon-object-ungroup:before { content: "\f248"; } .am-icon-sticky-note:before { content: "\f249"; } .am-icon-sticky-note-o:before { content: "\f24a"; } .am-icon-cc-jcb:before { content: "\f24b"; } .am-icon-cc-diners-club:before { content: "\f24c"; } .am-icon-clone:before { content: "\f24d"; } .am-icon-balance-scale:before { content: "\f24e"; } .am-icon-hourglass-o:before { content: "\f250"; } .am-icon-hourglass-1:before, .am-icon-hourglass-start:before { content: "\f251"; } .am-icon-hourglass-2:before, .am-icon-hourglass-half:before { content: "\f252"; } .am-icon-hourglass-3:before, .am-icon-hourglass-end:before { content: "\f253"; } .am-icon-hourglass:before { content: "\f254"; } .am-icon-hand-grab-o:before, .am-icon-hand-rock-o:before { content: "\f255"; } .am-icon-hand-stop-o:before, .am-icon-hand-paper-o:before { content: "\f256"; } .am-icon-hand-scissors-o:before { content: "\f257"; } .am-icon-hand-lizard-o:before { content: "\f258"; } .am-icon-hand-spock-o:before { content: "\f259"; } .am-icon-hand-pointer-o:before { content: "\f25a"; } .am-icon-hand-peace-o:before { content: "\f25b"; } .am-icon-trademark:before { content: "\f25c"; } .am-icon-registered:before { content: "\f25d"; } .am-icon-creative-commons:before { content: "\f25e"; } .am-icon-gg:before { content: "\f260"; } .am-icon-gg-circle:before { content: "\f261"; } .am-icon-tripadvisor:before { content: "\f262"; } .am-icon-odnoklassniki:before { content: "\f263"; } .am-icon-odnoklassniki-square:before { content: "\f264"; } .am-icon-get-pocket:before { content: "\f265"; } .am-icon-wikipedia-w:before { content: "\f266"; } .am-icon-safari:before { content: "\f267"; } .am-icon-chrome:before { content: "\f268"; } .am-icon-firefox:before { content: "\f269"; } .am-icon-opera:before { content: "\f26a"; } .am-icon-internet-explorer:before { content: "\f26b"; } .am-icon-tv:before, .am-icon-television:before { content: "\f26c"; } .am-icon-contao:before { content: "\f26d"; } .am-icon-500px:before { content: "\f26e"; } .am-icon-amazon:before { content: "\f270"; } .am-icon-calendar-plus-o:before { content: "\f271"; } .am-icon-calendar-minus-o:before { content: "\f272"; } .am-icon-calendar-times-o:before { content: "\f273"; } .am-icon-calendar-check-o:before { content: "\f274"; } .am-icon-industry:before { content: "\f275"; } .am-icon-map-pin:before { content: "\f276"; } .am-icon-map-signs:before { content: "\f277"; } .am-icon-map-o:before { content: "\f278"; } .am-icon-map:before { content: "\f279"; } .am-icon-commenting:before { content: "\f27a"; } .am-icon-commenting-o:before { content: "\f27b"; } .am-icon-houzz:before { content: "\f27c"; } .am-icon-vimeo:before { content: "\f27d"; } .am-icon-black-tie:before { content: "\f27e"; } .am-icon-fonticons:before { content: "\f280"; } .am-icon-reddit-alien:before { content: "\f281"; } .am-icon-edge:before { content: "\f282"; } .am-icon-credit-card-alt:before { content: "\f283"; } .am-icon-codiepie:before { content: "\f284"; } .am-icon-modx:before { content: "\f285"; } .am-icon-fort-awesome:before { content: "\f286"; } .am-icon-usb:before { content: "\f287"; } .am-icon-product-hunt:before { content: "\f288"; } .am-icon-mixcloud:before { content: "\f289"; } .am-icon-scribd:before { content: "\f28a"; } .am-icon-pause-circle:before { content: "\f28b"; } .am-icon-pause-circle-o:before { content: "\f28c"; } .am-icon-stop-circle:before { content: "\f28d"; } .am-icon-stop-circle-o:before { content: "\f28e"; } .am-icon-shopping-bag:before { content: "\f290"; } .am-icon-shopping-basket:before { content: "\f291"; } .am-icon-hashtag:before { content: "\f292"; } .am-icon-bluetooth:before { content: "\f293"; } .am-icon-bluetooth-b:before { content: "\f294"; } .am-icon-percent:before { content: "\f295"; } /* Modifier: `am-icon-spin` ============================================================================= */ @-webkit-keyframes icon-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } @keyframes icon-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } .am-icon-spin { -webkit-animation: icon-spin 2s infinite linear; animation: icon-spin 2s infinite linear; } .am-icon-pulse { -webkit-animation: icon-spin 1s infinite steps(8); animation: icon-spin 1s infinite steps(8); } .am-icon-ul { padding-left: 0; margin-left: 2.14285714em; list-style-type: none; } .am-icon-ul > li { position: relative; } .am-icon-li { position: absolute; left: -2.14285714em; width: 2.14285714em; top: 0.14285714em; text-align: center; } /* ========================================================================== Component: Input group ============================================================================ */ .am-input-group { position: relative; display: table; border-collapse: separate; } .am-input-group .am-form-field { position: relative; z-index: 2; float: left; width: 100%; margin-bottom: 0; } .am-input-group-label, .am-input-group-btn, .am-input-group .am-form-field { display: table-cell; } .am-input-group-label:not(:first-child):not(:last-child), .am-input-group-btn:not(:first-child):not(:last-child), .am-input-group .am-form-field:not(:first-child):not(:last-child) { border-radius: 0; } .am-input-group-label, .am-input-group-btn { width: 1%; white-space: nowrap; vertical-align: middle; } .am-input-group-label { height: 38px; padding: 0 1em; font-size: 1.6rem; font-weight: normal; line-height: 36px; color: #555555; text-align: center; background-color: #eeeeee; border: 1px solid #ccc; border-radius: 2px; } .am-input-group-label input[type="radio"], .am-input-group-label input[type="checkbox"] { margin-top: 0; } .am-input-group .am-form-field:first-child, .am-input-group-label:first-child, .am-input-group-btn:first-child > .am-btn, .am-input-group-btn:first-child > .am-btn-group > .am-btn, .am-input-group-btn:first-child > .am-dropdown-toggle, .am-input-group-btn:last-child > .am-btn:not(:last-child):not(.dropdown-toggle), .am-input-group-btn:last-child > .am-btn-group:not(:last-child) > .am-btn { border-bottom-right-radius: 0; border-top-right-radius: 0; } .am-input-group-label:first-child { border-right: 0; } .am-input-group .am-form-field:last-child, .am-input-group-label:last-child, .am-input-group-btn:last-child > .am-btn, .am-input-group-btn:last-child > .am-btn-group > .am-btn, .am-input-group-btn:last-child > .am-dropdown-toggle, .am-input-group-btn:first-child > .am-btn:not(:first-child), .am-input-group-btn:first-child > .am-btn-group:not(:first-child) > .am-btn { border-bottom-left-radius: 0; border-top-left-radius: 0; } .am-input-group-label:last-child { border-left: 0; } .am-input-group-btn { position: relative; font-size: 0; white-space: nowrap; } .am-input-group-btn > .am-btn { position: relative; border-color: #ccc; } .am-input-group-btn > .am-btn + .am-btn { margin-left: -1px; } .am-input-group-btn > .am-btn:hover, .am-input-group-btn > .am-btn:focus, .am-input-group-btn > .am-btn:active { z-index: 2; } .am-input-group-btn:first-child > .am-btn, .am-input-group-btn:first-child > .am-btn-group { margin-right: -2px; } .am-input-group-btn:last-child > .am-btn, .am-input-group-btn:last-child > .am-btn-group { margin-left: -1px; } .am-input-group .am-form-field, .am-input-group-btn > .am-btn { height: 38px; padding-bottom: auto; } .am-input-group-lg > .am-form-field, .am-input-group-lg > .am-input-group-label, .am-input-group-lg > .am-input-group-btn > .am-btn { height: 42px; font-size: 1.8rem !important; } .am-input-group-lg > .am-input-group-label { line-height: 40px; } .am-input-group-sm > .am-form-field, .am-input-group-sm > .am-input-group-label, .am-input-group-sm > .am-input-group-btn > .am-btn { height: 33px; font-size: 1.4rem !important; } .am-input-group-sm > .am-input-group-label { line-height: 31px; } .am-input-group-primary .am-input-group-label { background: #0e90d2; color: #fff; } .am-input-group-primary .am-input-group-label, .am-input-group-primary .am-input-group-btn > .am-btn, .am-input-group-primary.am-input-group .am-form-field { border-color: #0e90d2; } .am-input-group-secondary .am-input-group-label { background: #3bb4f2; color: #fff; } .am-input-group-secondary .am-input-group-label, .am-input-group-secondary .am-input-group-btn > .am-btn, .am-input-group-secondary.am-input-group .am-form-field { border-color: #3bb4f2; } .am-input-group-success .am-input-group-label { background: #5eb95e; color: #fff; } .am-input-group-success .am-input-group-label, .am-input-group-success .am-input-group-btn > .am-btn, .am-input-group-success.am-input-group .am-form-field { border-color: #5eb95e; } .am-input-group-warning .am-input-group-label { background: #F37B1D; color: #fff; } .am-input-group-warning .am-input-group-label, .am-input-group-warning .am-input-group-btn > .am-btn, .am-input-group-warning.am-input-group .am-form-field { border-color: #F37B1D; } .am-input-group-danger .am-input-group-label { background: #dd514c; color: #fff; } .am-input-group-danger .am-input-group-label, .am-input-group-danger .am-input-group-btn > .am-btn, .am-input-group-danger.am-input-group .am-form-field { border-color: #dd514c; } /* ========================================================================== Component: List ============================================================================ */ .am-list { margin-bottom: 1.6rem; padding-left: 0; } .am-list > li { position: relative; display: block; margin-bottom: -1px; background-color: #fff; border: 1px solid #dedede; border-width: 1px 0; } .am-list > li > a { display: block; padding: 1rem 0; } .am-list > li > a.am-active, .am-list > li > a.am-active:hover, .am-list > li > a.am-active:focus { z-index: 2; color: #fff; background-color: #0e90d2; border-color: #0e90d2; } .am-list > li > a.am-active .am-list-item-heading, .am-list > li > a.am-active:hover .am-list-item-heading, .am-list > li > a.am-active:focus .am-list-item-heading { color: inherit; } .am-list > li > a.am-active .am-list-item-text, .am-list > li > a.am-active:hover .am-list-item-text, .am-list > li > a.am-active:focus .am-list-item-text { color: #b2e2fa; } .am-list > li > .am-badge { float: right; } .am-list > li > .am-badge + .am-badge { margin-right: 5px; } /* Pure text list */ .am-list-static > li { padding: .8rem .2rem; } .am-list-static.am-list-border > li { padding: 1rem; } /* with border */ .am-list-border > li, .am-list-bordered > li { border-width: 1px; } .am-list-border > li:first-child, .am-list-bordered > li:first-child, .am-list-border > li:first-child > a, .am-list-bordered > li:first-child > a { border-top-right-radius: 2px; border-top-left-radius: 2px; } .am-list-border > li:last-child, .am-list-bordered > li:last-child, .am-list-border > li:last-child > a, .am-list-bordered > li:last-child > a { margin-bottom: 0; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } .am-list-border > li > a, .am-list-bordered > li > a { padding: 1rem; } .am-list-border > li > a:hover, .am-list-bordered > li > a:hover, .am-list-border > li > a:focus, .am-list-bordered > li > a:focus { background-color: #f5f5f5; } /* Striped */ .am-list-striped > li:nth-of-type(even) { background: #f5f5f5; } .am-list-item-hd { margin-top: 0; } .am-list-item-text { line-height: 1.4; font-size: 1.3rem; color: #999999; margin: 0; } /* ========================================================================== Component: Panel ============================================================================ */ .am-panel { margin-bottom: 20px; background-color: #fff; border: 1px solid transparent; border-radius: 2px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); } /* Panel header */ .am-panel-hd { padding: 0.6rem 1.25rem; border-bottom: 1px solid transparent; border-top-right-radius: 2px; border-top-left-radius: 2px; } /* Panel content */ .am-panel-bd { padding: 1.25rem; } .am-panel-title { margin: 0; font-size: 100%; color: inherit; } .am-panel-title > a { color: inherit; } /* Panel footer */ .am-panel-footer { padding: 0.6rem 1.25rem; background-color: #f5f5f5; border-top: 1px solid #ddd; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } .am-panel-default { border-color: #ddd; } .am-panel-default > .am-panel-hd { color: #444; background-color: #f5f5f5; border-color: #ddd; } .am-panel-default > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #ddd; } .am-panel-default > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #ddd; } .am-panel-primary { border-color: #10a0ea; } .am-panel-primary > .am-panel-hd { color: #fff; background-color: #0e90d2; border-color: #10a0ea; } .am-panel-primary > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #10a0ea; } .am-panel-primary > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #10a0ea; } .am-panel-secondary { border-color: #caebfb; } .am-panel-secondary > .am-panel-hd { color: #14a6ef; background-color: rgba(59, 180, 242, 0.15); border-color: #caebfb; } .am-panel-secondary > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #caebfb; } .am-panel-secondary > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #caebfb; } .am-panel-success { border-color: #c9e7c9; } .am-panel-success > .am-panel-hd { color: #5eb95e; background-color: rgba(94, 185, 94, 0.15); border-color: #c9e7c9; } .am-panel-success > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #c9e7c9; } .am-panel-success > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #c9e7c9; } .am-panel-warning { border-color: #fbd0ae; } .am-panel-warning > .am-panel-hd { color: #F37B1D; background-color: rgba(243, 123, 29, 0.15); border-color: #fbd0ae; } .am-panel-warning > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #fbd0ae; } .am-panel-warning > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #fbd0ae; } .am-panel-danger { border-color: #f5cecd; } .am-panel-danger > .am-panel-hd { color: #dd514c; background-color: rgba(221, 81, 76, 0.15); border-color: #f5cecd; } .am-panel-danger > .am-panel-hd + .am-panel-collapse > .am-panel-bd { border-top-color: #f5cecd; } .am-panel-danger > .am-panel-footer + .am-panel-collapse > .am-panel-bd { border-bottom-color: #f5cecd; } .am-panel > .am-table { margin-bottom: 0; } .am-panel > .am-table:first-child { border-top-right-radius: 2px; border-top-left-radius: 2px; } .am-panel > .am-table:first-child > thead:first-child > tr:first-child td:first-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:first-child, .am-panel > .am-table:first-child > thead:first-child > tr:first-child th:first-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:first-child { border-top-left-radius: 2px; } .am-panel > .am-table:first-child > thead:first-child > tr:first-child td:last-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child td:last-child, .am-panel > .am-table:first-child > thead:first-child > tr:first-child th:last-child, .am-panel > .am-table:first-child > tbody:first-child > tr:first-child th:last-child { border-top-right-radius: 2px; } .am-panel > .am-table:last-child { border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } .am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:first-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:first-child, .am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:first-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:first-child { border-bottom-left-radius: 2px; } .am-panel > .am-table:last-child > tbody:last-child > tr:last-child td:last-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child td:last-child, .am-panel > .am-table:last-child > tbody:last-child > tr:last-child th:last-child, .am-panel > .am-table:last-child > tfoot:last-child > tr:last-child th:last-child { border-bottom-right-radius: 2px; } .am-panel > .am-panel-bd + .am-table { border-top: 1px solid #ddd; } .am-panel > .am-table > tbody:first-child > tr:first-child th, .am-panel > .am-table > tbody:first-child > tr:first-child td { border-top: 0; } .am-panel > .am-table-bd { border: 0; } .am-panel > .am-table-bd > thead > tr > th:first-child, .am-panel > .am-table-bd > tbody > tr > th:first-child, .am-panel > .am-table-bd > tfoot > tr > th:first-child, .am-panel > .am-table-bd > thead > tr > td:first-child, .am-panel > .am-table-bd > tbody > tr > td:first-child, .am-panel > .am-table-bd > tfoot > tr > td:first-child { border-left: 0; } .am-panel > .am-table-bd > thead > tr > th:last-child, .am-panel > .am-table-bd > tbody > tr > th:last-child, .am-panel > .am-table-bd > tfoot > tr > th:last-child, .am-panel > .am-table-bd > thead > tr > td:last-child, .am-panel > .am-table-bd > tbody > tr > td:last-child, .am-panel > .am-table-bd > tfoot > tr > td:last-child { border-right: 0; } .am-panel > .am-table-bd > thead > tr:first-child > td, .am-panel > .am-table-bd > tbody > tr:first-child > td, .am-panel > .am-table-bd > thead > tr:first-child > th, .am-panel > .am-table-bd > tbody > tr:first-child > th { border-bottom: 0; } .am-panel > .am-table-bd > tbody > tr:last-child > td, .am-panel > .am-table-bd > tfoot > tr:last-child > td, .am-panel > .am-table-bd > tbody > tr:last-child > th, .am-panel > .am-table-bd > tfoot > tr:last-child > th { border-bottom: 0; } /* Wrap list */ .am-panel > .am-list { margin: 0; } .am-panel > .am-list > li > a { padding-left: 1rem; padding-right: 1rem; } .am-panel > .am-list-static li { padding-left: 1rem; padding-right: 1rem; } /* Panel group */ .am-panel-group { margin-bottom: 2rem; } .am-panel-group .am-panel { margin-bottom: 0; border-radius: 2px; } .am-panel-group .am-panel + .am-panel { margin-top: 6px; } .am-panel-group .am-panel-hd { border-bottom: 0; } .am-panel-group .am-panel-hd + .am-panel-collapse .am-panel-bd { border-top: 1px solid #ddd; } .am-panel-group .am-panel-footer { border-top: 0; } .am-panel-group .am-panel-footer + .am-panel-collapse .am-panel-bd { border-bottom: 1px solid #ddd; } /* ========================================================================== Component: Progress ============================================================================ */ /* Progress bar animation */ @-webkit-keyframes progress-bar-stripes { from { background-position: 36px 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 36px 0; } to { background-position: 0 0; } } /* Progress container */ .am-progress { overflow: hidden; height: 2rem; margin-bottom: 2rem; background-color: #f5f5f5; border-radius: 2px; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } /* Progress bar */ .am-progress-bar { float: left; width: 0; height: 100%; font-size: 1.2rem; line-height: 2rem; color: #fff; text-align: center; background-color: #0e90d2; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-transition: width .6s ease; transition: width .6s ease; } .am-progress-striped .am-progress-bar { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 36px 36px; background-size: 36px 36px; } .am-progress.am-active .am-progress-bar { -webkit-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .am-progress-bar[aria-valuenow="1"], .am-progress-bar[aria-valuenow="2"] { min-width: 30px; } .am-progress-bar[aria-valuenow="0"] { color: #999999; min-width: 30px; background: none; -webkit-box-shadow: none; box-shadow: none; } .am-progress-bar-secondary { background-color: #3bb4f2; } .am-progress-striped .am-progress-bar-secondary { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-bar-success { background-color: #5eb95e; } .am-progress-striped .am-progress-bar-success { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-bar-warning { background-color: #F37B1D; } .am-progress-striped .am-progress-bar-warning { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-bar-danger { background-color: #dd514c; } .am-progress-striped .am-progress-bar-danger { background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .am-progress-xs { height: 0.6rem; } .am-progress-sm { height: 1.2rem; } /* ========================================================================== Component: Thumbnail ============================================================================ */ .am-thumbnail { display: block; padding: 2px; margin-bottom: 2rem; background-color: #fff; border: 1px solid #ddd; border-radius: 2px; -webkit-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; } .am-thumbnail > img, .am-thumbnail a > img { margin-left: auto; margin-right: auto; display: block; } .am-thumbnail a.am-thumbnail:hover, .am-thumbnail a.am-thumbnail:focus, .am-thumbnail a.am-thumbnail.active { border-color: #0e90d2; background-color: #fff; } img.am-thumbnail, .am-thumbnail > img, .am-thumbnail a > img { max-width: 100%; height: auto; } /* Image caption */ .am-thumbnail-caption { margin: 0; padding: 0.8rem; color: #333; font-weight: normal; } .am-thumbnail-caption *:last-child { margin-bottom: 0; } .am-thumbnails { margin-left: -0.5rem; margin-right: -0.5rem; } .am-thumbnails > li { padding: 0 .5rem 1rem .5rem; } /* ========================================================================== Component: Utility ============================================================================ */ .am-scrollable-horizontal { width: 100%; overflow-y: hidden; overflow-x: auto; -ms-overflow-style: -ms-autohiding-scrollbar; -webkit-overflow-scrolling: touch; } .am-scrollable-vertical { height: 240px; overflow-y: scroll; -webkit-overflow-scrolling: touch; resize: vertical; } /* Border-radius*/ .am-square { border-radius: 0; } .am-radius { border-radius: 2px; } .am-round { border-radius: 1000px; } .am-circle { border-radius: 50%; } /* Float blocks*/ .am-cf:before, .am-cf:after { content: " "; display: table; } .am-cf:after { clear: both; } .am-fl { float: left; } .am-fr { float: right; } .am-nbfc { overflow: hidden; } .am-center { display: block; margin-left: auto; margin-right: auto; } /* Display */ .am-block { display: block !important; } .am-inline { display: inline !important; } .am-inline-block { display: inline-block !important; } .am-hide { display: none !important; visibility: hidden !important; } /* * Remove whitespace between child elements when using `inline-block` */ .am-vertical-align { font-size: 0.001px; } /* * The `@{ns}vertical-align` container needs a specific height */ .am-vertical-align:before { content: ''; display: inline-block; height: 100%; vertical-align: middle; } /* * Sub-object which can have any height * 1. Reset whitespace hack */ .am-vertical-align-middle, .am-vertical-align-bottom { display: inline-block; font-size: 1.6rem; /* 1 */ max-width: 100%; } .am-vertical-align-middle { vertical-align: middle; } .am-vertical-align-bottom { vertical-align: bottom; } .am-responsive-width { -webkit-box-sizing: border-box; box-sizing: border-box; max-width: 100%; height: auto; } /* Margin helpers */ .am-margin { margin: 1.6rem; } .am-margin-0 { margin: 0!important; } .am-margin-xs { margin: 0.5rem; } .am-margin-sm { margin: 1rem; } .am-margin-lg { margin: 2.4rem; } .am-margin-xl { margin: 3.2rem; } .am-margin-horizontal { margin-left: 1.6rem; margin-right: 1.6rem; } .am-margin-horizontal-0 { margin-left: 0!important; margin-right: 0!important; } .am-margin-horizontal-xs { margin-left: 0.5rem; margin-right: 0.5rem; } .am-margin-horizontal-sm { margin-left: 1rem; margin-right: 1rem; } .am-margin-horizontal-lg { margin-left: 2.4rem; margin-right: 2.4rem; } .am-margin-horizontal-xl { margin-left: 3.2rem; margin-right: 3.2rem; } .am-margin-vertical { margin-top: 1.6rem; margin-bottom: 1.6rem; } .am-margin-vertical-0 { margin-top: 0!important; margin-bottom: 0!important; } .am-margin-vertical-xs { margin-top: 0.5rem; margin-bottom: 0.5rem; } .am-margin-vertical-sm { margin-top: 1rem; margin-bottom: 1rem; } .am-margin-vertical-lg { margin-top: 2.4rem; margin-bottom: 2.4rem; } .am-margin-vertical-xl { margin-top: 3.2rem; margin-bottom: 3.2rem; } .am-margin-top { margin-top: 1.6rem; } .am-margin-top-0 { margin-top: 0!important; } .am-margin-top-xs { margin-top: 0.5rem; } .am-margin-top-sm { margin-top: 1rem; } .am-margin-top-lg { margin-top: 2.4rem; } .am-margin-top-xl { margin-top: 3.2rem; } .am-margin-bottom { margin-bottom: 1.6rem; } .am-margin-bottom-0 { margin-bottom: 0!important; } .am-margin-bottom-xs { margin-bottom: 0.5rem; } .am-margin-bottom-sm { margin-bottom: 1rem; } .am-margin-bottom-lg { margin-bottom: 2.4rem; } .am-margin-bottom-xl { margin-bottom: 3.2rem; } .am-margin-left { margin-left: 1.6rem; } .am-margin-left-0 { margin-left: 0!important; } .am-margin-left-xs { margin-left: 0.5rem; } .am-margin-left-sm { margin-left: 1rem; } .am-margin-left-lg { margin-left: 2.4rem; } .am-margin-left-xl { margin-left: 3.2rem; } .am-margin-right { margin-right: 1.6rem; } .am-margin-right-0 { margin-right: 0!important; } .am-margin-right-xs { margin-right: 0.5rem; } .am-margin-right-sm { margin-right: 1rem; } .am-margin-right-lg { margin-right: 2.4rem; } .am-margin-right-xl { margin-right: 3.2rem; } /* Padding helpers */ .am-padding { padding: 1.6rem; } .am-padding-0 { padding: 0!important; } .am-padding-xs { padding: 0.5rem; } .am-padding-sm { padding: 1rem; } .am-padding-lg { padding: 2.4rem; } .am-padding-xl { padding: 3.2rem; } .am-padding-horizontal { padding-left: 1.6rem; padding-right: 1.6rem; } .am-padding-horizontal-0 { padding-left: 0!important; padding-right: 0!important; } .am-padding-horizontal-xs { padding-left: 0.5rem; padding-right: 0.5rem; } .am-padding-horizontal-sm { padding-left: 1rem; padding-right: 1rem; } .am-padding-horizontal-lg { padding-left: 2.4rem; padding-right: 2.4rem; } .am-padding-horizontal-xl { padding-left: 3.2rem; padding-right: 3.2rem; } .am-padding-vertical { padding-top: 1.6rem; padding-bottom: 1.6rem; } .am-padding-vertical-0 { padding-top: 0!important; padding-bottom: 0!important; } .am-padding-vertical-xs { padding-top: 0.5rem; padding-bottom: 0.5rem; } .am-padding-vertical-sm { padding-top: 1rem; padding-bottom: 1rem; } .am-padding-vertical-lg { padding-top: 2.4rem; padding-bottom: 2.4rem; } .am-padding-vertical-xl { padding-top: 3.2rem; padding-bottom: 3.2rem; } .am-padding-top { padding-top: 1.6rem; } .am-padding-top-0 { padding-top: 0!important; } .am-padding-top-xs { padding-top: 0.5rem; } .am-padding-top-sm { padding-top: 1rem; } .am-padding-top-lg { padding-top: 2.4rem; } .am-padding-top-xl { padding-top: 3.2rem; } .am-padding-bottom { padding-bottom: 1.6rem; } .am-padding-bottom-0 { padding-bottom: 0!important; } .am-padding-bottom-xs { padding-bottom: 0.5rem; } .am-padding-bottom-sm { padding-bottom: 1rem; } .am-padding-bottom-lg { padding-bottom: 2.4rem; } .am-padding-bottom-xl { padding-bottom: 3.2rem; } .am-padding-left { padding-left: 1.6rem; } .am-padding-left-0 { padding-left: 0!important; } .am-padding-left-xs { padding-left: 0.5rem; } .am-padding-left-sm { padding-left: 1rem; } .am-padding-left-lg { padding-left: 2.4rem; } .am-padding-left-xl { padding-left: 3.2rem; } .am-padding-right { padding-right: 1.6rem; } .am-padding-right-0 { padding-right: 0!important; } .am-padding-right-xs { padding-right: 0.5rem; } .am-padding-right-sm { padding-right: 1rem; } .am-padding-right-lg { padding-right: 2.4rem; } .am-padding-right-xl { padding-right: 3.2rem; } /* small displays */ @media only screen { .am-show-sm-only, .am-show-sm-up, .am-show-sm, .am-show-sm-down, .am-hide-md-only, .am-hide-md-up, .am-hide-md, .am-show-md-down, .am-hide-lg-only, .am-hide-lg-up, .am-hide-lg, .am-show-lg-down { display: inherit !important; } .am-hide-sm-only, .am-hide-sm-up, .am-hide-sm, .am-hide-sm-down, .am-show-md-only, .am-show-md-up, .am-show-md, .am-hide-md-down, .am-show-lg-only, .am-show-lg-up, .am-show-lg, .am-hide-lg-down { display: none !important; } /* table */ table.am-show-sm-only, table.am-show-sm-up, table.am-show-sm, table.am-show-sm-down, table.am-hide-md-only, table.am-hide-md-up, table.am-hide-md, table.am-show-md-down, table.am-hide-lg-only, table.am-hide-lg-up, table.am-hide-lg, table.am-show-lg-down { display: table !important; } thead.am-show-sm-only, thead.am-show-sm-up, thead.am-show-sm, thead.am-show-sm-down, thead.am-hide-md-only, thead.am-hide-md-up, thead.am-hide-md, thead.am-show-md-down, thead.am-hide-lg-only, thead.am-hide-lg-up, thead.am-hide-lg, thead.am-show-lg-down { display: table-header-group !important; } tbody.am-show-sm-only, tbody.am-show-sm-up, tbody.am-show-sm, tbody.am-show-sm-down, tbody.am-hide-md-only, tbody.am-hide-md-up, tbody.am-hide-md, tbody.am-show-md-down, tbody.am-hide-lg-only, tbody.am-hide-lg-up, tbody.am-hide-lg, tbody.am-show-lg-down { display: table-row-group !important; } tr.am-show-sm-only, tr.am-show-sm-up, tr.am-show-sm, tr.am-show-sm-down, tr.am-hide-md-only, tr.am-hide-md-up, tr.am-hide-md, tr.am-show-md-down, tr.am-hide-lg-only, tr.am-hide-lg-up, tr.am-hide-lg, tr.am-show-lg-down { display: table-row !important; } th.am-show-sm-only, td.am-show-sm-only, th.am-show-sm-up, td.am-show-sm-up, th.am-show-sm, td.am-show-sm, th.am-show-sm-down, td.am-show-sm-down, th.am-hide-md-only, td.am-hide-md-only, th.am-hide-md-up, td.am-hide-md-up, th.am-hide-md, td.am-hide-md, th.am-show-md-down, td.am-show-md-down, th.am-hide-lg-only, td.am-hide-lg-only, th.am-hide-lg-up, td.am-hide-lg-up, th.am-hide-lg, td.am-hide-lg, th.am-show-lg-down, td.am-show-lg-down { display: table-cell !important; } } /* medium displays */ @media only screen and (min-width:641px) { .am-hide-sm-only, .am-show-sm-up, .am-hide-sm, .am-hide-sm-down, .am-show-md-only, .am-show-md-up, .am-show-md, .am-show-md-down, .am-hide-lg-only, .am-hide-lg-up, .am-hide-lg, .am-show-lg-down { display: inherit !important; } .am-show-sm-only, .am-hide-sm-up, .am-show-sm, .am-show-sm-down, .am-hide-md-only, .am-hide-md-up, .am-hide-md, .am-hide-md-down, .am-show-lg-only, .am-show-lg-up, .am-show-lg, .am-hide-lg-down { display: none !important; } table.am-hide-sm-only, table.am-show-sm-up, table.am-hide-sm, table.am-hide-sm-down, table.am-show-md-only, table.am-show-md-up, table.am-show-md, table.am-show-md-down, table.am-hide-lg-only, table.am-hide-lg-up, table.am-hide-lg, table.am-show-lg-down { display: table !important; } thead.am-hide-sm-only, thead.am-show-sm-up, thead.am-hide-sm, thead.am-hide-sm-down, thead.am-show-md-only, thead.am-show-md-up, thead.am-show-md, thead.am-show-md-down, thead.am-hide-lg-only, thead.am-hide-lg-up, thead.am-hide-lg, thead.am-show-lg-down { display: table-header-group !important; } tbody.am-hide-sm-only, tbody.am-show-sm-up, tbody.am-hide-sm, tbody.am-hide-sm-down, tbody.am-show-md-only, tbody.am-show-md-up, tbody.am-show-md, tbody.am-show-md-down, tbody.am-hide-lg-only, tbody.am-hide-lg-up, tbody.am-hide-lg, tbody.am-show-lg-down { display: table-row-group !important; } tr.am-hide-sm-only, tr.am-show-sm-up, tr.am-hide-sm, tr.am-hide-sm-down, tr.am-show-md-only, tr.am-show-md-up, tr.am-show-md, tr.am-show-md-down, tr.am-hide-lg-only, tr.am-hide-lg-up, tr.am-hide-lg, tr.am-show-lg-down { display: table-row !important; } th.am-hide-sm-only, td.am-hide-sm-only, th.am-show-sm-up, td.am-show-sm-up, th.am-hide-sm, td.am-hide-sm, th.am-hide-sm-down, td.am-hide-sm-down, th.am-show-md-only, td.am-show-md-only, th.am-show-md-up, td.am-show-md-up, th.am-show-md, td.am-show-md, th.am-show-md-down, td.am-show-md-down, th.am-hide-lg-only, td.am-hide-lg-only, th.am-hide-lg-up, td.am-hide-lg-up, th.am-hide-lg, td.am-hide-lg, th.am-show-lg-down, td.am-show-lg-down { display: table-cell !important; } } /* large displays */ @media only screen and (min-width:1025px) { .am-hide-sm-only, .am-show-sm-up, .am-hide-sm, .am-hide-sm-down, .am-hide-md-only, .am-show-md-up, .am-hide-md, .am-hide-md-down, .am-show-lg-only, .am-show-lg-up, .am-show-lg, .am-show-lg-down { display: inherit !important; } .am-show-sm-only, .am-hide-sm-up, .am-show-sm, .am-show-sm-down, .am-show-md-only, .am-hide-md-up, .am-show-md, .am-show-md-down, .am-hide-lg-only, .am-hide-lg-up, .am-hide-lg, .am-hide-lg-down { display: none !important; } table.am-hide-sm-only, table.am-show-sm-up, table.am-hide-sm, table.am-hide-sm-down, table.am-hide-md-only, table.am-show-md-up, table.am-hide-md, table.am-hide-md-down, table.am-show-lg-only, table.am-show-lg-up, table.am-show-lg, table.am-show-lg-down { display: table !important; } thead.am-hide-sm-only, thead.am-show-sm-up, thead.am-hide-sm, thead.am-hide-sm-down, thead.am-hide-md-only, thead.am-show-md-up, thead.am-hide-md, thead.am-hide-md-down, thead.am-show-lg-only, thead.am-show-lg-up, thead.am-show-lg, thead.am-show-lg-down { display: table-header-group !important; } tbody.am-hide-sm-only, tbody.am-show-sm-up, tbody.am-hide-sm, tbody.am-hide-sm-down, tbody.am-hide-md-only, tbody.am-show-md-up, tbody.am-hide-md, tbody.am-hide-md-down, tbody.am-show-lg-only, tbody.am-show-lg-up, tbody.am-show-lg, tbody.am-show-lg-down { display: table-row-group !important; } tr.am-hide-sm-only, tr.am-show-sm-up, tr.am-hide-sm, tr.am-hide-sm-down, tr.am-hide-md-only, tr.am-show-md-up, tr.am-hide-md, tr.am-hide-md-down, tr.am-show-lg-only, tr.am-show-lg-up, tr.am-show-lg, tr.am-show-lg-down { display: table-row !important; } th.am-hide-sm-only, td.am-hide-sm-only, th.am-show-sm-up, td.am-show-sm-up, th.am-hide-sm, td.am-hide-sm, th.am-hide-sm-down, td.am-hide-sm-down, th.am-hide-md-only, td.am-hide-md-only, th.am-show-md-up, td.am-show-md-up, th.am-hide-md, td.am-hide-md, th.am-hide-md-down, td.am-hide-md-down, th.am-show-lg-only, td.am-show-lg-only, th.am-show-lg-up, td.am-show-lg-up, th.am-show-lg, td.am-show-lg, th.am-show-lg-down, td.am-show-lg-down { display: table-cell !important; } } @media only screen and (orientation: landscape) { .am-show-landscape, .am-hide-portrait { display: inherit !important; } .am-hide-landscape, .am-show-portrait { display: none !important; } } @media only screen and (orientation: portrait) { .am-show-portrait, .am-hide-landscape { display: inherit !important; } .am-hide-portrait, .am-show-landscape { display: none !important; } } .am-sans-serif { font-family: "Segoe UI", "Lucida Grande", Helvetica, Arial, "Microsoft YaHei", FreeSans, Arimo, "Droid Sans", "wenquanyi micro hei", "Hiragino Sans GB", "Hiragino Sans GB W3", "FontAwesome", sans-serif; } .am-serif { font-family: Georgia, "Times New Roman", Times, SimSun, "FontAwesome", serif; } .am-kai { font-family: Georgia, "Times New Roman", Times, Kai, "Kaiti SC", KaiTi, BiauKai, "FontAwesome", serif; } .am-monospace { font-family: Monaco, Menlo, Consolas, "Courier New", "FontAwesome", monospace; } .am-text-primary { color: #0e90d2; } .am-text-secondary { color: #3bb4f2; } .am-text-success { color: #5eb95e; } .am-text-warning { color: #F37B1D; } .am-text-danger { color: #dd514c; } .am-link-muted { color: #666; } .am-link-muted a { color: #666; } .am-link-muted:hover, .am-link-muted a:hover { color: #555; } .am-text-default { font-size: 1.6rem; } /* .@{ns}text-xxs { font-size: @font-size-xxs; } */ .am-text-xs { font-size: 1.2rem; } .am-text-sm { font-size: 1.4rem; } .am-text-lg { font-size: 1.8rem; } .am-text-xl { font-size: 2.4rem; } .am-text-xxl { font-size: 3.2rem; } .am-text-xxxl { font-size: 4.2rem; } .am-ellipsis, .am-text-truncate { word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-text-break { word-wrap: break-word; -webkit-hyphens: auto; -ms-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } .am-text-nowrap { white-space: nowrap; } [class*='am-align-'] { margin-bottom: 1rem; } .am-align-left { margin-right: 1rem; float: left; } .am-align-right { margin-left: 1rem; float: right; } /** Only display content to screen readers * See: http://a11yproject.com/posts/how-to-hide-content/ */ .am-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } /* Text Image Replacement */ .am-text-ir { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } /* Text align */ @media only screen { .am-text-left { text-align: left !important; } .am-text-right { text-align: right !important; } .am-text-center { text-align: center !important; } .am-text-justify { text-align: justify !important; } } @media only screen and (max-width: 640px) { .am-sm-only-text-left { text-align: left !important; } .am-sm-only-text-right { text-align: right !important; } .am-sm-only-text-center { text-align: center !important; } .am-sm-only-text-justify { text-align: justify !important; } } @media only screen and (min-width:641px) and (max-width:1024px) { .am-md-only-text-left { text-align: left !important; } .am-md-only-text-right { text-align: right !important; } .am-md-only-text-center { text-align: center !important; } .am-md-only-text-justify { text-align: justify !important; } } @media only screen and (min-width:641px) { .am-md-text-left { text-align: left !important; } .am-md-text-right { text-align: right !important; } .am-md-text-center { text-align: center !important; } .am-md-text-justify { text-align: justify !important; } } @media only screen and (min-width:1025px) { .am-lg-text-left { text-align: left !important; } .am-lg-text-right { text-align: right !important; } .am-lg-text-center { text-align: center !important; } .am-lg-text-justify { text-align: justify !important; } } .am-text-top { vertical-align: top !important; } .am-text-middle { vertical-align: middle !important; } .am-text-bottom { vertical-align: bottom !important; } .am-angle { position: absolute; } .am-angle:before, .am-angle:after { position: absolute; display: block; content: ""; width: 0; height: 0; border: 8px dashed transparent; z-index: 1; } .am-angle-up { top: 0; } .am-angle-up:before, .am-angle-up:after { border-bottom-style: solid; border-width: 0 8px 8px; } .am-angle-up:before { border-bottom-color: #ddd; bottom: 0; } .am-angle-up:after { border-bottom-color: #fff; bottom: -1px; } .am-angle-down { bottom: -9px; } .am-angle-down:before, .am-angle-down:after { border-top-style: solid; border-width: 8px 8px 0; } .am-angle-down:before { border-top-color: #ddd; bottom: 0; } .am-angle-down:after { border-top-color: #fff; bottom: 1px; } .am-angle-left { left: -9px; } .am-angle-left:before, .am-angle-left:after { border-right-style: solid; border-width: 8px 8px 8px 0; } .am-angle-left:before { border-right-color: #ddd; left: 0; } .am-angle-left:after { border-right-color: #fff; left: 1px; } .am-angle-right { right: 0; } .am-angle-right:before, .am-angle-right:after { border-left-style: solid; border-width: 8px 0 8px 8px; } .am-angle-right:before { border-left-color: #ddd; left: 0; } .am-angle-right:after { border-left-color: #fff; left: -1px; } /* ========================================================================== Component: Alert Plugin ============================================================================ */ .am-alert { margin-bottom: 1em; padding: 0.625em; background: #0e90d2; color: #fff; border: 1px solid #0c7cb5; border-radius: 2px; } .am-alert a { color: #fff; } .am-alert h1, .am-alert h2, .am-alert h3, .am-alert h4, .am-alert h5, .am-alert h6 { color: inherit; } .am-alert .am-close { opacity: .4; } .am-alert .am-close:hover { opacity: .6; } /* Add margin if adjacent element */ * + .am-alert { margin-top: 1em; } /* Remove margin from the last-child */ .am-alert > :last-child { margin-bottom: 0; } /* within am-form-group */ .am-form-group .am-alert { margin: 5px 0 0; padding: 0.25em 0.625em; font-size: 1.3rem; } /* Close in alert */ .am-alert > .am-close:first-child { float: right; height: auto; margin: -3px -5px auto auto; } /* Remove margin from adjacent element */ .am-alert > .am-close:first-child + * { margin-top: 0; } .am-alert-secondary { background-color: #eeeeee; border-color: #dfdfdf; color: #555555; } .am-alert-success { background-color: #5eb95e; border-color: #4bad4b; color: #fff; } .am-alert-warning { background-color: #F37B1D; border-color: #e56c0c; color: #fff; } .am-alert-danger { background-color: #dd514c; border-color: #d83832; color: #fff; } .am-dropdown { position: relative; display: inline-block; } .am-dropdown-toggle:focus { outline: 0; } .am-dropdown-content { position: absolute; top: 100%; left: 0; z-index: 1020; display: none; float: left; min-width: 160px; padding: 15px; margin: 9px 0 0; text-align: left; line-height: 1.6; background-color: #fff; border: 1px solid #ddd; border-radius: 2px; -webkit-background-clip: padding-box; background-clip: padding-box; -webkit-animation-duration: .15s; animation-duration: .15s; } .am-dropdown-content:before, .am-dropdown-content:after { position: absolute; display: block; content: ""; width: 0; height: 0; border: 8px dashed transparent; z-index: 1; } .am-dropdown-content:before, .am-dropdown-content:after { border-bottom-style: solid; border-width: 0 8px 8px; } .am-dropdown-content:before { border-bottom-color: #ddd; bottom: 0; } .am-dropdown-content:after { border-bottom-color: #fff; bottom: -1px; } .am-dropdown-content:before, .am-dropdown-content:after { left: 10px; top: -8px; pointer-events: none; } .am-dropdown-content:after { top: -7px; } .am-active > .am-dropdown-content { display: block; } .am-dropdown-content :first-child { margin-top: 0; } .am-dropdown-up .am-dropdown-content { top: auto; bottom: 100%; margin: 0 0 9px; } .am-dropdown-up .am-dropdown-content:before, .am-dropdown-up .am-dropdown-content:after { border-bottom: none; border-top: 8px solid #ddd; top: auto; bottom: -8px; } .am-dropdown-up .am-dropdown-content:after { bottom: -7px; border-top-color: #fff; } .am-dropdown-flip .am-dropdown-content { left: auto; right: 0; } .am-dropdown-flip .am-dropdown-content:before, .am-dropdown-flip .am-dropdown-content:after { left: auto; right: 10px; } ul.am-dropdown-content { list-style: none; padding: 5px 0; } ul.am-dropdown-content.am-fr { right: 0; left: auto; } ul.am-dropdown-content .am-divider { height: 1px; margin: 0rem 0; overflow: hidden; background-color: #e5e5e5; } ul.am-dropdown-content > li > a { display: block; padding: 6px 20px; clear: both; font-weight: normal; color: #333333; white-space: nowrap; } ul.am-dropdown-content > li > a:hover, ul.am-dropdown-content > li > a:focus { text-decoration: none; color: #262626; background-color: #f5f5f5; } ul.am-dropdown-content > .am-active > a, ul.am-dropdown-content > .am-active > a:hover, ul.am-dropdown-content > .am-active > a:focus { color: #fff; text-decoration: none; outline: 0; background-color: #0e90d2; } ul.am-dropdown-content > .am-disabled > a, ul.am-dropdown-content > .am-disabled > a:hover, ul.am-dropdown-content > .am-disabled > a:focus { color: #999999; } ul.am-dropdown-content > .am-disabled > a:hover, ul.am-dropdown-content > .am-disabled > a:focus { text-decoration: none; background-color: transparent; background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); cursor: not-allowed; } .am-dropdown-header { display: block; padding: 6px 20px; font-size: 1.2rem; color: #999999; } .am-fr > .am-dropdown-content { right: 0; left: auto; } .am-fr > .am-dropdown-content:before { right: 10px; left: auto; } .am-dropdown-animation { -webkit-animation: am-dropdown-animation 0.15s ease-out; animation: am-dropdown-animation 0.15s ease-out; } @-webkit-keyframes am-dropdown-animation { 0% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } 100% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } } @keyframes am-dropdown-animation { 0% { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); } 100% { opacity: 0; -webkit-transform: translateY(-10px); transform: translateY(-10px); } } /* ========================================================================== Component: Flex Slider Plugin ============================================================================ */ .am-slider a:hover, .am-slider a:focus { outline: none; } .am-slides, .am-control-nav, .am-direction-nav { margin: 0; padding: 0; list-style: none; } .am-slider { margin: 0; padding: 0; } .am-slider .am-slides:before, .am-slider .am-slides:after { content: " "; display: table; } .am-slider .am-slides:after { clear: both; } .am-slider .am-slides > li { display: none; -webkit-backface-visibility: hidden; position: relative; } .no-js .am-slider .am-slides > li:first-child { display: block; } .am-slider .am-slides img { width: 100%; display: block; } .am-pauseplay span { text-transform: capitalize; } .am-slider { position: relative; } .am-viewport { -webkit-transition: all 1s ease; transition: all 1s ease; } .am-slider-carousel li { margin-right: 5px; } .am-control-nav { position: absolute; } .am-control-nav li { display: inline-block; } .am-control-thumbs { position: static; overflow: hidden; } .am-control-thumbs img { -webkit-transition: all 1s ease; transition: all 1s ease; } .am-slider-slide .am-slides > li { display: none; position: relative; } @media all and (transform-3d), (-webkit-transform-3d) { .am-slider-slide .am-slides > li { -webkit-transition: -webkit-transform 0.6s ease-in-out; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .am-slider-slide .am-slides > li.next, .am-slider-slide .am-slides > li.active.right { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); left: 0; } .am-slider-slide .am-slides > li.prev, .am-slider-slide .am-slides > li.active.left { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); left: 0; } .am-slider-slide .am-slides > li.next.left, .am-slider-slide .am-slides > li.prev.right, .am-slider-slide .am-slides > li.active { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); left: 0; } } .am-slider-slide .am-slides > .active, .am-slider-slide .am-slides > .next, .am-slider-slide .am-slides > .prev { display: block; } .am-slider-slide .am-slides > .active { left: 0; } .am-slider-slide .am-slides > .next, .am-slider-slide .am-slides > .prev { position: absolute; top: 0; width: 100%; } .am-slider-slide .am-slides > .next { left: 100%; } .am-slider-slide .am-slides > .prev { left: -100%; } .am-slider-slide .am-slides > .next.left, .am-slider-slide .am-slides > .prev.right { left: 0; } .am-slider-slide .am-slides > .active.left { left: -100%; } .am-slider-slide .am-slides > .active.right { left: 100%; } /** * Slider Theme: Default */ .am-slider-default { margin: 0 0 20px; background-color: #fff; border-radius: 2px; -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15); box-shadow: 0 0 2px rgba(0, 0, 0, 0.15); /* Direction Nav */ /* Pause/Play */ /* Control Nav */ } .am-slider-default .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-default .am-viewport { max-height: 300px; } .am-slider-default .carousel li { margin-right: 5px; } .am-slider-default .am-direction-nav a { position: absolute; top: 50%; z-index: 10; display: block; width: 36px; height: 36px; margin: -18px 0 0; overflow: hidden; opacity: 0.45; cursor: pointer; color: rgba(0, 0, 0, 0.65); -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-default .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); width: 100%; color: #333333; content: "\f137"; font-size: 24px!important; text-align: center; line-height: 36px!important; height: 36px; } .am-slider-default .am-direction-nav a.am-next:before { content: "\f138"; } .am-slider-default .am-direction-nav .am-prev { left: 10px; } .am-slider-default .am-direction-nav .am-next { right: 10px; text-align: right; } .am-slider-default .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-default:hover .am-prev { opacity: 0.7; left: 10px; } .am-slider-default:hover .am-prev:hover { opacity: 1; } .am-slider-default:hover .am-next { opacity: 0.7; right: 10px; } .am-slider-default:hover .am-next:hover { opacity: 1; } .am-slider-default .am-pauseplay a { display: block; width: 20px; height: 20px; position: absolute; bottom: 5px; left: 10px; opacity: 0.8; z-index: 10; overflow: hidden; cursor: pointer; color: #000; } .am-slider-default .am-pauseplay a::before { font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); font-size: 20px; display: inline-block; content: "\f04c"; } .am-slider-default .am-pauseplay a:hover { opacity: 1; } .am-slider-default .am-pauseplay a.am-play::before { content: "\f04b"; } .am-slider-default .am-slider-desc { background-color: rgba(0, 0, 0, 0.7); position: absolute; bottom: 0; padding: 10px; width: 100%; color: #fff; } .am-slider-default .am-control-nav { width: 100%; position: absolute; bottom: -15px; text-align: center; } .am-slider-default .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-default .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: #666; background-color: rgba(0, 0, 0, 0.5); line-height: 0; font-size: 0; cursor: pointer; text-indent: -9999px; border-radius: 20px; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-default .am-control-nav li a:hover { background-color: #333; background-color: rgba(0, 0, 0, 0.7); } .am-slider-default .am-control-nav li a.am-active { background-color: #000; background-color: #0e90d2; cursor: default; } .am-slider-default .am-control-thumbs { margin: 5px 0 0; position: static; overflow: hidden; } .am-slider-default .am-control-thumbs li { width: 25%; float: left; margin: 0; } .am-slider-default .am-control-thumbs img { width: 100%; height: auto; display: block; opacity: .7; cursor: pointer; } .am-slider-default .am-control-thumbs img:hover { opacity: 1; } .am-slider-default .am-control-thumbs .am-active { opacity: 1; cursor: default; } .am-slider-default .am-control-thumbs i { position: absolute; } /* TODO: 1. 动画应该放在 dialog 上,不再是整个 modal,涉及 JS 逻辑,需要统筹修改 2. modal 滚动条处理,是否需要添加一个滚动条宽度的水平 padding? */ /* ========================================================================== Component: Modal Plugin ============================================================================ */ .am-modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1110; display: none; opacity: 0; outline: 0; text-align: center; -webkit-transform: scale(1.185); -ms-transform: scale(1.185); transform: scale(1.185); -webkit-transition-property: opacity, -webkit-transform; transition-property: opacity, -webkit-transform; transition-property: transform, opacity; transition-property: transform, opacity, -webkit-transform; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .am-modal:focus { outline: 0; } .am-modal.am-modal-active { opacity: 1; -webkit-transition-duration: 300ms; transition-duration: 300ms; -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1); overflow-x: hidden; overflow-y: auto; } .am-modal.am-modal-out { opacity: 0; z-index: 1109; -webkit-transition-duration: 300ms; transition-duration: 300ms; -webkit-transform: scale(0.815); -ms-transform: scale(0.815); transform: scale(0.815); } .am-modal:before { content: "\200B"; display: inline-block; height: 100%; vertical-align: middle; } .am-modal-dialog { position: relative; display: inline-block; vertical-align: middle; margin-left: auto; margin-right: auto; width: 270px; max-width: 100%; border-radius: 2px; background: #f8f8f8; /*@media @large-up { width: @modal-lg; margin-left: -@modal-lg/2; }*/ } @media only screen and (min-width:641px) { .am-modal-dialog { width: 540px; } } .am-modal-hd { padding: 15px 10px 5px 10px; font-size: 1.8rem; font-weight: 500; } .am-modal-hd + .am-modal-bd { padding-top: 0; } .am-modal-hd .am-close { position: absolute; top: 4px; right: 4px; } .am-modal-bd { padding: 15px 10px; text-align: center; border-bottom: 1px solid #dedede; border-radius: 2px 2px 0 0; } .am-modal-bd + .am-modal-bd { margin-top: 5px; } .am-modal-prompt-input { display: block; margin: 5px auto 0 auto; border-radius: 2px; padding: 5px; line-height: 1.8rem; width: 80%; border: 1px solid #dedede; -webkit-appearance: none; -moz-appearance: none; -ms-appearance: none; appearance: none; } .am-modal-prompt-input:focus { outline: none; border-color: #d6d6d6; } .am-modal-footer { height: 44px; overflow: hidden; display: table; width: 100%; border-collapse: collapse; } .am-modal-btn { display: table-cell !important; padding: 0 5px; height: 44px; -webkit-box-sizing: border-box !important; box-sizing: border-box !important; font-size: 1.6rem; line-height: 44px; text-align: center; color: #0e90d2; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; cursor: pointer; border-right: 1px solid #dedede; } .am-modal-btn:first-child { border-radius: 0 0 0 2px; } .am-modal-btn:last-child { border-right: none; border-radius: 0 0 2px 0; } .am-modal-btn:first-child:last-child { border-radius: 0 0 2px 2px; } .am-modal-btn.am-modal-btn-bold { font-weight: 500; } .am-modal-btn:active { background: #d4d4d4; } .am-modal-btn + .am-modal-btn { border-left: 1px solid #dedede; } .am-modal-no-btn .am-modal-dialog { border-radius: 2px; border-bottom: none; } .am-modal-no-btn .am-modal-bd { border-bottom: none; } .am-modal-no-btn .am-modal-footer { display: none; } .am-modal-loading .am-modal-bd { border-bottom: none; } .am-modal-loading .am-icon-spin { display: inline-block; font-size: 2.4rem; } .am-modal-loading .am-modal-footer { display: none; } .am-modal-actions { position: fixed; left: 0; bottom: 0; z-index: 1110; width: 100%; max-height: 100%; overflow-x: hidden; overflow-y: auto; text-align: center; border-radius: 2px; -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); -webkit-transition: -webkit-transform 300ms; transition: -webkit-transform 300ms; transition: transform 300ms; transition: transform 300ms, -webkit-transform 300ms; } .am-modal-actions.am-modal-active { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); } .am-modal-actions.am-modal-out { z-index: 1109; -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); } .am-modal-actions-group { margin: 10px; } .am-modal-actions-group .am-list { margin: 0; border-radius: 2px; } .am-modal-actions-group .am-list > li { margin-bottom: 0; border-bottom: none; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015); box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.015); } .am-modal-actions-group .am-list > li > a { padding: 1rem; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-modal-actions-group .am-list > li:first-child { border-top: none; border-top-right-radius: 2px; border-top-left-radius: 2px; } .am-modal-actions-group .am-list > li:last-child { border-bottom: none; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } .am-modal-actions-header { padding: 1rem; color: #999999; font-size: 1.4rem; } .am-modal-actions-danger { color: #dd514c; } .am-modal-actions-danger a { color: inherit; } .am-popup { position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 1110; background: #fff; display: none; overflow: hidden; -webkit-transition-property: -webkit-transform; transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); } .am-popup.am-modal-active, .am-popup.am-modal-out { -webkit-transition-duration: 300ms; transition-duration: 300ms; } .am-popup.am-modal-active { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); } .am-popup.am-modal-out { -webkit-transform: translateY(100%); -ms-transform: translateY(100%); transform: translateY(100%); } @media all and (min-width: 630px) and (min-height: 630px) { .am-popup { width: 630px; height: 630px; left: 50%; top: 50%; margin-left: -315px; margin-top: -315px; -webkit-transform: translateY(1024px); -ms-transform: translateY(1024px); transform: translateY(1024px); } .am-popup.am-modal-active { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); } .am-popup.am-modal-out { -webkit-transform: translateY(1024px); -ms-transform: translateY(1024px); transform: translateY(1024px); } } .am-popup-inner { padding-top: 44px; height: 100%; overflow: auto; -webkit-overflow-scrolling: touch; } .am-popup-hd { position: absolute; top: 0; z-index: 1000; width: 100%; height: 43px; border-bottom: 1px solid #dedede; background-color: #fff; } .am-popup-hd .am-popup-title { font-size: 1.8rem; font-weight: bold; line-height: 43px; text-align: center; margin: 0 30px; color: #333333; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-popup-hd .am-close { position: absolute; right: 10px; top: 8px; cursor: pointer; -webkit-transition: all 0.3s; transition: all 0.3s; color: #999999; } .am-popup-hd .am-close:hover { -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); color: #555555; } .am-popup-bd { padding: 15px; background: #f8f8f8; color: #555555; } /* ========================================================================== Component: OffCanvas Plugin ============================================================================ */ /* Off-canvas overlay and bar container */ .am-offcanvas { display: none; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1090; background: rgba(0, 0, 0, 0.15); } .am-offcanvas.am-active { display: block; } /** * .@{ns}offcanvas-page * * Prepares the whole HTML page to slide-out * 1. Fix the main page and disallow scrolling * 2. Side-out transition */ .am-offcanvas-page { position: fixed; /* 1 */ -webkit-transition: margin-left 0.3s ease-in-out; transition: margin-left 0.3s ease-in-out; /* 2 */ } /* Sub-object .@{ns}offcanvas-bar */ .am-offcanvas-bar { position: fixed; top: 0; bottom: 0; left: 0; z-index: 1091; width: 270px; max-width: 100%; background: #333; overflow-y: auto; /* scrollable */ -webkit-overflow-scrolling: touch; /* scrollable */ -webkit-transition: -webkit-transform 0.3s ease-in-out; transition: -webkit-transform 0.3s ease-in-out; transition: transform 0.3s ease-in-out; transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; -webkit-transform: translateX(-100%); -ms-transform: translateX(-100%); transform: translateX(-100%); } .am-offcanvas-bar:after { content: ""; display: block; position: absolute; top: 0; bottom: 0; right: 0; width: 1px; background: #262626; } .am-offcanvas.am-active .am-offcanvas-bar.am-offcanvas-bar-active { -webkit-transform: translateX(0); -ms-transform: translateX(0); transform: translateX(0); } /* .@{ns}offcanvas-bar-flip */ .am-offcanvas-bar-flip { left: auto; right: 0; -webkit-transform: translateX(100%); -ms-transform: translateX(100%); transform: translateX(100%); } .am-offcanvas-bar-flip:after { right: auto; left: 0; } .am-offcanvas-content { padding: 15px; color: #999; } .am-offcanvas-content a { color: #ccc; } /* ========================================================================== Component: Popover Plugin ============================================================================ */ .am-popover { position: absolute; top: 0; left: 0; margin: 0; border-radius: 2px; background: #333333; color: #fff; border: 1px solid #333333; display: none; font-size: 1.6rem; z-index: 1030; opacity: 0; -webkit-transition: opacity 300ms; transition: opacity 300ms; } .am-popover.am-active { display: block !important; opacity: 1; } .am-popover-inner { position: relative; background: #333333; padding: 8px; z-index: 110; } .am-popover-caret { position: absolute; top: 0; z-index: 100; display: inline-block; width: 0; height: 0; vertical-align: middle; border-bottom: 8px solid #333333; border-right: 8px solid transparent; border-left: 8px solid transparent; border-top: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); overflow: hidden; } .am-popover-top .am-popover-caret { top: auto; bottom: -8px; -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } .am-popover-bottom .am-popover-caret { top: -8px; } .am-popover-top .am-popover-caret, .am-popover-bottom .am-popover-caret { left: 50%; margin-left: -8px; } .am-popover-left .am-popover-caret { top: auto; left: auto; right: -12px; -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .am-popover-right .am-popover-caret { right: auto; left: -12px; -webkit-transform: rotate(-90deg); -ms-transform: rotate(-90deg); transform: rotate(-90deg); } .am-popover-left .am-popover-caret, .am-popover-right .am-popover-caret { top: 50%; margin-top: -4px; } .am-popover-sm { font-size: 1.4rem; } .am-popover-sm .am-popover-inner { padding: 5px; } .am-popover-lg { font-size: 1.8rem; } .am-popover-primary { border-color: #0e90d2; } .am-popover-primary .am-popover-inner { background: #0e90d2; } .am-popover-primary .am-popover-caret { border-bottom-color: #0e90d2; } .am-popover-secondary { border-color: #3bb4f2; } .am-popover-secondary .am-popover-inner { background: #3bb4f2; } .am-popover-secondary .am-popover-caret { border-bottom-color: #3bb4f2; } .am-popover-success { border-color: #5eb95e; } .am-popover-success .am-popover-inner { background: #5eb95e; } .am-popover-success .am-popover-caret { border-bottom-color: #5eb95e; } .am-popover-warning { border-color: #F37B1D; } .am-popover-warning .am-popover-inner { background: #F37B1D; } .am-popover-warning .am-popover-caret { border-bottom-color: #F37B1D; } .am-popover-danger { border-color: #dd514c; } .am-popover-danger .am-popover-inner { background: #dd514c; } .am-popover-danger .am-popover-caret { border-bottom-color: #dd514c; } /* ========================================================================== Component: Progress Plugin ============================================================================ */ #nprogress { /* Make clicks pass-through */ pointer-events: none; /* Fancy blur effect */ } #nprogress .nprogress-bar { position: fixed; top: 0; left: 0; z-index: 2000; width: 100%; height: 2px; background: #5eb95e; } #nprogress .nprogress-peg { display: block; position: absolute; right: 0; width: 100px; height: 100%; -webkit-box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e; box-shadow: 0 0 10px #5eb95e, 0 0 5px #5eb95e; opacity: 1; -webkit-transform: rotate(3deg) translate(0px, -4px); -ms-transform: rotate(3deg) translate(0px, -4px); transform: rotate(3deg) translate(0px, -4px); } #nprogress .nprogress-spinner { position: fixed; top: 15px; right: 15px; z-index: 2000; display: block; } #nprogress .nprogress-spinner-icon { width: 18px; height: 18px; -webkit-box-sizing: border-box; box-sizing: border-box; border: solid 2px transparent; border-top-color: #5eb95e; border-left-color: #5eb95e; border-radius: 50%; -webkit-animation: nprogress-spinner 400ms linear infinite; animation: nprogress-spinner 400ms linear infinite; } @-webkit-keyframes nprogress-spinner { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes nprogress-spinner { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } /* ========================================================================== Component: Tabs Plugin ============================================================================ */ .am-tabs-bd { position: relative; overflow: hidden; border: 1px solid #ddd; border-top: none; z-index: 100; -webkit-transition: height .3s; transition: height .3s; } .am-tabs-bd:before, .am-tabs-bd:after { content: " "; display: table; } .am-tabs-bd:after { clear: both; } .am-tabs-bd .am-tab-panel { position: absolute; top: 0; z-index: 99; float: left; width: 100%; padding: 10px 10px 15px; visibility: hidden; -webkit-transition: -webkit-transform 0.3s; transition: -webkit-transform 0.3s; transition: transform 0.3s; transition: transform 0.3s, -webkit-transform 0.3s; -webkit-transform: translateX(-100%); -ms-transform: translateX(-100%); transform: translateX(-100%); } .am-tabs-bd .am-tab-panel * { -webkit-user-drag: none; } .am-tabs-bd .am-tab-panel.am-active { position: relative; z-index: 100; visibility: visible; -webkit-transform: translateX(0); -ms-transform: translateX(0); transform: translateX(0); } .am-tabs-bd .am-tab-panel.am-active ~ .am-tab-panel { -webkit-transform: translateX(100%); -ms-transform: translateX(100%); transform: translateX(100%); } .am-tabs-bd .am-tabs-bd { border: none; } .am-tabs-bd-ofv { overflow: visible; } .am-tabs-fade .am-tab-panel { opacity: 0; -webkit-transition: opacity .25s linear; transition: opacity .25s linear; } .am-tabs-fade .am-tab-panel.am-in { opacity: 1; } /* ========================================================================== Component: Share Plugin ============================================================================ */ .am-share { font-size: 14px; } .am-share-title { padding: 10px 0 0; margin: 0 10px; font-weight: normal; text-align: center; color: #555555; background-color: #f8f8f8; border-bottom: 1px solid #fff; border-top-right-radius: 2px; border-top-left-radius: 2px; } .am-share-title:after { content: ""; display: block; width: 100%; height: 0; margin-top: 10px; border-bottom: 1px solid #dfdfdf; } .am-share-sns { margin: 0 10px; padding-top: 15px; background-color: #f8f8f8; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } .am-share-sns li { margin-bottom: 15px; } .am-share-sns a { display: block; color: #555555; } .am-share-sns span { display: block; } .am-share-sns [class*='am-icon'] { background-color: #3bb4f2; border-radius: 50%; width: 36px; height: 36px; line-height: 36px; color: #fff; margin-bottom: 5px; font-size: 18px; } .am-share-sns .am-icon-weibo { background-color: #ea1328; } .am-share-sns .am-icon-qq { background-color: #009cda; } .am-share-sns .am-icon-star { background-color: #ffc028; } .am-share-sns .am-icon-tencent-weibo { background-color: #23ccfe; } .am-share-sns .am-icon-wechat, .am-share-sns .am-icon-weixin { background-color: #44b549; } .am-share-sns .am-icon-renren { background-color: #105ba3; } .am-share-sns .am-icon-comment { background-color: #5eb95e; } .am-share-footer { margin: 10px; } .am-share-footer .am-btn { color: #555555; } .am-share-wechat-qr { font-size: 14px; color: #777; } .am-share-wechat-qr .am-modal-dialog { background-color: #fff; border: 1px solid #dedede; } .am-share-wechat-qr .am-modal-hd { padding-top: 10px; text-align: left; margin-bottom: 10px; } .am-share-wechat-qr .am-share-wx-qr { margin-bottom: 10px; } .am-share-wechat-qr .am-share-wechat-tip { text-align: left; } .am-share-wechat-qr .am-share-wechat-tip em { color: #dd514c; font-weight: bold; font-style: normal; margin-left: 3px; margin-right: 3px; } /* ========================================================================== Component: PureView Plugin ============================================================================ */ .am-pureview { position: fixed; left: 0; top: 0; bottom: 0; right: 0; z-index: 1120; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.95); display: none; overflow: hidden; -webkit-transition: -webkit-transform .3s; transition: -webkit-transform .3s; transition: transform .3s; transition: transform .3s, -webkit-transform .3s; -webkit-transform: translate(0, 100%); -ms-transform: translate(0, 100%); transform: translate(0, 100%); } .am-pureview.am-active { -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-pureview ul, .am-pureview ol { list-style: none; padding: 0; margin: 0; width: 100%; } .am-pureview-slider { overflow: hidden; height: 100%; } .am-pureview-slider li { position: absolute; width: 100%; height: 100%; top: 0; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; vertical-align: middle; -webkit-transition: all .3s linear; transition: all .3s linear; z-index: 100; visibility: hidden; } .am-pureview-slider li.am-pureview-slide-prev { -webkit-transform: translate(-100%, 0); -ms-transform: translate(-100%, 0); transform: translate(-100%, 0); z-index: 109; } .am-pureview-slider li.am-pureview-slide-next { -webkit-transform: translate(100%, 0); -ms-transform: translate(100%, 0); transform: translate(100%, 0); z-index: 109; } .am-pureview-slider li.am-active { position: relative; z-index: 110; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); visibility: visible; } .am-pureview-slider .pinch-zoom-container { width: 100%; z-index: 1121; } .am-pureview-slider .am-pinch-zoom { position: relative; width: 100%; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; } .am-pureview-slider .am-pinch-zoom:after { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f110"; -webkit-animation: icon-spin 2s infinite linear; animation: icon-spin 2s infinite linear; font-size: 24px; line-height: 24px; color: #eee; position: absolute; top: 50%; left: 50%; margin-left: -12px; margin-top: -12px; z-index: 1; } .am-pureview-slider .am-pinch-zoom.am-pureview-loaded:after { display: none; } .am-pureview-slider img { position: relative; display: block; max-width: 100%; max-height: 100%; opacity: 0; z-index: 200; -webkit-user-drag: none; -webkit-transition: opacity 0.2s ease-in; transition: opacity 0.2s ease-in; } .am-pureview-slider img.am-img-loaded { opacity: 1; } .am-pureview-direction { position: absolute; top: 50%; width: 100%; margin-top: -18px !important; z-index: 1122; } .am-touch .am-pureview-direction, .am-pureview-only .am-pureview-direction { display: none; } .am-pureview-direction li { position: absolute; width: 36px; height: 36px; } .am-pureview-direction a { display: block; height: 36px; border: none; color: #ccc; opacity: 0.5; cursor: pointer; text-align: center; z-index: 1125; } .am-pureview-direction a:before { content: "\f137"; line-height: 36px; font-size: 24px; } .am-pureview-direction a:hover { opacity: 1; } .am-pureview-direction .am-pureview-prev { left: 15px; } .am-pureview-direction .am-pureview-next { right: 15px; } .am-pureview-direction .am-pureview-next a:before { content: "\f138"; } .am-pureview-bar { position: absolute; bottom: 0; height: 45px; width: 100%; background-color: rgba(0, 0, 0, 0.35); color: #eeeeee; line-height: 45px; padding: 0 10px; font-size: 14px; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } .am-pureview-bar .am-pureview-title { display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; margin-left: 6px; -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; } .am-pureview-bar .am-pureview-total { font-size: 10px; line-height: 48px; } .am-pureview-actions { position: absolute; z-index: 1130; left: 0; right: 0; top: 0; height: 45px; background-color: rgba(0, 0, 0, 0.35); } .am-pureview-actions a { position: absolute; left: 10px; color: #ccc; display: block; width: 45px; line-height: 45px; text-align: left; font-size: 16px; } .am-pureview-actions a:hover { color: #fff; } .am-pureview-actions [data-am-toggle="share"] { left: auto; right: 10px; } .am-pureview-bar, .am-pureview-actions { opacity: 0; -webkit-transition: all .15s; transition: all .15s; z-index: 1130; } .am-pureview-bar-active .am-pureview-bar, .am-pureview-bar-active .am-pureview-actions { opacity: 1; } .am-pureview-nav { position: absolute; bottom: 15px; left: 0; right: 0; text-align: center; z-index: 1131; } .am-pureview-bar-active .am-pureview-nav { display: none; } .am-pureview-nav li { display: inline-block; background: #ccc; background: rgba(255, 255, 255, 0.5); width: 8px; height: 8px; margin: 0 3px; border-radius: 50%; text-indent: -9999px; overflow: hidden; cursor: pointer; } .am-pureview-nav .am-active { background: #fff; background: rgba(255, 255, 255, 0.9); } [data-am-pureview] img { cursor: pointer; } .am-pureview-active { overflow: hidden; } .ath-viewport * { -webkit-box-sizing: border-box; box-sizing: border-box; } .ath-viewport { position: relative; z-index: 2147483641; pointer-events: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-text-size-adjust: none; -ms-text-size-adjust: none; text-size-adjust: none; } .ath-modal { pointer-events: auto !important; background: rgba(0, 0, 0, 0.6); } .ath-mandatory { background: #000; } .ath-container { pointer-events: auto !important; position: absolute; z-index: 2147483641; padding: 0.7em 0.6em; width: 18em; background: #eee; -webkit-background-size: 100% auto; background-size: 100% auto; -webkit-box-shadow: 0 0.2em 0 #d1d1d1; box-shadow: 0 0.2em 0 #d1d1d1; font-family: sans-serif; font-size: 15px; line-height: 1.5em; text-align: center; } .ath-container small { font-size: 0.8em; line-height: 1.3em; display: block; margin-top: 0.5em; } .ath-ios.ath-phone { bottom: 1.8em; left: 50%; margin-left: -9em; } .ath-ios6.ath-tablet { left: 5em; top: 1.8em; } .ath-ios7.ath-tablet { left: 0.7em; top: 1.8em; } .ath-ios8.ath-tablet { right: 0.4em; top: 1.8em; } .ath-android { bottom: 1.8em; left: 50%; margin-left: -9em; } /* close icon */ .ath-container:before { content: ''; position: relative; display: block; float: right; margin: -0.7em -0.6em 0 0.5em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAAAdVBMVEUAAAA5OTkzMzM7Ozs3NzdBQUFAQEA/Pz8+Pj5BQUFAQEA/Pz8+Pj5BQUFAQEA/Pz9BQUE+Pj4/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8+Pj4/Pz8+Pj4/Pz8/Pz8/Pz8/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8/Pz9AQEA/Pz+fdCaPAAAAJnRSTlMACQoNDjM4OTo7PEFCQ0RFS6ytsbS1tru8vcTFxu7x8vX19vf4+C5yomAAAAJESURBVHgBvdzLTsJAGEfxr4C2KBcVkQsIDsK8/yPaqIsPzVlyzrKrX/5p0kkXEz81L23otc9NpIbbWia2YVLqdnhlqFlhGWpSDHe1aopsSIpRb8gK0dC3G30b9rVmhWZIimTICsvQtx/FsuYOrWHoDjX3Gu31gzJxdki934WrAIOsAIOsAIOiAMPhPsJTgKGN0BVsYIVsYIVpYIVpYIVpYIVpYIVpYIVpYIVpYIVlAIVgEBRs8BRs8BRs8BRs8BRs8BRs8BRs8BRTNmgKNngKNngKNngKNngKNhiKGxgiOlZoBlaYBlaYBlaYBlaYBlaYBlaYBlaYBlZIBlBMfQMrVAMr2KAqBENSHFHhGEABhi5CV6gGUKgGUKgGUKgGUFwuqgEUvoEVsoEVpoEUpgEUggF+gKTKY+h1fxSlC7/Z+RrxOQ3fcEoAPPHZBlaYBlaYBlaYBlZYBlYIhvLBCstw7PgM7hkiWOEZWGEaWGEaWGEaIsakEAysmHkGVpxmvoEVqoEVpoEVpoEVpoEVpoEVpoEVkoEVgkFQsEFSsEFQsGEcoSvY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnmbNAUT2c2WAo2eAo2eAo2eAo2eAo2eArNEPFACjZ4CjZ4CjZ4CjaIird/rBvFH6llNCvewdli1URWCIakSIZesUaDoFg36dKFWk9zCZDei3TtwmCj7pC22AwikiIZPEU29IpFNliKxa/hC9DFITjQPYhcAAAAAElFTkSuQmCC); background-color: rgba(255, 255, 255, 0.8); -webkit-background-size: 50% 50%; background-size: 50%; background-repeat: no-repeat; background-position: 50%; width: 2.7em; height: 2.7em; text-align: center; overflow: hidden; color: #a33; z-index: 2147483642; } .ath-container.ath-icon:before { position: absolute; top: 0; right: 0; margin: 0; float: none; } .ath-mandatory .ath-container:before { display: none; } .ath-container.ath-android:before { float: left; margin: -0.7em 0.5em 0 -0.6em; } .ath-container.ath-android.ath-icon:before { position: absolute; right: auto; left: 0; margin: 0; float: none; } /* applied only if the application icon is shown */ .ath-action-icon { display: inline-block; vertical-align: middle; background-position: 50%; background-repeat: no-repeat; text-indent: -9999em; overflow: hidden; } .ath-ios7 .ath-action-icon, .ath-ios8 .ath-action-icon { width: 1.6em; height: 1.6em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAACtCAYAAAB7l7tOAAAF6UlEQVR4AezZWWxUZRiH8VcQEdxZEFFiUZBFUCIa1ABBDARDcCciYGKMqTEGww3SOcNSAwQTjOBiiIpEhRjAhRgXRC8MFxojEhAFZUGttVhaoSxlaW3n8W3yXZxm6vTrOMM5Q98n+V9MMu1pvl++uZhKuypghu49KaaTWGdZSYoVN6VD95nMpLNYZ9XNbdQR2od2k88O3Gm6Bh0t7H0p5Vwp2Ax3ajpu2tYbciFWwkTFO63DY6+JcI4USFaSyYpWp8N7SVZJKR3EinkBk9JxvZFXxhnZSjBaoWp1ZL0ES8WKYXMZp0AndORgy8WKFe5Yf1zvvSBWDEpys2LU6MjD5kmEWQlGKsJRHXlcqUSQVcItEnDEA6gAb7LhjvD9WO6yIEfICQI5A1nzGCYB1T4og5bBiFcyv2f6ujYhl4iVxwKG6qp8MK55HsqPwK0rMr9v/yEo3uCPrJstVh5KMER30Aeh31Ioq0FrHfjXw9CYghnrvYFTuqfEymFzGSwBlT4ARYr7u+K6GLmCVGvAGg2NMG0d/sgJnpScZLjXSkC5z8H3eQ72/k24Q8NfzvwFyK4qtuJSZKaubRPyE/K/Mtx+EvCHL+7uasId1t10w0scz/RzSzYzAfgKV30D3LPaG7lRkR8RK4tKKJKAMp+D7r0EfmmOe0x3m2itAc/ZxBjgAt1mXHWKPPkdb+QGSTJdrDaU5EoJ2OtzwD0WwY7KNNzbRfMFFg24WPdtGHnS221Cflgsj56hjwTs8TnY7oq7/QDhjutGicsb2AVcovsO18l6uPPNNiE/JFaGAq7Q7fY50G4LYVtz3FrdaNGyBXbIl+q24DqhyHes9EaulwR3SwtZs+ktAT/7HORliru1gnCndONFyx44Dfn7MPLYN7yR6yTJZAllJeguAT/4HOBFz8I3ZWm4E0TLFbBD7qn7EVdtHYx53R9ZN0ksrZRuErDN5+AuLIWvm+Oe1k0ULdfADrmX7idcR0/DyBXeyCdlLuMMOGCBz4F1ng+f7yFcve5e0fIFHELeiav6BAx70Rt5p0yhY3u/wR0kyarW/uX35b403PtFyzewQ75ctwtXzSkY8WqruHslSV8RscrL6TJ1bcvfWJ0/HzbtIdw/ugdFyzdwOOAq3T6fmzxwGQ3vbmO8iFioIWqYSsHMj9M/ljfuTsOdItoZBXYBfXX7cVXVwvXLm/8+fU3lcdCqdEMNGBbgUmRmfQISQKd5sGEn4VK6YtEiAXYBA3QVuA4q8hCHrDcafR1ul65jewfuovsCl7vJrNlOuEbdo6JFCuwCrtb9hqusBu56Cw4cI1y1briIWEBn3Ue0XKPuMdGiBg4H9NdV0HJ/6QZLOEPmPN0GmpfSPS5arIBdwHUtIFfoBsl/ZsgfhHCfFi2WwC5goO4AmvanbqBkzJA76tboZokWa2AXMEi3RTdAvDLkDqJFAhzB32xFD2wZsGXA0WfAlgFbBmwZsGXAlgFbBpzk04JaKb0iA9ZnF9x5SQAFtRKKIgPWZxfaeRmwAZ/BGbAB37eaG6MCbnq2Aed5czYyKirgpmcbsAHHZAZswN0Wwo7KeG1fFf2jAm56dtzOQ42yB+65mDhWFBUwUETMUiMDNmADbp/APRaTAh6I2bpGCNw1bufRZJQ1cPdF/NueHZsgDEBBGLbMGoIu4AZu5gLOZeEaYmEXeznF3jRPyEv4frgJvvJe3qTefY0AAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwb8rwADBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgz4/sz1Nia/9hizA7zgklwy3RYwYMBzBRjw4bPjxAbAAizAAtwgwAIswAIswAIMGDBgARZgARZgAS4FWIAFWIAFWIABAwYswAIswAIswIUAC7AAC7AACzBgwIAFWIAFWIAFuBBgARZgARZgAQYMGPApQ99ZCdgWtzqwATbABtgAG2DbnxNb7zbRimsMLMACrDf2wMWI/WasfQAAAABJRU5ErkJggg==); margin-top: -0.3em; -webkit-background-size: auto 100%; background-size: auto 100%; } .ath-ios6 .ath-action-icon { width: 1.8em; height: 1.8em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAB0CAQAAADAmnOnAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAWwEAAFsBAXkZiFwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAF4klEQVR4Ae3a/a+XdR3H8ec5HM45HDmKICoVohkZsxESRRCzcZM/2JKkdGR5MrSkleA0Pd00O4u5IVuNM2yYc6XSzCExU4oUNRPCJFdMUAhsYZpUGhscOHA4N8/WZzsL6HBxvofvdV3fa3yer//gsV3vH659KHzncBsJxUYhDzOEhCKQbORs+ip2wzgM+wvj+P9i35qAGLaHGcQSgKSTrxBLABJppZpYApCspoFYApBsZjSxBCD5OxOJJQBJG1cQSwCSLpqJJQCJ3MvgCGTinuSMCJS8LZwfgZL3FtMiUPIOcU0ESl4PLRHoRPsJtREoeRsYGYGS9yrvo6RmpbLaigWSfzOdErLs6+bLUMFA0sF1+QF1cz1UNlBYK9V5AHXyWSgEkKyiIWOgGh829Ki1lLcaxjCVK7mJRSxjBY+zgRf/u9pXcMB7jhEZAg32EUP3O6hMKOP5Iq2sZQeHMZXt5KKMgOpcY+iHVnFyjeQKlrCBdsxge5ieAVC9vzLUelI8H+A7bKIHM10H81IGGuKvDf1ggDxVTKOV1zG3/Yia1ICG+ltD32MgNTKfP2HuW0VDKkCNrjfUTOm9i6XswwrZJkaVHeh0f2fodkrtfO6jAytqrzG+rEDDfVG1x1sprZEs5RBW4PZxeT+Bbrf5hPu9arfzKaU6WjiAFbseWvoF1GW/6vYGSmkyW7Dit4xB5QHq9Br6Xx2t9GAhtp6zkoHsfNp1J9wX6H+jeR4LtJc4LxGopZZyNpN/YcG2mw9nBTSPLizgOmjKAujGgvJID3ekD7QYi7nGzkvmQtpA38Vi7iJf0TedlC7QTVjMfcY2QyvSBPpUMW/PIBfbo9pls1XpAX2EdizeznStob3OJpQO0DB2YfE21q2GtnghpAm0Gou3T9tm6BGHQppA12HRVt17eboNlydNoLHsx2JtmL801OYcQmkC/QKLtQt9ydBW3wNpA30ci7Ur3WdolUMhbaBqNhf/8qQJ9Hkszs5wjaH9XkUobaAqtmFRdoGbDb3sWMgG6DIs5852knO82RaXer+P+qyb3eWeo7ZNBrRZvm1otY2QFdBjeHIb6hTne49Put12+9ObMoDdYmfy5UkF6AK6cCCr9aM2u9IddptcOYCG+FNDB5xLKCugO7G01TndFp/xgAntdYvrfdwVLnORt3q9Vx25F27DUjbGPxr6qxMgW6Cd2N+d6wLXedA+6nKbK73Lr/pJxzusvE/wZrvX0FOOgGyBxmF/dprXutYOj6nNdS6xyYnWp/dGcaGdhr5vDWQN9E1MXrUzfcA2j2qPj/l1J1uT9iPOeh8w1O7nCGUN9HzyGZ7ndo9qp0ucanU2r1xH+wdDu5wIeQDVVx0+/kd1i697RNv8thdn+Qz4Uv9p6DeOhHyApmBfq3OBu+3Nfd7nVELZAX3Nw4ZarYG8gG7GY1dlk6/Zm3/2Rk8jlB1QvT82dNAmQjkBVf8Mj957fdrefM7ZVhPKEuidvmDob06CXIGGbsX/bZDf8KAhfdbJhLIGmuZuQ084HHIGatiLvRvrRkP6qldbBXkAzbfD0N0OhryBGqrEMOd50FC7d1hPKGugBh8ydMh5hPIGGouI1d5lj6F1vptQ9kDvcKOhN5wMlQH0QcRGnzC03yZCeQDN9G1D6xwBFQI07FI8x02GdjgB8gJqttPQcmuhYoAumzvG7YZWejrkA1TrPYYO+SVCFQO0aM4bqj0uJJQH0LluSP7PkyeQU9QOmyAvoBm+Zegpz4LKA/qYB/wE5AXUe3m81zqoRKAPOYWcuvP9dxvqcD6h7IAKkaNU3eUlHLcI9EzS5YlAi62h/zUy89QCqqKUmvgHywsJlEHnsQYxAvXVIJo5gIhnPhiBju1iNmLvLn85Ah1ZPYs5jBGo72awEzEC9dVwHqQHI9DxWoAYgSLQQKteGIESu/qhCJTYtT+PQBEoAkWgCBSBkotAEehUWwSKQBEoAkWg/BeBIlAEikARKAJFoFmealu4gVLy1Gt5dkARKAL9BzujPSurTmu/AAAAAElFTkSuQmCC); margin-bottom: 0.4em; -webkit-background-size: 100% auto; background-size: 100% auto; } .ath-android .ath-action-icon { width: 1.4em; height: 1.4em; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVmZmb///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZW6fJrAAAAEXRSTlMAAAYHG21ub8fLz9DR8/T4+RrZ9owAAAB3SURBVHja7dNLDoAgDATQWv4gKve/rEajJOJiWLgg6WzpSyB0aHqHiNj6nL1lovb4C+hYzkSNAT7mryQFAVOeGAj4CjwEtgrWXpD/uZKtwEJApXt+Vn0flzRhgNiFZQkOXY0aADQZCOCPlsZJ46Rx0jhp3IiN2wGDHhxtldrlwQAAAABJRU5ErkJggg==); -webkit-background-size: 100% auto; background-size: 100% auto; } .ath-container p { margin: 0; padding: 0; position: relative; z-index: 2147483642; text-shadow: 0 0.1em 0 #fff; font-size: 1.1em; } .ath-ios.ath-phone:after { content: ''; background: #eee; position: absolute; width: 2em; height: 2em; bottom: -0.9em; left: 50%; margin-left: -1em; -webkit-transform: scaleX(0.9) rotate(45deg); -ms-transform: scaleX(0.9) rotate(45deg); transform: scaleX(0.9) rotate(45deg); -webkit-box-shadow: 0.2em 0.2em 0 #d1d1d1; box-shadow: 0.2em 0.2em 0 #d1d1d1; } .ath-ios.ath-tablet:after { content: ''; background: #eee; position: absolute; width: 2em; height: 2em; top: -0.9em; left: 50%; margin-left: -1em; -webkit-transform: scaleX(0.9) rotate(45deg); -ms-transform: scaleX(0.9) rotate(45deg); transform: scaleX(0.9) rotate(45deg); z-index: 2147483641; } .ath-application-icon { position: relative; padding: 0; border: 0; margin: 0 auto 0.2em auto; height: 6em; width: 6em; z-index: 2147483642; } .ath-container.ath-ios .ath-application-icon { border-radius: 1em; -webkit-box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5); box-shadow: 0 0.2em 0.4em rgba(0, 0, 0, 0.3), inset 0 0.07em 0 rgba(255, 255, 255, 0.5); margin: 0 auto 0.4em auto; } @media only screen and (orientation: landscape) { .ath-container.ath-phone { width: 24em; } .ath-android.ath-phone { margin-left: -12em; } .ath-ios.ath-phone { margin-left: -12em; } .ath-ios6:after { left: 39%; } .ath-ios8.ath-phone { left: auto; bottom: auto; right: 0.4em; top: 1.8em; } .ath-ios8.ath-phone:after { bottom: auto; top: -0.9em; left: 68%; z-index: 2147483641; -webkit-box-shadow: none; box-shadow: none; } } /* ========================================================================== Component: uCheck Plugin ============================================================================ */ .am-checkbox, .am-radio, .am-checkbox-inline, .am-radio-inline { padding-left: 22px; position: relative; -webkit-transition: color .25s linear; transition: color .25s linear; font-size: 14px; line-height: 1.5; } label.am-checkbox, label.am-radio { font-weight: normal; } .am-ucheck-icons { color: #999999; display: block; height: 20px; top: 0; left: 0; position: absolute; width: 20px; text-align: center; line-height: 21px; font-size: 18px; cursor: pointer; } .am-checkbox .am-icon-checked, .am-radio .am-icon-checked, .am-checkbox-inline .am-icon-checked, .am-radio-inline .am-icon-checked, .am-checkbox .am-icon-unchecked, .am-radio .am-icon-unchecked, .am-checkbox-inline .am-icon-unchecked, .am-radio-inline .am-icon-unchecked { position: absolute; left: 0; top: 0; display: inline-table; margin: 0; background-color: transparent; -webkit-transition: color .25s linear; transition: color .25s linear; } .am-checkbox .am-icon-checked:before, .am-radio .am-icon-checked:before, .am-checkbox-inline .am-icon-checked:before, .am-radio-inline .am-icon-checked:before, .am-checkbox .am-icon-unchecked:before, .am-radio .am-icon-unchecked:before, .am-checkbox-inline .am-icon-unchecked:before, .am-radio-inline .am-icon-unchecked:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-checkbox .am-icon-checked, .am-radio .am-icon-checked, .am-checkbox-inline .am-icon-checked, .am-radio-inline .am-icon-checked { opacity: 0; } .am-checkbox .am-icon-checked:before, .am-checkbox-inline .am-icon-checked:before { content: "\f046"; } .am-checkbox .am-icon-unchecked:before, .am-checkbox-inline .am-icon-unchecked:before { content: "\f096"; } .am-radio .am-icon-checked:before, .am-radio-inline .am-icon-checked:before { content: "\f192"; } .am-radio .am-icon-unchecked:before, .am-radio-inline .am-icon-unchecked:before { content: "\f10c"; } .am-ucheck-checkbox, .am-ucheck-radio { position: absolute; left: 0; top: 0; margin: 0; padding: 0; width: 20px; height: 20px; opacity: 0; outline: none !important; } .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #0e90d2; } .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-ucheck-radio:checked + .am-ucheck-icons { color: #0e90d2; } .am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-unchecked, .am-ucheck-radio:checked + .am-ucheck-icons .am-icon-unchecked { opacity: 0; } .am-ucheck-checkbox:checked + .am-ucheck-icons .am-icon-checked, .am-ucheck-radio:checked + .am-ucheck-icons .am-icon-checked { opacity: 1; } .am-ucheck-checkbox:disabled + .am-ucheck-icons, .am-ucheck-radio:disabled + .am-ucheck-icons { cursor: default; color: #d8d8d8; } .am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-unchecked, .am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-unchecked { opacity: 0; } .am-ucheck-checkbox:disabled:checked + .am-ucheck-icons .am-icon-checked, .am-ucheck-radio:disabled:checked + .am-ucheck-icons .am-icon-checked { opacity: 1; color: #d8d8d8; } .am-checkbox.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #3bb4f2; } .am-checkbox.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-secondary .am-ucheck-radio:checked + .am-ucheck-icons { color: #3bb4f2; } .am-checkbox.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #5eb95e; } .am-checkbox.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-success .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-success .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-success .am-ucheck-radio:checked + .am-ucheck-icons { color: #5eb95e; } .am-checkbox.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #F37B1D; } .am-checkbox.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-warning .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-warning .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-warning .am-ucheck-radio:checked + .am-ucheck-icons { color: #F37B1D; } .am-checkbox.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled) + .am-ucheck-icons { color: #dd514c; } .am-checkbox.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-checkbox:checked + .am-ucheck-icons, .am-checkbox.am-danger .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio.am-danger .am-ucheck-radio:checked + .am-ucheck-icons, .am-checkbox-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons, .am-radio-inline.am-danger .am-ucheck-radio:checked + .am-ucheck-icons { color: #dd514c; } .am-field-error + .am-ucheck-icons { color: #dd514c; } .am-field-valid + .am-ucheck-icons { color: #5eb95e; } /* // Group Addon .@{ns}input-group-label { .@{ns}radio, .@{ns}checkbox { margin: -2px 0; padding-left: 15px; } } // Form inline style .@{ns}form-inline .@{ns}checkbox, .@{ns}form-inline .@{ns}radio { padding-left: 24px; } */ /* ========================================================================== Component: Selected Plugin ============================================================================ */ .am-selected { width: 200px; } .am-selected-btn { width: 100%; padding-left: 10px; text-align: right; } .am-selected-btn.am-btn-default { background: none; } .am-invalid .am-selected-btn { border-color: #dd514c; } .am-selected-header { height: 45px; background-color: #f2f2f2; border-bottom: 1px solid #ddd; display: none; } .am-selected-status { text-align: left; width: 100%; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-selected-content { padding: 10px 0; } .am-selected-search { padding: 0 10px 10px; } .am-selected-search .am-form-field { padding: .5em; } .am-selected-list { margin: 0; padding: 0; list-style: none; font-size: 1.5rem; } .am-selected-list li { position: relative; cursor: pointer; padding: 5px 10px; -webkit-transition: background-color 0.15s; transition: background-color 0.15s; } .am-selected-list li:hover { background-color: #f8f8f8; } .am-selected-list li:hover .am-icon-check { opacity: .6; } .am-selected-list li.am-checked .am-icon-check { opacity: 1; color: #0e90d2; } .am-selected-list li.am-disabled { opacity: .5; pointer-events: none; cursor: not-allowed; } .am-selected-list .am-selected-list-header { margin-top: 8px; font-size: 1.3rem; color: #999999; border-bottom: 1px solid #e5e5e5; cursor: default; } .am-selected-list .am-selected-list-header:hover { background: none; } .am-selected-list .am-selected-list-header:first-child { margin-top: 0; } .am-selected-list .am-selected-text { display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; margin-right: 30px; } .am-selected-list .am-icon-check { position: absolute; right: 8px; top: 5px; color: #999999; opacity: 0; -webkit-transition: opacity .15s; transition: opacity .15s; } .am-selected-hint { line-height: 1.2; color: #dd514c; } .am-selected-hint:not(:empty) { margin-top: 10px; border-top: 1px solid #e5e5e5; padding: 10px 10px 0; } .am-selected-placeholder { opacity: .65; } /* ========================================================================== Component: JS Plugins helpers ============================================================================ */ .am-fade { opacity: 0; -webkit-transition: opacity .2s linear; transition: opacity .2s linear; } .am-fade.am-in { opacity: 1; } .am-collapse { display: none; } .am-collapse.am-in { display: block; } tr.am-collapse.am-in { display: table-row; } tbody.am-collapse.am-in { display: table-row-group; } .am-collapsing { position: relative; height: 0; overflow: hidden; -webkit-transition: height .3s ease; transition: height .3s ease; } .am-sticky { position: fixed !important; z-index: 1010; -webkit-transform-origin: 0 0; -ms-transform-origin: 0 0; transform-origin: 0 0; } [data-am-sticky][class*="am-animation-"] { -webkit-animation-duration: .2s; animation-duration: .2s; } .am-dimmer-active { overflow: hidden; } .am-dimmer { position: fixed; top: 0; right: 0; bottom: 0; left: 0; display: none; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); z-index: 1100; opacity: 0; } .am-dimmer.am-active { opacity: 1; } [data-am-collapse] { cursor: pointer; } .am-datepicker { top: 0; left: 0; border-radius: 2px; background: #fff; -webkit-box-shadow: 0 0 10px #ccc; box-shadow: 0 0 10px #ccc; padding-bottom: 10px; margin-top: 10px; width: 238px; color: #555; display: none; } .am-datepicker > div { display: none; } .am-datepicker table { width: 100%; } .am-datepicker tr.am-datepicker-header { font-size: 1.6rem; color: #fff; background: #3bb4f2; } .am-datepicker td, .am-datepicker th { text-align: center; font-weight: normal; cursor: pointer; } .am-datepicker th { height: 48px; } .am-datepicker td { font-size: 1.4rem; } .am-datepicker td.am-datepicker-day { height: 34px; width: 34px; } .am-datepicker td.am-datepicker-day:hover { background: #F0F0F0; height: 34px; width: 34px; } .am-datepicker td.am-datepicker-day.am-disabled { cursor: no-drop; color: #999; background: #fafafa; } .am-datepicker td.am-datepicker-old, .am-datepicker td.am-datepicker-new { color: #89d7ff; } .am-datepicker td.am-active, .am-datepicker td.am-active:hover { border-radius: 2px; color: #0084c7; background: #F0F0F0; } .am-datepicker td span { display: block; width: 79.33333333px; height: 40px; line-height: 40px; float: left; cursor: pointer; } .am-datepicker td span:hover { background: #F0F0F0; } .am-datepicker td span.am-active { color: #0084c7; background: #F0F0F0; } .am-datepicker td span.am-disabled { cursor: no-drop; color: #999; background: #fafafa; } .am-datepicker td span.am-datepicker-old { color: #89d7ff; } .am-datepicker .am-datepicker-dow { height: 40px; color: #0c80ba; } .am-datepicker-caret { display: block!important; display: inline-block; width: 0; height: 0; vertical-align: middle; border-bottom: 7px solid #3bb4f2; border-right: 7px solid transparent; border-left: 7px solid transparent; border-top: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); position: absolute; top: -7px; left: 6px; } .am-datepicker-right .am-datepicker-caret { left: auto; right: 7px; } .am-datepicker-up .am-datepicker-caret { top: auto; bottom: -7px; display: inline-block; width: 0; height: 0; vertical-align: middle; border-top: 7px solid #fff; border-right: 7px solid transparent; border-left: 7px solid transparent; border-bottom: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } .am-datepicker-select { height: 34px; line-height: 34px; text-align: center; -webkit-transition: background-color 300ms ease-out; transition: background-color 300ms ease-out; } .am-datepicker-select:hover { background: rgba(154, 217, 248, 0.5); color: #0c80ba; } .am-datepicker-prev, .am-datepicker-next { width: 34px; height: 34px; } .am-datepicker-prev-icon, .am-datepicker-next-icon { width: 34px; height: 34px; line-height: 34px; display: inline-block; -webkit-transition: background-color 300ms ease-out; transition: background-color 300ms ease-out; } .am-datepicker-prev-icon:hover, .am-datepicker-next-icon:hover { background: rgba(154, 217, 248, 0.5); color: #0c80ba; } .am-datepicker-prev-icon:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; } .am-datepicker-next-icon:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f054"; } .am-datepicker-dropdown { position: absolute; z-index: 1120; } @media only screen and (max-width: 640px) { .am-datepicker { width: 100%; } .am-datepicker td span { width: 33.33%; } .am-datepicker-caret { display: none!important; } .am-datepicker-prev, .am-datepicker-next { width: 44px; height: 44px; } } .am-datepicker-success tr.am-datepicker-header { background: #5eb95e; } .am-datepicker-success td.am-datepicker-day.am-disabled { color: #999; } .am-datepicker-success td.am-datepicker-old, .am-datepicker-success td.am-datepicker-new { color: #94df94; } .am-datepicker-success td.am-active, .am-datepicker-success td.am-active:hover { color: #1b961b; } .am-datepicker-success td span.am-datepicker-old { color: #94df94; } .am-datepicker-success td span.am-active { color: #1b961b; } .am-datepicker-success .am-datepicker-caret { border-bottom-color: #5eb95e; } .am-datepicker-success .am-datepicker-dow { color: #367b36; } .am-datepicker-success .am-datepicker-select:hover, .am-datepicker-success .am-datepicker-prev-icon:hover, .am-datepicker-success .am-datepicker-next-icon:hover { background: rgba(165, 216, 165, 0.5); color: #367b36; } .am-datepicker-danger tr.am-datepicker-header { background: #dd514c; } .am-datepicker-danger td.am-datepicker-day.am-disabled { color: #999; } .am-datepicker-danger td.am-datepicker-old, .am-datepicker-danger td.am-datepicker-new { color: #f59490; } .am-datepicker-danger td.am-active, .am-datepicker-danger td.am-active:hover { color: #c10802; } .am-datepicker-danger td span.am-datepicker-old { color: #f59490; } .am-datepicker-danger td span.am-active { color: #c10802; } .am-datepicker-danger .am-datepicker-caret { border-bottom-color: #dd514c; } .am-datepicker-danger .am-datepicker-dow { color: #a4241f; } .am-datepicker-danger .am-datepicker-select:hover, .am-datepicker-danger .am-datepicker-prev-icon:hover, .am-datepicker-danger .am-datepicker-next-icon:hover { background: rgba(237, 164, 162, 0.5); color: #a4241f; } .am-datepicker-warning tr.am-datepicker-header { background: #F37B1D; } .am-datepicker-warning td.am-datepicker-day.am-disabled { color: #999; } .am-datepicker-warning td.am-datepicker-old, .am-datepicker-warning td.am-datepicker-new { color: #ffad6d; } .am-datepicker-warning td.am-active, .am-datepicker-warning td.am-active:hover { color: #aa4b00; } .am-datepicker-warning td span.am-datepicker-old { color: #ffad6d; } .am-datepicker-warning td span.am-active { color: #aa4b00; } .am-datepicker-warning .am-datepicker-caret { border-bottom-color: #F37B1D; } .am-datepicker-warning .am-datepicker-dow { color: #a14c09; } .am-datepicker-warning .am-datepicker-select:hover, .am-datepicker-warning .am-datepicker-prev-icon:hover, .am-datepicker-warning .am-datepicker-next-icon:hover { background: rgba(248, 180, 126, 0.5); color: #a14c09; } .am-datepicker > div { display: block; } .am-datepicker > div span.am-datepicker-hour { width: 59.5px; } .am-datepicker-date { display: block; } .am-datepicker-date.am-input-group { display: table; } .am-datepicker-time-box { padding: 30px 0 30px 0; } .am-datepicker-time-box strong { font-size: 5.2rem; display: inline-block; height: 70px; width: 70px; line-height: 70px; font-weight: normal; } .am-datepicker-time-box strong:hover { border-radius: 4px; background: #ECECEC; } .am-datepicker-time-box em { display: inline-block; height: 70px; width: 20px; line-height: 70px; font-size: 5.2rem; font-style: normal; } .am-datepicker-toggle { text-align: center; cursor: pointer; padding: 10px 0; } .am-datepicker-toggle:hover { background: #f0f0f0; } /* ========================================================================== Component: Print ============================================================================ */ @media print { *, *:before, *:after { background: transparent !important; color: #000 !important; /* Black prints faster: h5bp.com/s */ -webkit-box-shadow: none !important; box-shadow: none !important; text-shadow: none !important; } a, a:visited { text-decoration: underline; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " [" attr(title) "] "; } /** * Don't show links that are fragment identifiers, * or use the `javascript:` pseudo protocol */ a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; /* h5bp.com/t */ } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } @page { margin: 0.5cm; } select { background: #fff !important; } .am-topbar { display: none; } .am-table td, .am-table th { background-color: #fff !important; } .am-table { border-collapse: collapse !important; } .am-table-bordered th, .am-table-bordered td { border: 1px solid #ddd !important; } } /* print helper classes */ .am-print-block { display: none !important; } @media print { .am-print-block { display: block !important; } } .am-print-inline { display: none !important; } @media print { .am-print-inline { display: inline !important; } } .am-print-inline-block { display: none !important; } @media print { .am-print-inline-block { display: inline-block !important; } } @media print { .am-print-hide { display: none !important; } } .lte9 #nprogress .nprogress-spinner { display: none !important; } .lte8 .am-dimmer { background-color: #000; filter: alpha(opacity=60); } .lte8 .am-modal-actions { display: none; } .lte8 .am-modal-actions.am-modal-active { display: block; } .lte8 .am-offcanvas.am-active { background: #000; } .lte8 .am-popover .am-popover-caret { border: 8px solid transparent; } .lte8 .am-popover-top .am-popover-caret { border-top: 8px solid #333333; border-bottom: none; } .lte8 .am-popover-left .am-popover-caret { right: -8px; margin-top: -6px; border-left: 8px solid #333333; border-right: none; } .lte8 .am-popover-right .am-popover-caret { left: -8px; margin-top: -6px; border-right: 8px solid #333333; border-left: none; } .am-accordion-item { margin: 0; } .am-accordion-title { font-weight: normal; cursor: pointer; } .am-accordion-item.am-disabled .am-accordion-title { cursor: default; pointer-events: none; } .am-accordion-bd { margin: 0 !important; padding: 0 !important; border: none !important; } .am-accordion-content { margin-top: 0; padding: 0.8rem 1rem 1.2rem; font-size: 1.4rem; } /** * Accordion Theme: default * Author: Minwe (minwe@yunshipei.com) */ .am-accordion-default { margin: 1rem; border-radius: 2px; -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); } .am-accordion-default .am-accordion-item { border-top: 1px solid rgba(0, 0, 0, 0.05); } .am-accordion-default .am-accordion-item:first-child { border-top: none; } .am-accordion-default .am-accordion-title { color: rgba(0, 0, 0, 0.6); -webkit-transition: background-color 0.2s ease-out; transition: background-color 0.2s ease-out; padding: .8rem 1rem; } .am-accordion-default .am-accordion-title:before { content: "\f0da"; display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); -webkit-transition: -webkit-transform .2s ease; transition: -webkit-transform .2s ease; transition: transform .2s ease; transition: transform .2s ease, -webkit-transform .2s ease; -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); margin-right: 5px; } .am-accordion-default .am-accordion-title:hover { color: #0e90d2; } .am-accordion-default .am-accordion-content { color: #666; } .am-accordion-default .am-active .am-accordion-title { background-color: #eeeeee; color: #0e90d2; } .am-accordion-default .am-active .am-accordion-title:before { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } /** * Accordion Theme: basic * Author: Minwe (minwe@yunshipei.com) */ .am-accordion-basic { margin: 1rem; } .am-accordion-basic .am-accordion-title { color: #333333; -webkit-transition: background-color 0.2s ease-out; transition: background-color 0.2s ease-out; padding: .8rem 0 0; } .am-accordion-basic .am-accordion-title:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f0da"; -webkit-transition: -webkit-transform .2s ease; transition: -webkit-transform .2s ease; transition: transform .2s ease; transition: transform .2s ease, -webkit-transform .2s ease; -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); margin-right: .5rem; } .am-accordion-basic .am-accordion-content { color: #666; } .am-accordion-basic .am-active .am-accordion-title { color: #0e90d2; } .am-accordion-basic .am-active .am-accordion-title:before { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } /** * Accordion Theme: gapped * Author: Minwe (minwe@yunshipei.com) */ .am-accordion-gapped { margin: .5rem 1rem; } .am-accordion-gapped .am-accordion-item { border: 1px solid #dedede; border-bottom: none; margin: .5rem 0; } .am-accordion-gapped .am-accordion-item.am-active { border-bottom: 1px solid #dedede; } .am-accordion-gapped .am-accordion-title { color: rgba(0, 0, 0, 0.6); -webkit-transition: background-color 0.15s ease-out; transition: background-color 0.15s ease-out; border-bottom: 1px solid #dedede; padding: 0.8rem 2rem 0.8rem 1rem; position: relative; } .am-accordion-gapped .am-accordion-title:after { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f105"; -webkit-transition: -webkit-transform .2s linear; transition: -webkit-transform .2s linear; transition: transform .2s linear; transition: transform .2s linear, -webkit-transform .2s linear; position: absolute; right: 10px; top: 50%; margin-top: -0.8rem; } .am-accordion-gapped .am-accordion-title:hover { color: rgba(0, 0, 0, 0.8); } .am-accordion-gapped .am-accordion-content { color: #666; } .am-accordion-gapped .am-active .am-accordion-title { background-color: #f5f5f5; color: rgba(0, 0, 0, 0.8); } .am-accordion-gapped .am-active .am-accordion-title:after { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .am-divider { height: 0; margin: 1.5rem auto; overflow: hidden; clear: both; } /** * Divider Theme: default */ .am-divider-default { border-top: 1px solid #ddd; } /** * Divider Theme: dotted */ .am-divider-dotted { border-top: 1px dotted #ccc; } /** * Divider Theme: dashed */ .am-divider-dashed { border-top: 1px dashed #ccc; } .am-figure-zoomable { position: relative; cursor: pointer; } .am-figure-zoomable:after { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f00e"; position: absolute; top: 1rem; right: 1rem; color: #999999; font-size: 1.6rem; -webkit-transition: all 0.2s; transition: all 0.2s; pointer-events: none; } .am-figure-zoomable:hover:after { color: #eeeeee; } .am-figure-default { margin: 10px; } .am-figure-default img { display: block; max-width: 100%; height: auto; padding: 2px; border: 1px solid #eeeeee; margin: 10px auto; } .am-figure-default figcaption { text-align: center; font-size: 1.4rem; margin-bottom: 15px; color: #333333; } .am-footer { text-align: center; padding: 1em 0; font-size: 1.6rem; } .am-footer .am-switch-mode-ysp { cursor: pointer; } .am-footer .am-footer-text { margin-top: 10px; font-size: 14px; } .am-footer .am-footer-text-left { text-align: left; padding-left: 10px; } .am-modal-footer-hd { padding-bottom: 10px; } /** * Footer Theme: default */ .am-footer-default { background-color: #fff; } .am-footer-default a { color: #555555; } .am-footer-default .am-footer-switch { margin-bottom: 10px; font-weight: bold; } .am-footer-default .am-footer-ysp { color: #555555; cursor: pointer; } .am-footer-default .am-footer-divider { color: #ccc; } .am-footer-default .am-footer-desktop { color: #0e90d2; } .am-footer-default .am-footer-miscs { color: #999999; font-size: 13px; } .am-footer-default .am-footer-miscs p { margin: 5px 0; } @media only screen and (min-width:641px) { .am-footer-default .am-footer-miscs p { display: inline-block; margin: 5px; } } .am-gallery { padding: 5px 5px 0 5px; list-style: none; } .am-gallery h3 { margin: 0; } [data-am-gallery*='pureview'] img { cursor: pointer; } /** * Gallery Theme: default * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-default > li { padding: 5px; } .am-gallery-default .am-gallery-item img { width: 100%; height: auto; } .am-gallery-default .am-gallery-title { margin-top: 10px; font-weight: normal; font-size: 1.4rem; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; color: #555555; } .am-gallery-default .am-gallery-desc { color: #999999; font-size: 1.2rem; } /** * Gallery Theme: overlay * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-overlay > li { padding: 5px; } .am-gallery-overlay .am-gallery-item { position: relative; } .am-gallery-overlay .am-gallery-item img { width: 100%; height: auto; } .am-gallery-overlay .am-gallery-title { font-weight: normal; font-size: 1.4rem; color: #FFF; position: absolute; bottom: 0; width: 100%; background-color: rgba(0, 0, 0, 0.5); text-indent: 5px; height: 30px; line-height: 30px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-gallery-overlay .am-gallery-desc { display: none; } /** * Accordion Theme: bordered * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-bordered > li { padding: 5px; } .am-gallery-bordered .am-gallery-item { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); padding: 5px; } .am-gallery-bordered .am-gallery-item img { width: 100%; height: auto; } .am-gallery-bordered .am-gallery-title { margin-top: 10px; font-weight: normal; font-size: 1.4rem; color: #555555; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-gallery-bordered .am-gallery-desc { color: #999999; font-size: 1.2rem; } /** * Gallery Theme: imgbordered * Author: Minwe (minwe@yunshipei.com) */ .am-gallery-imgbordered > li { padding: 5px; } .am-gallery-imgbordered .am-gallery-item img { width: 100%; height: auto; border: 3px solid #FFF; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); box-shadow: 0 0 3px rgba(0, 0, 0, 0.35); } .am-gallery-imgbordered .am-gallery-title { margin-top: 10px; font-weight: normal; font-size: 1.4rem; color: #555555; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-gallery-imgbordered .am-gallery-desc { color: #999999; font-size: 1.2rem; } .am-gotop a { display: inline-block; text-decoration: none; } /** * Gotop Theme: default */ .am-gotop-default { text-align: center; margin: 10px 0; } .am-gotop-default a { background-color: #0e90d2; padding: .5em 1.5em; border-radius: 2px; color: #fff; } .am-gotop-default a img { display: none; } /** * Gotop Theme: fixed */ .am-gotop-fixed { position: fixed; right: 10px; bottom: 10px; z-index: 1010; opacity: 0; width: 32px; min-height: 32px; overflow: hidden; border-radius: 2px; text-align: center; } .am-gotop-fixed.am-active { opacity: .9; } .am-gotop-fixed.am-active:hover { opacity: 1; } .am-gotop-fixed a { display: block; } .am-gotop-fixed .am-gotop-title { display: none; } .am-gotop-fixed .am-gotop-icon-custom { display: inline-block; max-width: 30px; vertical-align: middle; } .am-gotop-fixed .am-gotop-icon { width: 100%; line-height: 32px; background-color: #555555; vertical-align: middle; color: #ddd; } .am-gotop-fixed .am-gotop-icon:hover { color: #fff; } .am-with-fixed-navbar .am-gotop-fixed { bottom: 60px; } .am-header { position: relative; width: 100%; height: 49px; line-height: 49px; padding: 0 10px; } .am-header h1 { margin-top: 0; margin-bottom: 0; } .am-header .am-header-title { margin: 0 30%; font-size: 2rem; font-weight: normal; text-align: center; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-header .am-header-title img { margin-top: 12px; height: 25px; vertical-align: top; } .am-header .am-header-nav { position: absolute; top: 0; } .am-header .am-header-nav img { height: 16px; width: auto; vertical-align: middle; } .am-header .am-header-left { left: 10px; } .am-header .am-header-right { right: 10px; } .am-header-fixed { position: fixed; top: 0; left: 0; right: 0; width: 100%; z-index: 1010; } .am-with-fixed-header { padding-top: 49px; } /** * Header Theme: default */ .am-header-default { background-color: #0e90d2; } .am-header-default .am-header-title { color: #fff; } .am-header-default .am-header-title a { color: #fff; } .am-header-default .am-header-icon { font-size: 20px; } .am-header-default .am-header-nav { color: #eeeeee; } .am-header-default .am-header-nav > a { display: inline-block; min-width: 36px; text-align: center; color: #eeeeee; } .am-header-default .am-header-nav > a + a { margin-left: 5px; } .am-header-default .am-header-nav .am-btn { margin-top: 9px; height: 31px; padding: 0 0.5em; line-height: 30px; font-size: 14px; vertical-align: top; } .am-header-default .am-header-nav .am-btn .am-header-icon { font-size: inherit; } .am-header-default .am-header-nav .am-btn-default { color: #999999; } .am-header-default .am-header-nav-title, .am-header-default .am-header-nav-title + .am-header-icon { font-size: 14px; } .am-intro { position: relative; } .am-intro img { max-width: 100%; } .am-intro-hd { position: relative; height: 45px; line-height: 45px; } .am-intro-title { font-size: 18px; margin: 0; font-weight: bold; } .am-intro-more-top { position: absolute; right: 10px; top: 0; font-size: 1.4rem; } .am-intro-bd { padding-top: 15px; padding-bottom: 15px; font-size: 1.4rem; } .am-intro-bd p:last-child { margin-bottom: 0; } .am-intro-more-bottom { clear: both; text-align: center; } .am-intro-more-bottom .am-btn { font-size: 14px; } /** * Intro Theme: default */ .am-intro-default .am-intro-hd { background-color: #0e90d2; color: #fff; padding: 0 10px; } .am-intro-default .am-intro-hd a { color: #eee; } .am-intro-default .am-intro-right { padding-left: 0; } .am-list-news-hd { padding-top: 1.2rem; padding-bottom: 0.8rem; } .am-list-news-hd a { display: block; } .am-list-news-hd h2 { font-size: 1.6rem; float: left; margin: 0; height: 2rem; line-height: 2rem; } .am-list-news-hd h3 { margin: 0; } .am-list-news-hd .am-list-news-more { font-size: 1.3rem; height: 2rem; line-height: 2rem; } .am-list .am-list-item-dated a { padding-right: 80px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-list .am-list-item-dated a::after { display: none; } .am-list .am-list-item-desced a, .am-list .am-list-item-thumbed a { padding-right: 0; } .am-list-news .am-list-item-hd { margin: 0; } .am-list-date { position: absolute; right: 5px; font-size: 1.3rem; top: 1.3rem; } .am-list-item-desced { padding-bottom: 1rem; } .am-list-item-desced > a { padding: 1rem 0; } .am-list-item-desced .am-list-date { position: static; } .am-list-item-thumbed { padding-top: 1em; } .am-list-news-ft { text-align: center; } .am-list-news .am-titlebar { margin-left: 0; margin-right: 0; } .am-list-news .am-titlebar ~ .am-list-news-bd .am-list > li:first-child { border-top: none; } /** * list_news Theme: default */ .am-list-news-default { margin: 10px; } .am-list-news-default .am-g { margin-left: auto; margin-right: auto; } .am-list-news-default .am-list-item-hd { font-weight: normal; } .am-list-news-default .am-list-date { color: #999999; } .am-list-news-default .am-list > li { border-color: #dedede; } .am-list-news-default .am-list .am-list-item-desced { padding-top: 1rem; padding-bottom: 1rem; } .am-list-news-default .am-list .am-list-item-desced > a { padding: 0; } .am-list-news-default .am-list .am-list-item-desced .am-list-item-text { margin-top: 0.5rem; color: #757575; } .am-list-news-default .am-list .am-list-item-text { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; line-height: 1.3em; -webkit-line-clamp: 2; /* number of lines to show */ max-height: 2.6em; } .am-list-news-default .am-list .am-list-item-thumb-top .am-list-thumb { padding: 0; margin-bottom: 0.8rem; } .am-list-news-default .am-list .am-list-item-thumb-top .am-list-main { padding: 0; } .am-list-news-default .am-list .am-list-item-thumb-left .am-list-thumb { padding-left: 0; } .am-list-news-default .am-list .am-list-item-desced .am-list-main { padding: 0; } .am-list-news-default .am-list .am-list-item-thumb-right .am-list-thumb { padding-right: 0; } .am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-item-hd { clear: both; padding-bottom: 0.5rem; } .am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-thumb { padding-left: 0; } .am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-item-hd { clear: both; padding-bottom: 0.5rem; } .am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-thumb { padding-right: 0; } .am-list-news-default .am-list .am-list-thumb img { width: 100%; display: block; } @media only screen and (max-width: 640px) { .am-list-news-default .am-list-item-thumb-left .am-list-thumb, .am-list-news-default .am-list-item-thumb-right .am-list-thumb { max-height: 80px; overflow: hidden; } .am-list-news-default .am-list-item-thumb-bottom-left .am-list-item-text, .am-list-news-default .am-list-item-thumb-bottom-right .am-list-item-text { -webkit-line-clamp: 3; /* number of lines to show */ max-height: 3.9em; } .am-list-news-default .am-list-item-thumb-bottom-left .am-list-thumb, .am-list-news-default .am-list-item-thumb-bottom-right .am-list-thumb { max-height: 60px; overflow: hidden; } } .am-map { width: 100%; height: 300px; } /** * Accordion Theme: default * Author: Hzp (hzp@yunshipei.com) */ .am-map-default #bd-map { width: 100%; height: 100%; overflow: hidden; margin: 0; font-size: 14px; line-height: 1.4!important; } .am-map-default .BMap_bubble_title { font-weight: bold; } .am-map-default #BMap_mask { width: 100%; } .am-mechat { margin: 1rem; } .am-mechat .section-cbox-wap .cbox-post-wap .post-action-wap .action-function-wap .function-list-wap .list-upload-wap .upload-mutual-wap { -webkit-box-sizing: content-box; box-sizing: content-box; } .am-menu { position: relative; padding: 0; margin: 0; } .am-menu ul { padding: 0; margin: 0; } .am-menu li { list-style: none; } .am-menu a:after, .am-menu a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-menu-sub { z-index: 1050; } .am-menu-toggle { display: none; z-index: 1015; } .am-menu-toggle img { display: inline-block; height: 16px; width: auto; vertical-align: middle; } .am-menu-nav a { display: block; padding: 0.8rem 0; -webkit-transition: all 0.45s; transition: all 0.45s; } /** * Menu Theme: default * Author: Minwe (minwe@yunshipei.com) */ .am-menu-default .am-menu-nav { padding-top: 8px; padding-bottom: 8px; } .am-menu-default .am-menu-nav a { text-align: center; height: 36px; line-height: 36px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; padding: 0; color: #0e90d2; } .am-menu-default .am-menu-nav > .am-parent > a { position: relative; -webkit-transition: .15s; transition: .15s; } .am-menu-default .am-menu-nav > .am-parent > a:after { content: "\f107"; margin-left: 5px; -webkit-transition: .15s; transition: .15s; } .am-menu-default .am-menu-nav > .am-parent > a:before { position: absolute; top: 100%; margin-top: -16px; left: 50%; margin-left: -12px; content: "\f0d8"; display: none; color: #f1f1f1; font-size: 24px; } .am-menu-default .am-menu-nav > .am-parent.am-open > a { color: #095f8a; } .am-menu-default .am-menu-nav > .am-parent.am-open > a:before { display: block; } .am-menu-default .am-menu-nav > .am-parent.am-open > a:after { -webkit-transform: rotate(-180deg); -ms-transform: rotate(-180deg); transform: rotate(-180deg); } .am-menu-default .am-menu-sub { position: absolute; left: 5px; right: 5px; background-color: #f1f1f1; border-radius: 2px; padding-top: 8px; padding-bottom: 8px; } .am-menu-default .am-menu-sub > li > a { color: #555555; } @media only screen and (min-width:641px) { .am-menu-default .am-menu-nav li { width: auto; float: left; clear: none; display: inline; } .am-menu-default .am-menu-nav a { padding-left: 1.5rem; padding-right: .5rem; } } /** /** * Menu Theme: dropdown1 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-dropdown1 { position: relative; /*@media @medium-up { .am-menu-toggle { display: none!important; } .am-menu-nav { &.am-collapse { display: block; } .am-menu-sub { background-color: ;//@menu-sub-bg; display: block; & > li { clear: none; } } .am-menu-lv2 { & > li { clear: none; width: auto; } } } }*/ } .am-menu-dropdown1 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-dropdown1 a { -webkit-transition: all .4s; transition: all .4s; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-menu-dropdown1 .am-menu-nav { position: absolute; left: 0; right: 0; z-index: 1050; } .am-menu-dropdown1 .am-menu-nav a { padding: 0.8rem; } .am-menu-dropdown1 .am-menu-nav > li { width: 100%; } .am-menu-dropdown1 .am-menu-nav > li.am-parent > a { position: relative; } .am-menu-dropdown1 .am-menu-nav > li.am-parent > a::before { content: "\f067"; position: absolute; right: 1rem; top: 1.4rem; } .am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a { background-color: #0c80ba; border-bottom: none; color: #fff; } .am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:before { content: "\f068"; } .am-menu-dropdown1 .am-menu-nav > li.am-parent.am-open > a:after { content: ""; display: inline-block; width: 0; height: 0; vertical-align: middle; border-top: 8px solid #0c80ba; border-right: 8px solid transparent; border-left: 8px solid transparent; border-bottom: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); position: absolute; top: 100%; left: 50%; margin-left: -4px; } .am-menu-dropdown1 .am-menu-nav > li > a { border-bottom: 1px solid #0b76ac; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); background-color: #0e90d2; color: #fff; height: 49px; line-height: 49px; padding: 0; text-indent: 10px; } .am-menu-dropdown1 .am-menu-sub { background-color: #fff; } .am-menu-dropdown1 .am-menu-sub a { color: #555; height: 44px; line-height: 44px; text-indent: 5px; padding: 0; } .am-menu-dropdown1 .am-menu-sub a:before { content: "\f105"; color: #aaa; font-size: 16px; margin-right: 5px; } /** * Menu Theme: dropdown2 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-dropdown2 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-dropdown2 .am-menu-nav { position: absolute; left: 0; right: 0; background-color: #f5f5f5; -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); z-index: 1050; padding-top: 8px; padding-bottom: 8px; } .am-menu-dropdown2 .am-menu-nav a { height: 38px; line-height: 38px; padding: 0; text-align: center; } .am-menu-dropdown2 .am-menu-nav > li > a { color: #333333; } .am-menu-dropdown2 .am-menu-nav > li.am-parent > a { position: relative; } .am-menu-dropdown2 .am-menu-nav > li.am-parent > a:after { content: "\f107"; margin-left: 5px; -webkit-transition: -webkit-transform .2s; transition: -webkit-transform .2s; transition: transform .2s; transition: transform .2s, -webkit-transform .2s; } .am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a { position: relative; } .am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:after { color: #0e90d2; -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } .am-menu-dropdown2 .am-menu-nav > li.am-parent.am-open > a:before { position: absolute; top: 100%; margin-top: -16px; left: 50%; margin-left: -12px; font-size: 24px; content: "\f0d8"; color: rgba(0, 0, 0, 0.2); } .am-menu-dropdown2 .am-menu-sub { position: absolute; left: 5px; right: 5px; padding: 8px 0; border-radius: 2px; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); background-color: #fff; z-index: 1055; } .am-menu-dropdown2 .am-menu-sub a { padding: 0; height: 35px; color: #555555; line-height: 35px; } @media only screen and (min-width:641px) { .am-menu-dropdown2 .am-menu-toggle { display: none !important; } .am-menu-dropdown2 .am-menu-nav { position: static; display: block; } .am-menu-dropdown2 .am-menu-nav > li { float: none; width: auto; display: inline-block; } .am-menu-dropdown2 .am-menu-nav > li a { padding-left: 1.5rem; padding-right: 1.5rem; } .am-menu-dropdown2 .am-menu-sub { left: auto; right: auto; } .am-menu-dropdown2 .am-menu-sub > li { float: none; width: auto; } .am-menu-dropdown2 .am-menu-sub a { padding-left: 2rem; padding-right: 2rem; } } /** * Menu Theme: slide1 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-slide1 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-slide1 .am-menu-nav { background-color: #f5f5f5; padding-top: 8px; padding-bottom: 8px; } .am-menu-slide1 .am-menu-nav.am-in:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f0d8"; font-size: 24px; color: #f5f5f5; position: absolute; right: 16px; top: -16px; } .am-menu-slide1 .am-menu-nav a { line-height: 38px; height: 38px; display: block; padding: 0; text-align: center; } .am-menu-slide1 .am-menu-nav > li > a { color: #333333; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-menu-slide1 .am-menu-nav > .am-parent > a { position: relative; -webkit-transition: .15s; transition: .15s; } .am-menu-slide1 .am-menu-nav > .am-parent > a:after { content: "\f107"; margin-left: 5px; -webkit-transition: .15s; transition: .15s; } .am-menu-slide1 .am-menu-nav > .am-parent > a:before { position: absolute; top: 100%; margin-top: -16px; left: 50%; margin-left: -12px; content: "\f0d8"; display: none; color: #0e90d2; font-size: 24px; } .am-menu-slide1 .am-menu-nav > .am-parent.am-open > a { color: #0e90d2; } .am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:before { display: block; } .am-menu-slide1 .am-menu-nav > .am-parent.am-open > a:after { -webkit-transform: rotate(-180deg); -ms-transform: rotate(-180deg); transform: rotate(-180deg); } .am-menu-slide1 .am-menu-sub { position: absolute; left: 5px; right: 5px; background-color: #0e90d2; border-radius: 2px; padding-top: 8px; padding-bottom: 8px; } .am-menu-slide1 .am-menu-sub > li > a { color: #fff; } @media only screen and (min-width:641px) { .am-menu-slide1 .am-menu-toggle { display: none !important; } .am-menu-slide1 .am-menu-nav { background-color: #f5f5f5; display: block; } .am-menu-slide1 .am-menu-nav.am-in:before { display: none; } .am-menu-slide1 .am-menu-nav li { width: auto; clear: none; } .am-menu-slide1 .am-menu-nav li a { padding-left: 1.5rem; padding-right: 1.5rem; } } /** * Menu Theme: offcanvas1 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-offcanvas1 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-offcanvas1 .am-menu-nav { border-bottom: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); } .am-menu-offcanvas1 .am-menu-nav > li > a { height: 44px; line-height: 44px; text-indent: 15px; padding: 0; position: relative; color: #ccc; border-top: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); } .am-menu-offcanvas1 .am-menu-nav > .am-open > a, .am-menu-offcanvas1 .am-menu-nav > li > a:hover, .am-menu-offcanvas1 .am-menu-nav > li > a:focus { background-color: #474747; color: #fff; outline: none; } .am-menu-offcanvas1 .am-menu-nav > .am-active > a { background-color: #1a1a1a; color: #fff; } .am-menu-offcanvas1 .am-menu-nav > .am-parent > a { -webkit-transition: all .3s; transition: all .3s; } .am-menu-offcanvas1 .am-menu-nav > .am-parent > a:after { content: "\f104"; position: absolute; right: 1.5rem; top: 1.3rem; } .am-menu-offcanvas1 .am-menu-nav > .am-parent.am-open > a:after { content: "\f107"; } .am-menu-offcanvas1 .am-menu-sub { border-top: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); padding: 5px 0 5px 15px; background-color: #1a1a1a; font-size: 1.4rem; } .am-menu-offcanvas1 .am-menu-sub a { color: #eee; } .am-menu-offcanvas1 .am-menu-sub a:hover { color: #fff; } .am-menu-offcanvas1 .am-nav-divider { border-top: 1px solid #1a1a1a; } /** * Menu Theme: offcanvas2 * Author: Minwe (minwe@yunshipei.com) */ .am-menu-offcanvas2 .am-menu-toggle { position: absolute; right: 5px; top: -47px; display: block; width: 44px; height: 44px; line-height: 44px; text-align: center; color: #fff; } .am-menu-offcanvas2 .am-menu-nav { padding: 10px 5px; } .am-menu-offcanvas2 .am-menu-nav > li { padding: 5px; } .am-menu-offcanvas2 .am-menu-nav > li > a { -webkit-transition: all 0.3s; transition: all 0.3s; background-color: #404040; color: #ccc; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; border: 1px solid rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); height: 44px; line-height: 44px; padding: 0; text-align: center; } .am-menu-offcanvas2 .am-menu-nav > li > a:hover, .am-menu-offcanvas2 .am-menu-nav > li > a:focus { background-color: #262626; color: #fff; outline: none; } .am-menu-offcanvas2 .am-menu-nav > .am-active > a { background-color: #262626; color: #fff; } /** * Menu Theme: stack * Author: Minwe (minwe@yunshipei.com) */ .am-menu-stack .am-menu-nav { border-bottom: 1px solid #dedede; -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05); } .am-menu-stack .am-menu-nav > .am-parent > a { -webkit-transition: all .3s; transition: all .3s; } .am-menu-stack .am-menu-nav > .am-parent > a:after { content: "\f105"; position: absolute; right: 1.5rem; top: 1.3rem; -webkit-transition: all .15s; transition: all .15s; } .am-menu-stack .am-menu-nav > .am-parent.am-open > a:after { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .am-menu-stack .am-menu-nav > li > a { position: relative; color: #333; background-color: #f5f5f5; border-top: 1px solid #dedede; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); height: 49px; line-height: 49px; text-indent: 10px; padding: 0; } .am-menu-stack .am-menu-nav > .am-open > a, .am-menu-stack .am-menu-nav > li > a:hover, .am-menu-stack .am-menu-nav > li > a:focus { background-color: #e5e5e5; color: #222; outline: none; } .am-menu-stack .am-menu-sub { padding: 0; font-size: 1.4rem; border-top: 1px solid #dedede; } .am-menu-stack .am-menu-sub a { border-bottom: 1px solid #dedede; padding-left: 2rem; color: #444; } .am-menu-stack .am-menu-sub a:hover { color: #333; } .am-menu-stack .am-menu-sub li:last-child a { border-bottom: none; } .am-menu-stack .am-menu-sub > li > a { height: 44px; line-height: 44px; text-indent: 15px; padding: 0; } @media only screen and (min-width:641px) { .am-menu-stack .am-menu-nav { background-color: #f5f5f5; } .am-menu-stack .am-menu-nav > li { float: left; width: auto; clear: none !important; display: inline-block; } .am-menu-stack .am-menu-nav > li a { padding-left: 1.5rem; padding-right: 1.5rem; } .am-menu-stack .am-menu-nav > li.am-parent > a:after { position: static; content: "\f107"; } .am-menu-stack .am-menu-nav > li.am-parent.am-open a { border-bottom: none; } .am-menu-stack .am-menu-nav > li.am-parent.am-open a:after { -webkit-transform: rotateX(-180deg); transform: rotateX(-180deg); } .am-menu-stack .am-menu-nav > li.am-parent.am-open .am-menu-sub { background-color: #e5e5e5; } .am-menu-stack .am-menu-sub { position: absolute; left: 0; right: 0; background-color: #ddd; border-top: none; } .am-menu-stack .am-menu-sub li { width: auto; float: left; clear: none; } } .am-navbar { position: fixed; left: 0; bottom: 0; width: 100%; height: 49px; line-height: 49px; z-index: 1010; } .am-navbar ul { padding-left: 0; margin: 0; list-style: none; width: 100%; } .am-navbar .am-navbar-nav { padding-left: 8px; padding-right: 8px; text-align: center; overflow: hidden; display: table; } .am-navbar .am-navbar-nav li { display: table-cell; width: 1%; float: none; } .am-navbar-nav { position: relative; z-index: 1015; } .am-navbar-nav a { display: inline-block; width: 100%; height: 49px; line-height: 20px; } .am-navbar-nav a img { display: block; vertical-align: middle; height: 24px; width: 24px; margin: 4px auto 0; } .am-navbar-nav a [class*="am-icon"] { width: 24px; height: 24px; margin: 4px auto 0; display: block; line-height: 24px; } .am-navbar-nav a [class*="am-icon"]:before { font-size: 22px; vertical-align: middle; } .am-navbar-nav a .am-navbar-label { padding-top: 2px; line-height: 1; font-size: 12px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-navbar-more [class*="am-icon-"] { -webkit-transition: 0.15s; transition: 0.15s; } .am-navbar-more.am-active [class*="am-icon-"] { -webkit-transform: rotateX(-180deg); transform: rotateX(-180deg); } .am-navbar-actions { position: absolute; bottom: 49px; right: 0; left: 0; z-index: 1009; opacity: 0; -webkit-transition: .3s; transition: .3s; -webkit-transform: translate(0, 100%); -ms-transform: translate(0, 100%); transform: translate(0, 100%); } .am-navbar-actions.am-active { opacity: 1; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .am-navbar-actions li { line-height: 42px; position: relative; } .am-navbar-actions li a { display: block; width: 100%; height: 40px; -webkit-box-shadow: inset 0 1px rgba(220, 220, 220, 0.25); box-shadow: inset 0 1px rgba(220, 220, 220, 0.25); padding-left: 20px; padding-right: 36px; } .am-navbar-actions li a :after { font-family: "FontAwesome", sans-serif; content: "\f105"; display: inline-block; position: absolute; top: 0; right: 20px; } .am-navbar-actions li a img { vertical-align: middle; height: 20px; width: 20px; display: inline; } #am-navbar-qrcode { width: 220px; height: 220px; margin-left: -110px; } #am-navbar-qrcode .am-modal-bd { padding: 10px; } #am-navbar-qrcode canvas { display: block; width: 200px; height: 200px; } .am-with-fixed-navbar { padding-bottom: 54px; } /** * Navbar Theme: default * Author: hzp (hzp@yunshipei.com) */ .am-navbar-default a { color: #fff; } .am-navbar-default .am-navbar-nav { background-color: #0e90d2; } .am-navbar-default .am-navbar-actions { background-color: #0d86c4; } .am-navbar-default .am-navbar-actions a { border-bottom: 1px solid #0b6fa2; } .am-pagination { position: relative; } /** * Pagination Theme: default */ .am-pagination-default { margin-left: 10px; margin-right: 10px; font-size: 1.6rem; } .am-pagination-default .am-pagination-prev, .am-pagination-default .am-pagination-next { float: none; } /** * Pagination Theme: select */ .am-pagination-select { margin-left: 10px; margin-right: 10px; font-size: 1.6rem; } .am-pagination-select > li > a { line-height: 36px; background-color: #eeeeee; padding: 0 15px; border: 0; color: #555555; } .am-pagination-select .am-pagination-select { position: absolute; top: 0; left: 50%; margin-left: -35px; width: 70px; height: 36px; text-align: center; border-radius: 2px; } .am-pagination-select .am-pagination-select select { display: block; border: 0; line-height: 36px; width: 70px; height: 36px; border-radius: 2px; color: #555555; background-color: #eeeeee; -webkit-appearance: none; -moz-appearance: none; appearance: none; padding-left: 18px; } .am-paragraph p { margin: 10px 0; } .am-paragraph img { max-width: 100%; } .am-paragraph h1, .am-paragraph h2, .am-paragraph h3, .am-paragraph h4, .am-paragraph h5, .am-paragraph h6 { color: #222222; } .am-paragraph table { max-width: none; } .am-paragraph-table-container { overflow: hidden; background: #eeeeee; max-width: none; } .am-paragraph-table-container table { width: 100%; max-width: none; } .am-paragraph-table-container table th { background: #bce5fb; height: 40px; border: 1px solid #999999; text-align: center; } .am-paragraph-table-container table td { border: 1px solid #999999; text-align: center; vertical-align: middle; background: #fff; } .am-paragraph-table-container table td p { text-indent: 0; font-size: 1.4rem; } .am-paragraph-table-container table td a { font-size: 1.4rem; } /** * Paragraph Theme: default */ .am-paragraph-default { margin: 0 10px; color: #333333; background-color: transparent; } .am-paragraph-default p { font-size: 1.4rem; } .am-paragraph-default img { max-width: 98%; display: block; margin: 5px auto; border: 1px solid #eeeeee; padding: 2px; } .am-paragraph-default a { color: #0e90d2; } /** * Slider Theme: a1 */ .am-slider-a1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a1 .am-viewport { max-height: 300px; } .am-slider-a1 .am-control-nav { width: 100%; position: absolute; bottom: 5px; text-align: center; line-height: 0; } .am-slider-a1 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a1 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-a1 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a1 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-a1 .am-direction-nav, .am-slider-a1 .am-pauseplay { display: none; } /** * Slider Theme: a2 */ .am-slider-a2 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a2 .am-viewport { max-height: 300px; } .am-slider-a2 .am-control-nav { width: 100%; position: absolute; bottom: 5px; text-align: center; line-height: 0; } .am-slider-a2 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a2 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-a2 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a2 .am-control-nav li a.am-active { background: #0e93d7; cursor: default; } .am-slider-a2 .am-direction-nav, .am-slider-a2 .am-pauseplay { display: none; } /** * Slider Theme: a3 */ .am-slider-a3 { margin-bottom: 20px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a3 .am-viewport { max-height: 300px; } .am-slider-a3 .am-control-nav { width: 100%; position: absolute; bottom: -20px; text-align: center; height: 20px; background-color: #000; padding-top: 5px; line-height: 0; } .am-slider-a3 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a3 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; -webkit-box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3); box-shadow: inset 0 0 3px rgba(200, 200, 200, 0.3); } .am-slider-a3 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a3 .am-control-nav li a.am-active { background: #0e90d2; cursor: default; } .am-slider-a3 .am-direction-nav, .am-slider-a3 .am-pauseplay { display: none; } /** * Slider Theme: a4 */ .am-slider-a4 { margin-bottom: 30px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a4 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a4 .am-viewport { max-height: 300px; } .am-slider-a4 .am-control-nav { width: 100%; position: absolute; bottom: -15px; text-align: center; line-height: 0; } .am-slider-a4 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-a4 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-a4 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a4 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-a4 .am-direction-nav, .am-slider-a4 .am-pauseplay { display: none; } /** * Slider Theme: a5 */ .am-slider-a5 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-a5 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-a5 .am-viewport { max-height: 300px; } .am-slider-a5 .am-control-nav { width: 100%; position: absolute; text-align: center; height: 6px; display: table; bottom: 0; font-size: 0; line-height: 0; } .am-slider-a5 .am-control-nav li { display: table-cell; } .am-slider-a5 .am-control-nav li a { width: 100%; height: 6px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; } .am-slider-a5 .am-control-nav li a:hover { background-color: rgba(0, 0, 0, 0.7); } .am-slider-a5 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-a5 .am-direction-nav, .am-slider-a5 .am-pauseplay { display: none; } /** * Slider Theme: b1 */ .am-slider-b1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b1 .am-viewport { max-height: 300px; } .am-slider-b1 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 8px 0; margin: -20px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #fff; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); background-color: rgba(0, 0, 0, 0.5); font-size: 0; text-align: center; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b1 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 24px; } .am-slider-b1 .am-direction-nav a.am-prev { left: 0; padding-right: 5px; border-bottom-right-radius: 5px; border-top-right-radius: 5px; } .am-slider-b1 .am-direction-nav a.am-next { right: 0; padding-left: 5px; border-bottom-left-radius: 5px; border-top-left-radius: 5px; } .am-slider-b1 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b1 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b1:hover .am-prev { opacity: 0.7; } .am-slider-b1:hover .am-prev:hover { opacity: 1; } .am-slider-b1:hover .am-next { opacity: 0.7; } .am-slider-b1:hover .am-next:hover { opacity: 1; } .am-slider-b1 .am-control-nav, .am-slider-b1 .am-pauseplay { display: none; } /** * Slider Theme: b2 */ .am-slider-b2 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b2 .am-viewport { max-height: 300px; } .am-slider-b2 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px; margin: -16px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #fff; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); background-color: rgba(0, 0, 0, 0.5); font-size: 0; text-align: center; border-radius: 50%; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b2 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 16px; line-height: 24px; } .am-slider-b2 .am-direction-nav a.am-prev { left: 5px; } .am-slider-b2 .am-direction-nav a.am-next { right: 5px; } .am-slider-b2 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b2 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b2:hover .am-prev { opacity: 0.7; } .am-slider-b2:hover .am-prev:hover { opacity: 1; } .am-slider-b2:hover .am-next { opacity: 0.7; } .am-slider-b2:hover .am-next:hover { opacity: 1; } .am-slider-b2 .am-control-nav, .am-slider-b2 .am-pauseplay { display: none; } /** * Slider Theme: b3 */ .am-slider-b3 { margin: 15px 30px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b3 .am-viewport { max-height: 300px; } .am-slider-b3 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px; margin: -16px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #333333; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b3 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 24px; } .am-slider-b3 .am-direction-nav a.am-prev { left: -25px; } .am-slider-b3 .am-direction-nav a.am-next { right: -25px; text-align: right; } .am-slider-b3 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b3 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b3:hover .am-prev { opacity: 0.7; } .am-slider-b3:hover .am-prev:hover { opacity: 1; } .am-slider-b3:hover .am-next { opacity: 0.7; } .am-slider-b3:hover .am-next:hover { opacity: 1; } .am-slider-b3 .am-control-nav, .am-slider-b3 .am-pauseplay { display: none; } /** * Slider Theme: b4 */ .am-slider-b4 { margin: 15px 20px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-b4 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-b4 .am-viewport { max-height: 300px; } .am-slider-b4 .am-direction-nav a { position: absolute; top: 50%; z-index: 10; display: block; -webkit-box-sizing: content-box; box-sizing: content-box; width: 24px; height: 24px; margin: -16px 0 0; padding: 4px; overflow: hidden; opacity: 0.45; background-color: rgba(0, 0, 0, 0.8); cursor: pointer; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; border-radius: 50%; text-align: center; color: #fff; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-b4 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 20px; line-height: 24px; } .am-slider-b4 .am-direction-nav a.am-prev { left: -15px; } .am-slider-b4 .am-direction-nav a.am-next { right: -15px; } .am-slider-b4 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-b4 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-b4:hover .am-prev { opacity: 0.7; } .am-slider-b4:hover .am-prev:hover { opacity: 0.9; } .am-slider-b4:hover .am-next { opacity: 0.7; } .am-slider-b4:hover .am-next:hover { opacity: 0.9; } .am-slider-b4 .am-control-nav, .am-slider-b4 .am-pauseplay { display: none; } /** * Slider Theme: c1 */ .am-slider-c1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-c1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c1 .am-viewport { max-height: 300px; } .am-slider-c1 .am-control-nav { position: absolute; bottom: 0; display: table; width: 100%; height: 6px; font-size: 0; line-height: 0; text-align: center; } .am-slider-c1 .am-control-nav li { display: table-cell; width: 1%; } .am-slider-c1 .am-control-nav li a { width: 100%; height: 6px; display: block; background-color: rgba(0, 0, 0, 0.7); cursor: pointer; text-indent: -9999px; } .am-slider-c1 .am-control-nav li a:hover { background: rgba(0, 0, 0, 0.8); } .am-slider-c1 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-c1 .am-slider-desc { background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 6px; padding: 8px; width: 100%; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c1 .am-direction-nav, .am-slider-c1 .am-pauseplay { display: none; } /** * Slider Theme: c2 */ .am-slider-c2 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-c2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c2 .am-viewport { max-height: 300px; } .am-slider-c2 .am-control-nav { position: absolute; bottom: 15px; right: 0; height: 6px; text-align: center; font-size: 0; line-height: 0; } .am-slider-c2 .am-control-nav li { display: inline-block; margin-right: 6px; } .am-slider-c2 .am-control-nav li a { width: 6px; height: 6px; display: block; background-color: rgba(255, 255, 255, 0.4); cursor: pointer; text-indent: -9999px; } .am-slider-c2 .am-control-nav li a:hover { background: rgba(230, 230, 230, 0.4); } .am-slider-c2 .am-control-nav li a.am-active { background-color: #0e90d2; cursor: default; } .am-slider-c2 .am-slider-desc { background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 0; padding: 8px 60px 8px 8px; width: 100%; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c2 .am-direction-nav, .am-slider-c2 .am-pauseplay { display: none; } /** * Slider Theme: c3 */ .am-slider-c3 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-c3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c3 .am-viewport { max-height: 300px; } .am-slider-c3 .am-slider-desc { background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 10px; right: 60px; height: 30px; left: 0; padding-right: 5px; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c3 .am-slider-counter { margin-right: 5px; display: inline-block; height: 30px; background-color: #0e90d2; width: 40px; text-align: center; line-height: 30px; color: #eee; font-size: 1rem; } .am-slider-c3 .am-slider-counter .am-active { font-size: 1.8rem; font-weight: bold; color: #fff; } .am-slider-c3 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px 0; margin: -16px 0 0; position: absolute; top: 50%; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; color: #fff; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); background-color: rgba(0, 0, 0, 0.5); font-size: 0; text-align: center; -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-c3 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 16px; line-height: 24px; } .am-slider-c3 .am-direction-nav a.am-prev { left: 0; padding-right: 5px; } .am-slider-c3 .am-direction-nav a.am-next { right: 0; padding-left: 5px; } .am-slider-c3 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-c3 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-c3:hover .am-prev { opacity: 0.7; } .am-slider-c3:hover .am-prev:hover { opacity: 1; } .am-slider-c3:hover .am-next { opacity: 0.7; } .am-slider-c3:hover .am-next:hover { opacity: 1; } .am-slider-c3 .am-control-nav, .am-slider-c3 .am-pauseplay { display: none; } /** * Slider Theme: c4 */ .am-slider-c4 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-c4 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-c4 .am-viewport { max-height: 300px; } .am-slider-c4 .am-slider-desc { width: 100%; background-color: rgba(0, 0, 0, 0.6); position: absolute; bottom: 0; right: 0; left: 0; padding: 8px 40px; color: #fff; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-c4 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; padding: 4px 0; margin: 0; position: absolute; bottom: 4px; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; text-align: center; color: rgba(0, 0, 0, 0.7); -webkit-transition: all .3s ease; transition: all .3s ease; } .am-slider-c4 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 24px; } .am-slider-c4 .am-direction-nav a.am-prev { left: 0; padding-right: 5px; } .am-slider-c4 .am-direction-nav a.am-next { right: 0; padding-left: 5px; } .am-slider-c4 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-c4 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-c4:hover .am-prev { opacity: 0.7; } .am-slider-c4:hover .am-prev:hover { opacity: 1; } .am-slider-c4:hover .am-next { opacity: 0.7; } .am-slider-c4:hover .am-next:hover { opacity: 1; } .am-slider-c4 .am-control-nav, .am-slider-c4 .am-pauseplay { display: none; } /** * Slider Theme: d1 */ .am-slider-d1 { -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Direction Nav */ } .am-slider-d1 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-d1 .am-viewport { max-height: 300px; } .am-slider-d1 .am-slider-desc { padding: 8px 35px; width: 100%; color: #fff; background-color: #0e90d2; } .am-slider-d1 .am-slider-title { font-weight: normal; margin-bottom: 2px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d1 .am-slider-more { color: #eeeeee; font-size: 1.3rem; } .am-slider-d1 .am-direction-nav a { -webkit-box-sizing: content-box; box-sizing: content-box; display: block; width: 24px; height: 24px; margin: 0; position: absolute; bottom: 18px; z-index: 10; overflow: hidden; opacity: 0.45; cursor: pointer; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3); font-size: 0; text-align: center; border: 1px solid rgba(255, 255, 255, 0.9); color: rgba(255, 255, 255, 0.9); border-radius: 50%; -webkit-transition: all 03s ease; transition: all 03s ease; } .am-slider-d1 .am-direction-nav a:before { display: inline-block; font: normal normal normal 1.6rem/1 "FontAwesome", sans-serif; /*font-weight: normal; // 2 font-style: normal; // 2 vertical-align: baseline; // 3 line-height: 1; // 4*/ font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f053"; font-size: 16px; line-height: 24px; } .am-slider-d1 .am-direction-nav a.am-prev { left: 5px; } .am-slider-d1 .am-direction-nav a.am-next { right: 5px; } .am-slider-d1 .am-direction-nav a.am-next:before { content: "\f054"; } .am-slider-d1 .am-direction-nav .am-disabled { opacity: 0!important; cursor: default; } .am-slider-d1:hover .am-prev { opacity: 0.7; } .am-slider-d1:hover .am-prev:hover { opacity: 1; } .am-slider-d1:hover .am-next { opacity: 0.7; } .am-slider-d1:hover .am-next:hover { opacity: 1; } .am-slider-d1 .am-control-nav, .am-slider-d1 .am-pauseplay { display: none; } /** * Slider Theme: d2 */ .am-slider-d2 { margin-bottom: 20px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-d2 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-d2 .am-viewport { max-height: 300px; } .am-slider-d2 .am-slider-desc { position: absolute; left: 10px; bottom: 20px; right: 50px; color: #fff; } .am-slider-d2 .am-slider-content { background-color: rgba(0, 0, 0, 0.7); padding: 10px 6px; margin-bottom: 10px; } .am-slider-d2 .am-slider-content p { margin: 0; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; font-size: 1.4rem; } .am-slider-d2 .am-slider-title { font-weight: normal; margin-bottom: 5px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d2 .am-slider-more { color: #eeeeee; font-size: 1.3rem; background-color: #0e90d2; padding: 2px 10px; } .am-slider-d2 .am-control-nav { width: 100%; position: absolute; bottom: -15px; text-align: center; } .am-slider-d2 .am-control-nav li { margin: 0 6px; display: inline-block; } .am-slider-d2 .am-control-nav li a { width: 8px; height: 8px; display: block; background-color: rgba(0, 0, 0, 0.5); cursor: pointer; text-indent: -9999px; border-radius: 50%; font-size: 0; line-height: 0; -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3); } .am-slider-d2 .am-control-nav li a:hover { background: rgba(0, 0, 0, 0.5); } .am-slider-d2 .am-control-nav li a.am-active { background: #0e90d2; cursor: default; } .am-slider-d2 .am-direction-nav, .am-slider-d2 .am-pauseplay { display: none; } /** * Slider Theme: d3 */ .am-slider-d3 { margin-bottom: 10px; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); /* Control Nav */ } .am-slider-d3 .am-viewport { max-height: 2000px; -webkit-transition: all 1s ease; transition: all 1s ease; } .loading .am-slider-d3 .am-viewport { max-height: 300px; } .am-slider-d3 .am-slider-desc { position: absolute; bottom: 0; color: #fff; width: 100%; background-color: rgba(0, 0, 0, 0.7); padding: 8px 5px; } .am-slider-d3 .am-slider-desc p { margin: 0; font-size: 1.3rem; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d3 .am-slider-title { font-weight: normal; margin-bottom: 5px; display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .am-slider-d3 .am-control-thumbs { position: static; overflow: hidden; } .am-slider-d3 .am-control-thumbs li { padding: 12px 4px 4px; position: relative; } .am-slider-d3 .am-control-thumbs img { width: 100%; display: block; opacity: .85; cursor: pointer; } .am-slider-d3 .am-control-thumbs img:hover { opacity: 1; } .am-slider-d3 .am-control-thumbs .am-active { opacity: 1; cursor: default; } .am-slider-d3 .am-control-thumbs .am-active + i { position: absolute; top: 0; left: 50%; content: ""; display: inline-block; width: 0; height: 0; vertical-align: middle; border-top: 8px solid rgba(0, 0, 0, 0.7); border-right: 8px solid transparent; border-left: 8px solid transparent; border-bottom: 0 dotted; -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); margin-left: -4px; -webkit-transition: all 0.2s; transition: all 0.2s; } .am-slider-d3 .am-direction-nav, .am-slider-d3 .am-pauseplay { display: none; } .am-slider-d3 .am-control-thumbs { display: table; } .am-slider-d3 .am-control-thumbs li { display: table-cell; width: 1%; } [data-am-widget='tabs'] { margin: 10px; } [data-am-widget='tabs'] .am-tabs-nav { width: 100%; padding: 0; margin: 0; list-style: none; text-align: center; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } [data-am-widget='tabs'] .am-tabs-nav li { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; } [data-am-widget='tabs'] .am-tabs-nav a { display: block; word-wrap: normal; /* for IE */ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } /** * Tabs Theme: default */ .am-tabs-default .am-tabs-nav { line-height: 40px; background-color: #eeeeee; } .am-tabs-default .am-tabs-nav a { color: #222222; line-height: 42px; } .am-tabs-default .am-tabs-nav > .am-active a { background-color: #0e90d2; color: #fff; } /** * Tabs Theme: d2 */ .am-tabs-d2 .am-tabs-nav { background-color: #eeeeee; } .am-tabs-d2 .am-tabs-nav li { height: 42px; } .am-tabs-d2 .am-tabs-nav a { color: #222222; line-height: 42px; } .am-tabs-d2 .am-tabs-nav > .am-active { position: relative; background-color: #fcfcfc; border-bottom: 2px solid #0e90d2; } .am-tabs-d2 .am-tabs-nav > .am-active a { line-height: 40px; color: #0e90d2; } .am-tabs-d2 .am-tabs-nav > .am-active:after { position: absolute; width: 0; height: 0; bottom: 0px; left: 50%; margin-left: -5px; border: 6px rgba(0, 0, 0, 0) solid; content: ""; z-index: 1; border-bottom-color: #0e90d2; } .am-titlebar { margin-top: 20px; height: 45px; font-size: 100%; } .am-titlebar h2 { margin-top: 0; margin-bottom: 0; font-size: 1.6rem; } .am-titlebar .am-titlebar-title img { height: 24px; width: auto; } /** * Titlebar Theme: default */ .am-titlebar-default { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; margin-left: 10px; margin-right: 10px; background-color: transparent; border-bottom: 1px solid #dedede; line-height: 44px; } .am-titlebar-default a { color: #0e90d2; } .am-titlebar-default .am-titlebar-title { position: relative; padding-left: 12px; color: #0e90d2; font-size: 1.8rem; text-align: left; font-weight: bold; } .am-titlebar-default .am-titlebar-title:before { content: ""; position: absolute; left: 2px; top: 8px; bottom: 8px; border-left: 3px solid #0e90d2; } .am-titlebar-default .am-titlebar-nav { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; text-align: right; } .am-titlebar-default .am-titlebar-nav a { margin-right: 10px; } .am-titlebar-default .am-titlebar-nav a:last-child { margin-right: 5px; } /** * Titlebar Theme: multi */ .am-titlebar-multi { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; background-color: #f5f5f5; border-top: 2px solid #3bb4f2; border-bottom: 1px solid #e8e8e8; } .am-titlebar-multi a { color: #0e90d2; } .am-titlebar-multi .am-titlebar-title { padding-left: 10px; color: #0e90d2; font-size: 1.8rem; text-align: left; font-weight: bold; line-height: 42px; } .am-titlebar-multi .am-titlebar-nav { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; text-align: right; line-height: 42px; } .am-titlebar-multi .am-titlebar-nav a { margin-right: 10px; } /** * Titlebar Theme: cols */ .am-titlebar-cols { position: relative; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; padding-left: 10px; background-color: #f5f5f5; color: #555555; font-size: 18px; border-top: 2px solid #e1e1e1; line-height: 41px; } .am-titlebar-cols a { color: #555555; } .am-titlebar-cols .am-titlebar-title { color: #0e90d2; margin-right: 15px; border-bottom: 2px solid #0e90d2; font-weight: bold; } .am-titlebar-cols .am-titlebar-title a { color: #0e90d2; } .am-titlebar-cols .am-titlebar-nav { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; } .am-titlebar-cols .am-titlebar-nav a { display: inline-block; margin-right: 15px; line-height: 41px; border-bottom: 2px solid transparent; } .am-titlebar-cols .am-titlebar-nav a:hover { color: #3c3c3c; border-bottom-color: #0e90d2; } .am-titlebar-cols .am-titlebar-nav a:last-child { margin-right: 10px; } .am-wechatpay .am-wechatpay-btn { margin-top: 1rem; margin-bottom: 1rem; } ================================================ FILE: open-layui-web/src/main/view/static/assets/css/app.css ================================================ /* Write your styles */ /*html,body{background: #444444;}*/ /* 登陆logo */ .myapp-login { overflow: auto; top: 0; bottom: 0; left: 0; right: 0; height: 100%; overflow: hidden; width: 100%; } .myapp-login-logo-block { width: 100%;} .myapp-login-logo {width: 100%; text-align: center; padding-top: 30px;} .myapp-login-logo i { color: #eb602e; font-size: 120px;display: inline-block;} .myapp-login-logo-text {font-family: "Lucida Grande",Helvetica,Arial,"Microsoft YaHei",FreeSans,Arimo,"Droid Sans","wenquanyi micro hei","Hiragino Sans GB","Hiragino Sans GB W3",FontAwesome,sans-serif; color:#fff; font-weight: bold;font-size: 40px; margin-top: -40px; text-align: center; width: 100%;} .myapp-login-logo-text span {color: #eb602e;} .myapp-login-logo-text .info { padding-bottom: 30px; border-bottom: 1px solid #4d4d4d;font-family: FreeSans,Arimo,"Droid Sans","wenquanyi micro hei","Hiragino Sans GB","Hiragino Sans GB W3",FontAwesome,sans-serif; width: 100%; font-weight: normal; font-size: 14px; color: #fff;} .login-font {font-size: 12px; font-family:"wenquanyi micro hei","Hiragino Sans GB","Hiragino Sans GB W3",FontAwesome,sans-serif; width: 100%; color: #5e5e5e; text-align: center; padding: 20px 0;} .login-font i {color: #eb602e; font-style: normal;} .login-font span { color: #fff;} .login-am-center { margin: 0 auto; float:none;} .login-am-center .am-form input { background: #565656; border: none; font-size: 12px; line-height: 30px; text-indent: 10px;} .login-am-center .am-btn-default { width: 100%; background: #eb602e; border: none; color: #fff; font-size: 14px; line-height: 30px;} body { background-image: linear-gradient(-180deg, #1a1454 0%, #0e81a5 100%); background-repeat: no-repeat; background-size: cover; margin: 0 auto; } .osc_git_box { background-color: #fff; margin-top: 20px; } canvas { z-index:-999; position: fixed; left: 0; right: 0; top: 0; bottom: 0; } ================================================ FILE: open-layui-web/src/main/view/static/assets/css/login.css ================================================ /** EasyWeb */ body { background-image: linear-gradient(-180deg, #1a1454 0%, #0e81a5 100%); /*background-image: url("../images/bg_login.png");*/ background-repeat: no-repeat; background-size: cover; } .login-wrapper, body, html { height: 100%; } .login-wrapper { overflow: auto; position: absolute; top: 0; bottom: 0; left: 0; right: 0; height: 100%; overflow: hidden; width: 100%; } .login-body { padding: 10px 10px 40px 10px; } .login-body > .layui-card { max-width: 360px; margin: 0 auto; } .login-body .layui-card-header { font-weight: 700; font-size: 15px; } .login-body .layui-form-pane .layui-form-label { width: 48px; } .login-body .layui-form-pane .layui-input-block { margin-left: 48px; } .login-body .login-captcha { width: 100%; cursor: pointer; } .login-body .login-other > * { display: inline-block; vertical-align: middle; margin-right: 10px; font-size: 14px; } .login-body .login-other .layui-icon { position: relative; top: 2px; font-size: 26px; } .login-body .login-other a:hover { opacity: .8; } .layui-icon-login-qq { color: #3492ED } .layui-icon-login-wechat { color: #4DAF29 } .layui-icon-login-weibo { color: #CF1900 } /** 底部样式 */ .login-footer { text-align: center; line-height: 30px; color: rgba(255, 255, 255, 0.7) !important; padding-bottom: 20px; } .login-footer span { padding: 0 5px } .login-footer a { padding: 0 5px; color: rgba(255, 255, 255, 0.7) !important; } .login-footer a:hover { color: rgba(255, 255, 255, 0.4) !important; } /** 头部样式 */ .login-header { font-size: 20px; font-weight: bold; color: rgba(255, 255, 255, 0.85) !important; padding: 10px; } .login-header img { height: 40px; } /** 移动设备样式 */ @media screen and (min-height: 590px) { .login-footer { position: absolute; bottom: 0; width: 100%; } } @media screen and (min-height: 670px) { .login-body { padding: 250px 10px 40px 10px; } } /** 辅助样式 */ .layui-link { color: #029789 !important; } .layui-link:hover { opacity: .8; } .pull-right { float: right; } .inline-block { display: inline-block; } .osc_git_box { background-color: #fff; margin-top: 20px; } canvas { /*position:relative;*/ z-index:-999; position: fixed; left: 0; right: 0; top: 0; bottom: 0; } ================================================ FILE: open-layui-web/src/main/view/static/assets/js/amazeui.ie8polyfill.js ================================================ /*! Amaze UI v2.6.0 ~ IE8 Fucker | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-03-31T14:28:54+0800 */ /*! * https://github.com/es-shims/es5-shim * @license es5-shim Copyright 2009-2015 by contributors, MIT License * see https://github.com/es-shims/es5-shim/blob/master/LICENSE */ // vim: ts=4 sts=4 sw=4 expandtab // Add semicolon to prevent IIFE from being passed as argument to concatenated code. ; // UMD (Universal Module Definition) // see https://github.com/umdjs/umd/blob/master/templates/returnExports.js (function (root, factory) { 'use strict'; /* global define, exports, module */ if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(factory); } else if (typeof exports === 'object') { // Node. Does not work with strict CommonJS, but // only CommonJS-like enviroments that support module.exports, // like Node. module.exports = factory(); } else { // Browser globals (root is window) root.returnExports = factory(); } }(this, function () { /** * Brings an environment as close to ECMAScript 5 compliance * as is possible with the facilities of erstwhile engines. * * Annotated ES5: http://es5.github.com/ (specific links below) * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/ */ // Shortcut to an often accessed properties, in order to avoid multiple // dereference that costs universally. This also holds a reference to known-good // functions. var $Array = Array; var ArrayPrototype = $Array.prototype; var $Object = Object; var ObjectPrototype = $Object.prototype; var $Function = Function; var FunctionPrototype = $Function.prototype; var $String = String; var StringPrototype = $String.prototype; var $Number = Number; var NumberPrototype = $Number.prototype; var array_slice = ArrayPrototype.slice; var array_splice = ArrayPrototype.splice; var array_push = ArrayPrototype.push; var array_unshift = ArrayPrototype.unshift; var array_concat = ArrayPrototype.concat; var array_join = ArrayPrototype.join; var call = FunctionPrototype.call; var apply = FunctionPrototype.apply; var max = Math.max; var min = Math.min; // Having a toString local variable name breaks in Opera so use to_string. var to_string = ObjectPrototype.toString; /* global Symbol */ /* eslint-disable one-var-declaration-per-line, no-redeclare */ var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol'; var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, constructorRegex = /^\s*class /, isES6ClassFn = function isES6ClassFn(value) { try { var fnStr = fnToStr.call(value); var singleStripped = fnStr.replace(/\/\/.*\n/g, ''); var multiStripped = singleStripped.replace(/\/\*[.\s\S]*\*\//g, ''); var spaceStripped = multiStripped.replace(/\n/mg, ' ').replace(/ {2}/g, ' '); return constructorRegex.test(spaceStripped); } catch (e) { return false; /* not a function */ } }, tryFunctionObject = function tryFunctionObject(value) { try { if (isES6ClassFn(value)) { return false; } fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]', isCallable = function isCallable(value) { if (!value) { return false; } if (typeof value !== 'function' && typeof value !== 'object') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } if (isES6ClassFn(value)) { return false; } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; }; var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; }; var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; }; /* eslint-enable one-var-declaration-per-line, no-redeclare */ /* inlined from http://npmjs.com/define-properties */ var supportsDescriptors = $Object.defineProperty && (function () { try { var obj = {}; $Object.defineProperty(obj, 'x', { enumerable: false, value: obj }); for (var _ in obj) { return false; } return obj.x === obj; } catch (e) { /* this is ES3 */ return false; } }()); var defineProperties = (function (has) { // Define configurable, writable, and non-enumerable props // if they don't exist. var defineProperty; if (supportsDescriptors) { defineProperty = function (object, name, method, forceAssign) { if (!forceAssign && (name in object)) { return; } $Object.defineProperty(object, name, { configurable: true, enumerable: false, writable: true, value: method }); }; } else { defineProperty = function (object, name, method, forceAssign) { if (!forceAssign && (name in object)) { return; } object[name] = method; }; } return function defineProperties(object, map, forceAssign) { for (var name in map) { if (has.call(map, name)) { defineProperty(object, name, map[name], forceAssign); } } }; }(ObjectPrototype.hasOwnProperty)); // // Util // ====== // /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */ var isPrimitive = function isPrimitive(input) { var type = typeof input; return input === null || (type !== 'object' && type !== 'function'); }; var isActualNaN = $Number.isNaN || function (x) { return x !== x; }; var ES = { // ES5 9.4 // http://es5.github.com/#x9.4 // http://jsperf.com/to-integer /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */ ToInteger: function ToInteger(num) { var n = +num; if (isActualNaN(n)) { n = 0; } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) { n = (n > 0 || -1) * Math.floor(Math.abs(n)); } return n; }, /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */ ToPrimitive: function ToPrimitive(input) { var val, valueOf, toStr; if (isPrimitive(input)) { return input; } valueOf = input.valueOf; if (isCallable(valueOf)) { val = valueOf.call(input); if (isPrimitive(val)) { return val; } } toStr = input.toString; if (isCallable(toStr)) { val = toStr.call(input); if (isPrimitive(val)) { return val; } } throw new TypeError(); }, // ES5 9.9 // http://es5.github.com/#x9.9 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */ ToObject: function (o) { if (o == null) { // this matches both null and undefined throw new TypeError("can't convert " + o + ' to object'); } return $Object(o); }, /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */ ToUint32: function ToUint32(x) { return x >>> 0; } }; // // Function // ======== // // ES-5 15.3.4.5 // http://es5.github.com/#x15.3.4.5 var Empty = function Empty() {}; defineProperties(FunctionPrototype, { bind: function bind(that) { // .length is 1 // 1. Let Target be the this value. var target = this; // 2. If IsCallable(Target) is false, throw a TypeError exception. if (!isCallable(target)) { throw new TypeError('Function.prototype.bind called on incompatible ' + target); } // 3. Let A be a new (possibly empty) internal list of all of the // argument values provided after thisArg (arg1, arg2 etc), in order. // XXX slicedArgs will stand in for "A" if used var args = array_slice.call(arguments, 1); // for normal call // 4. Let F be a new native ECMAScript object. // 11. Set the [[Prototype]] internal property of F to the standard // built-in Function prototype object as specified in 15.3.3.1. // 12. Set the [[Call]] internal property of F as described in // 15.3.4.5.1. // 13. Set the [[Construct]] internal property of F as described in // 15.3.4.5.2. // 14. Set the [[HasInstance]] internal property of F as described in // 15.3.4.5.3. var bound; var binder = function () { if (this instanceof bound) { // 15.3.4.5.2 [[Construct]] // When the [[Construct]] internal method of a function object, // F that was created using the bind function is called with a // list of arguments ExtraArgs, the following steps are taken: // 1. Let target be the value of F's [[TargetFunction]] // internal property. // 2. If target has no [[Construct]] internal method, a // TypeError exception is thrown. // 3. Let boundArgs be the value of F's [[BoundArgs]] internal // property. // 4. Let args be a new list containing the same values as the // list boundArgs in the same order followed by the same // values as the list ExtraArgs in the same order. // 5. Return the result of calling the [[Construct]] internal // method of target providing args as the arguments. var result = apply.call( target, this, array_concat.call(args, array_slice.call(arguments)) ); if ($Object(result) === result) { return result; } return this; } else { // 15.3.4.5.1 [[Call]] // When the [[Call]] internal method of a function object, F, // which was created using the bind function is called with a // this value and a list of arguments ExtraArgs, the following // steps are taken: // 1. Let boundArgs be the value of F's [[BoundArgs]] internal // property. // 2. Let boundThis be the value of F's [[BoundThis]] internal // property. // 3. Let target be the value of F's [[TargetFunction]] internal // property. // 4. Let args be a new list containing the same values as the // list boundArgs in the same order followed by the same // values as the list ExtraArgs in the same order. // 5. Return the result of calling the [[Call]] internal method // of target providing boundThis as the this value and // providing args as the arguments. // equiv: target.call(this, ...boundArgs, ...args) return apply.call( target, that, array_concat.call(args, array_slice.call(arguments)) ); } }; // 15. If the [[Class]] internal property of Target is "Function", then // a. Let L be the length property of Target minus the length of A. // b. Set the length own property of F to either 0 or L, whichever is // larger. // 16. Else set the length own property of F to 0. var boundLength = max(0, target.length - args.length); // 17. Set the attributes of the length own property of F to the values // specified in 15.3.5.1. var boundArgs = []; for (var i = 0; i < boundLength; i++) { array_push.call(boundArgs, '$' + i); } // XXX Build a dynamic function with desired amount of arguments is the only // way to set the length property of a function. // In environments where Content Security Policies enabled (Chrome extensions, // for ex.) all use of eval or Function costructor throws an exception. // However in all of these environments Function.prototype.bind exists // and so this code will never be executed. bound = $Function('binder', 'return function (' + array_join.call(boundArgs, ',') + '){ return binder.apply(this, arguments); }')(binder); if (target.prototype) { Empty.prototype = target.prototype; bound.prototype = new Empty(); // Clean up dangling references. Empty.prototype = null; } // TODO // 18. Set the [[Extensible]] internal property of F to true. // TODO // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3). // 20. Call the [[DefineOwnProperty]] internal method of F with // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and // false. // 21. Call the [[DefineOwnProperty]] internal method of F with // arguments "arguments", PropertyDescriptor {[[Get]]: thrower, // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, // and false. // TODO // NOTE Function objects created using Function.prototype.bind do not // have a prototype property or the [[Code]], [[FormalParameters]], and // [[Scope]] internal properties. // XXX can't delete prototype in pure-js. // 22. Return F. return bound; } }); // _Please note: Shortcuts are defined after `Function.prototype.bind` as we // use it in defining shortcuts. var owns = call.bind(ObjectPrototype.hasOwnProperty); var toStr = call.bind(ObjectPrototype.toString); var arraySlice = call.bind(array_slice); var arraySliceApply = apply.bind(array_slice); var strSlice = call.bind(StringPrototype.slice); var strSplit = call.bind(StringPrototype.split); var strIndexOf = call.bind(StringPrototype.indexOf); var pushCall = call.bind(array_push); var isEnum = call.bind(ObjectPrototype.propertyIsEnumerable); var arraySort = call.bind(ArrayPrototype.sort); // // Array // ===== // var isArray = $Array.isArray || function isArray(obj) { return toStr(obj) === '[object Array]'; }; // ES5 15.4.4.12 // http://es5.github.com/#x15.4.4.13 // Return len+argCount. // [bugfix, ielt8] // IE < 8 bug: [].unshift(0) === undefined but should be "1" var hasUnshiftReturnValueBug = [].unshift(0) !== 1; defineProperties(ArrayPrototype, { unshift: function () { array_unshift.apply(this, arguments); return this.length; } }, hasUnshiftReturnValueBug); // ES5 15.4.3.2 // http://es5.github.com/#x15.4.3.2 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray defineProperties($Array, { isArray: isArray }); // The IsCallable() check in the Array functions // has been replaced with a strict check on the // internal class of the object to trap cases where // the provided function was actually a regular // expression literal, which in V8 and // JavaScriptCore is a typeof "function". Only in // V8 are regular expression literals permitted as // reduce parameters, so it is desirable in the // general case for the shim to match the more // strict and common behavior of rejecting regular // expressions. // ES5 15.4.4.18 // http://es5.github.com/#x15.4.4.18 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach // Check failure of by-index access of string characters (IE < 9) // and failure of `0 in boxedString` (Rhino) var boxedString = $Object('a'); var splitString = boxedString[0] !== 'a' || !(0 in boxedString); var properlyBoxesContext = function properlyBoxed(method) { // Check node 0.6.21 bug where third parameter is not boxed var properlyBoxesNonStrict = true; var properlyBoxesStrict = true; var threwException = false; if (method) { try { method.call('foo', function (_, __, context) { if (typeof context !== 'object') { properlyBoxesNonStrict = false; } }); method.call([1], function () { 'use strict'; properlyBoxesStrict = typeof this === 'string'; }, 'x'); } catch (e) { threwException = true; } } return !!method && !threwException && properlyBoxesNonStrict && properlyBoxesStrict; }; defineProperties(ArrayPrototype, { forEach: function forEach(callbackfn/*, thisArg*/) { var object = ES.ToObject(this); var self = splitString && isString(this) ? strSplit(this, '') : object; var i = -1; var length = ES.ToUint32(self.length); var T; if (arguments.length > 1) { T = arguments[1]; } // If no callback function or if callback is not a callable function if (!isCallable(callbackfn)) { throw new TypeError('Array.prototype.forEach callback must be a function'); } while (++i < length) { if (i in self) { // Invoke the callback function with call, passing arguments: // context, property value, property key, thisArg object if (typeof T === 'undefined') { callbackfn(self[i], i, object); } else { callbackfn.call(T, self[i], i, object); } } } } }, !properlyBoxesContext(ArrayPrototype.forEach)); // ES5 15.4.4.19 // http://es5.github.com/#x15.4.4.19 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map defineProperties(ArrayPrototype, { map: function map(callbackfn/*, thisArg*/) { var object = ES.ToObject(this); var self = splitString && isString(this) ? strSplit(this, '') : object; var length = ES.ToUint32(self.length); var result = $Array(length); var T; if (arguments.length > 1) { T = arguments[1]; } // If no callback function or if callback is not a callable function if (!isCallable(callbackfn)) { throw new TypeError('Array.prototype.map callback must be a function'); } for (var i = 0; i < length; i++) { if (i in self) { if (typeof T === 'undefined') { result[i] = callbackfn(self[i], i, object); } else { result[i] = callbackfn.call(T, self[i], i, object); } } } return result; } }, !properlyBoxesContext(ArrayPrototype.map)); // ES5 15.4.4.20 // http://es5.github.com/#x15.4.4.20 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter defineProperties(ArrayPrototype, { filter: function filter(callbackfn/*, thisArg*/) { var object = ES.ToObject(this); var self = splitString && isString(this) ? strSplit(this, '') : object; var length = ES.ToUint32(self.length); var result = []; var value; var T; if (arguments.length > 1) { T = arguments[1]; } // If no callback function or if callback is not a callable function if (!isCallable(callbackfn)) { throw new TypeError('Array.prototype.filter callback must be a function'); } for (var i = 0; i < length; i++) { if (i in self) { value = self[i]; if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) { pushCall(result, value); } } } return result; } }, !properlyBoxesContext(ArrayPrototype.filter)); // ES5 15.4.4.16 // http://es5.github.com/#x15.4.4.16 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every defineProperties(ArrayPrototype, { every: function every(callbackfn/*, thisArg*/) { var object = ES.ToObject(this); var self = splitString && isString(this) ? strSplit(this, '') : object; var length = ES.ToUint32(self.length); var T; if (arguments.length > 1) { T = arguments[1]; } // If no callback function or if callback is not a callable function if (!isCallable(callbackfn)) { throw new TypeError('Array.prototype.every callback must be a function'); } for (var i = 0; i < length; i++) { if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) { return false; } } return true; } }, !properlyBoxesContext(ArrayPrototype.every)); // ES5 15.4.4.17 // http://es5.github.com/#x15.4.4.17 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some defineProperties(ArrayPrototype, { some: function some(callbackfn/*, thisArg */) { var object = ES.ToObject(this); var self = splitString && isString(this) ? strSplit(this, '') : object; var length = ES.ToUint32(self.length); var T; if (arguments.length > 1) { T = arguments[1]; } // If no callback function or if callback is not a callable function if (!isCallable(callbackfn)) { throw new TypeError('Array.prototype.some callback must be a function'); } for (var i = 0; i < length; i++) { if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) { return true; } } return false; } }, !properlyBoxesContext(ArrayPrototype.some)); // ES5 15.4.4.21 // http://es5.github.com/#x15.4.4.21 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce var reduceCoercesToObject = false; if (ArrayPrototype.reduce) { reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object'; } defineProperties(ArrayPrototype, { reduce: function reduce(callbackfn/*, initialValue*/) { var object = ES.ToObject(this); var self = splitString && isString(this) ? strSplit(this, '') : object; var length = ES.ToUint32(self.length); // If no callback function or if callback is not a callable function if (!isCallable(callbackfn)) { throw new TypeError('Array.prototype.reduce callback must be a function'); } // no value to return if no initial value and an empty array if (length === 0 && arguments.length === 1) { throw new TypeError('reduce of empty array with no initial value'); } var i = 0; var result; if (arguments.length >= 2) { result = arguments[1]; } else { do { if (i in self) { result = self[i++]; break; } // if array contains no values, no initial value to return if (++i >= length) { throw new TypeError('reduce of empty array with no initial value'); } } while (true); } for (; i < length; i++) { if (i in self) { result = callbackfn(result, self[i], i, object); } } return result; } }, !reduceCoercesToObject); // ES5 15.4.4.22 // http://es5.github.com/#x15.4.4.22 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight var reduceRightCoercesToObject = false; if (ArrayPrototype.reduceRight) { reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object'; } defineProperties(ArrayPrototype, { reduceRight: function reduceRight(callbackfn/*, initial*/) { var object = ES.ToObject(this); var self = splitString && isString(this) ? strSplit(this, '') : object; var length = ES.ToUint32(self.length); // If no callback function or if callback is not a callable function if (!isCallable(callbackfn)) { throw new TypeError('Array.prototype.reduceRight callback must be a function'); } // no value to return if no initial value, empty array if (length === 0 && arguments.length === 1) { throw new TypeError('reduceRight of empty array with no initial value'); } var result; var i = length - 1; if (arguments.length >= 2) { result = arguments[1]; } else { do { if (i in self) { result = self[i--]; break; } // if array contains no values, no initial value to return if (--i < 0) { throw new TypeError('reduceRight of empty array with no initial value'); } } while (true); } if (i < 0) { return result; } do { if (i in self) { result = callbackfn(result, self[i], i, object); } } while (i--); return result; } }, !reduceRightCoercesToObject); // ES5 15.4.4.14 // http://es5.github.com/#x15.4.4.14 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1; defineProperties(ArrayPrototype, { indexOf: function indexOf(searchElement/*, fromIndex */) { var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this); var length = ES.ToUint32(self.length); if (length === 0) { return -1; } var i = 0; if (arguments.length > 1) { i = ES.ToInteger(arguments[1]); } // handle negative indices i = i >= 0 ? i : max(0, length + i); for (; i < length; i++) { if (i in self && self[i] === searchElement) { return i; } } return -1; } }, hasFirefox2IndexOfBug); // ES5 15.4.4.15 // http://es5.github.com/#x15.4.4.15 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1; defineProperties(ArrayPrototype, { lastIndexOf: function lastIndexOf(searchElement/*, fromIndex */) { var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this); var length = ES.ToUint32(self.length); if (length === 0) { return -1; } var i = length - 1; if (arguments.length > 1) { i = min(i, ES.ToInteger(arguments[1])); } // handle negative indices i = i >= 0 ? i : length - Math.abs(i); for (; i >= 0; i--) { if (i in self && searchElement === self[i]) { return i; } } return -1; } }, hasFirefox2LastIndexOfBug); // ES5 15.4.4.12 // http://es5.github.com/#x15.4.4.12 var spliceNoopReturnsEmptyArray = (function () { var a = [1, 2]; var result = a.splice(); return a.length === 2 && isArray(result) && result.length === 0; }()); defineProperties(ArrayPrototype, { // Safari 5.0 bug where .splice() returns undefined splice: function splice(start, deleteCount) { if (arguments.length === 0) { return []; } else { return array_splice.apply(this, arguments); } } }, !spliceNoopReturnsEmptyArray); var spliceWorksWithEmptyObject = (function () { var obj = {}; ArrayPrototype.splice.call(obj, 0, 0, 1); return obj.length === 1; }()); defineProperties(ArrayPrototype, { splice: function splice(start, deleteCount) { if (arguments.length === 0) { return []; } var args = arguments; this.length = max(ES.ToInteger(this.length), 0); if (arguments.length > 0 && typeof deleteCount !== 'number') { args = arraySlice(arguments); if (args.length < 2) { pushCall(args, this.length - start); } else { args[1] = ES.ToInteger(deleteCount); } } return array_splice.apply(this, args); } }, !spliceWorksWithEmptyObject); var spliceWorksWithLargeSparseArrays = (function () { // Per https://github.com/es-shims/es5-shim/issues/295 // Safari 7/8 breaks with sparse arrays of size 1e5 or greater var arr = new $Array(1e5); // note: the index MUST be 8 or larger or the test will false pass arr[8] = 'x'; arr.splice(1, 1); // note: this test must be defined *after* the indexOf shim // per https://github.com/es-shims/es5-shim/issues/313 return arr.indexOf('x') === 7; }()); var spliceWorksWithSmallSparseArrays = (function () { // Per https://github.com/es-shims/es5-shim/issues/295 // Opera 12.15 breaks on this, no idea why. var n = 256; var arr = []; arr[n] = 'a'; arr.splice(n + 1, 0, 'b'); return arr[n] === 'a'; }()); defineProperties(ArrayPrototype, { splice: function splice(start, deleteCount) { var O = ES.ToObject(this); var A = []; var len = ES.ToUint32(O.length); var relativeStart = ES.ToInteger(start); var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len); var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart); var k = 0; var from; while (k < actualDeleteCount) { from = $String(actualStart + k); if (owns(O, from)) { A[k] = O[from]; } k += 1; } var items = arraySlice(arguments, 2); var itemCount = items.length; var to; if (itemCount < actualDeleteCount) { k = actualStart; var maxK = len - actualDeleteCount; while (k < maxK) { from = $String(k + actualDeleteCount); to = $String(k + itemCount); if (owns(O, from)) { O[to] = O[from]; } else { delete O[to]; } k += 1; } k = len; var minK = len - actualDeleteCount + itemCount; while (k > minK) { delete O[k - 1]; k -= 1; } } else if (itemCount > actualDeleteCount) { k = len - actualDeleteCount; while (k > actualStart) { from = $String(k + actualDeleteCount - 1); to = $String(k + itemCount - 1); if (owns(O, from)) { O[to] = O[from]; } else { delete O[to]; } k -= 1; } } k = actualStart; for (var i = 0; i < items.length; ++i) { O[k] = items[i]; k += 1; } O.length = len - actualDeleteCount + itemCount; return A; } }, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays); var originalJoin = ArrayPrototype.join; var hasStringJoinBug; try { hasStringJoinBug = Array.prototype.join.call('123', ',') !== '1,2,3'; } catch (e) { hasStringJoinBug = true; } if (hasStringJoinBug) { defineProperties(ArrayPrototype, { join: function join(separator) { var sep = typeof separator === 'undefined' ? ',' : separator; return originalJoin.call(isString(this) ? strSplit(this, '') : this, sep); } }, hasStringJoinBug); } var hasJoinUndefinedBug = [1, 2].join(undefined) !== '1,2'; if (hasJoinUndefinedBug) { defineProperties(ArrayPrototype, { join: function join(separator) { var sep = typeof separator === 'undefined' ? ',' : separator; return originalJoin.call(this, sep); } }, hasJoinUndefinedBug); } var pushShim = function push(item) { var O = ES.ToObject(this); var n = ES.ToUint32(O.length); var i = 0; while (i < arguments.length) { O[n + i] = arguments[i]; i += 1; } O.length = n + i; return n + i; }; var pushIsNotGeneric = (function () { var obj = {}; var result = Array.prototype.push.call(obj, undefined); return result !== 1 || obj.length !== 1 || typeof obj[0] !== 'undefined' || !owns(obj, 0); }()); defineProperties(ArrayPrototype, { push: function push(item) { if (isArray(this)) { return array_push.apply(this, arguments); } return pushShim.apply(this, arguments); } }, pushIsNotGeneric); // This fixes a very weird bug in Opera 10.6 when pushing `undefined var pushUndefinedIsWeird = (function () { var arr = []; var result = arr.push(undefined); return result !== 1 || arr.length !== 1 || typeof arr[0] !== 'undefined' || !owns(arr, 0); }()); defineProperties(ArrayPrototype, { push: pushShim }, pushUndefinedIsWeird); // ES5 15.2.3.14 // http://es5.github.io/#x15.4.4.10 // Fix boxed string bug defineProperties(ArrayPrototype, { slice: function (start, end) { var arr = isString(this) ? strSplit(this, '') : this; return arraySliceApply(arr, arguments); } }, splitString); var sortIgnoresNonFunctions = (function () { try { [1, 2].sort(null); [1, 2].sort({}); return true; } catch (e) { /**/ } return false; }()); var sortThrowsOnRegex = (function () { // this is a problem in Firefox 4, in which `typeof /a/ === 'function'` try { [1, 2].sort(/a/); return false; } catch (e) { /**/ } return true; }()); var sortIgnoresUndefined = (function () { // applies in IE 8, for one. try { [1, 2].sort(undefined); return true; } catch (e) { /**/ } return false; }()); defineProperties(ArrayPrototype, { sort: function sort(compareFn) { if (typeof compareFn === 'undefined') { return arraySort(this); } if (!isCallable(compareFn)) { throw new TypeError('Array.prototype.sort callback must be a function'); } return arraySort(this, compareFn); } }, sortIgnoresNonFunctions || !sortIgnoresUndefined || !sortThrowsOnRegex); // // Object // ====== // // ES5 15.2.3.14 // http://es5.github.com/#x15.2.3.14 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation var hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString'); var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype'); var hasStringEnumBug = !owns('x', '0'); var equalsConstructorPrototype = function (o) { var ctor = o.constructor; return ctor && ctor.prototype === o; }; var blacklistedKeys = { $window: true, $console: true, $parent: true, $self: true, $frame: true, $frames: true, $frameElement: true, $webkitIndexedDB: true, $webkitStorageInfo: true, $external: true }; var hasAutomationEqualityBug = (function () { /* globals window */ if (typeof window === 'undefined') { return false; } for (var k in window) { try { if (!blacklistedKeys['$' + k] && owns(window, k) && window[k] !== null && typeof window[k] === 'object') { equalsConstructorPrototype(window[k]); } } catch (e) { return true; } } return false; }()); var equalsConstructorPrototypeIfNotBuggy = function (object) { if (typeof window === 'undefined' || !hasAutomationEqualityBug) { return equalsConstructorPrototype(object); } try { return equalsConstructorPrototype(object); } catch (e) { return false; } }; var dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ]; var dontEnumsLength = dontEnums.length; // taken directly from https://github.com/ljharb/is-arguments/blob/master/index.js // can be replaced with require('is-arguments') if we ever use a build process instead var isStandardArguments = function isArguments(value) { return toStr(value) === '[object Arguments]'; }; var isLegacyArguments = function isArguments(value) { return value !== null && typeof value === 'object' && typeof value.length === 'number' && value.length >= 0 && !isArray(value) && isCallable(value.callee); }; var isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments; defineProperties($Object, { keys: function keys(object) { var isFn = isCallable(object); var isArgs = isArguments(object); var isObject = object !== null && typeof object === 'object'; var isStr = isObject && isString(object); if (!isObject && !isFn && !isArgs) { throw new TypeError('Object.keys called on a non-object'); } var theKeys = []; var skipProto = hasProtoEnumBug && isFn; if ((isStr && hasStringEnumBug) || isArgs) { for (var i = 0; i < object.length; ++i) { pushCall(theKeys, $String(i)); } } if (!isArgs) { for (var name in object) { if (!(skipProto && name === 'prototype') && owns(object, name)) { pushCall(theKeys, $String(name)); } } } if (hasDontEnumBug) { var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object); for (var j = 0; j < dontEnumsLength; j++) { var dontEnum = dontEnums[j]; if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) { pushCall(theKeys, dontEnum); } } } return theKeys; } }); var keysWorksWithArguments = $Object.keys && (function () { // Safari 5.0 bug return $Object.keys(arguments).length === 2; }(1, 2)); var keysHasArgumentsLengthBug = $Object.keys && (function () { var argKeys = $Object.keys(arguments); return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1; }(1)); var originalKeys = $Object.keys; defineProperties($Object, { keys: function keys(object) { if (isArguments(object)) { return originalKeys(arraySlice(object)); } else { return originalKeys(object); } } }, !keysWorksWithArguments || keysHasArgumentsLengthBug); // // Date // ==== // var hasNegativeMonthYearBug = new Date(-3509827329600292).getUTCMonth() !== 0; var aNegativeTestDate = new Date(-1509842289600292); var aPositiveTestDate = new Date(1449662400000); var hasToUTCStringFormatBug = aNegativeTestDate.toUTCString() !== 'Mon, 01 Jan -45875 11:59:59 GMT'; var hasToDateStringFormatBug; var hasToStringFormatBug; var timeZoneOffset = aNegativeTestDate.getTimezoneOffset(); if (timeZoneOffset < -720) { hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Tue Jan 02 -45875'; hasToStringFormatBug = !(/^Thu Dec 10 2015 \d\d:\d\d:\d\d GMT[-\+]\d\d\d\d(?: |$)/).test(aPositiveTestDate.toString()); } else { hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Mon Jan 01 -45875'; hasToStringFormatBug = !(/^Wed Dec 09 2015 \d\d:\d\d:\d\d GMT[-\+]\d\d\d\d(?: |$)/).test(aPositiveTestDate.toString()); } var originalGetFullYear = call.bind(Date.prototype.getFullYear); var originalGetMonth = call.bind(Date.prototype.getMonth); var originalGetDate = call.bind(Date.prototype.getDate); var originalGetUTCFullYear = call.bind(Date.prototype.getUTCFullYear); var originalGetUTCMonth = call.bind(Date.prototype.getUTCMonth); var originalGetUTCDate = call.bind(Date.prototype.getUTCDate); var originalGetUTCDay = call.bind(Date.prototype.getUTCDay); var originalGetUTCHours = call.bind(Date.prototype.getUTCHours); var originalGetUTCMinutes = call.bind(Date.prototype.getUTCMinutes); var originalGetUTCSeconds = call.bind(Date.prototype.getUTCSeconds); var originalGetUTCMilliseconds = call.bind(Date.prototype.getUTCMilliseconds); var dayName = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; var monthName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; var daysInMonth = function daysInMonth(month, year) { return originalGetDate(new Date(year, month, 0)); }; defineProperties(Date.prototype, { getFullYear: function getFullYear() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var year = originalGetFullYear(this); if (year < 0 && originalGetMonth(this) > 11) { return year + 1; } return year; }, getMonth: function getMonth() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var year = originalGetFullYear(this); var month = originalGetMonth(this); if (year < 0 && month > 11) { return 0; } return month; }, getDate: function getDate() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var year = originalGetFullYear(this); var month = originalGetMonth(this); var date = originalGetDate(this); if (year < 0 && month > 11) { if (month === 12) { return date; } var days = daysInMonth(0, year + 1); return (days - date) + 1; } return date; }, getUTCFullYear: function getUTCFullYear() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var year = originalGetUTCFullYear(this); if (year < 0 && originalGetUTCMonth(this) > 11) { return year + 1; } return year; }, getUTCMonth: function getUTCMonth() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var year = originalGetUTCFullYear(this); var month = originalGetUTCMonth(this); if (year < 0 && month > 11) { return 0; } return month; }, getUTCDate: function getUTCDate() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var year = originalGetUTCFullYear(this); var month = originalGetUTCMonth(this); var date = originalGetUTCDate(this); if (year < 0 && month > 11) { if (month === 12) { return date; } var days = daysInMonth(0, year + 1); return (days - date) + 1; } return date; } }, hasNegativeMonthYearBug); defineProperties(Date.prototype, { toUTCString: function toUTCString() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var day = originalGetUTCDay(this); var date = originalGetUTCDate(this); var month = originalGetUTCMonth(this); var year = originalGetUTCFullYear(this); var hour = originalGetUTCHours(this); var minute = originalGetUTCMinutes(this); var second = originalGetUTCSeconds(this); return dayName[day] + ', ' + (date < 10 ? '0' + date : date) + ' ' + monthName[month] + ' ' + year + ' ' + (hour < 10 ? '0' + hour : hour) + ':' + (minute < 10 ? '0' + minute : minute) + ':' + (second < 10 ? '0' + second : second) + ' GMT'; } }, hasNegativeMonthYearBug || hasToUTCStringFormatBug); // Opera 12 has `,` defineProperties(Date.prototype, { toDateString: function toDateString() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var day = this.getDay(); var date = this.getDate(); var month = this.getMonth(); var year = this.getFullYear(); return dayName[day] + ' ' + monthName[month] + ' ' + (date < 10 ? '0' + date : date) + ' ' + year; } }, hasNegativeMonthYearBug || hasToDateStringFormatBug); // can't use defineProperties here because of toString enumeration issue in IE <= 8 if (hasNegativeMonthYearBug || hasToStringFormatBug) { Date.prototype.toString = function toString() { if (!this || !(this instanceof Date)) { throw new TypeError('this is not a Date object.'); } var day = this.getDay(); var date = this.getDate(); var month = this.getMonth(); var year = this.getFullYear(); var hour = this.getHours(); var minute = this.getMinutes(); var second = this.getSeconds(); var timezoneOffset = this.getTimezoneOffset(); var hoursOffset = Math.floor(Math.abs(timezoneOffset) / 60); var minutesOffset = Math.floor(Math.abs(timezoneOffset) % 60); return dayName[day] + ' ' + monthName[month] + ' ' + (date < 10 ? '0' + date : date) + ' ' + year + ' ' + (hour < 10 ? '0' + hour : hour) + ':' + (minute < 10 ? '0' + minute : minute) + ':' + (second < 10 ? '0' + second : second) + ' GMT' + (timezoneOffset > 0 ? '-' : '+') + (hoursOffset < 10 ? '0' + hoursOffset : hoursOffset) + (minutesOffset < 10 ? '0' + minutesOffset : minutesOffset); }; if (supportsDescriptors) { $Object.defineProperty(Date.prototype, 'toString', { configurable: true, enumerable: false, writable: true }); } } // ES5 15.9.5.43 // http://es5.github.com/#x15.9.5.43 // This function returns a String value represent the instance in time // represented by this Date object. The format of the String is the Date Time // string format defined in 15.9.1.15. All fields are present in the String. // The time zone is always UTC, denoted by the suffix Z. If the time value of // this object is not a finite Number a RangeError exception is thrown. var negativeDate = -62198755200000; var negativeYearString = '-000001'; var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1; var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z'; var getTime = call.bind(Date.prototype.getTime); defineProperties(Date.prototype, { toISOString: function toISOString() { if (!isFinite(this) || !isFinite(getTime(this))) { // Adope Photoshop requires the second check. throw new RangeError('Date.prototype.toISOString called on non-finite value.'); } var year = originalGetUTCFullYear(this); var month = originalGetUTCMonth(this); // see https://github.com/es-shims/es5-shim/issues/111 year += Math.floor(month / 12); month = (month % 12 + 12) % 12; // the date time string format is specified in 15.9.1.15. var result = [month + 1, originalGetUTCDate(this), originalGetUTCHours(this), originalGetUTCMinutes(this), originalGetUTCSeconds(this)]; year = ( (year < 0 ? '-' : (year > 9999 ? '+' : '')) + strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6) ); for (var i = 0; i < result.length; ++i) { // pad months, days, hours, minutes, and seconds to have two digits. result[i] = strSlice('00' + result[i], -2); } // pad milliseconds to have three digits. return ( year + '-' + arraySlice(result, 0, 2).join('-') + 'T' + arraySlice(result, 2).join(':') + '.' + strSlice('000' + originalGetUTCMilliseconds(this), -3) + 'Z' ); } }, hasNegativeDateBug || hasSafari51DateBug); // ES5 15.9.5.44 // http://es5.github.com/#x15.9.5.44 // This function provides a String representation of a Date object for use by // JSON.stringify (15.12.3). var dateToJSONIsSupported = (function () { try { return Date.prototype.toJSON && new Date(NaN).toJSON() === null && new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 && Date.prototype.toJSON.call({ // generic toISOString: function () { return true; } }); } catch (e) { return false; } }()); if (!dateToJSONIsSupported) { Date.prototype.toJSON = function toJSON(key) { // When the toJSON method is called with argument key, the following // steps are taken: // 1. Let O be the result of calling ToObject, giving it the this // value as its argument. // 2. Let tv be ES.ToPrimitive(O, hint Number). var O = $Object(this); var tv = ES.ToPrimitive(O); // 3. If tv is a Number and is not finite, return null. if (typeof tv === 'number' && !isFinite(tv)) { return null; } // 4. Let toISO be the result of calling the [[Get]] internal method of // O with argument "toISOString". var toISO = O.toISOString; // 5. If IsCallable(toISO) is false, throw a TypeError exception. if (!isCallable(toISO)) { throw new TypeError('toISOString property is not callable'); } // 6. Return the result of calling the [[Call]] internal method of // toISO with O as the this value and an empty argument list. return toISO.call(O); // NOTE 1 The argument is ignored. // NOTE 2 The toJSON function is intentionally generic; it does not // require that its this value be a Date object. Therefore, it can be // transferred to other kinds of objects for use as a method. However, // it does require that any such object have a toISOString method. An // object is free to use the argument key to filter its // stringification. }; } // ES5 15.9.4.2 // http://es5.github.com/#x15.9.4.2 // based on work shared by Daniel Friesen (dantman) // http://gist.github.com/303249 var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15; var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')) || !isNaN(Date.parse('2012-12-31T23:59:60.000Z')); var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z')); if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) { // XXX global assignment won't work in embeddings that use // an alternate object for the context. /* global Date: true */ /* eslint-disable no-undef */ var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1; var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime()); /* eslint-disable no-implicit-globals */ Date = (function (NativeDate) { /* eslint-enable no-implicit-globals */ /* eslint-enable no-undef */ // Date.length === 7 var DateShim = function Date(Y, M, D, h, m, s, ms) { var length = arguments.length; var date; if (this instanceof NativeDate) { var seconds = s; var millis = ms; if (hasSafariSignedIntBug && length >= 7 && ms > maxSafeUnsigned32Bit) { // work around a Safari 8/9 bug where it treats the seconds as signed var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit; var sToShift = Math.floor(msToShift / 1e3); seconds += sToShift; millis -= sToShift * 1e3; } date = length === 1 && $String(Y) === Y ? // isString(Y) // We explicitly pass it through parse: new NativeDate(DateShim.parse(Y)) : // We have to manually make calls depending on argument // length here length >= 7 ? new NativeDate(Y, M, D, h, m, seconds, millis) : length >= 6 ? new NativeDate(Y, M, D, h, m, seconds) : length >= 5 ? new NativeDate(Y, M, D, h, m) : length >= 4 ? new NativeDate(Y, M, D, h) : length >= 3 ? new NativeDate(Y, M, D) : length >= 2 ? new NativeDate(Y, M) : length >= 1 ? new NativeDate(Y instanceof NativeDate ? +Y : Y) : new NativeDate(); } else { date = NativeDate.apply(this, arguments); } if (!isPrimitive(date)) { // Prevent mixups with unfixed Date object defineProperties(date, { constructor: DateShim }, true); } return date; }; // 15.9.1.15 Date Time String Format. var isoDateExpression = new RegExp('^' + '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign + // 6-digit extended year '(?:-(\\d{2})' + // optional month capture '(?:-(\\d{2})' + // optional day capture '(?:' + // capture hours:minutes:seconds.milliseconds 'T(\\d{2})' + // hours capture ':(\\d{2})' + // minutes capture '(?:' + // optional :seconds.milliseconds ':(\\d{2})' + // seconds capture '(?:(\\.\\d{1,}))?' + // milliseconds capture ')?' + '(' + // capture UTC offset component 'Z|' + // UTC capture '(?:' + // offset specifier +/-hours:minutes '([-+])' + // sign capture '(\\d{2})' + // hours offset capture ':(\\d{2})' + // minutes offset capture ')' + ')?)?)?)?' + '$'); var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]; var dayFromMonth = function dayFromMonth(year, month) { var t = month > 1 ? 1 : 0; return ( months[month] + Math.floor((year - 1969 + t) / 4) - Math.floor((year - 1901 + t) / 100) + Math.floor((year - 1601 + t) / 400) + 365 * (year - 1970) ); }; var toUTC = function toUTC(t) { var s = 0; var ms = t; if (hasSafariSignedIntBug && ms > maxSafeUnsigned32Bit) { // work around a Safari 8/9 bug where it treats the seconds as signed var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit; var sToShift = Math.floor(msToShift / 1e3); s += sToShift; ms -= sToShift * 1e3; } return $Number(new NativeDate(1970, 0, 1, 0, 0, s, ms)); }; // Copy any custom methods a 3rd party library may have added for (var key in NativeDate) { if (owns(NativeDate, key)) { DateShim[key] = NativeDate[key]; } } // Copy "native" methods explicitly; they may be non-enumerable defineProperties(DateShim, { now: NativeDate.now, UTC: NativeDate.UTC }, true); DateShim.prototype = NativeDate.prototype; defineProperties(DateShim.prototype, { constructor: DateShim }, true); // Upgrade Date.parse to handle simplified ISO 8601 strings var parseShim = function parse(string) { var match = isoDateExpression.exec(string); if (match) { // parse months, days, hours, minutes, seconds, and milliseconds // provide default values if necessary // parse the UTC offset component var year = $Number(match[1]), month = $Number(match[2] || 1) - 1, day = $Number(match[3] || 1) - 1, hour = $Number(match[4] || 0), minute = $Number(match[5] || 0), second = $Number(match[6] || 0), millisecond = Math.floor($Number(match[7] || 0) * 1000), // When time zone is missed, local offset should be used // (ES 5.1 bug) // see https://bugs.ecmascript.org/show_bug.cgi?id=112 isLocalTime = Boolean(match[4] && !match[8]), signOffset = match[9] === '-' ? 1 : -1, hourOffset = $Number(match[10] || 0), minuteOffset = $Number(match[11] || 0), result; var hasMinutesOrSecondsOrMilliseconds = minute > 0 || second > 0 || millisecond > 0; if ( hour < (hasMinutesOrSecondsOrMilliseconds ? 24 : 25) && minute < 60 && second < 60 && millisecond < 1000 && month > -1 && month < 12 && hourOffset < 24 && minuteOffset < 60 && // detect invalid offsets day > -1 && day < (dayFromMonth(year, month + 1) - dayFromMonth(year, month)) ) { result = ( (dayFromMonth(year, month) + day) * 24 + hour + hourOffset * signOffset ) * 60; result = ( (result + minute + minuteOffset * signOffset) * 60 + second ) * 1000 + millisecond; if (isLocalTime) { result = toUTC(result); } if (-8.64e15 <= result && result <= 8.64e15) { return result; } } return NaN; } return NativeDate.parse.apply(this, arguments); }; defineProperties(DateShim, { parse: parseShim }); return DateShim; }(Date)); /* global Date: false */ } // ES5 15.9.4.4 // http://es5.github.com/#x15.9.4.4 if (!Date.now) { Date.now = function now() { return new Date().getTime(); }; } // // Number // ====== // // ES5.1 15.7.4.5 // http://es5.github.com/#x15.7.4.5 var hasToFixedBugs = NumberPrototype.toFixed && ( (0.00008).toFixed(3) !== '0.000' || (0.9).toFixed(0) !== '1' || (1.255).toFixed(2) !== '1.25' || (1000000000000000128).toFixed(0) !== '1000000000000000128' ); var toFixedHelpers = { base: 1e7, size: 6, data: [0, 0, 0, 0, 0, 0], multiply: function multiply(n, c) { var i = -1; var c2 = c; while (++i < toFixedHelpers.size) { c2 += n * toFixedHelpers.data[i]; toFixedHelpers.data[i] = c2 % toFixedHelpers.base; c2 = Math.floor(c2 / toFixedHelpers.base); } }, divide: function divide(n) { var i = toFixedHelpers.size; var c = 0; while (--i >= 0) { c += toFixedHelpers.data[i]; toFixedHelpers.data[i] = Math.floor(c / n); c = (c % n) * toFixedHelpers.base; } }, numToString: function numToString() { var i = toFixedHelpers.size; var s = ''; while (--i >= 0) { if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) { var t = $String(toFixedHelpers.data[i]); if (s === '') { s = t; } else { s += strSlice('0000000', 0, 7 - t.length) + t; } } } return s; }, pow: function pow(x, n, acc) { return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc))); }, log: function log(x) { var n = 0; var x2 = x; while (x2 >= 4096) { n += 12; x2 /= 4096; } while (x2 >= 2) { n += 1; x2 /= 2; } return n; } }; var toFixedShim = function toFixed(fractionDigits) { var f, x, s, m, e, z, j, k; // Test for NaN and round fractionDigits down f = $Number(fractionDigits); f = isActualNaN(f) ? 0 : Math.floor(f); if (f < 0 || f > 20) { throw new RangeError('Number.toFixed called with invalid number of decimals'); } x = $Number(this); if (isActualNaN(x)) { return 'NaN'; } // If it is too big or small, return the string value of the number if (x <= -1e21 || x >= 1e21) { return $String(x); } s = ''; if (x < 0) { s = '-'; x = -x; } m = '0'; if (x > 1e-21) { // 1e-21 < x < 1e21 // -70 < log2(x) < 70 e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69; z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1)); z *= 0x10000000000000; // Math.pow(2, 52); e = 52 - e; // -18 < e < 122 // x = z / 2 ^ e if (e > 0) { toFixedHelpers.multiply(0, z); j = f; while (j >= 7) { toFixedHelpers.multiply(1e7, 0); j -= 7; } toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0); j = e - 1; while (j >= 23) { toFixedHelpers.divide(1 << 23); j -= 23; } toFixedHelpers.divide(1 << j); toFixedHelpers.multiply(1, 1); toFixedHelpers.divide(2); m = toFixedHelpers.numToString(); } else { toFixedHelpers.multiply(0, z); toFixedHelpers.multiply(1 << (-e), 0); m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f); } } if (f > 0) { k = m.length; if (k <= f) { m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m; } else { m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f); } } else { m = s + m; } return m; }; defineProperties(NumberPrototype, { toFixed: toFixedShim }, hasToFixedBugs); var hasToPrecisionUndefinedBug = (function () { try { return 1.0.toPrecision(undefined) === '1'; } catch (e) { return true; } }()); var originalToPrecision = NumberPrototype.toPrecision; defineProperties(NumberPrototype, { toPrecision: function toPrecision(precision) { return typeof precision === 'undefined' ? originalToPrecision.call(this) : originalToPrecision.call(this, precision); } }, hasToPrecisionUndefinedBug); // // String // ====== // // ES5 15.5.4.14 // http://es5.github.com/#x15.5.4.14 // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers] // Many browsers do not split properly with regular expressions or they // do not perform the split correctly under obscure conditions. // See http://blog.stevenlevithan.com/archives/cross-browser-split // I've tested in many browsers and this seems to cover the deviant ones: // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""] // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""] // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not // [undefined, "t", undefined, "e", ...] // ''.split(/.?/) should be [], not [""] // '.'.split(/()()/) should be ["."], not ["", "", "."] if ( 'ab'.split(/(?:ab)*/).length !== 2 || '.'.split(/(.?)(.?)/).length !== 4 || 'tesst'.split(/(s)*/)[1] === 't' || 'test'.split(/(?:)/, -1).length !== 4 || ''.split(/.?/).length || '.'.split(/()()/).length > 1 ) { (function () { var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group var maxSafe32BitInt = Math.pow(2, 32) - 1; StringPrototype.split = function (separator, limit) { var string = String(this); if (typeof separator === 'undefined' && limit === 0) { return []; } // If `separator` is not a regex, use native split if (!isRegex(separator)) { return strSplit(this, separator, limit); } var output = []; var flags = (separator.ignoreCase ? 'i' : '') + (separator.multiline ? 'm' : '') + (separator.unicode ? 'u' : '') + // in ES6 (separator.sticky ? 'y' : ''), // Firefox 3+ and ES6 lastLastIndex = 0, // Make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; var separatorCopy = new RegExp(separator.source, flags + 'g'); if (!compliantExecNpcg) { // Doesn't need flags gy, but they don't hurt separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags); } /* Values for `limit`, per the spec: * If undefined: 4294967295 // maxSafe32BitInt * If 0, Infinity, or NaN: 0 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; * If negative number: 4294967296 - Math.floor(Math.abs(limit)) * If other: Type-convert, then use the above rules */ var splitLimit = typeof limit === 'undefined' ? maxSafe32BitInt : ES.ToUint32(limit); match = separatorCopy.exec(string); while (match) { // `separatorCopy.lastIndex` is not reliable cross-browser lastIndex = match.index + match[0].length; if (lastIndex > lastLastIndex) { pushCall(output, strSlice(string, lastLastIndex, match.index)); // Fix browsers whose `exec` methods don't consistently return `undefined` for // nonparticipating capturing groups if (!compliantExecNpcg && match.length > 1) { /* eslint-disable no-loop-func */ match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (typeof arguments[i] === 'undefined') { match[i] = void 0; } } }); /* eslint-enable no-loop-func */ } if (match.length > 1 && match.index < string.length) { array_push.apply(output, arraySlice(match, 1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= splitLimit) { break; } } if (separatorCopy.lastIndex === match.index) { separatorCopy.lastIndex++; // Avoid an infinite loop } match = separatorCopy.exec(string); } if (lastLastIndex === string.length) { if (lastLength || !separatorCopy.test('')) { pushCall(output, ''); } } else { pushCall(output, strSlice(string, lastLastIndex)); } return output.length > splitLimit ? arraySlice(output, 0, splitLimit) : output; }; }()); // [bugfix, chrome] // If separator is undefined, then the result array contains just one String, // which is the this value (converted to a String). If limit is not undefined, // then the output array is truncated so that it contains no more than limit // elements. // "0".split(undefined, 0) -> [] } else if ('0'.split(void 0, 0).length) { StringPrototype.split = function split(separator, limit) { if (typeof separator === 'undefined' && limit === 0) { return []; } return strSplit(this, separator, limit); }; } var str_replace = StringPrototype.replace; var replaceReportsGroupsCorrectly = (function () { var groups = []; 'x'.replace(/x(.)?/g, function (match, group) { pushCall(groups, group); }); return groups.length === 1 && typeof groups[0] === 'undefined'; }()); if (!replaceReportsGroupsCorrectly) { StringPrototype.replace = function replace(searchValue, replaceValue) { var isFn = isCallable(replaceValue); var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source); if (!isFn || !hasCapturingGroups) { return str_replace.call(this, searchValue, replaceValue); } else { var wrappedReplaceValue = function (match) { var length = arguments.length; var originalLastIndex = searchValue.lastIndex; searchValue.lastIndex = 0; var args = searchValue.exec(match) || []; searchValue.lastIndex = originalLastIndex; pushCall(args, arguments[length - 2], arguments[length - 1]); return replaceValue.apply(this, args); }; return str_replace.call(this, searchValue, wrappedReplaceValue); } }; } // ECMA-262, 3rd B.2.3 // Not an ECMAScript standard, although ECMAScript 3rd Edition has a // non-normative section suggesting uniform semantics and it should be // normalized across all browsers // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE var string_substr = StringPrototype.substr; var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b'; defineProperties(StringPrototype, { substr: function substr(start, length) { var normalizedStart = start; if (start < 0) { normalizedStart = max(this.length + start, 0); } return string_substr.call(this, normalizedStart, length); } }, hasNegativeSubstrBug); // ES5 15.5.4.20 // whitespace from: http://es5.github.io/#x15.5.4.20 var ws = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' + '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' + '\u2029\uFEFF'; var zeroWidth = '\u200b'; var wsRegexChars = '[' + ws + ']'; var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*'); var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$'); var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim()); defineProperties(StringPrototype, { // http://blog.stevenlevithan.com/archives/faster-trim-javascript // http://perfectionkills.com/whitespace-deviations/ trim: function trim() { if (typeof this === 'undefined' || this === null) { throw new TypeError("can't convert " + this + ' to object'); } return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, ''); } }, hasTrimWhitespaceBug); var trim = call.bind(String.prototype.trim); var hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1; defineProperties(StringPrototype, { lastIndexOf: function lastIndexOf(searchString) { if (typeof this === 'undefined' || this === null) { throw new TypeError("can't convert " + this + ' to object'); } var S = $String(this); var searchStr = $String(searchString); var numPos = arguments.length > 1 ? $Number(arguments[1]) : NaN; var pos = isActualNaN(numPos) ? Infinity : ES.ToInteger(numPos); var start = min(max(pos, 0), S.length); var searchLen = searchStr.length; var k = start + searchLen; while (k > 0) { k = max(0, k - searchLen); var index = strIndexOf(strSlice(S, k, start + searchLen), searchStr); if (index !== -1) { return k + index; } } return -1; } }, hasLastIndexBug); var originalLastIndexOf = StringPrototype.lastIndexOf; defineProperties(StringPrototype, { lastIndexOf: function lastIndexOf(searchString) { return originalLastIndexOf.apply(this, arguments); } }, StringPrototype.lastIndexOf.length !== 1); // ES-5 15.1.2.2 /* eslint-disable radix */ if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) { /* eslint-enable radix */ /* global parseInt: true */ parseInt = (function (origParseInt) { var hexRegex = /^[\-+]?0[xX]/; return function parseInt(str, radix) { var string = trim(str); var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10); return origParseInt(string, defaultedRadix); }; }(parseInt)); } // https://es5.github.io/#x15.1.2.3 if (1 / parseFloat('-0') !== -Infinity) { /* global parseFloat: true */ parseFloat = (function (origParseFloat) { return function parseFloat(string) { var inputString = trim(string); var result = origParseFloat(inputString); return result === 0 && strSlice(inputString, 0, 1) === '-' ? -0 : result; }; }(parseFloat)); } if (String(new RangeError('test')) !== 'RangeError: test') { var errorToStringShim = function toString() { if (typeof this === 'undefined' || this === null) { throw new TypeError("can't convert " + this + ' to object'); } var name = this.name; if (typeof name === 'undefined') { name = 'Error'; } else if (typeof name !== 'string') { name = $String(name); } var msg = this.message; if (typeof msg === 'undefined') { msg = ''; } else if (typeof msg !== 'string') { msg = $String(msg); } if (!name) { return msg; } if (!msg) { return name; } return name + ': ' + msg; }; // can't use defineProperties here because of toString enumeration issue in IE <= 8 Error.prototype.toString = errorToStringShim; } if (supportsDescriptors) { var ensureNonEnumerable = function (obj, prop) { if (isEnum(obj, prop)) { var desc = Object.getOwnPropertyDescriptor(obj, prop); desc.enumerable = false; Object.defineProperty(obj, prop, desc); } }; ensureNonEnumerable(Error.prototype, 'message'); if (Error.prototype.message !== '') { Error.prototype.message = ''; } ensureNonEnumerable(Error.prototype, 'name'); } if (String(/a/mig) !== '/a/gim') { var regexToString = function toString() { var str = '/' + this.source + '/'; if (this.global) { str += 'g'; } if (this.ignoreCase) { str += 'i'; } if (this.multiline) { str += 'm'; } return str; }; // can't use defineProperties here because of toString enumeration issue in IE <= 8 RegExp.prototype.toString = regexToString; } })); /*! * https://github.com/es-shims/es5-shim * @license es5-shim Copyright 2009-2015 by contributors, MIT License * see https://github.com/es-shims/es5-shim/blob/master/LICENSE */ // vim: ts=4 sts=4 sw=4 expandtab // Add semicolon to prevent IIFE from being passed as argument to concatenated code. ; // UMD (Universal Module Definition) // see https://github.com/umdjs/umd/blob/master/templates/returnExports.js (function (root, factory) { 'use strict'; /* global define, exports, module */ if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(factory); } else if (typeof exports === 'object') { // Node. Does not work with strict CommonJS, but // only CommonJS-like enviroments that support module.exports, // like Node. module.exports = factory(); } else { // Browser globals (root is window) root.returnExports = factory(); } }(this, function () { var call = Function.call; var prototypeOfObject = Object.prototype; var owns = call.bind(prototypeOfObject.hasOwnProperty); var isEnumerable = call.bind(prototypeOfObject.propertyIsEnumerable); var toStr = call.bind(prototypeOfObject.toString); // If JS engine supports accessors creating shortcuts. var defineGetter; var defineSetter; var lookupGetter; var lookupSetter; var supportsAccessors = owns(prototypeOfObject, '__defineGetter__'); if (supportsAccessors) { /* eslint-disable no-underscore-dangle */ defineGetter = call.bind(prototypeOfObject.__defineGetter__); defineSetter = call.bind(prototypeOfObject.__defineSetter__); lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); /* eslint-enable no-underscore-dangle */ } // ES5 15.2.3.2 // http://es5.github.com/#x15.2.3.2 if (!Object.getPrototypeOf) { // https://github.com/es-shims/es5-shim/issues#issue/2 // http://ejohn.org/blog/objectgetprototypeof/ // recommended by fschaefer on github // // sure, and webreflection says ^_^ // ... this will nerever possibly return null // ... Opera Mini breaks here with infinite loops Object.getPrototypeOf = function getPrototypeOf(object) { /* eslint-disable no-proto */ var proto = object.__proto__; /* eslint-enable no-proto */ if (proto || proto === null) { return proto; } else if (toStr(object.constructor) === '[object Function]') { return object.constructor.prototype; } else if (object instanceof Object) { return prototypeOfObject; } else { // Correctly return null for Objects created with `Object.create(null)` // (shammed or native) or `{ __proto__: null}`. Also returns null for // cross-realm objects on browsers that lack `__proto__` support (like // IE <11), but that's the best we can do. return null; } }; } // ES5 15.2.3.3 // http://es5.github.com/#x15.2.3.3 var doesGetOwnPropertyDescriptorWork = function doesGetOwnPropertyDescriptorWork(object) { try { object.sentinel = 0; return Object.getOwnPropertyDescriptor(object, 'sentinel').value === 0; } catch (exception) { return false; } }; // check whether getOwnPropertyDescriptor works if it's given. Otherwise, shim partially. if (Object.defineProperty) { var getOwnPropertyDescriptorWorksOnObject = doesGetOwnPropertyDescriptorWork({}); var getOwnPropertyDescriptorWorksOnDom = typeof document === 'undefined' || doesGetOwnPropertyDescriptorWork(document.createElement('div')); if (!getOwnPropertyDescriptorWorksOnDom || !getOwnPropertyDescriptorWorksOnObject) { var getOwnPropertyDescriptorFallback = Object.getOwnPropertyDescriptor; } } if (!Object.getOwnPropertyDescriptor || getOwnPropertyDescriptorFallback) { var ERR_NON_OBJECT = 'Object.getOwnPropertyDescriptor called on a non-object: '; /* eslint-disable no-proto */ Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { if ((typeof object !== 'object' && typeof object !== 'function') || object === null) { throw new TypeError(ERR_NON_OBJECT + object); } // make a valiant attempt to use the real getOwnPropertyDescriptor // for I8's DOM elements. if (getOwnPropertyDescriptorFallback) { try { return getOwnPropertyDescriptorFallback.call(Object, object, property); } catch (exception) { // try the shim if the real one doesn't work } } var descriptor; // If object does not owns property return undefined immediately. if (!owns(object, property)) { return descriptor; } // If object has a property then it's for sure `configurable`, and // probably `enumerable`. Detect enumerability though. descriptor = { enumerable: isEnumerable(object, property), configurable: true }; // If JS engine supports accessor properties then property may be a // getter or setter. if (supportsAccessors) { // Unfortunately `__lookupGetter__` will return a getter even // if object has own non getter property along with a same named // inherited getter. To avoid misbehavior we temporary remove // `__proto__` so that `__lookupGetter__` will return getter only // if it's owned by an object. var prototype = object.__proto__; var notPrototypeOfObject = object !== prototypeOfObject; // avoid recursion problem, breaking in Opera Mini when // Object.getOwnPropertyDescriptor(Object.prototype, 'toString') // or any other Object.prototype accessor if (notPrototypeOfObject) { object.__proto__ = prototypeOfObject; } var getter = lookupGetter(object, property); var setter = lookupSetter(object, property); if (notPrototypeOfObject) { // Once we have getter and setter we can put values back. object.__proto__ = prototype; } if (getter || setter) { if (getter) { descriptor.get = getter; } if (setter) { descriptor.set = setter; } // If it was accessor property we're done and return here // in order to avoid adding `value` to the descriptor. return descriptor; } } // If we got this far we know that object has an own property that is // not an accessor so we set it as a value and return descriptor. descriptor.value = object[property]; descriptor.writable = true; return descriptor; }; /* eslint-enable no-proto */ } // ES5 15.2.3.4 // http://es5.github.com/#x15.2.3.4 if (!Object.getOwnPropertyNames) { Object.getOwnPropertyNames = function getOwnPropertyNames(object) { return Object.keys(object); }; } // ES5 15.2.3.5 // http://es5.github.com/#x15.2.3.5 if (!Object.create) { // Contributed by Brandon Benvie, October, 2012 var createEmpty; var supportsProto = !({ __proto__: null } instanceof Object); // the following produces false positives // in Opera Mini => not a reliable check // Object.prototype.__proto__ === null // Check for document.domain and active x support // No need to use active x approach when document.domain is not set // see https://github.com/es-shims/es5-shim/issues/150 // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346 /* global ActiveXObject */ var shouldUseActiveX = function shouldUseActiveX() { // return early if document.domain not set if (!document.domain) { return false; } try { return !!new ActiveXObject('htmlfile'); } catch (exception) { return false; } }; // This supports IE8 when document.domain is used // see https://github.com/es-shims/es5-shim/issues/150 // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346 var getEmptyViaActiveX = function getEmptyViaActiveX() { var empty; var xDoc; xDoc = new ActiveXObject('htmlfile'); xDoc.write('
    Snippet:
    Directive How Source Rendered
    ng-bind-html Automatically uses $sanitize
    <div ng-bind-html="snippet">
    </div>
    ng-bind-html Bypass $sanitize by explicitly trusting the dangerous value
    <div ng-bind-html="deliberatelyTrustDangerousSnippet()">
    </div>
    ng-bind Automatically escapes
    <div ng-bind="snippet">
    </div>
    it('should sanitize the html snippet by default', function() { expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). toBe('

    an html\nclick here\nsnippet

    '); }); it('should inline raw snippet if bound to a trusted value', function() { expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). toBe("

    an html\n" + "click here\n" + "snippet

    "); }); it('should escape snippet without any filter', function() { expect(element(by.css('#bind-default div')).getInnerHtml()). toBe("<p style=\"color:blue\">an html\n" + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + "snippet</p>"); }); it('should update', function() { element(by.model('snippet')).clear(); element(by.model('snippet')).sendKeys('new text'); expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). toBe('new text'); expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( 'new text'); expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( "new <b onclick=\"alert(1)\">text</b>"); });
    */ function $SanitizeProvider() { this.$get = ['$$sanitizeUri', function($$sanitizeUri) { return function(html) { var buf = []; htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { return !/^unsafe/.test($$sanitizeUri(uri, isImage)); })); return buf.join(''); }; }]; } function sanitizeText(chars) { var buf = []; var writer = htmlSanitizeWriter(buf, angular.noop); writer.chars(chars); return buf.join(''); } // Regular Expressions for parsing tags and attributes var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, BEGIN_TAG_REGEXP = /^/g, DOCTYPE_REGEXP = /]*?)>/i, CDATA_REGEXP = //g, // Match everything outside of normal chars and " (quote character) NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Good source of info about elements and attributes // http://dev.w3.org/html5/spec/Overview.html#semantics // http://simon.html5.org/html-elements // Safe Void Elements - HTML5 // http://dev.w3.org/html5/spec/Overview.html#void-elements var voidElements = makeMap("area,br,col,hr,img,wbr"); // Elements that you can, intentionally, leave open (and which close themselves) // http://dev.w3.org/html5/spec/Overview.html#optional-tags var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), optionalEndTagInlineElements = makeMap("rp,rt"), optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements); // Safe Block Elements - HTML5 var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); // Inline Elements - HTML5 var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); // Special Elements (can contain anything) var specialElements = makeMap("script,style"); var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements); //Attributes that have href and hence need to be sanitized var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); var validAttrs = angular.extend({}, uriAttrs, makeMap( 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+ 'valign,value,vspace,width')); function makeMap(str) { var obj = {}, items = str.split(','), i; for (i = 0; i < items.length; i++) obj[items[i]] = true; return obj; } /** * @example * htmlParser(htmlString, { * start: function(tag, attrs, unary) {}, * end: function(tag) {}, * chars: function(text) {}, * comment: function(text) {} * }); * * @param {string} html string * @param {object} handler */ function htmlParser( html, handler ) { var index, chars, match, stack = [], last = html; stack.last = function() { return stack[ stack.length - 1 ]; }; while ( html ) { chars = true; // Make sure we're not in a script or style element if ( !stack.last() || !specialElements[ stack.last() ] ) { // Comment if ( html.indexOf("", index) === index) { if (handler.comment) handler.comment( html.substring( 4, index ) ); html = html.substring( index + 3 ); chars = false; } // DOCTYPE } else if ( DOCTYPE_REGEXP.test(html) ) { match = html.match( DOCTYPE_REGEXP ); if ( match ) { html = html.replace( match[0] , ''); chars = false; } // end tag } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { match = html.match( END_TAG_REGEXP ); if ( match ) { html = html.substring( match[0].length ); match[0].replace( END_TAG_REGEXP, parseEndTag ); chars = false; } // start tag } else if ( BEGIN_TAG_REGEXP.test(html) ) { match = html.match( START_TAG_REGEXP ); if ( match ) { html = html.substring( match[0].length ); match[0].replace( START_TAG_REGEXP, parseStartTag ); chars = false; } } if ( chars ) { index = html.indexOf("<"); var text = index < 0 ? html : html.substring( 0, index ); html = index < 0 ? "" : html.substring( index ); if (handler.chars) handler.chars( decodeEntities(text) ); } } else { html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){ text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); if (handler.chars) handler.chars( decodeEntities(text) ); return ""; }); parseEndTag( "", stack.last() ); } if ( html == last ) { throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + "of html: {0}", html); } last = html; } // Clean up any remaining tags parseEndTag(); function parseStartTag( tag, tagName, rest, unary ) { tagName = angular.lowercase(tagName); if ( blockElements[ tagName ] ) { while ( stack.last() && inlineElements[ stack.last() ] ) { parseEndTag( "", stack.last() ); } } if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { parseEndTag( "", tagName ); } unary = voidElements[ tagName ] || !!unary; if ( !unary ) stack.push( tagName ); var attrs = {}; rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { var value = doubleQuotedValue || singleQuotedValue || unquotedValue || ''; attrs[name] = decodeEntities(value); }); if (handler.start) handler.start( tagName, attrs, unary ); } function parseEndTag( tag, tagName ) { var pos = 0, i; tagName = angular.lowercase(tagName); if ( tagName ) // Find the closest opened tag of the same type for ( pos = stack.length - 1; pos >= 0; pos-- ) if ( stack[ pos ] == tagName ) break; if ( pos >= 0 ) { // Close all the open elements, up the stack for ( i = stack.length - 1; i >= pos; i-- ) if (handler.end) handler.end( stack[ i ] ); // Remove the open elements from the stack stack.length = pos; } } } var hiddenPre=document.createElement("pre"); var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; /** * decodes all entities into regular string * @param value * @returns {string} A string with decoded entities. */ function decodeEntities(value) { if (!value) { return ''; } // Note: IE8 does not preserve spaces at the start/end of innerHTML // so we must capture them and reattach them afterward var parts = spaceRe.exec(value); var spaceBefore = parts[1]; var spaceAfter = parts[3]; var content = parts[2]; if (content) { hiddenPre.innerHTML=content.replace(//g, '>'); } /** * create an HTML/XML writer which writes to buffer * @param {Array} buf use buf.jain('') to get out sanitized html string * @returns {object} in the form of { * start: function(tag, attrs, unary) {}, * end: function(tag) {}, * chars: function(text) {}, * comment: function(text) {} * } */ function htmlSanitizeWriter(buf, uriValidator){ var ignore = false; var out = angular.bind(buf, buf.push); return { start: function(tag, attrs, unary){ tag = angular.lowercase(tag); if (!ignore && specialElements[tag]) { ignore = tag; } if (!ignore && validElements[tag] === true) { out('<'); out(tag); angular.forEach(attrs, function(value, key){ var lkey=angular.lowercase(key); var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); if (validAttrs[lkey] === true && (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { out(' '); out(key); out('="'); out(encodeEntities(value)); out('"'); } }); out(unary ? '/>' : '>'); } }, end: function(tag){ tag = angular.lowercase(tag); if (!ignore && validElements[tag] === true) { out(''); } if (tag == ignore) { ignore = false; } }, chars: function(chars){ if (!ignore) { out(encodeEntities(chars)); } } }; } // define ngSanitize module and register $sanitize service angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); /* global sanitizeText: false */ /** * @ngdoc filter * @name ngSanitize.filter:linky * @function * * @description * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and * plain email address links. * * Requires the {@link ngSanitize `ngSanitize`} module to be installed. * * @param {string} text Input text. * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. * @returns {string} Html-linkified text. * * @usage * * @example
    Snippet:
    Filter Source Rendered
    linky filter
    <div ng-bind-html="snippet | linky">
    </div>
    linky target
    <div ng-bind-html="snippetWithTarget | linky:'_blank'">
    </div>
    no filter
    <div ng-bind="snippet">
    </div>
    it('should linkify the snippet with urls', function() { expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); }); it('should not linkify snippet without the linky filter', function() { expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); }); it('should update', function() { element(by.model('snippet')).clear(); element(by.model('snippet')).sendKeys('new http://link.'); expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). toBe('new http://link.'); expect(element.all(by.css('#linky-filter a')).count()).toEqual(1); expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()) .toBe('new http://link.'); }); it('should work with the target property', function() { expect(element(by.id('linky-target')). element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). toBe('http://angularjs.org/'); expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); }); */ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, MAILTO_REGEXP = /^mailto:/; return function(text, target) { if (!text) return text; var match; var raw = text; var html = []; var url; var i; while ((match = raw.match(LINKY_URL_REGEXP))) { // We can not end in these as they are sometimes found at the end of the sentence url = match[0]; // if we did not match ftp/http/mailto then assume mailto if (match[2] == match[3]) url = 'mailto:' + url; i = match.index; addText(raw.substr(0, i)); addLink(url, match[0].replace(MAILTO_REGEXP, '')); raw = raw.substring(i + match[0].length); } addText(raw); return $sanitize(html.join('')); function addText(text) { if (!text) { return; } html.push(sanitizeText(text)); } function addLink(url, text) { html.push(''); addText(text); html.push(''); } }; }]); })(window, window.angular); ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/angular-translate-loader-static-files/.bower.json ================================================ { "name": "angular-translate-loader-static-files", "version": "0.1.6", "main": "./angular-translate-loader-static-files.js", "dependencies": { "angular": "1.0.8", "angular-translate": "~1.1.1" }, "homepage": "https://github.com/PascalPrecht/bower-angular-translate-loader-static-files", "_release": "0.1.6", "_resolution": { "type": "version", "tag": "0.1.6", "commit": "eaac546d29d6cde45873e6bad9d18cdff071d983" }, "_source": "git://github.com/PascalPrecht/bower-angular-translate-loader-static-files.git", "_target": "0.1.6", "_originalSource": "angular-translate-loader-static-files" } ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js ================================================ /*! * angular-translate - v2.4.2 - 2014-10-21 * http://github.com/angular-translate/angular-translate * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate').factory('$translateStaticFilesLoader', [ '$q', '$http', function ($q, $http) { return function (options) { if (!options || (!angular.isString(options.prefix) || !angular.isString(options.suffix))) { throw new Error('Couldn\'t load static files, no prefix or suffix specified!'); } var deferred = $q.defer(); $http(angular.extend({ url: [ options.prefix, options.key, options.suffix ].join(''), method: 'GET', params: '' }, options.$http)).success(function (data) { deferred.resolve(data); }).error(function (data) { deferred.reject(options.key); }); return deferred.promise; }; } ]); ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/angular-translate-storage-cookie/.bower.json ================================================ { "name": "angular-translate-storage-cookie", "version": "0.1.6", "main": "./angular-translate-storage-cookie.js", "dependencies": { "angular": "1.0.8", "angular-cookies": "1.0.8", "angular-translate": "~1.1.1" }, "homepage": "https://github.com/PascalPrecht/bower-angular-translate-storage-cookie", "_release": "0.1.6", "_resolution": { "type": "version", "tag": "0.1.6", "commit": "fc9ea3275f0f9bf0a60ca073b58488d934a348ac" }, "_source": "git://github.com/PascalPrecht/bower-angular-translate-storage-cookie.git", "_target": "0.1.6", "_originalSource": "angular-translate-storage-cookie" } ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js ================================================ /*! * angular-translate - v2.4.2 - 2014-10-21 * http://github.com/angular-translate/angular-translate * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate').factory('$translateCookieStorage', [ '$cookieStore', function ($cookieStore) { var $translateCookieStorage = { get: function (name) { return $cookieStore.get(name); }, set: function (name, value) { $cookieStore.put(name, value); } }; return $translateCookieStorage; } ]); ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js ================================================ /*! * angular-translate - v2.4.2 - 2014-10-21 * http://github.com/angular-translate/angular-translate * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate', ['ng']).run([ '$translate', function ($translate) { var key = $translate.storageKey(), storage = $translate.storage(); if (storage) { if (!storage.get(key)) { if (angular.isString($translate.preferredLanguage())) { $translate.use($translate.preferredLanguage()); } else { storage.set(key, $translate.use()); } } else { $translate.use(storage.get(key)); } } else if (angular.isString($translate.preferredLanguage())) { $translate.use($translate.preferredLanguage()); } } ]); angular.module('pascalprecht.translate').provider('$translate', [ '$STORAGE_KEY', function ($STORAGE_KEY) { var $translationTable = {}, $preferredLanguage, $availableLanguageKeys = [], $languageKeyAliases, $fallbackLanguage, $fallbackWasString, $uses, $nextLang, $storageFactory, $storageKey = $STORAGE_KEY, $storagePrefix, $missingTranslationHandlerFactory, $interpolationFactory, $interpolatorFactories = [], $interpolationSanitizationStrategy = false, $loaderFactory, $cloakClassName = 'translate-cloak', $loaderOptions, $notFoundIndicatorLeft, $notFoundIndicatorRight, $postCompilingEnabled = false, NESTED_OBJECT_DELIMITER = '.', loaderCache; var version = '2.4.2'; var getLocale = function () { var nav = window.navigator; return ((angular.isArray(nav.languages) ? nav.languages[0] : nav.language || nav.browserLanguage || nav.systemLanguage || nav.userLanguage) || '').split('-').join('_'); }; var indexOf = function (array, searchElement) { for (var i = 0, len = array.length; i < len; i++) { if (array[i] === searchElement) { return i; } } return -1; }; var trim = function () { return this.replace(/^\s+|\s+$/g, ''); }; var negotiateLocale = function (preferred) { var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length; for (; i < n; i++) { avail.push(angular.lowercase($availableLanguageKeys[i])); } if (indexOf(avail, locale) > -1) { return preferred; } if ($languageKeyAliases) { var alias; for (var langKeyAlias in $languageKeyAliases) { var hasWildcardKey = false; var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred); if (langKeyAlias.slice(-1) === '*') { hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1); } if (hasExactKey || hasWildcardKey) { alias = $languageKeyAliases[langKeyAlias]; if (indexOf(avail, angular.lowercase(alias)) > -1) { return alias; } } } } var parts = preferred.split('_'); if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) { return parts[0]; } return preferred; }; var translations = function (langKey, translationTable) { if (!langKey && !translationTable) { return $translationTable; } if (langKey && !translationTable) { if (angular.isString(langKey)) { return $translationTable[langKey]; } } else { if (!angular.isObject($translationTable[langKey])) { $translationTable[langKey] = {}; } angular.extend($translationTable[langKey], flatObject(translationTable)); } return this; }; this.translations = translations; this.cloakClassName = function (name) { if (!name) { return $cloakClassName; } $cloakClassName = name; return this; }; var flatObject = function (data, path, result, prevKey) { var key, keyWithPath, keyWithShortPath, val; if (!path) { path = []; } if (!result) { result = {}; } for (key in data) { if (!Object.prototype.hasOwnProperty.call(data, key)) { continue; } val = data[key]; if (angular.isObject(val)) { flatObject(val, path.concat(key), result, key); } else { keyWithPath = path.length ? '' + path.join(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key : key; if (path.length && key === prevKey) { keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER); result[keyWithShortPath] = '@:' + keyWithPath; } result[keyWithPath] = val; } } return result; }; this.addInterpolation = function (factory) { $interpolatorFactories.push(factory); return this; }; this.useMessageFormatInterpolation = function () { return this.useInterpolation('$translateMessageFormatInterpolation'); }; this.useInterpolation = function (factory) { $interpolationFactory = factory; return this; }; this.useSanitizeValueStrategy = function (value) { $interpolationSanitizationStrategy = value; return this; }; this.preferredLanguage = function (langKey) { setupPreferredLanguage(langKey); return this; }; var setupPreferredLanguage = function (langKey) { if (langKey) { $preferredLanguage = langKey; } return $preferredLanguage; }; this.translationNotFoundIndicator = function (indicator) { this.translationNotFoundIndicatorLeft(indicator); this.translationNotFoundIndicatorRight(indicator); return this; }; this.translationNotFoundIndicatorLeft = function (indicator) { if (!indicator) { return $notFoundIndicatorLeft; } $notFoundIndicatorLeft = indicator; return this; }; this.translationNotFoundIndicatorRight = function (indicator) { if (!indicator) { return $notFoundIndicatorRight; } $notFoundIndicatorRight = indicator; return this; }; this.fallbackLanguage = function (langKey) { fallbackStack(langKey); return this; }; var fallbackStack = function (langKey) { if (langKey) { if (angular.isString(langKey)) { $fallbackWasString = true; $fallbackLanguage = [langKey]; } else if (angular.isArray(langKey)) { $fallbackWasString = false; $fallbackLanguage = langKey; } if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) { $fallbackLanguage.push($preferredLanguage); } return this; } else { if ($fallbackWasString) { return $fallbackLanguage[0]; } else { return $fallbackLanguage; } } }; this.use = function (langKey) { if (langKey) { if (!$translationTable[langKey] && !$loaderFactory) { throw new Error('$translateProvider couldn\'t find translationTable for langKey: \'' + langKey + '\''); } $uses = langKey; return this; } return $uses; }; var storageKey = function (key) { if (!key) { if ($storagePrefix) { return $storagePrefix + $storageKey; } return $storageKey; } $storageKey = key; }; this.storageKey = storageKey; this.useUrlLoader = function (url, options) { return this.useLoader('$translateUrlLoader', angular.extend({ url: url }, options)); }; this.useStaticFilesLoader = function (options) { return this.useLoader('$translateStaticFilesLoader', options); }; this.useLoader = function (loaderFactory, options) { $loaderFactory = loaderFactory; $loaderOptions = options || {}; return this; }; this.useLocalStorage = function () { return this.useStorage('$translateLocalStorage'); }; this.useCookieStorage = function () { return this.useStorage('$translateCookieStorage'); }; this.useStorage = function (storageFactory) { $storageFactory = storageFactory; return this; }; this.storagePrefix = function (prefix) { if (!prefix) { return prefix; } $storagePrefix = prefix; return this; }; this.useMissingTranslationHandlerLog = function () { return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog'); }; this.useMissingTranslationHandler = function (factory) { $missingTranslationHandlerFactory = factory; return this; }; this.usePostCompiling = function (value) { $postCompilingEnabled = !!value; return this; }; this.determinePreferredLanguage = function (fn) { var locale = fn && angular.isFunction(fn) ? fn() : getLocale(); if (!$availableLanguageKeys.length) { $preferredLanguage = locale; } else { $preferredLanguage = negotiateLocale(locale); } return this; }; this.registerAvailableLanguageKeys = function (languageKeys, aliases) { if (languageKeys) { $availableLanguageKeys = languageKeys; if (aliases) { $languageKeyAliases = aliases; } return this; } return $availableLanguageKeys; }; this.useLoaderCache = function (cache) { if (cache === false) { loaderCache = undefined; } else if (cache === true) { loaderCache = true; } else if (typeof cache === 'undefined') { loaderCache = '$translationCache'; } else if (cache) { loaderCache = cache; } return this; }; this.$get = [ '$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) { var Storage, defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, startFallbackIteration; var $translate = function (translationId, interpolateParams, interpolationId) { if (angular.isArray(translationId)) { var translateAll = function (translationIds) { var results = {}; var promises = []; var translate = function (translationId) { var deferred = $q.defer(); var regardless = function (value) { results[translationId] = value; deferred.resolve([ translationId, value ]); }; $translate(translationId, interpolateParams, interpolationId).then(regardless, regardless); return deferred.promise; }; for (var i = 0, c = translationIds.length; i < c; i++) { promises.push(translate(translationIds[i])); } return $q.all(promises).then(function () { return results; }); }; return translateAll(translationId); } var deferred = $q.defer(); if (translationId) { translationId = trim.apply(translationId); } var promiseToWaitFor = function () { var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[$uses]; fallbackIndex = 0; if ($storageFactory && !promise) { var langKey = Storage.get($storageKey); promise = langPromises[langKey]; if ($fallbackLanguage && $fallbackLanguage.length) { var index = indexOf($fallbackLanguage, langKey); fallbackIndex = index === 0 ? 1 : 0; if (indexOf($fallbackLanguage, $preferredLanguage) < 0) { $fallbackLanguage.push($preferredLanguage); } } } return promise; }(); if (!promiseToWaitFor) { determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); } else { promiseToWaitFor.then(function () { determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); }, deferred.reject); } return deferred.promise; }; var applyNotFoundIndicators = function (translationId) { if ($notFoundIndicatorLeft) { translationId = [ $notFoundIndicatorLeft, translationId ].join(' '); } if ($notFoundIndicatorRight) { translationId = [ translationId, $notFoundIndicatorRight ].join(' '); } return translationId; }; var useLanguage = function (key) { $uses = key; $rootScope.$emit('$translateChangeSuccess', { language: key }); if ($storageFactory) { Storage.set($translate.storageKey(), $uses); } defaultInterpolator.setLocale($uses); angular.forEach(interpolatorHashMap, function (interpolator, id) { interpolatorHashMap[id].setLocale($uses); }); $rootScope.$emit('$translateChangeEnd', { language: key }); }; var loadAsync = function (key) { if (!key) { throw 'No language key specified for loading.'; } var deferred = $q.defer(); $rootScope.$emit('$translateLoadingStart', { language: key }); pendingLoader = true; var cache = loaderCache; if (typeof cache === 'string') { cache = $injector.get(cache); } var loaderOptions = angular.extend({}, $loaderOptions, { key: key, $http: angular.extend({}, { cache: cache }, $loaderOptions.$http) }); $injector.get($loaderFactory)(loaderOptions).then(function (data) { var translationTable = {}; $rootScope.$emit('$translateLoadingSuccess', { language: key }); if (angular.isArray(data)) { angular.forEach(data, function (table) { angular.extend(translationTable, flatObject(table)); }); } else { angular.extend(translationTable, flatObject(data)); } pendingLoader = false; deferred.resolve({ key: key, table: translationTable }); $rootScope.$emit('$translateLoadingEnd', { language: key }); }, function (key) { $rootScope.$emit('$translateLoadingError', { language: key }); deferred.reject(key); $rootScope.$emit('$translateLoadingEnd', { language: key }); }); return deferred.promise; }; if ($storageFactory) { Storage = $injector.get($storageFactory); if (!Storage.get || !Storage.set) { throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or set() method!'); } } if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) { defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); } if ($interpolatorFactories.length) { angular.forEach($interpolatorFactories, function (interpolatorFactory) { var interpolator = $injector.get(interpolatorFactory); interpolator.setLocale($preferredLanguage || $uses); if (angular.isFunction(interpolator.useSanitizeValueStrategy)) { interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); } interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator; }); } var getTranslationTable = function (langKey) { var deferred = $q.defer(); if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) { deferred.resolve($translationTable[langKey]); } else if (langPromises[langKey]) { langPromises[langKey].then(function (data) { translations(data.key, data.table); deferred.resolve(data.table); }, deferred.reject); } else { deferred.reject(); } return deferred.promise; }; var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) { var deferred = $q.defer(); getTranslationTable(langKey).then(function (translationTable) { if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { Interpolator.setLocale(langKey); deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams)); Interpolator.setLocale($uses); } else { deferred.reject(); } }, deferred.reject); return deferred.promise; }; var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) { var result, translationTable = $translationTable[langKey]; if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { Interpolator.setLocale(langKey); result = Interpolator.interpolate(translationTable[translationId], interpolateParams); Interpolator.setLocale($uses); } return result; }; var translateByHandler = function (translationId) { if ($missingTranslationHandlerFactory) { var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses); if (resultString !== undefined) { return resultString; } else { return translationId; } } else { return translationId; } }; var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { var deferred = $q.defer(); if (fallbackLanguageIndex < $fallbackLanguage.length) { var langKey = $fallbackLanguage[fallbackLanguageIndex]; getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(deferred.resolve, function () { resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator).then(deferred.resolve); }); } else { deferred.resolve(translateByHandler(translationId)); } return deferred.promise; }; var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { var result; if (fallbackLanguageIndex < $fallbackLanguage.length) { var langKey = $fallbackLanguage[fallbackLanguageIndex]; result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator); if (!result) { result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator); } } return result; }; var fallbackTranslation = function (translationId, interpolateParams, Interpolator) { return resolveForFallbackLanguage(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); }; var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) { return resolveForFallbackLanguageInstant(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); }; var determineTranslation = function (translationId, interpolateParams, interpolationId) { var deferred = $q.defer(); var table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { var translation = table[translationId]; if (translation.substr(0, 2) === '@:') { $translate(translation.substr(2), interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); } else { deferred.resolve(Interpolator.interpolate(translation, interpolateParams)); } } else { var missingTranslationHandlerTranslation; if ($missingTranslationHandlerFactory && !pendingLoader) { missingTranslationHandlerTranslation = translateByHandler(translationId); } if ($uses && $fallbackLanguage && $fallbackLanguage.length) { fallbackTranslation(translationId, interpolateParams, Interpolator).then(function (translation) { deferred.resolve(translation); }, function (_translationId) { deferred.reject(applyNotFoundIndicators(_translationId)); }); } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { deferred.resolve(missingTranslationHandlerTranslation); } else { deferred.reject(applyNotFoundIndicators(translationId)); } } return deferred.promise; }; var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) { var result, table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { var translation = table[translationId]; if (translation.substr(0, 2) === '@:') { result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId); } else { result = Interpolator.interpolate(translation, interpolateParams); } } else { var missingTranslationHandlerTranslation; if ($missingTranslationHandlerFactory && !pendingLoader) { missingTranslationHandlerTranslation = translateByHandler(translationId); } if ($uses && $fallbackLanguage && $fallbackLanguage.length) { fallbackIndex = 0; result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator); } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { result = missingTranslationHandlerTranslation; } else { result = applyNotFoundIndicators(translationId); } } return result; }; $translate.preferredLanguage = function (langKey) { if (langKey) { setupPreferredLanguage(langKey); } return $preferredLanguage; }; $translate.cloakClassName = function () { return $cloakClassName; }; $translate.fallbackLanguage = function (langKey) { if (langKey !== undefined && langKey !== null) { fallbackStack(langKey); if ($loaderFactory) { if ($fallbackLanguage && $fallbackLanguage.length) { for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { if (!langPromises[$fallbackLanguage[i]]) { langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]); } } } } $translate.use($translate.use()); } if ($fallbackWasString) { return $fallbackLanguage[0]; } else { return $fallbackLanguage; } }; $translate.useFallbackLanguage = function (langKey) { if (langKey !== undefined && langKey !== null) { if (!langKey) { startFallbackIteration = 0; } else { var langKeyPosition = indexOf($fallbackLanguage, langKey); if (langKeyPosition > -1) { startFallbackIteration = langKeyPosition; } } } }; $translate.proposedLanguage = function () { return $nextLang; }; $translate.storage = function () { return Storage; }; $translate.use = function (key) { if (!key) { return $uses; } var deferred = $q.defer(); $rootScope.$emit('$translateChangeStart', { language: key }); var aliasedKey = negotiateLocale(key); if (aliasedKey) { key = aliasedKey; } if (!$translationTable[key] && $loaderFactory && !langPromises[key]) { $nextLang = key; langPromises[key] = loadAsync(key).then(function (translation) { translations(translation.key, translation.table); deferred.resolve(translation.key); useLanguage(translation.key); if ($nextLang === key) { $nextLang = undefined; } }, function (key) { if ($nextLang === key) { $nextLang = undefined; } $rootScope.$emit('$translateChangeError', { language: key }); deferred.reject(key); $rootScope.$emit('$translateChangeEnd', { language: key }); }); } else { deferred.resolve(key); useLanguage(key); } return deferred.promise; }; $translate.storageKey = function () { return storageKey(); }; $translate.isPostCompilingEnabled = function () { return $postCompilingEnabled; }; $translate.refresh = function (langKey) { if (!$loaderFactory) { throw new Error('Couldn\'t refresh translation table, no loader registered!'); } var deferred = $q.defer(); function resolve() { deferred.resolve(); $rootScope.$emit('$translateRefreshEnd', { language: langKey }); } function reject() { deferred.reject(); $rootScope.$emit('$translateRefreshEnd', { language: langKey }); } $rootScope.$emit('$translateRefreshStart', { language: langKey }); if (!langKey) { var tables = [], loadingKeys = {}; if ($fallbackLanguage && $fallbackLanguage.length) { for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { tables.push(loadAsync($fallbackLanguage[i])); loadingKeys[$fallbackLanguage[i]] = true; } } if ($uses && !loadingKeys[$uses]) { tables.push(loadAsync($uses)); } $q.all(tables).then(function (tableData) { angular.forEach(tableData, function (data) { if ($translationTable[data.key]) { delete $translationTable[data.key]; } translations(data.key, data.table); }); if ($uses) { useLanguage($uses); } resolve(); }); } else if ($translationTable[langKey]) { loadAsync(langKey).then(function (data) { translations(data.key, data.table); if (langKey === $uses) { useLanguage($uses); } resolve(); }, reject); } else { reject(); } return deferred.promise; }; $translate.instant = function (translationId, interpolateParams, interpolationId) { if (translationId === null || angular.isUndefined(translationId)) { return translationId; } if (angular.isArray(translationId)) { var results = {}; for (var i = 0, c = translationId.length; i < c; i++) { results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId); } return results; } if (angular.isString(translationId) && translationId.length < 1) { return translationId; } if (translationId) { translationId = trim.apply(translationId); } var result, possibleLangKeys = []; if ($preferredLanguage) { possibleLangKeys.push($preferredLanguage); } if ($uses) { possibleLangKeys.push($uses); } if ($fallbackLanguage && $fallbackLanguage.length) { possibleLangKeys = possibleLangKeys.concat($fallbackLanguage); } for (var j = 0, d = possibleLangKeys.length; j < d; j++) { var possibleLangKey = possibleLangKeys[j]; if ($translationTable[possibleLangKey]) { if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') { result = determineTranslationInstant(translationId, interpolateParams, interpolationId); } } if (typeof result !== 'undefined') { break; } } if (!result && result !== '') { result = defaultInterpolator.interpolate(translationId, interpolateParams); if ($missingTranslationHandlerFactory && !pendingLoader) { result = translateByHandler(translationId); } } return result; }; $translate.versionInfo = function () { return version; }; $translate.loaderCache = function () { return loaderCache; }; if ($loaderFactory) { if (angular.equals($translationTable, {})) { $translate.use($translate.use()); } if ($fallbackLanguage && $fallbackLanguage.length) { var processAsyncResult = function (translation) { translations(translation.key, translation.table); $rootScope.$emit('$translateChangeEnd', { language: translation.key }); }; for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult); } } } return $translate; } ]; } ]); angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', [ '$interpolate', function ($interpolate) { var $translateInterpolator = {}, $locale, $identifier = 'default', $sanitizeValueStrategy = null, sanitizeValueStrategies = { escaped: function (params) { var result = {}; for (var key in params) { if (Object.prototype.hasOwnProperty.call(params, key)) { result[key] = angular.element('
    ').text(params[key]).html(); } } return result; } }; var sanitizeParams = function (params) { var result; if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) { result = sanitizeValueStrategies[$sanitizeValueStrategy](params); } else { result = params; } return result; }; $translateInterpolator.setLocale = function (locale) { $locale = locale; }; $translateInterpolator.getInterpolationIdentifier = function () { return $identifier; }; $translateInterpolator.useSanitizeValueStrategy = function (value) { $sanitizeValueStrategy = value; return this; }; $translateInterpolator.interpolate = function (string, interpolateParams) { if ($sanitizeValueStrategy) { interpolateParams = sanitizeParams(interpolateParams); } return $interpolate(string)(interpolateParams || {}); }; return $translateInterpolator; } ]); angular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY'); angular.module('pascalprecht.translate').directive('translate', [ '$translate', '$q', '$interpolate', '$compile', '$parse', '$rootScope', function ($translate, $q, $interpolate, $compile, $parse, $rootScope) { return { restrict: 'AE', scope: true, compile: function (tElement, tAttr) { var translateValuesExist = tAttr.translateValues ? tAttr.translateValues : undefined; var translateInterpolation = tAttr.translateInterpolation ? tAttr.translateInterpolation : undefined; var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i); var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)'; return function linkFn(scope, iElement, iAttr) { scope.interpolateParams = {}; scope.preText = ''; scope.postText = ''; iAttr.$observe('translate', function (translationId) { if (angular.equals(translationId, '') || !angular.isDefined(translationId)) { var interpolateMatches = iElement.text().match(interpolateRegExp); if (angular.isArray(interpolateMatches)) { scope.preText = interpolateMatches[1]; scope.postText = interpolateMatches[3]; scope.translationId = $interpolate(interpolateMatches[2])(scope.$parent); } else { scope.translationId = iElement.text().replace(/^\s+|\s+$/g, ''); } } else { scope.translationId = translationId; } }); iAttr.$observe('translateDefault', function (value) { scope.defaultText = value; }); if (translateValuesExist) { iAttr.$observe('translateValues', function (interpolateParams) { if (interpolateParams) { scope.$parent.$watch(function () { angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent)); }); } }); } if (translateValueExist) { var fn = function (attrName) { iAttr.$observe(attrName, function (value) { scope.interpolateParams[angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15)] = value; }); }; for (var attr in iAttr) { if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') { fn(attr); } } } var applyElementContent = function (value, scope, successful) { if (!successful && typeof scope.defaultText !== 'undefined') { value = scope.defaultText; } iElement.html(scope.preText + value + scope.postText); var globallyEnabled = $translate.isPostCompilingEnabled(); var locallyDefined = typeof tAttr.translateCompile !== 'undefined'; var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false'; if (globallyEnabled && !locallyDefined || locallyEnabled) { $compile(iElement.contents())(scope); } }; var updateTranslationFn = function () { if (!translateValuesExist && !translateValueExist) { return function () { var unwatch = scope.$watch('translationId', function (value) { if (scope.translationId && value) { $translate(value, {}, translateInterpolation).then(function (translation) { applyElementContent(translation, scope, true); unwatch(); }, function (translationId) { applyElementContent(translationId, scope, false); unwatch(); }); } }, true); }; } else { return function () { var updateTranslations = function () { if (scope.translationId && scope.interpolateParams) { $translate(scope.translationId, scope.interpolateParams, translateInterpolation).then(function (translation) { applyElementContent(translation, scope, true); }, function (translationId) { applyElementContent(translationId, scope, false); }); } }; scope.$watch('interpolateParams', updateTranslations, true); scope.$watch('translationId', updateTranslations); }; } }(); var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslationFn); updateTranslationFn(); scope.$on('$destroy', unbind); }; } }; } ]); angular.module('pascalprecht.translate').directive('translateCloak', [ '$rootScope', '$translate', function ($rootScope, $translate) { return { compile: function (tElement) { var applyCloak = function () { tElement.addClass($translate.cloakClassName()); }, removeCloak = function () { tElement.removeClass($translate.cloakClassName()); }, removeListener = $rootScope.$on('$translateChangeEnd', function () { removeCloak(); removeListener(); removeListener = null; }); applyCloak(); return function linkFn(scope, iElement, iAttr) { if (iAttr.translateCloak && iAttr.translateCloak.length) { iAttr.$observe('translateCloak', function (translationId) { $translate(translationId).then(removeCloak, applyCloak); }); } }; } }; } ]); angular.module('pascalprecht.translate').filter('translate', [ '$parse', '$translate', function ($parse, $translate) { var translateFilter = function (translationId, interpolateParams, interpolation) { if (!angular.isObject(interpolateParams)) { interpolateParams = $parse(interpolateParams)(this); } return $translate.instant(translationId, interpolateParams, interpolation); }; translateFilter.$stateful = true; return translateFilter; } ]); ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css ================================================ /*! * Stylesheet for the Date Range Picker, for use with Bootstrap 3.x * * Copyright 2013 Dan Grossman ( http://www.dangrossman.info ) * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Built for http://www.improvely.com */ .daterangepicker.dropdown-menu { max-width: none; z-index: 3000; } .daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar { float: left; margin: 4px; } .daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar { float: right; margin: 4px; } .daterangepicker .ranges { width: 160px; text-align: left; } .daterangepicker .ranges .range_inputs>div { float: left; } .daterangepicker .ranges .range_inputs>div:nth-child(2) { padding-left: 11px; } .daterangepicker .calendar { display: none; max-width: 270px; } .daterangepicker.show-calendar .calendar { display: block; } .daterangepicker .calendar.single .calendar-date { border: none; } .daterangepicker .calendar th, .daterangepicker .calendar td { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; white-space: nowrap; text-align: center; min-width: 32px; } .daterangepicker .daterangepicker_start_input label, .daterangepicker .daterangepicker_end_input label { color: #333; display: block; font-size: 11px; font-weight: normal; height: 20px; line-height: 20px; margin-bottom: 2px; text-shadow: #fff 1px 1px 0px; text-transform: uppercase; width: 74px; } .daterangepicker .ranges input { font-size: 11px; } .daterangepicker .ranges .input-mini { background-color: #eee; border: 1px solid #ccc; border-radius: 4px; color: #555; display: block; font-size: 11px; height: 30px; line-height: 30px; vertical-align: middle; margin: 0 0 10px 0; padding: 0 6px; width: 74px; } .daterangepicker .ranges ul { list-style: none; margin: 0; padding: 0; } .daterangepicker .ranges li { font-size: 13px; background: #f5f5f5; border: 1px solid #f5f5f5; color: #08c; padding: 3px 12px; margin-bottom: 8px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; cursor: pointer; } .daterangepicker .ranges li.active, .daterangepicker .ranges li:hover { background: #08c; border: 1px solid #08c; color: #fff; } .daterangepicker .calendar-date { border: 1px solid #ddd; padding: 4px; border-radius: 4px; background: #fff; } .daterangepicker .calendar-time { text-align: center; margin: 8px auto 0 auto; line-height: 30px; } .daterangepicker { position: absolute; background: #fff; top: 100px; left: 20px; padding: 4px; margin-top: 1px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .daterangepicker.opensleft:before { position: absolute; top: -7px; right: 9px; display: inline-block; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-left: 7px solid transparent; border-bottom-color: rgba(0, 0, 0, 0.2); content: ''; } .daterangepicker.opensleft:after { position: absolute; top: -6px; right: 10px; display: inline-block; border-right: 6px solid transparent; border-bottom: 6px solid #fff; border-left: 6px solid transparent; content: ''; } .daterangepicker.opensright:before { position: absolute; top: -7px; left: 9px; display: inline-block; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-left: 7px solid transparent; border-bottom-color: rgba(0, 0, 0, 0.2); content: ''; } .daterangepicker.opensright:after { position: absolute; top: -6px; left: 10px; display: inline-block; border-right: 6px solid transparent; border-bottom: 6px solid #fff; border-left: 6px solid transparent; content: ''; } .daterangepicker table { width: 100%; margin: 0; } .daterangepicker td, .daterangepicker th { text-align: center; width: 20px; height: 20px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; cursor: pointer; white-space: nowrap; } .daterangepicker td.off { color: #999; } .daterangepicker td.disabled { color: #999; } .daterangepicker td.available:hover, .daterangepicker th.available:hover { background: #eee; } .daterangepicker td.in-range { background: #ebf4f8; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .daterangepicker td.active, .daterangepicker td.active:hover { background-color: #357ebd; border-color: #3071a9; color: #fff; } .daterangepicker td.week, .daterangepicker th.week { font-size: 80%; color: #ccc; } .daterangepicker select.monthselect, .daterangepicker select.yearselect { font-size: 12px; padding: 1px; height: auto; margin: 0; cursor: default; } .daterangepicker select.monthselect { margin-right: 2%; width: 56%; } .daterangepicker select.yearselect { width: 40%; } .daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.ampmselect { width: 50px; margin-bottom: 0; } .daterangepicker_start_input { float: left; } .daterangepicker_end_input { float: left; padding-left: 11px } .daterangepicker th.month { width: auto; } ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js ================================================ /** * @version: 1.3.7 * @author: Dan Grossman http://www.dangrossman.info/ * @date: 2014-04-29 * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved. * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0 * @website: http://www.improvely.com/ */ !function ($, moment) { var DateRangePicker = function (element, options, cb) { // by default, the daterangepicker element is placed at the bottom of HTML body this.parentEl = 'body'; //element that triggered the date range picker this.element = $(element); //create the picker HTML object var DRPTemplate = ''; //custom options if (typeof options !== 'object' || options === null) options = {}; this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl); this.container = $(DRPTemplate).appendTo(this.parentEl); this.setOptions(options, cb); //apply CSS classes and labels to buttons var c = this.container; $.each(this.buttonClasses, function (idx, val) { c.find('button').addClass(val); }); this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel); this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel); if (this.applyClass.length) this.container.find('.applyBtn').addClass(this.applyClass); if (this.cancelClass.length) this.container.find('.cancelBtn').addClass(this.cancelClass); this.container.find('.applyBtn').html(this.locale.applyLabel); this.container.find('.cancelBtn').html(this.locale.cancelLabel); //event listeners this.container.find('.calendar') .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this)) .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this)) .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this)) .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this)) .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this)) .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this)) .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this)) .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this)); this.container.find('.ranges') .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this)) .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this)) .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this)) .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this)) .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this)) .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this)); if (this.element.is('input')) { this.element.on({ 'click.daterangepicker': $.proxy(this.show, this), 'focus.daterangepicker': $.proxy(this.show, this), 'keyup.daterangepicker': $.proxy(this.updateFromControl, this) }); } else { this.element.on('click.daterangepicker', $.proxy(this.toggle, this)); } }; DateRangePicker.prototype = { constructor: DateRangePicker, setOptions: function(options, callback) { this.startDate = moment().startOf('day'); this.endDate = moment().endOf('day'); this.minDate = false; this.maxDate = false; this.dateLimit = false; this.showDropdowns = false; this.showWeekNumbers = false; this.timePicker = false; this.timePickerIncrement = 30; this.timePicker12Hour = true; this.singleDatePicker = false; this.ranges = {}; this.opens = 'right'; if (this.element.hasClass('pull-right')) this.opens = 'left'; this.buttonClasses = ['btn', 'btn-small']; this.applyClass = 'btn-success'; this.cancelClass = 'btn-default'; this.format = 'MM/DD/YYYY'; this.separator = ' - '; this.locale = { applyLabel: 'Apply', cancelLabel: 'Cancel', fromLabel: 'From', toLabel: 'To', weekLabel: 'W', customRangeLabel: 'Custom Range', daysOfWeek: moment()._lang._weekdaysMin.slice(), monthNames: moment()._lang._monthsShort.slice(), firstDay: 0 }; this.cb = function () { }; if (typeof options.format === 'string') this.format = options.format; if (typeof options.separator === 'string') this.separator = options.separator; if (typeof options.startDate === 'string') this.startDate = moment(options.startDate, this.format); if (typeof options.endDate === 'string') this.endDate = moment(options.endDate, this.format); if (typeof options.minDate === 'string') this.minDate = moment(options.minDate, this.format); if (typeof options.maxDate === 'string') this.maxDate = moment(options.maxDate, this.format); if (typeof options.startDate === 'object') this.startDate = moment(options.startDate); if (typeof options.endDate === 'object') this.endDate = moment(options.endDate); if (typeof options.minDate === 'object') this.minDate = moment(options.minDate); if (typeof options.maxDate === 'object') this.maxDate = moment(options.maxDate); if (typeof options.applyClass === 'string') this.applyClass = options.applyClass; if (typeof options.cancelClass === 'string') this.cancelClass = options.cancelClass; if (typeof options.dateLimit === 'object') this.dateLimit = options.dateLimit; // update day names order to firstDay if (typeof options.locale === 'object') { if (typeof options.locale.daysOfWeek === 'object') { // Create a copy of daysOfWeek to avoid modification of original // options object for reusability in multiple daterangepicker instances this.locale.daysOfWeek = options.locale.daysOfWeek.slice(); } if (typeof options.locale.monthNames === 'object') { this.locale.monthNames = options.locale.monthNames.slice(); } if (typeof options.locale.firstDay === 'number') { this.locale.firstDay = options.locale.firstDay; var iterator = options.locale.firstDay; while (iterator > 0) { this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift()); iterator--; } } if (typeof options.locale.applyLabel === 'string') { this.locale.applyLabel = options.locale.applyLabel; } if (typeof options.locale.cancelLabel === 'string') { this.locale.cancelLabel = options.locale.cancelLabel; } if (typeof options.locale.fromLabel === 'string') { this.locale.fromLabel = options.locale.fromLabel; } if (typeof options.locale.toLabel === 'string') { this.locale.toLabel = options.locale.toLabel; } if (typeof options.locale.weekLabel === 'string') { this.locale.weekLabel = options.locale.weekLabel; } if (typeof options.locale.customRangeLabel === 'string') { this.locale.customRangeLabel = options.locale.customRangeLabel; } } if (typeof options.opens === 'string') this.opens = options.opens; if (typeof options.showWeekNumbers === 'boolean') { this.showWeekNumbers = options.showWeekNumbers; } if (typeof options.buttonClasses === 'string') { this.buttonClasses = [options.buttonClasses]; } if (typeof options.buttonClasses === 'object') { this.buttonClasses = options.buttonClasses; } if (typeof options.showDropdowns === 'boolean') { this.showDropdowns = options.showDropdowns; } if (typeof options.singleDatePicker === 'boolean') { this.singleDatePicker = options.singleDatePicker; } if (typeof options.timePicker === 'boolean') { this.timePicker = options.timePicker; } if (typeof options.timePickerIncrement === 'number') { this.timePickerIncrement = options.timePickerIncrement; } if (typeof options.timePicker12Hour === 'boolean') { this.timePicker12Hour = options.timePicker12Hour; } var start, end, range; //if no start/end dates set, check if an input element contains initial values if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') { if ($(this.element).is('input[type=text]')) { var val = $(this.element).val(); var split = val.split(this.separator); start = end = null; if (split.length == 2) { start = moment(split[0], this.format); end = moment(split[1], this.format); } else if (this.singleDatePicker) { start = moment(val, this.format); end = moment(val, this.format); } if (start !== null && end !== null) { this.startDate = start; this.endDate = end; } } } if (typeof options.ranges === 'object') { for (range in options.ranges) { start = moment(options.ranges[range][0]); end = moment(options.ranges[range][1]); // If we have a min/max date set, bound this range // to it, but only if it would otherwise fall // outside of the min/max. if (this.minDate && start.isBefore(this.minDate)) start = moment(this.minDate); if (this.maxDate && end.isAfter(this.maxDate)) end = moment(this.maxDate); // If the end of the range is before the minimum (if min is set) OR // the start of the range is after the max (also if set) don't display this // range option. if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) { continue; } this.ranges[range] = [start, end]; } var list = '
      '; for (range in this.ranges) { list += '
    • ' + range + '
    • '; } list += '
    • ' + this.locale.customRangeLabel + '
    • '; list += '
    '; this.container.find('.ranges ul').remove(); this.container.find('.ranges').prepend(list); } if (typeof callback === 'function') { this.cb = callback; } if (!this.timePicker) { this.startDate = this.startDate.startOf('day'); this.endDate = this.endDate.endOf('day'); } if (this.singleDatePicker) { this.opens = 'right'; this.container.find('.calendar.right').show(); this.container.find('.calendar.left').hide(); this.container.find('.ranges').hide(); if (!this.container.find('.calendar.right').hasClass('single')) this.container.find('.calendar.right').addClass('single'); } else { this.container.find('.calendar.right').removeClass('single'); this.container.find('.ranges').show(); } this.oldStartDate = this.startDate.clone(); this.oldEndDate = this.endDate.clone(); this.oldChosenLabel = this.chosenLabel; this.leftCalendar = { month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]), calendar: [] }; this.rightCalendar = { month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]), calendar: [] }; if (this.opens == 'right') { //swap calendar positions var left = this.container.find('.calendar.left'); var right = this.container.find('.calendar.right'); left.removeClass('left').addClass('right'); right.removeClass('right').addClass('left'); } if (typeof options.ranges === 'undefined' && !this.singleDatePicker) { this.container.addClass('show-calendar'); } this.container.addClass('opens' + this.opens); this.updateView(); this.updateCalendars(); }, setStartDate: function(startDate) { if (typeof startDate === 'string') this.startDate = moment(startDate, this.format); if (typeof startDate === 'object') this.startDate = moment(startDate); if (!this.timePicker) this.startDate = this.startDate.startOf('day'); this.oldStartDate = this.startDate.clone(); this.updateView(); this.updateCalendars(); }, setEndDate: function(endDate) { if (typeof endDate === 'string') this.endDate = moment(endDate, this.format); if (typeof endDate === 'object') this.endDate = moment(endDate); if (!this.timePicker) this.endDate = this.endDate.endOf('day'); this.oldEndDate = this.endDate.clone(); this.updateView(); this.updateCalendars(); }, updateView: function () { this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()); this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()); this.updateFormInputs(); }, updateFormInputs: function () { this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format)); this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format)); if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) { this.container.find('button.applyBtn').removeAttr('disabled'); } else { this.container.find('button.applyBtn').attr('disabled', 'disabled'); } }, updateFromControl: function () { if (!this.element.is('input')) return; if (!this.element.val().length) return; var dateString = this.element.val().split(this.separator), start = null, end = null; if(dateString.length === 2) { start = moment(dateString[0], this.format); end = moment(dateString[1], this.format); } if (this.singleDatePicker || start === null || end === null) { start = moment(this.element.val(), this.format); end = start; } if (end.isBefore(start)) return; this.oldStartDate = this.startDate.clone(); this.oldEndDate = this.endDate.clone(); this.startDate = start; this.endDate = end; if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) this.notify(); this.updateCalendars(); }, notify: function () { this.updateView(); this.cb(this.startDate, this.endDate, this.chosenLabel); }, move: function () { var parentOffset = { top: 0, left: 0 }; if (!this.parentEl.is('body')) { parentOffset = { top: this.parentEl.offset().top - this.parentEl.scrollTop(), left: this.parentEl.offset().left - this.parentEl.scrollLeft() }; } if (this.opens == 'left') { this.container.css({ top: this.element.offset().top + this.element.outerHeight() - parentOffset.top, right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left, left: 'auto' }); if (this.container.offset().left < 0) { this.container.css({ right: 'auto', left: 9 }); } } else { this.container.css({ top: this.element.offset().top + this.element.outerHeight() - parentOffset.top, left: this.element.offset().left - parentOffset.left, right: 'auto' }); if (this.container.offset().left + this.container.outerWidth() > $(window).width()) { this.container.css({ left: 'auto', right: 0 }); } } }, toggle: function (e) { if (this.element.hasClass('active')) { this.hide(); } else { this.show(); } }, show: function (e) { this.element.addClass('active'); this.container.show(); this.move(); // Create a click proxy that is private to this instance of datepicker, for unbinding this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this); // Bind global datepicker mousedown for hiding and $(document) .on('mousedown.daterangepicker', this._outsideClickProxy) // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy) // and also close when focus changes to outside the picker (eg. tabbing between controls) .on('focusin.daterangepicker', this._outsideClickProxy); this.element.trigger('show.daterangepicker', this); }, outsideClick: function (e) { var target = $(e.target); // if the page is clicked anywhere except within the daterangerpicker/button // itself then call this.hide() if ( target.closest(this.element).length || target.closest(this.container).length || target.closest('.calendar-date').length ) return; this.hide(); }, hide: function (e) { $(document) .off('mousedown.daterangepicker', this._outsideClickProxy) .off('click.daterangepicker', this._outsideClickProxy) .off('focusin.daterangepicker', this._outsideClickProxy); this.element.removeClass('active'); this.container.hide(); if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) this.notify(); this.oldStartDate = this.startDate.clone(); this.oldEndDate = this.endDate.clone(); this.element.trigger('hide.daterangepicker', this); }, enterRange: function (e) { // mouse pointer has entered a range label var label = e.target.innerHTML; if (label == this.locale.customRangeLabel) { this.updateView(); } else { var dates = this.ranges[label]; this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format)); this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format)); } }, showCalendars: function() { this.container.addClass('show-calendar'); this.move(); }, hideCalendars: function() { this.container.removeClass('show-calendar'); }, updateInputText: function() { if (this.element.is('input') && !this.singleDatePicker) { this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format)); } else if (this.element.is('input')) { this.element.val(this.startDate.format(this.format)); } }, clickRange: function (e) { var label = e.target.innerHTML; this.chosenLabel = label; if (label == this.locale.customRangeLabel) { this.showCalendars(); } else { var dates = this.ranges[label]; this.startDate = dates[0]; this.endDate = dates[1]; if (!this.timePicker) { this.startDate.startOf('day'); this.endDate.endOf('day'); } this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute()); this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute()); this.updateCalendars(); this.updateInputText(); this.hideCalendars(); this.hide(); this.element.trigger('apply.daterangepicker', this); } }, clickPrev: function (e) { var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.leftCalendar.month.subtract('month', 1); } else { this.rightCalendar.month.subtract('month', 1); } this.updateCalendars(); }, clickNext: function (e) { var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.leftCalendar.month.add('month', 1); } else { this.rightCalendar.month.add('month', 1); } this.updateCalendars(); }, enterDate: function (e) { var title = $(e.target).attr('data-title'); var row = title.substr(1, 1); var col = title.substr(3, 1); var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format)); } else { this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format)); } }, clickDate: function (e) { var title = $(e.target).attr('data-title'); var row = title.substr(1, 1); var col = title.substr(3, 1); var cal = $(e.target).parents('.calendar'); var startDate, endDate; if (cal.hasClass('left')) { startDate = this.leftCalendar.calendar[row][col]; endDate = this.endDate; if (typeof this.dateLimit === 'object') { var maxDate = moment(startDate).add(this.dateLimit).startOf('day'); if (endDate.isAfter(maxDate)) { endDate = maxDate; } } } else { startDate = this.startDate; endDate = this.rightCalendar.calendar[row][col]; if (typeof this.dateLimit === 'object') { var minDate = moment(endDate).subtract(this.dateLimit).startOf('day'); if (startDate.isBefore(minDate)) { startDate = minDate; } } } if (this.singleDatePicker && cal.hasClass('left')) { endDate = startDate.clone(); } else if (this.singleDatePicker && cal.hasClass('right')) { startDate = endDate.clone(); } cal.find('td').removeClass('active'); if (startDate.isSame(endDate) || startDate.isBefore(endDate)) { $(e.target).addClass('active'); this.startDate = startDate; this.endDate = endDate; this.chosenLabel = this.locale.customRangeLabel; } else if (startDate.isAfter(endDate)) { $(e.target).addClass('active'); var difference = this.endDate.diff(this.startDate); this.startDate = startDate; this.endDate = moment(startDate).add('ms', difference); this.chosenLabel = this.locale.customRangeLabel; } this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()); this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()); this.updateCalendars(); if (!this.timePicker) endDate.endOf('day'); if (this.singleDatePicker) this.clickApply(); }, clickApply: function (e) { this.updateInputText(); this.hide(); this.element.trigger('apply.daterangepicker', this); }, clickCancel: function (e) { this.startDate = this.oldStartDate; this.endDate = this.oldEndDate; this.chosenLabel = this.oldChosenLabel; this.updateView(); this.updateCalendars(); this.hide(); this.element.trigger('cancel.daterangepicker', this); }, updateMonthYear: function (e) { var isLeft = $(e.target).closest('.calendar').hasClass('left'), leftOrRight = isLeft ? 'left' : 'right', cal = this.container.find('.calendar.'+leftOrRight); // Month must be Number for new moment versions var month = parseInt(cal.find('.monthselect').val(), 10); var year = cal.find('.yearselect').val(); this[leftOrRight+'Calendar'].month.month(month).year(year); this.updateCalendars(); }, updateTime: function(e) { var cal = $(e.target).closest('.calendar'), isLeft = cal.hasClass('left'); var hour = parseInt(cal.find('.hourselect').val(), 10); var minute = parseInt(cal.find('.minuteselect').val(), 10); if (this.timePicker12Hour) { var ampm = cal.find('.ampmselect').val(); if (ampm === 'PM' && hour < 12) hour += 12; if (ampm === 'AM' && hour === 12) hour = 0; } if (isLeft) { var start = this.startDate.clone(); start.hour(hour); start.minute(minute); this.startDate = start; this.leftCalendar.month.hour(hour).minute(minute); } else { var end = this.endDate.clone(); end.hour(hour); end.minute(minute); this.endDate = end; this.rightCalendar.month.hour(hour).minute(minute); } this.updateCalendars(); }, updateCalendars: function () { this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left'); this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right'); this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate)); this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate)); this.container.find('.ranges li').removeClass('active'); var customRange = true; var i = 0; for (var range in this.ranges) { if (this.timePicker) { if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) { customRange = false; this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')') .addClass('active').html(); } } else { //ignore times when comparing dates if time picker is not enabled if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) { customRange = false; this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')') .addClass('active').html(); } } i++; } if (customRange) { this.chosenLabel = this.container.find('.ranges li:last') .addClass('active').html(); } }, buildCalendar: function (month, year, hour, minute, side) { var firstDay = moment([year, month, 1]); var lastMonth = moment(firstDay).subtract('month', 1).month(); var lastYear = moment(firstDay).subtract('month', 1).year(); var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth(); var dayOfWeek = firstDay.day(); var i; //initialize a 6 rows x 7 columns array for the calendar var calendar = []; for (i = 0; i < 6; i++) { calendar[i] = []; } //populate the calendar with date objects var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1; if (startDay > daysInLastMonth) startDay -= 7; if (dayOfWeek == this.locale.firstDay) startDay = daysInLastMonth - 6; var curDate = moment([lastYear, lastMonth, startDay, 12, minute]); var col, row; for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) { if (i > 0 && col % 7 === 0) { col = 0; row++; } calendar[row][col] = curDate.clone().hour(hour); curDate.hour(12); } return calendar; }, renderDropdowns: function (selected, minDate, maxDate) { var currentMonth = selected.month(); var monthHtml = '"; var currentYear = selected.year(); var maxYear = (maxDate && maxDate.year()) || (currentYear + 5); var minYear = (minDate && minDate.year()) || (currentYear - 50); var yearHtml = ''; return monthHtml + yearHtml; }, renderCalendar: function (calendar, selected, minDate, maxDate) { var html = '
    '; html += ''; html += ''; html += ''; // add empty cell for week number if (this.showWeekNumbers) html += ''; if (!minDate || minDate.isBefore(calendar[1][1])) { html += ''; } else { html += ''; } var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY"); if (this.showDropdowns) { dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate); } html += ''; if (!maxDate || maxDate.isAfter(calendar[1][1])) { html += ''; } else { html += ''; } html += ''; html += ''; // add week number label if (this.showWeekNumbers) html += ''; $.each(this.locale.daysOfWeek, function (index, dayOfWeek) { html += ''; }); html += ''; html += ''; html += ''; for (var row = 0; row < 6; row++) { html += ''; // add week number if (this.showWeekNumbers) html += ''; for (var col = 0; col < 7; col++) { var cname = 'available '; cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off'; if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) { cname = ' off disabled '; } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) { cname += ' active '; if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) { cname += ' start-date '; } if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) { cname += ' end-date '; } } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) { cname += ' in-range '; if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; } if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; } } var title = 'r' + row + 'c' + col; html += ''; } html += ''; } html += ''; html += '
    ' + dateHtml + '
    ' + this.locale.weekLabel + '' + dayOfWeek + '
    ' + calendar[row][0].week() + '' + calendar[row][col].date() + '
    '; html += '
    '; var i; if (this.timePicker) { html += '
    '; html += ' : '; html += ' '; if (this.timePicker12Hour) { html += ''; } html += '
    '; } return html; }, remove: function() { this.container.remove(); this.element.off('.daterangepicker'); this.element.removeData('daterangepicker'); } }; $.fn.daterangepicker = function (options, cb) { this.each(function () { var el = $(this); if (el.data('daterangepicker')) el.data('daterangepicker').remove(); el.data('daterangepicker', new DateRangePicker(el, options, cb)); }); return this; }; }(window.jQuery, window.moment); ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/jquery.autogrow-textarea.js ================================================ (function($) { /** * Auto-growing textareas; technique ripped from Facebook * * http://github.com/jaz303/jquery-grab-bag/tree/master/javascripts/jquery.autogrow-textarea.js */ $.fn.autogrow = function(options) { return this.filter('textarea').each(function() { var self = this; var $self = $(self); var minHeight = $self.height(); var noFlickerPad = $self.hasClass('autogrow-short') ? 0 : parseInt($self.css('lineHeight')) || 0; var shadow = $('
    ').css({ position: 'absolute', top: -10000, left: -10000, width: $self.width(), fontSize: $self.css('fontSize'), fontFamily: $self.css('fontFamily'), fontWeight: $self.css('fontWeight'), lineHeight: $self.css('lineHeight'), resize: 'none', 'word-wrap': 'break-word' }).appendTo(document.body); var update = function(event) { var times = function(string, number) { for (var i=0, r=''; i/g, '>') .replace(/&/g, '&') .replace(/\n$/, '
     ') .replace(/\n/g, '
    ') .replace(/ {2,}/g, function(space){ return times(' ', space.length - 1) + ' ' }); // Did enter get pressed? Resize in this keydown event so that the flicker doesn't occur. if (event && event.data && event.data.event === 'keydown' && event.keyCode === 13) { val += '
    '; } shadow.css('width', $self.width()); shadow.html(val + (noFlickerPad === 0 ? '...' : '')); // Append '...' to resize pre-emptively. $self.height(Math.max(shadow.height() + noFlickerPad, minHeight)); } $self.change(update).keyup(update).keydown({event:'keydown'},update); $(window).resize(update); update(); }); }; })(jQuery); ================================================ FILE: open-layui-web/src/main/view/static/editor-app/libs/ng-grid-2.0.7-min.js ================================================ (function(e,t){"use strict";var n=6,o=4,i="asc",r="desc",l="_ng_field_",a="_ng_depth_",s="_ng_hidden_",c="_ng_column_",g=/CUSTOM_FILTERS/g,d=/COL_FIELD/g,u=/DISPLAY_CELL_TEMPLATE/g,f=/EDITABLE_CELL_TEMPLATE/g,h=/<.+>/;e.ngGrid={},e.ngGrid.i18n={},angular.module("ngGrid.services",[]);var p=angular.module("ngGrid.directives",[]),m=angular.module("ngGrid.filters",[]);angular.module("ngGrid",["ngGrid.services","ngGrid.directives","ngGrid.filters"]);var v=function(e,t,o,i){if(void 0===e.selectionProvider.selectedItems)return!0;var r,l=o.which||o.keyCode,a=!1,s=!1,c=void 0===e.selectionProvider.lastClickedRow?1:e.selectionProvider.lastClickedRow.rowIndex,g=e.columns.filter(function(e){return e.visible}),d=e.columns.filter(function(e){return e.pinned});if(e.col&&(r=g.indexOf(e.col)),37!==l&&38!==l&&39!==l&&40!==l&&9!==l&&13!==l)return!0;if(e.enableCellSelection){9===l&&o.preventDefault();var u=e.showSelectionCheckbox?1===e.col.index:0===e.col.index,f=1===e.$index||0===e.$index,h=e.$index===e.renderedColumns.length-1||e.$index===e.renderedColumns.length-2,p=g.indexOf(e.col)===g.length-1,m=d.indexOf(e.col)===d.length-1;if(37===l||9===l&&o.shiftKey){var v=0;u||(r-=1),f?u&&9===l&&o.shiftKey?(v=i.$canvas.width(),r=g.length-1,s=!0):v=i.$viewport.scrollLeft()-e.col.width:d.length>0&&(v=i.$viewport.scrollLeft()-g[r].width),i.$viewport.scrollLeft(v)}else(39===l||9===l&&!o.shiftKey)&&(h?p&&9===l&&!o.shiftKey?(i.$viewport.scrollLeft(0),r=e.showSelectionCheckbox?1:0,a=!0):i.$viewport.scrollLeft(i.$viewport.scrollLeft()+e.col.width):m&&i.$viewport.scrollLeft(0),p||(r+=1))}var w;w=e.configGroups.length>0?i.rowFactory.parsedData.filter(function(e){return!e.isAggRow}):i.filteredRows;var C=0;if(0!==c&&(38===l||13===l&&o.shiftKey||9===l&&o.shiftKey&&s)?C=-1:c!==w.length-1&&(40===l||13===l&&!o.shiftKey||9===l&&a)&&(C=1),C){var b=w[c+C];b.beforeSelectionChange(b,o)&&(b.continueSelection(o),e.$emit("ngGridEventDigestGridParent"),e.selectionProvider.lastClickedRow.renderedRowIndex>=e.renderedRows.length-n-2?i.$viewport.scrollTop(i.$viewport.scrollTop()+e.rowHeight):n+2>=e.selectionProvider.lastClickedRow.renderedRowIndex&&i.$viewport.scrollTop(i.$viewport.scrollTop()-e.rowHeight))}return e.enableCellSelection&&setTimeout(function(){e.domAccessProvider.focusCellElement(e,e.renderedColumns.indexOf(g[r]))},3),!1};String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length>>>0,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=t);t>n;n++)if(n in this&&this[n]===e)return n;return-1}),Array.prototype.filter||(Array.prototype.filter=function(e){var t=Object(this),n=t.length>>>0;if("function"!=typeof e)throw new TypeError;for(var o=[],i=arguments[1],r=0;n>r;r++)if(r in t){var l=t[r];e.call(i,l,r,t)&&o.push(l)}return o}),m.filter("checkmark",function(){return function(e){return e?"✔":"✘"}}),m.filter("ngColumns",function(){return function(e){return e.filter(function(e){return!e.isAggCol})}}),angular.module("ngGrid.services").factory("$domUtilityService",["$utilityService",function(e){var n={},o={},i=function(){var e=t("
    ");e.appendTo("body"),e.height(100).width(100).css("position","absolute").css("overflow","scroll"),e.append('
    '),n.ScrollH=e.height()-e[0].clientHeight,n.ScrollW=e.width()-e[0].clientWidth,e.empty(),e.attr("style",""),e.append('M'),n.LetterW=e.children().first().width(),e.remove()};return n.eventStorage={},n.AssignGridContainers=function(e,o,i){i.$root=t(o),i.$topPanel=i.$root.find(".ngTopPanel"),i.$groupPanel=i.$root.find(".ngGroupPanel"),i.$headerContainer=i.$topPanel.find(".ngHeaderContainer"),e.$headerContainer=i.$headerContainer,i.$headerScroller=i.$topPanel.find(".ngHeaderScroller"),i.$headers=i.$headerScroller.children(),i.$viewport=i.$root.find(".ngViewport"),i.$canvas=i.$viewport.find(".ngCanvas"),i.$footerPanel=i.$root.find(".ngFooterPanel"),e.$watch(function(){return i.$viewport.scrollLeft()},function(e){return i.$headerContainer.scrollLeft(e)}),n.UpdateGridLayout(e,i)},n.getRealWidth=function(e){var n=0,o={visibility:"hidden",display:"block"},i=e.parents().andSelf().not(":visible");return t.swap(i[0],o,function(){n=e.outerWidth()}),n},n.UpdateGridLayout=function(e,t){var o=t.$viewport.scrollTop();t.elementDims.rootMaxW=t.$root.width(),t.$root.is(":hidden")&&(t.elementDims.rootMaxW=n.getRealWidth(t.$root)),t.elementDims.rootMaxH=t.$root.height(),t.refreshDomSizes(),e.adjustScrollTop(o,!0)},n.numberOfGrids=0,n.BuildStyles=function(o,i,r){var l,a=i.config.rowHeight,s=i.$styleSheet,c=i.gridId,g=o.columns,d=0;s||(s=t("#"+c),s[0]||(s=t("').appendTo('head'); } }; // Construct trees style based on user options Tree.prototype.buildStyle = function () { var style = '.node-' + this.elementId + '{'; if (this.options.color) { style += 'color:' + this.options.color + ';'; } if (this.options.backColor) { style += 'background-color:' + this.options.backColor + ';'; } if (!this.options.showBorder) { style += 'border:none;'; } else if (this.options.borderColor) { style += 'border:1px solid ' + this.options.borderColor + ';'; } style += '}'; if (this.options.onhoverColor) { style += '.node-' + this.elementId + ':not(.node-disabled):hover{' + 'background-color:' + this.options.onhoverColor + ';' + '}'; } return this.css + style; }; Tree.prototype.template = { list: '
      ', item: '
    • ', indent: '', icon: '', link: '', badge: '' }; Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}' /** Returns a single node object that matches the given node id. @param {Number} nodeId - A node's unique identifier @return {Object} node - Matching node */ Tree.prototype.getNode = function (nodeId) { return this.nodes[nodeId]; }; /** Returns the parent node of a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id @returns {Object} node - The parent node */ Tree.prototype.getParent = function (identifier) { var node = this.identifyNode(identifier); return this.nodes[node.parentId]; }; /** Returns an array of sibling nodes for a given node, if valid otherwise returns undefined. @param {Object|Number} identifier - A valid node or node id @returns {Array} nodes - Sibling nodes */ Tree.prototype.getSiblings = function (identifier) { var node = this.identifyNode(identifier); var parent = this.getParent(node); var nodes = parent ? parent.nodes : this.tree; return nodes.filter(function (obj) { return obj.nodeId !== node.nodeId; }); }; /** Returns an array of selected nodes. @returns {Array} nodes - Selected nodes */ Tree.prototype.getSelected = function () { return this.findNodes('true', 'g', 'state.selected'); }; /** Returns an array of unselected nodes. @returns {Array} nodes - Unselected nodes */ Tree.prototype.getUnselected = function () { return this.findNodes('false', 'g', 'state.selected'); }; /** Returns an array of expanded nodes. @returns {Array} nodes - Expanded nodes */ Tree.prototype.getExpanded = function () { return this.findNodes('true', 'g', 'state.expanded'); }; /** Returns an array of collapsed nodes. @returns {Array} nodes - Collapsed nodes */ Tree.prototype.getCollapsed = function () { return this.findNodes('false', 'g', 'state.expanded'); }; /** Returns an array of checked nodes. @returns {Array} nodes - Checked nodes */ Tree.prototype.getChecked = function () { return this.findNodes('true', 'g', 'state.checked'); }; /** Returns an array of unchecked nodes. @returns {Array} nodes - Unchecked nodes */ Tree.prototype.getUnchecked = function () { return this.findNodes('false', 'g', 'state.checked'); }; /** Returns an array of disabled nodes. @returns {Array} nodes - Disabled nodes */ Tree.prototype.getDisabled = function () { return this.findNodes('true', 'g', 'state.disabled'); }; /** Returns an array of enabled nodes. @returns {Array} nodes - Enabled nodes */ Tree.prototype.getEnabled = function () { return this.findNodes('false', 'g', 'state.disabled'); }; /** Set a node state to selected @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.selectNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setSelectedState(node, true, options); }, this)); this.render(); }; /** Set a node state to unselected @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.unselectNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setSelectedState(node, false, options); }, this)); this.render(); }; /** Toggles a node selected state; selecting if unselected, unselecting if selected. @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.toggleNodeSelected = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleSelectedState(node, options); }, this)); this.render(); }; /** Collapse all tree nodes @param {optional Object} options */ Tree.prototype.collapseAll = function (options) { var identifiers = this.findNodes('true', 'g', 'state.expanded'); this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, false, options); }, this)); this.render(); }; /** Collapse a given tree node @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.collapseNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, false, options); }, this)); this.render(); }; /** Expand all tree nodes @param {optional Object} options */ Tree.prototype.expandAll = function (options) { options = $.extend({}, _default.options, options); if (options && options.levels) { this.expandLevels(this.tree, options.levels, options); } else { var identifiers = this.findNodes('false', 'g', 'state.expanded'); this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); }, this)); } this.render(); }; /** Expand a given tree node @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.expandNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setExpandedState(node, true, options); if (node.nodes && (options && options.levels)) { this.expandLevels(node.nodes, options.levels-1, options); } }, this)); this.render(); }; Tree.prototype.expandLevels = function (nodes, level, options) { options = $.extend({}, _default.options, options); $.each(nodes, $.proxy(function (index, node) { this.setExpandedState(node, (level > 0) ? true : false, options); if (node.nodes) { this.expandLevels(node.nodes, level-1, options); } }, this)); }; /** Reveals a given tree node, expanding the tree from node to root. @param {Object|Number|Array} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.revealNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { var parentNode = this.getParent(node); while (parentNode) { this.setExpandedState(parentNode, true, options); parentNode = this.getParent(parentNode); }; }, this)); this.render(); }; /** Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed. @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.toggleNodeExpanded = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleExpandedState(node, options); }, this)); this.render(); }; /** Check all tree nodes @param {optional Object} options */ Tree.prototype.checkAll = function (options) { var identifiers = this.findNodes('false', 'g', 'state.checked'); this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, true, options); }, this)); this.render(); }; /** Check a given tree node @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.checkNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, true, options); }, this)); this.render(); }; /** Uncheck all tree nodes @param {optional Object} options */ Tree.prototype.uncheckAll = function (options) { var identifiers = this.findNodes('true', 'g', 'state.checked'); this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, false, options); }, this)); this.render(); }; /** Uncheck a given tree node @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.uncheckNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setCheckedState(node, false, options); }, this)); this.render(); }; /** Toggles a nodes checked state; checking if unchecked, unchecking if checked. @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.toggleNodeChecked = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.toggleCheckedState(node, options); }, this)); this.render(); }; /** Disable all tree nodes @param {optional Object} options */ Tree.prototype.disableAll = function (options) { var identifiers = this.findNodes('false', 'g', 'state.disabled'); this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setDisabledState(node, true, options); }, this)); this.render(); }; /** Disable a given tree node @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.disableNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setDisabledState(node, true, options); }, this)); this.render(); }; /** Enable all tree nodes @param {optional Object} options */ Tree.prototype.enableAll = function (options) { var identifiers = this.findNodes('true', 'g', 'state.disabled'); this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setDisabledState(node, false, options); }, this)); this.render(); }; /** Enable a given tree node @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.enableNode = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setDisabledState(node, false, options); }, this)); this.render(); }; /** Toggles a nodes disabled state; disabling is enabled, enabling if disabled. @param {Object|Number} identifiers - A valid node, node id or array of node identifiers @param {optional Object} options */ Tree.prototype.toggleNodeDisabled = function (identifiers, options) { this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) { this.setDisabledState(node, !node.state.disabled, options); }, this)); this.render(); }; /** Common code for processing multiple identifiers */ Tree.prototype.forEachIdentifier = function (identifiers, options, callback) { options = $.extend({}, _default.options, options); if (!(identifiers instanceof Array)) { identifiers = [identifiers]; } $.each(identifiers, $.proxy(function (index, identifier) { callback(this.identifyNode(identifier), options); }, this)); }; /* Identifies a node from either a node id or object */ Tree.prototype.identifyNode = function (identifier) { return ((typeof identifier) === 'number') ? this.nodes[identifier] : identifier; }; /** Searches the tree for nodes (text) that match given criteria @param {String} pattern - A given string to match against @param {optional Object} options - Search criteria options @return {Array} nodes - Matching nodes */ Tree.prototype.search = function (pattern, options) { options = $.extend({}, _default.searchOptions, options); this.clearSearch({ render: false }); var results = []; if (pattern && pattern.length > 0) { if (options.exactMatch) { pattern = '^' + pattern + '$'; } var modifier = 'g'; if (options.ignoreCase) { modifier += 'i'; } results = this.findNodes(pattern, modifier); // Add searchResult property to all matching nodes // This will be used to apply custom styles // and when identifying result to be cleared $.each(results, function (index, node) { node.searchResult = true; }) } // If revealResults, then render is triggered from revealNode // otherwise we just call render. if (options.revealResults) { this.revealNode(results); } else { this.render(); } this.$element.trigger('searchComplete', $.extend(true, {}, results)); return results; }; /** Clears previous search results */ Tree.prototype.clearSearch = function (options) { options = $.extend({}, { render: true }, options); var results = $.each(this.findNodes('true', 'g', 'searchResult'), function (index, node) { node.searchResult = false; }); if (options.render) { this.render(); } this.$element.trigger('searchCleared', $.extend(true, {}, results)); }; /** Find nodes that match a given criteria @param {String} pattern - A given string to match against @param {optional String} modifier - Valid RegEx modifiers @param {optional String} attribute - Attribute to compare pattern against @return {Array} nodes - Nodes that match your criteria */ Tree.prototype.findNodes = function (pattern, modifier, attribute) { modifier = modifier || 'g'; attribute = attribute || 'text'; var _this = this; return $.grep(this.nodes, function (node) { var val = _this.getNodeValue(node, attribute); if (typeof val === 'string') { return val.match(new RegExp(pattern, modifier)); } }); }; /** Recursive find for retrieving nested attributes values All values are return as strings, unless invalid @param {Object} obj - Typically a node, could be any object @param {String} attr - Identifies an object property using dot notation @return {String} value - Matching attributes string representation */ Tree.prototype.getNodeValue = function (obj, attr) { var index = attr.indexOf('.'); if (index > 0) { var _obj = obj[attr.substring(0, index)]; var _attr = attr.substring(index + 1, attr.length); return this.getNodeValue(_obj, _attr); } else { if (obj.hasOwnProperty(attr)) { return obj[attr].toString(); } else { return undefined; } } }; var logError = function (message) { if (window.console) { window.console.error(message); } }; // Prevent against multiple instantiations, // handle updates and method calls $.fn[pluginName] = function (options, args) { var result; this.each(function () { var _this = $.data(this, pluginName); if (typeof options === 'string') { if (!_this) { logError('Not initialized, can not call method : ' + options); } else if (!$.isFunction(_this[options]) || options.charAt(0) === '_') { logError('No such method : ' + options); } else { if (!(args instanceof Array)) { args = [ args ]; } result = _this[options].apply(_this, args); } } else if (typeof options === 'boolean') { result = _this; } else { $.data(this, pluginName, new Tree(this, $.extend(true, {}, options))); } }); return result || this; }; })(jQuery, window, document); ================================================ FILE: open-layui-web/src/main/view/static/js/common.js ================================================ //form序列化为json $.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); $.each(a, function() { if (o[this.name] !== undefined) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); return o; }; //获取url后的参数值 function getUrlParam(key) { var href = window.location.href; var url = href.split("?"); if(url.length <= 1){ return ""; } var params = url[1].split("&"); for(var i=0; i全部"); } $.each(data, function(k, v) { select.append(""); }); return data; } function getDict(type) { var v = sessionStorage[type]; if (v == null || v == "") { $.ajax({ type : 'get', url : '/dicts?type=' + type, async : false, success : function(data) { v = {}; $.each(data, function(i, d) { v[d.k] = d.val; }); sessionStorage[type] = JSON.stringify(v); } }); } return JSON.parse(sessionStorage[type]); } ================================================ FILE: open-layui-web/src/main/view/static/js/index.js ================================================ initMenu(); function initMenu(){ $.ajax({ url:"/permissions/current", type:"get", async:false, success:function(data){ if(!$.isArray(data)){ location.href='/login.html'; return; } var menu = $("#menu"); $.each(data, function(i,item){ var a = $(""); var css = item.css; if(css!=null && css!=""){ a.append(""); } a.append(""+item.name+""); a.attr("lay-id", item.id); var href = item.href; if(href != null && href != ""){ a.attr("href", href); } var li = $("
    • "); // 默认第一项不展开 // if (i == 0) { // li.addClass("layui-nav-itemed"); // } li.append(a); //二级菜单 var child2 = item.child; if(child2 != null && child2.length > 0){ $.each(child2, function(j,item2){ var ca = $(""); ca.attr("data-url", item2.href); ca.attr("lay-id", item2.id); var css2 = item2.css; if(css2!=null && css2!=""){ ca.append(""); } ca.append(""+item2.name+""); var dd = $("
      "); dd.append(ca); var dl = $("
      "); dl.append(dd); li.append(dl); }); } menu.append(li); }); } }); } // 登陆用户头像昵称 showLoginInfo(); function showLoginInfo(){ $.ajax({ type : 'get', url : '/users/current', async : false, success : function(data) { $(".admin-header-user span").text(data.nickname); var pro = window.location.protocol; var host = window.location.host; var domain = pro + "//" + host; var sex = data.sex; var url = data.headImgUrl; if(url == null || url == ""){ if(sex == 1){ url = "/img/avatars/sunny.png"; } else { url = "/img/avatars/1.png"; } url = domain + url; } else { url = domain + "/statics" + url; } var img = $(".admin-header-user img"); img.attr("src", url); } }); } showUnreadNotice(); function showUnreadNotice(){ $.ajax({ type : 'get', url : '/notices/count-unread', success : function(data) { $("[unreadNotice]").each(function(){ if(data>0){ $(this).html(""+data+""); }else{ $(this).html(""); } }); } }); } function logout(){ $.ajax({ type : 'get', url : '/logout', success : function(data) { localStorage.removeItem("token"); location.href='/login.html'; } }); } var active; layui.use(['layer', 'element'], function() { var $ = layui.jquery, layer = layui.layer; var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块 element.on('nav(demo)', function(elem){ //layer.msg(elem.text()); }); //触发事件 active = { tabAdd: function(obj){ var lay_id = $(this).attr("lay-id"); var title = $(this).html() + ''; //新增一个Tab项 element.tabAdd('admin-tab', { title: title, content: '', id: lay_id }); element.tabChange("admin-tab", lay_id); }, tabDelete: function(lay_id){ element.tabDelete("admin-tab", lay_id); }, tabChange: function(lay_id){ element.tabChange('admin-tab', lay_id); } }; //添加tab $(document).on('click','a',function(){ if(!$(this)[0].hasAttribute('data-url') || $(this).attr('data-url')===''){ return; } var tabs = $(".layui-tab-title").children(); var lay_id = $(this).attr("lay-id"); for(var i = 0; i < tabs.length; i++) { if($(tabs).eq(i).attr("lay-id") == lay_id) { active.tabChange(lay_id); return; } } active["tabAdd"].call(this); resize(); }); //iframe自适应 function resize(){ var $content = $('.admin-nav-card .layui-tab-content'); $content.height($(this).height() - 147); $content.find('iframe').each(function() { $(this).height($content.height()); }); } $(window).on('resize', function() { var $content = $('.admin-nav-card .layui-tab-content'); $content.height($(this).height() - 147); $content.find('iframe').each(function() { $(this).height($content.height()); }); }).resize(); //toggle左侧菜单 $('.admin-side-toggle').on('click', function() { var sideWidth = $('#admin-side').width(); if(sideWidth === 200) { $('#admin-body').animate({ left: '0' }); $('#admin-footer').animate({ left: '0' }); $('#admin-side').animate({ width: '0' }); } else { $('#admin-body').animate({ left: '200px' }); $('#admin-footer').animate({ left: '200px' }); $('#admin-side').animate({ width: '200px' }); } }); //手机设备的简单适配 var treeMobile = $('.site-tree-mobile'), shadeMobile = $('.site-mobile-shade'); treeMobile.on('click', function () { $('body').addClass('site-mobile'); }); shadeMobile.on('click', function () { $('body').removeClass('site-mobile'); }); }); ================================================ FILE: open-layui-web/src/main/view/static/js/jq.js ================================================ $.ajaxSetup({ cache : false, headers : { "access_token" : localStorage.getItem("token") }, error : function(xhr, textStatus, errorThrown) { var msg = xhr.responseText; var response = JSON.parse(msg); var code = response.code; var message = response.message; if (code == 400) { layer.msg(message); } else if (code == 401) { localStorage.removeItem("token"); location.href = '/login.html'; } else if (code == 403) { console.log("未授权:" + message); layer.msg('未授权'); } else if (code == 500) { layer.msg('系统错误:' + message); } } }); function buttonDel(data, permission, pers){ if(permission != ""){ if ($.inArray(permission, pers) < 0) { return ""; } } var btn = $(""); return btn.prop("outerHTML"); } function buttonEdit(href, permission, pers){ if(permission != ""){ if ($.inArray(permission, pers) < 0) { return ""; } } var btn = $(""); return btn.prop("outerHTML"); } function buttonInfo(data, permission, pers){ if(permission != ""){ if ($.inArray(permission, pers) < 0) { return ""; } } var btn = $(""); return btn.prop("outerHTML"); } function buttonOps(data, permission, pers){ if(permission != ""){ if ($.inArray(permission, pers) < 0) { return ""; } } var btn ; if(data.status=='UP'){ btn = $(""); }else{ btn = $(""); } return btn.prop("outerHTML"); } function buttonRefresh(data, permission, pers){ if(permission != ""){ if ($.inArray(permission, pers) < 0) { return ""; } } var btn ; btn = $(""); return btn.prop("outerHTML"); } function buttonEInfo(data, permission, pers){ if(permission != ""){ if ($.inArray(permission, pers) < 0) { return ""; } } var info ; info.ip =data.ip ; info.port= data.port ; info.operate = 5 ; var btn = $(""); return btn.prop("outerHTML"); } function deleteCurrentTab(){ var lay_id = $(parent.document).find("ul.layui-tab-title").children("li.layui-this").attr("lay-id"); parent.active.tabDelete(lay_id); } ================================================ FILE: open-layui-web/src/main/view/static/js/libs/jquery.treetable.js ================================================ /* * jQuery treetable Plugin 3.2.0 * http://ludo.cubicphuse.nl/jquery-treetable * * Copyright 2013, Ludo van den Boom * Dual licensed under the MIT or GPL Version 2 licenses. */ (function($) { var Node, Tree, methods; Node = (function() { function Node(row, tree, settings) { var parentId; this.row = row; this.tree = tree; this.settings = settings; // TODO Ensure id/parentId is always a string (not int) this.id = this.row.data(this.settings.nodeIdAttr); // TODO Move this to a setParentId function? parentId = this.row.data(this.settings.parentIdAttr); if (parentId != null && parentId !== "") { this.parentId = parentId; } this.treeCell = $(this.row.children(this.settings.columnElType)[this.settings.column]); this.expander = $(this.settings.expanderTemplate); this.indenter = $(this.settings.indenterTemplate); this.children = []; this.initialized = false; this.treeCell.prepend(this.indenter); } Node.prototype.addChild = function(child) { return this.children.push(child); }; Node.prototype.ancestors = function() { var ancestors, node; node = this; ancestors = []; while (node = node.parentNode()) { ancestors.push(node); } return ancestors; }; Node.prototype.collapse = function() { if (this.collapsed()) { return this; } this.row.removeClass("expanded").addClass("collapsed"); this._hideChildren(); this.expander.attr("title", this.settings.stringExpand); if (this.initialized && this.settings.onNodeCollapse != null) { this.settings.onNodeCollapse.apply(this); } return this; }; Node.prototype.collapsed = function() { return this.row.hasClass("collapsed"); }; // TODO destroy: remove event handlers, expander, indenter, etc. Node.prototype.expand = function() { if (this.expanded()) { return this; } this.row.removeClass("collapsed").addClass("expanded"); if (this.initialized && this.settings.onNodeExpand != null) { this.settings.onNodeExpand.apply(this); } if ($(this.row).is(":visible")) { this._showChildren(); } this.expander.attr("title", this.settings.stringCollapse); return this; }; Node.prototype.expanded = function() { return this.row.hasClass("expanded"); }; Node.prototype.hide = function() { this._hideChildren(); this.row.hide(); return this; }; Node.prototype.isBranchNode = function() { if(this.children.length > 0 || this.row.data(this.settings.branchAttr) === true) { return true; } else { return false; } }; Node.prototype.updateBranchLeafClass = function(){ this.row.removeClass('branch'); this.row.removeClass('leaf'); this.row.addClass(this.isBranchNode() ? 'branch' : 'leaf'); }; Node.prototype.level = function() { return this.ancestors().length; }; Node.prototype.parentNode = function() { if (this.parentId != null) { return this.tree[this.parentId]; } else { return null; } }; Node.prototype.removeChild = function(child) { var i = $.inArray(child, this.children); return this.children.splice(i, 1) }; Node.prototype.render = function() { var handler, settings = this.settings, target; if (settings.expandable === true && this.isBranchNode()) { handler = function(e) { $(this).parents("table").treetable("node", $(this).parents("tr").data(settings.nodeIdAttr)).toggle(); return e.preventDefault(); }; this.indenter.html(this.expander); target = settings.clickableNodeNames === true ? this.treeCell : this.expander; target.off("click.treetable").on("click.treetable", handler); target.off("keydown.treetable").on("keydown.treetable", function(e) { if (e.keyCode == 13) { handler.apply(this, [e]); } }); } this.indenter[0].style.paddingLeft = "" + (this.level() * settings.indent) + "px"; return this; }; Node.prototype.reveal = function() { if (this.parentId != null) { this.parentNode().reveal(); } return this.expand(); }; Node.prototype.setParent = function(node) { if (this.parentId != null) { this.tree[this.parentId].removeChild(this); } this.parentId = node.id; this.row.data(this.settings.parentIdAttr, node.id); return node.addChild(this); }; Node.prototype.show = function() { if (!this.initialized) { this._initialize(); } this.row.show(); if (this.expanded()) { this._showChildren(); } return this; }; Node.prototype.toggle = function() { if (this.expanded()) { this.collapse(); } else { this.expand(); } return this; }; Node.prototype._hideChildren = function() { var child, _i, _len, _ref, _results; _ref = this.children; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; _results.push(child.hide()); } return _results; }; Node.prototype._initialize = function() { var settings = this.settings; this.render(); if (settings.expandable === true && settings.initialState === "collapsed") { this.collapse(); } else { this.expand(); } if (settings.onNodeInitialized != null) { settings.onNodeInitialized.apply(this); } return this.initialized = true; }; Node.prototype._showChildren = function() { var child, _i, _len, _ref, _results; _ref = this.children; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; _results.push(child.show()); } return _results; }; return Node; })(); Tree = (function() { function Tree(table, settings) { this.table = table; this.settings = settings; this.tree = {}; // Cache the nodes and roots in simple arrays for quick access/iteration this.nodes = []; this.roots = []; } Tree.prototype.collapseAll = function() { var node, _i, _len, _ref, _results; _ref = this.nodes; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { node = _ref[_i]; _results.push(node.collapse()); } return _results; }; Tree.prototype.expandAll = function() { var node, _i, _len, _ref, _results; _ref = this.nodes; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { node = _ref[_i]; _results.push(node.expand()); } return _results; }; Tree.prototype.findLastNode = function (node) { if (node.children.length > 0) { return this.findLastNode(node.children[node.children.length - 1]); } else { return node; } }; Tree.prototype.loadRows = function(rows) { var node, row, i; if (rows != null) { for (i = 0; i < rows.length; i++) { row = $(rows[i]); if (row.data(this.settings.nodeIdAttr) != null) { node = new Node(row, this.tree, this.settings); this.nodes.push(node); this.tree[node.id] = node; if (node.parentId != null && this.tree[node.parentId]) { this.tree[node.parentId].addChild(node); } else { this.roots.push(node); } } } } for (i = 0; i < this.nodes.length; i++) { node = this.nodes[i].updateBranchLeafClass(); } return this; }; Tree.prototype.move = function(node, destination) { // Conditions: // 1: +node+ should not be inserted as a child of +node+ itself. // 2: +destination+ should not be the same as +node+'s current parent (this // prevents +node+ from being moved to the same location where it already // is). // 3: +node+ should not be inserted in a location in a branch if this would // result in +node+ being an ancestor of itself. var nodeParent = node.parentNode(); if (node !== destination && destination.id !== node.parentId && $.inArray(node, destination.ancestors()) === -1) { node.setParent(destination); this._moveRows(node, destination); // Re-render parentNode if this is its first child node, and therefore // doesn't have the expander yet. if (node.parentNode().children.length === 1) { node.parentNode().render(); } } if(nodeParent){ nodeParent.updateBranchLeafClass(); } if(node.parentNode()){ node.parentNode().updateBranchLeafClass(); } node.updateBranchLeafClass(); return this; }; Tree.prototype.removeNode = function(node) { // Recursively remove all descendants of +node+ this.unloadBranch(node); // Remove node from DOM () node.row.remove(); // Remove node from parent children list if (node.parentId != null) { node.parentNode().removeChild(node); } // Clean up Tree object (so Node objects are GC-ed) delete this.tree[node.id]; this.nodes.splice($.inArray(node, this.nodes), 1); return this; } Tree.prototype.render = function() { var root, _i, _len, _ref; _ref = this.roots; for (_i = 0, _len = _ref.length; _i < _len; _i++) { root = _ref[_i]; // Naming is confusing (show/render). I do not call render on node from // here. root.show(); } return this; }; Tree.prototype.sortBranch = function(node, sortFun) { // First sort internal array of children node.children.sort(sortFun); // Next render rows in correct order on page this._sortChildRows(node); return this; }; Tree.prototype.unloadBranch = function(node) { // Use a copy of the children array to not have other functions interfere // with this function if they manipulate the children array // (eg removeNode). var children = node.children.slice(0), i; for (i = 0; i < children.length; i++) { this.removeNode(children[i]); } // Reset node's collection of children node.children = []; node.updateBranchLeafClass(); return this; }; Tree.prototype._moveRows = function(node, destination) { var children = node.children, i; node.row.insertAfter(destination.row); node.render(); // Loop backwards through children to have them end up on UI in correct // order (see #112) for (i = children.length - 1; i >= 0; i--) { this._moveRows(children[i], node); } }; // Special _moveRows case, move children to itself to force sorting Tree.prototype._sortChildRows = function(parentNode) { return this._moveRows(parentNode, parentNode); }; return Tree; })(); // jQuery Plugin methods = { init: function(options, force) { var settings; settings = $.extend({ branchAttr: "ttBranch", clickableNodeNames: false, column: 0, columnElType: "td", // i.e. 'td', 'th' or 'td,th' expandable: false, expanderTemplate: " ", indent: 19, indenterTemplate: "", initialState: "collapsed", nodeIdAttr: "ttId", // maps to data-tt-id parentIdAttr: "ttParentId", // maps to data-tt-parent-id stringExpand: "Expand", stringCollapse: "Collapse", // Events onInitialized: null, onNodeCollapse: null, onNodeExpand: null, onNodeInitialized: null }, options); return this.each(function() { var el = $(this), tree; if (force || el.data("treetable") === undefined) { tree = new Tree(this, settings); tree.loadRows(this.rows).render(); el.addClass("treetable").data("treetable", tree); if (settings.onInitialized != null) { settings.onInitialized.apply(tree); } } return el; }); }, destroy: function() { return this.each(function() { return $(this).removeData("treetable").removeClass("treetable"); }); }, collapseAll: function() { this.data("treetable").collapseAll(); return this; }, collapseNode: function(id) { var node = this.data("treetable").tree[id]; if (node) { node.collapse(); } else { throw new Error("Unknown node '" + id + "'"); } return this; }, expandAll: function() { this.data("treetable").expandAll(); return this; }, expandNode: function(id) { var node = this.data("treetable").tree[id]; if (node) { if (!node.initialized) { node._initialize(); } node.expand(); } else { throw new Error("Unknown node '" + id + "'"); } return this; }, loadBranch: function(node, rows) { var settings = this.data("treetable").settings, tree = this.data("treetable").tree; // TODO Switch to $.parseHTML rows = $(rows); if (node == null) { // Inserting new root nodes this.append(rows); } else { var lastNode = this.data("treetable").findLastNode(node); rows.insertAfter(lastNode.row); } this.data("treetable").loadRows(rows); // Make sure nodes are properly initialized rows.filter("tr").each(function() { tree[$(this).data(settings.nodeIdAttr)].show(); }); if (node != null) { // Re-render parent to ensure expander icon is shown (#79) node.render().expand(); } return this; }, move: function(nodeId, destinationId) { var destination, node; node = this.data("treetable").tree[nodeId]; destination = this.data("treetable").tree[destinationId]; this.data("treetable").move(node, destination); return this; }, node: function(id) { return this.data("treetable").tree[id]; }, removeNode: function(id) { var node = this.data("treetable").tree[id]; if (node) { this.data("treetable").removeNode(node); } else { throw new Error("Unknown node '" + id + "'"); } return this; }, reveal: function(id) { var node = this.data("treetable").tree[id]; if (node) { node.reveal(); } else { throw new Error("Unknown node '" + id + "'"); } return this; }, sortBranch: function(node, columnOrFunction) { var settings = this.data("treetable").settings, prepValue, sortFun; columnOrFunction = columnOrFunction || settings.column; sortFun = columnOrFunction; if ($.isNumeric(columnOrFunction)) { sortFun = function(a, b) { var extractValue, valA, valB; extractValue = function(node) { var val = node.row.find("td:eq(" + columnOrFunction + ")").text(); // Ignore trailing/leading whitespace and use uppercase values for // case insensitive ordering return $.trim(val).toUpperCase(); } valA = extractValue(a); valB = extractValue(b); if (valA < valB) return -1; if (valA > valB) return 1; return 0; }; } this.data("treetable").sortBranch(node, sortFun); return this; }, unloadBranch: function(node) { this.data("treetable").unloadBranch(node); return this; } }; $.fn.treetable = function(method) { if (methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method === 'object' || !method) { return methods.init.apply(this, arguments); } else { return $.error("Method " + method + " does not exist on jQuery.treetable"); } }; // Expose classes to world this.TreeTable || (this.TreeTable = {}); this.TreeTable.Node = Node; this.TreeTable.Tree = Tree; })(jQuery); ================================================ FILE: open-layui-web/src/main/view/static/js/main.js ================================================ initMenu(); function initMenu(){ $.ajax({ url:"/permissions/current", type:"get", async:false, success:function(data){ if(!$.isArray(data)){ location.href='/login.html'; return; } var menu = $("#menu"); $.each(data, function(i,item){ var a = $(""); var css = item.css; if(css!=null && css!=""){ a.append(""); } a.append(""+item.name+""); a.attr("lay-id", item.id); var href = item.href; if(href != null && href != ""){ a.attr("data-url", href); } var li = $("
    • "); // 默认第一项不展开 // if (i == 0) { // li.addClass("layui-nav-itemed"); // } li.append(a); //二级菜单 var child2 = item.child; if(child2 != null && child2.length > 0){ $.each(child2, function(j,item2){ var ca = $(""); ca.attr("data-url", item2.href); ca.attr("lay-id", item2.id); var css2 = item2.css; if(css2!=null && css2!=""){ ca.append(""); } ca.append(""+item2.name+""); var dd = $("
      "); dd.append(ca); var dl = $("
      "); dl.append(dd); li.append(dl); }); } menu.append(li); }); } }); } // 登陆用户头像昵称 showLoginInfo(); function showLoginInfo(){ $.ajax({ type : 'get', url : '/users/current', async : false, success : function(data) { $(".admin-header-user span").text(data.nickname); var pro = window.location.protocol; var host = window.location.host; var domain = pro + "//" + host; var sex = data.sex; var url = data.headImgUrl; if(url == null || url == ""){ if(sex == 1){ url = "/img/avatars/sunny.png"; } else { url = "/img/avatars/1.png"; } url = domain + url; } else { url = domain + "/statics" + url; } var img = $(".admin-header-user img"); img.attr("src", url); } }); } showUnreadNotice(); function showUnreadNotice(){ $.ajax({ type : 'get', url : '/notices/count-unread', success : function(data) { $("[unreadNotice]").each(function(){ if(data>0){ $(this).html(""+data+""); }else{ $(this).html(""); } }); } }); } function logout(){ $.ajax({ type : 'get', url : '/logout', success : function(data) { localStorage.removeItem("token"); location.href='/login.html'; } }); } var active; layui.use(['layer', 'element'], function() { var $ = layui.jquery, layer = layui.layer; var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块 element.on('nav(demo)', function(elem){ //layer.msg(elem.text()); }); //触发事件 active = { tabAdd: function(obj){ var lay_id = $(this).attr("lay-id"); var title = $(this).html() + ''; //新增一个Tab项 element.tabAdd('admin-tab', { title: title, content: '', id: lay_id }); element.tabChange("admin-tab", lay_id); }, tabDelete: function(lay_id){ element.tabDelete("admin-tab", lay_id); }, tabChange: function(lay_id){ element.tabChange('admin-tab', lay_id); } }; //添加tab $(document).on('click','a',function(){ if(!$(this)[0].hasAttribute('data-url') || $(this).attr('data-url')===''){ return; } var tabs = $(".layui-tab-title").children(); var lay_id = $(this).attr("lay-id"); for(var i = 0; i < tabs.length; i++) { if($(tabs).eq(i).attr("lay-id") == lay_id) { active.tabChange(lay_id); return; } } active["tabAdd"].call(this); resize(); }); //iframe自适应 function resize(){ var $content = $('.admin-nav-card .layui-tab-content'); $content.height($(this).height() - 147); $content.find('iframe').each(function() { $(this).height($content.height()); }); } $(window).on('resize', function() { var $content = $('.admin-nav-card .layui-tab-content'); $content.height($(this).height() - 147); $content.find('iframe').each(function() { $(this).height($content.height()); }); }).resize(); //toggle左侧菜单 $('.admin-side-toggle').on('click', function() { var sideWidth = $('#admin-side').width(); if(sideWidth === 200) { $('#admin-body').animate({ left: '0' }); $('#admin-footer').animate({ left: '0' }); $('#admin-side').animate({ width: '0' }); } else { $('#admin-body').animate({ left: '200px' }); $('#admin-footer').animate({ left: '200px' }); $('#admin-side').animate({ width: '200px' }); } }); //手机设备的简单适配 var treeMobile = $('.site-tree-mobile'), shadeMobile = $('.site-mobile-shade'); treeMobile.on('click', function () { $('body').addClass('site-mobile'); }); shadeMobile.on('click', function () { $('body').removeClass('site-mobile'); }); }); ================================================ FILE: open-layui-web/src/main/view/static/js/main2.js ================================================ initMenu(); function initMenu(){ $.ajax({ url:"/permissions/current", type:"get", async:false, success:function(data){ if(!$.isArray(data)){ location.href='/login.html'; return; } var menu = $("#menu"); $.each(data, function(i,item){ var a = $(""); var css = item.css; if(css!=null && css!=""){ a.append(""); } var span1 = $(""+item.name+"") ; a.append(span1); a.attr("lay-id", item.id); var href = item.href; if(href != null && href != ""){ a.attr("href", href); a.attr("iframe-uuid", "uuid-main"); a.attr("class","admin-open-new-tab"); a.click(function(){ $('#admin-tab-body-index').tabs('open', 0); }) } var li = $("
    • "); // 默认第一项不展开 // if (i == 0) { // li.addClass("layui-nav-itemed"); // } li.append(a); //二级菜单 var child2 = item.child; if(child2 != null && child2.length > 0){ var dl = $("
        "); span1.append(""); $.each(child2, function(j,item2){ var ca = $("
        "); ca.attr("href", item2.href); ca.attr("lay-id", item2.id); li.attr("class","admin-parent"); a.attr("data-am-collapse","{target: '#collapse-nav"+ item.id+"'}") var css2 = item2.css; if(css2!=null && css2!=""){ ca.append(""); } ca.append(""+item2.name+""); var dd = $("
      • "); dd.append(ca); dl.append(dd); }); li.append(dl); } menu.append(li); }); } }); } // 登陆用户头像昵称 showLoginInfo(); function showLoginInfo(){ $.ajax({ type : 'get', url : '/users/current', async : false, success : function(data) { $(".admin-header-user span").text(data.nickname); var pro = window.location.protocol; var host = window.location.host; var domain = pro + "//" + host; var sex = data.sex; var url = data.headImgUrl; if(url == null || url == ""){ if(sex == 1){ url = "/img/avatars/sunny.png"; } else { url = "/img/avatars/1.png"; } url = domain + url; } else { url = domain + "/statics" + url; } var img = $(".admin-header-user img"); img.attr("src", url); } }); } showUnreadNotice(); function showUnreadNotice(){ $.ajax({ type : 'get', url : '/notices/count-unread', success : function(data) { $("[unreadNotice]").each(function(){ if(data>0){ $(this).html(""+data+""); }else{ $(this).html(""); } }); } }); } function logout(){ $.ajax({ type : 'get', url : '/logout', success : function(data) { localStorage.removeItem("token"); location.href='/login.html'; } }); } var active; layui.use(['layer', 'element'], function() { var $ = layui.jquery, layer = layui.layer; var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块 element.on('nav(demo)', function(elem){ //layer.msg(elem.text()); }); //触发事件 active = { tabAdd: function(obj){ var lay_id = $(this).attr("lay-id"); var title = $(this).html() + ''; //新增一个Tab项 element.tabAdd('admin-tab', { title: title, content: '', id: lay_id }); element.tabChange("admin-tab", lay_id); }, tabDelete: function(lay_id){ element.tabDelete("admin-tab", lay_id); }, tabChange: function(lay_id){ element.tabChange('admin-tab', lay_id); } }; //添加tab $(document).on('click','a',function(){ if(!$(this)[0].hasAttribute('data-url') || $(this).attr('data-url')===''){ return; } var tabs = $(".layui-tab-title").children(); var lay_id = $(this).attr("lay-id"); for(var i = 0; i < tabs.length; i++) { if($(tabs).eq(i).attr("lay-id") == lay_id) { active.tabChange(lay_id); return; } } active["tabAdd"].call(this); resize(); }); //iframe自适应 function resize(){ var $content = $('.admin-nav-card .layui-tab-content'); $content.height($(this).height() - 147); $content.find('iframe').each(function() { $(this).height($content.height()); }); } $(window).on('resize', function() { var $content = $('.admin-nav-card .layui-tab-content'); $content.height($(this).height() - 147); $content.find('iframe').each(function() { $(this).height($content.height()); }); }).resize(); //toggle左侧菜单 $('.admin-side-toggle').on('click', function() { var sideWidth = $('#admin-side').width(); if(sideWidth === 200) { $('#admin-body').animate({ left: '0' }); $('#admin-footer').animate({ left: '0' }); $('#admin-side').animate({ width: '0' }); } else { $('#admin-body').animate({ left: '200px' }); $('#admin-footer').animate({ left: '200px' }); $('#admin-side').animate({ width: '200px' }); } }); //手机设备的简单适配 var treeMobile = $('.site-tree-mobile'), shadeMobile = $('.site-mobile-shade'); treeMobile.on('click', function () { $('body').addClass('site-mobile'); }); shadeMobile.on('click', function () { $('body').removeClass('site-mobile'); }); }); ================================================ FILE: open-layui-web/src/main/view/static/js/my/job.js ================================================ function checkCron() { var cron = $("#cron").val(); if (cron != "") { $.ajax({ type : 'get', url : '/jobs?cron=' + cron, success : function(data) { var msg = "正确"; if (!data) { msg = "cron表达式不对"; } layer.msg(msg, { shift : -1, time : 1000 }, function() { }); } }); } else { layer.msg("cron表达式不能为空", { shift : -1, time : 1000 }, function() { }); } } function initBeanNames() { $.ajax({ type : 'get', url : '/jobs/beans', async : false, success : function(data) { var select = $("#springBeanName"); for (var i = 0; i < data.length; i++) { var v = data[i]; select.append("") } $("#springBeanName").selectpicker('refresh'); } }); } function showMethods() { var val = $("#springBeanName").val(); if (val == "") { return; } $.ajax({ type : 'get', url : '/jobs/beans/' + val, async : false, success : function(data) { var select = $("#methodName"); select.empty(); if (data.length == 0) { return; } for (var i = 0; i < data.length; i++) { var v = data[i]; select.append("") } } }); } ================================================ FILE: open-layui-web/src/main/view/static/js/my/permission.js ================================================ function checkPermission() { var pers = []; $.ajax({ type : 'get', url : '/permissions/owns', contentType : "application/json; charset=utf-8", async : false, success : function(data) { pers = data; $("[permission]").each(function() { var per = $(this).attr("permission"); if ($.inArray(per, data) < 0) { $(this).hide(); } }); } }); return pers; } ================================================ FILE: open-layui-web/src/main/view/static/js/my/roles/role.js ================================================ function initRoles() { $.ajax({ type : 'get', url : '/roles/all', async : false, success : function(data) { var r = $("#roles"); for (var i = 0; i < data.length; i++) { var d = data[i]; var id = d['id']; var name = d['name']; var t = "   "; r.append(t); } } }); } function getCheckedRoleIds() { var ids = []; $("#roles input[type='checkbox']").each(function() { if ($(this).prop("checked")) { ids.push($(this).val()); } }); return ids; } function initRoleDatas(userId) { $.ajax({ type : 'get', url : '/roles?userId=' + userId, success : function(data) { var length = data.length; for (var i = 0; i < length; i++) { $("input[type='checkbox']").each(function() { var v = $(this).val(); if (v == data[i]['id']) { $(this).attr("checked", true); } }); } } }); } ================================================ FILE: open-layui-web/src/main/view/static/js/my/ztree-menu.js ================================================ function getMenuTree() { var root = { id : 0, name : "root", open : true, }; $.ajax({ type : 'get', url : '/permissions/all', contentType : "application/json; charset=utf-8", async : false, success : function(data) { var length = data.length; var children = []; for (var i = 0; i < length; i++) { var d = data[i]; var node = createNode(d); children[i] = node; } root.children = children; } }); return root; } function initMenuDatas(roleId){ $.ajax({ type : 'get', url : '/permissions?roleId=' + roleId, success : function(data) { var length = data.length; var ids = []; for(var i=0; i 0){ var node = treeObj.getNodeByParam("id", 0, null); treeObj.checkNode(node, true, false); } for(var i=0; i 0) { var children = []; for (var i = 0; i < length; i++) { children[i] = createNode(child[i]); } node.children = children; } } return node; } function initParentMenuSelect(){ $.ajax({ type : 'get', url : '/permissions/parents', async : false, success : function(data) { var select = $("#parentId"); select.append(""); for(var i=0; i" +name+""); } } }); } function initModuleSelect(){ $.ajax({ type : 'get', url : '/sys/module', async : false, success : function(data) { var select = $("#moduleId"); select.append(""); for(var i=0; i" +name+""); } } }); } function getParentServer() { var moduleId = $("#moduleId option:selected").val(); $.ajax({ type : 'post', url : '/sys/server/list', dataType:"json", data:{moduleId:moduleId}, async:false, cache: false, success : function(data) { var select = $("#parentId"); select.html(""); select.append(""); for(var i=0; i" +name+""); } } }); } function getSettting() { var setting = { check : { enable : true, chkboxType : { "Y" : "ps", "N" : "ps" } }, async : { enable : true, }, data : { simpleData : { enable : true, idKey : "id", pIdKey : "pId", rootPId : 0 } }, callback : { onCheck : zTreeOnCheck } }; return setting; } function zTreeOnCheck(event, treeId, treeNode) { // console.log(treeNode.id + ", " + treeNode.name + "," + treeNode.checked // + "," + treeNode.pId); // console.log(JSON.stringify(treeNode)); } ================================================ FILE: open-layui-web/src/main/view/static/js/my/ztree-service.js ================================================ function getMenuTree() { var root = { id : 0, name : "root", open : true, }; $.ajax({ type : 'get', url : '/services/all', contentType : "application/json; charset=utf-8", async : false, success : function(data) { var length = data.length; var children = []; for (var i = 0; i < length; i++) { var d = data[i]; var node = createNode(d); children[i] = node; } root.children = children; } }); return root; } function initMenuDatas(clientId){ $.ajax({ type : 'get', url : '/services?clientId=' + clientId, success : function(data) { var length = data.length; var ids = []; for(var i=0; i 0){ var node = treeObj.getNodeByParam("id", 0, null); treeObj.checkNode(node, true, false); } for(var i=0; i 0) { var children = []; for (var i = 0; i < length; i++) { children[i] = createNode(child[i]); } node.children = children; } } return node; } function initParentMenuSelect(){ $.ajax({ type : 'get', url : '/services/parents', async : false, success : function(data) { var select = $("#parentId"); select.append(""); for(var i=0; i" +name+""); } } }); } function initModuleSelect(){ $.ajax({ type : 'get', url : '/sys/module', async : false, success : function(data) { var select = $("#moduleId"); select.append(""); for(var i=0; i" +name+""); } } }); } function getParentServer() { var moduleId = $("#moduleId option:selected").val(); $.ajax({ type : 'post', url : '/sys/server/list', dataType:"json", data:{moduleId:moduleId}, async:false, cache: false, success : function(data) { var select = $("#parentId"); select.html(""); select.append(""); for(var i=0; i" +name+""); } } }); } function getSettting() { var setting = { check : { enable : true, chkboxType : { "Y" : "ps", "N" : "ps" } }, async : { enable : true, }, data : { simpleData : { enable : true, idKey : "id", pIdKey : "pId", rootPId : 0 } }, callback : { onCheck : zTreeOnCheck } }; return setting; } function zTreeOnCheck(event, treeId, treeNode) { // console.log(treeNode.id + ", " + treeNode.name + "," + treeNode.checked // + "," + treeNode.pId); // console.log(JSON.stringify(treeNode)); } ================================================ FILE: open-layui-web/src/main/view/static/js/plugin/datatables/Chinese.lang ================================================ { "sProcessing": "处理中...", "sLengthMenu": "显示 _MENU_ 项结果", "sZeroRecords": "没有匹配结果", "sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项", "sInfoEmpty": "显示第 0 至 0 项结果,共 0 项", "sInfoFiltered": "(由 _MAX_ 项结果过滤)", "sInfoPostFix": "", "sSearch": "搜索:", "sUrl": "", "sEmptyTable": "表中数据为空", "sLoadingRecords": "载入中...", "sInfoThousands": ",", "oPaginate": { "sFirst": "首页", "sPrevious": "上页", "sNext": "下页", "sLast": "末页" }, "oAria": { "sSortAscending": ": 以升序排列此列", "sSortDescending": ": 以降序排列此列" } } ================================================ FILE: open-layui-web/src/main/view/static/js/util/ajaxutils.js ================================================ /** * Created by nbfujx on 2017/12/28. */ function getJSON (url) { return new Promise( (resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { debugger; if(this.responseText!="401") { resolve(this.responseText, this) }else{ window.location.href="/login"; } } else { var resJson = { code: this.status, response: this.response } reject(resJson, this) } } } xhr.send() }) } function postJSON(url, data) { return new Promise( (resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open("POST", url, true) xhr.setRequestHeader("Content-type", "application/json"); xhr.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { if(this.responseText!="401") { resolve(JSON.parse(this.responseText), this) }else{ window.location.href="/login"; } } else { var resJson = { code: this.status, response: this.response } reject(resJson, this) } } } xhr.send(JSON.stringify(data)) }) } function serializeObject(form){ var o ={}; $.each(form.serializeArray(),function(index){ if(o[this['name']]){ o[this['name']] = o[this['name']] +","+this['value']; }else{ o[this['name']] = this['value']; } }); return o; } ================================================ FILE: open-layui-web/src/main/view/static/layui/css/layui.css ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ .layui-inline,img{display:inline-block;vertical-align:middle}.layui-rate,li{list-style:none}h1,h2,h3,h4,h5,h6{font-weight:400}.layui-edge,.layui-header,.layui-inline,.layui-main{position:relative}.layui-btn,.layui-edge,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-disabled,.layui-icon,.layui-unselect{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{border:none}table{border-collapse:collapse;border-spacing:0}h4,h5,h6{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:24px;font:14px Helvetica Neue,Helvetica,PingFang SC,\5FAE\8F6F\96C5\9ED1,Tahoma,Arial,sans-serif}hr{height:1px;margin:10px 0;border:0;clear:both}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{*display:inline;*zoom:1}.layui-edge{display:inline-block;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=230-rc1);src:url(../font/iconfont.eot?v=230-rc1#iefix) format('embedded-opentype'),url(../font/iconfont.svg?v=230-rc1#iconfont) format('svg'),url(../font/iconfont.woff?v=230-rc1) format('woff'),url(../font/iconfont.ttf?v=230-rc1) format('truetype')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-search:before{content:"\e615"}.layui-icon-share:before{content:"\e641"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-engine:before{content:"\e628"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-star:before{content:"\e600"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-chat:before{content:"\e606"}.layui-icon-release:before{content:"\e609"}.layui-icon-list:before{content:"\e60a"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-ok-circle:before{content:"\1005"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-table:before{content:"\e62d"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-edit:before{content:"\e642"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-down:before{content:"\e61a"}.layui-icon-file:before{content:"\e621"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-read:before{content:"\e705"}.layui-icon-404:before{content:"\e61c"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-help:before{content:"\e607"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-water:before{content:"\e636"}.layui-icon-username:before{content:"\e66f"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-about:before{content:"\e60b"}.layui-icon-location:before{content:"\e715"}.layui-icon-up:before{content:"\e619"}.layui-icon-pause:before{content:"\e651"}.layui-icon-date:before{content:"\e637"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-delete:before{content:"\e640"}.layui-icon-play:before{content:"\e652"}.layui-icon-top:before{content:"\e604"}.layui-icon-friends:before{content:"\e612"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-ok:before{content:"\e605"}.layui-icon-layer:before{content:"\e638"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-group:before{content:"\e613"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-link:before{content:"\e64c"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-log:before{content:"\e60e"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-return:before{content:"\e65c"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-form:before{content:"\e63c"}.layui-icon-cart:before{content:"\e657"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-fire:before{content:"\e756"}.layui-icon-set:before{content:"\e716"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-tips:before{content:"\e702"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-home:before{content:"\e68e"}.layui-icon-user:before{content:"\e770"}.layui-icon-notice:before{content:"\e667"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-voice:before{content:"\e688"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-template:before{content:"\e663"}.layui-icon-auz:before{content:"\e672"}.layui-icon-console:before{content:"\e665"}.layui-icon-app:before{content:"\e653"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-next:before{content:"\e65b"}.layui-icon-component:before{content:"\e857"}.layui-icon-more:before{content:"\e65f"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-camera:before{content:"\e660"}.layui-icon-note:before{content:"\e66e"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-password:before{content:"\e673"}.layui-icon-senior:before{content:"\e674"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-cellphone:before{content:"\e678"}.layui-main{width:1140px;margin:0 auto}.layui-header{z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{position:relative;width:220px;height:100%;overflow-x:hidden}.layui-body{position:absolute;left:200px;right:0;top:0;bottom:0;z-index:998;width:auto;overflow:hidden;overflow-y:auto;box-sizing:border-box}.layui-layout-body{overflow:hidden}.layui-layout-admin .layui-header{background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{top:60px;bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;height:44px;line-height:44px;padding:0 15px;background-color:#eee}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#009688;font-size:16px}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;padding:0 15px;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:'';display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:768px){.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:750px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:970px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1170px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space3{margin:-1.5px}.layui-col-space3>*{padding:1.5px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space8{margin:-3.5px}.layui-col-space8>*{padding:3.5px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:22px;border-left:5px solid #009688;border-radius:0 2px 2px 0;background-color:#f2f2f2}.layui-quote-nm{border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border-width:1px 0 0}.layui-field-box{padding:10px 15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#e2e2e2}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#f2f2f2;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:22px;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card-body,.layui-card-header,.layui-form-label,.layui-form-mid,.layui-form-select,.layui-input-block,.layui-input-inline,.layui-textarea{position:relative}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f6f6f6;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-bg-black,.layui-bg-blue,.layui-bg-cyan,.layui-bg-green,.layui-bg-orange,.layui-bg-red{color:#fff!important}.layui-card-body{padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #E6E6E6;background-color:#fff}.layui-bg-red{background-color:#FF5722!important}.layui-bg-orange{background-color:#FFB800!important}.layui-bg-green{background-color:#009688!important}.layui-bg-cyan{background-color:#2F4056!important}.layui-bg-blue{background-color:#1E9FFF!important}.layui-bg-black{background-color:#393D49!important}.layui-bg-gray{background-color:#eee!important;color:#666!important}.layui-badge-rim,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-layedit,.layui-layedit-tool,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#e6e6e6}.layui-timeline-item:before,hr{background-color:#e6e6e6}.layui-text{line-height:22px;font-size:14px;color:#666}.layui-text h1,.layui-text h2,.layui-text h3{font-weight:500;color:#333}.layui-text h1{font-size:30px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text a:not(.layui-btn){color:#01AAED}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text ul{padding:5px 0 5px 15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text em,.layui-word-aux{color:#999!important;padding:0 5px!important}.layui-btn{display:inline-block;height:38px;line-height:38px;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border:none;border-radius:2px;cursor:pointer}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{font-size:0}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{margin-right:3px;font-size:18px;vertical-align:bottom;vertical-align:middle\9}.layui-btn-primary{border:1px solid #C9C9C9;background-color:#fff;color:#555}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#FFB800}.layui-btn-danger{background-color:#FF5722}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border:1px solid #e6e6e6;background-color:#FBFBFB;color:#C9C9C9;cursor:not-allowed;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-sm i{font-size:16px!important}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:14px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#C9C9C9;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #c9c9c9}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#D2D2D2!important}.layui-input:focus,.layui-textarea:focus{border-color:#C9C9C9!important}.layui-textarea{min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#FF5722!important}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:999;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f2f2f2}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\9}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:30px;margin-right:10px;padding-right:30px;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;top:0;width:30px;height:28px;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;border:none!important;margin-right:0;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{float:right;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{position:relative;top:0;width:16px;height:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878;background-color:#5FB878;color:#fff}.layui-checkbox-disbaled[lay-skin=primary] span{background:0 0!important;color:#c2c2c2}.layui-checkbox-disbaled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;min-width:35px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:relative;top:0;width:25px;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-checkbox-disbaled,.layui-checkbox-disbaled i{border-color:#e2e2e2!important}.layui-form-onswitch i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch em{margin-left:5px;margin-right:21px;color:#fff!important}.layui-checkbox-disbaled span{background-color:#e2e2e2!important}.layui-checkbox-disbaled:hover i{color:#fff!important}[lay-radio]{display:none}.layui-form-radio,.layui-form-radio *{display:inline-block;vertical-align:middle}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio *{font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio>i:hover,.layui-form-radioed>i{color:#5FB878}.layui-radio-disbaled>i{color:#e2e2e2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#FBFBFB;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-layedit{border-width:1px;border-style:solid;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom-width:1px;border-bottom-style:solid;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #e2e2e2}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#e2e2e2;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #e2e2e2}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage a:hover{color:#009688}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage a{text-decoration:none}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{display:inline-block;width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#009688!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-table,.layui-table-view{margin:10px 0}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;background-color:#fff;color:#666}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:400}.layui-table tbody tr:hover,.layui-table thead tr,.layui-table-click,.layui-table-header,.layui-table-hover,.layui-table-mend,.layui-table-patch,.layui-table-tool,.layui-table[lay-even] tr:nth-child(even){background-color:#f2f2f2}.layui-table td,.layui-table th,.layui-table-fixed-r,.layui-table-header,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#e6e6e6}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0 0 1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0 1px 0 0}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding:15px 30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:40px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{font-size:12px;padding:5px 10px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:20px;line-height:20px}.layui-table[lay-data]{display:none}.layui-table-box,.layui-table-view{position:relative;overflow:hidden}.layui-table-view .layui-table{position:relative;width:auto;margin:0}.layui-table-body,.layui-table-header .layui-table,.layui-table-page{margin-bottom:-1px}.layui-table-view .layui-table[lay-skin=line]{border-width:0 1px 0 0}.layui-table-view .layui-table[lay-skin=row]{border-width:0 0 1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:5px 0;border-top:none;border-left:none}.layui-table-view .layui-table td{cursor:default}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px}.layui-table-header{border-width:0 0 1px;overflow:hidden}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:4px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#666}.layui-table-sort .layui-table-sort-desc{bottom:4px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#666}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:28px;line-height:28px;padding:0 15px;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary],.layui-table-cell .layui-form-radio[lay-skin=primary]{top:-1px;vertical-align:middle}.layui-table-cell .layui-form-radio{padding-right:0}.layui-table-cell .layui-form-radio>i{margin-right:0}.layui-table-cell .layui-table-link{color:#01AAED}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{padding:0;text-align:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px}.layui-table-body .layui-none{line-height:40px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:0 -1px 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0 0 0 1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px}.layui-table-tool{position:relative;width:100%;height:50px;line-height:30px;padding:10px 15px;border-width:0 0 1px}.layui-table-page{position:relative;width:100%;padding:7px 7px 0;border-width:1px 0 0;height:41px;font-size:12px}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-7px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-view select[lay-ignore]{display:inline-block}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 14px 1px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15)}.layui-table-edit:focus{border-color:#5FB878!important}select.layui-table-edit{padding:0 0 0 10px;border-color:#C9C9C9}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0;box-sizing:content-box}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.1)}.layui-table-tips-main{margin:-44px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#333}.layui-table-tips-c{position:absolute;right:-3px;top:-12px;width:18px;height:18px;padding:3px;text-align:center;font-weight:700;border-radius:100%;font-size:14px;cursor:pointer;background-color:#666}.layui-table-tips-c:hover{background-color:#999}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-drag,.layui-upload-form,.layui-upload-wrap{display:inline-block}.layui-upload-list{margin:10px 0}.layui-upload-choose{padding:0 10px;color:#999}.layui-upload-drag{position:relative;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#009688}.layui-upload-drag[lay-over]{border-color:#009688}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:10px 5px 10px 0;font-size:0}.layui-rate li i.layui-icon{font-size:20px;color:#FFB800;margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New;font-size:12px}.layui-tree{line-height:26px}.layui-tree li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-tree li .layui-tree-spread,.layui-tree li a{display:inline-block;vertical-align:top;height:26px;*display:inline;*zoom:1;cursor:pointer}.layui-tree li a{font-size:0}.layui-tree li a i{font-size:16px}.layui-tree li a cite{padding:0 6px;font-size:14px;font-style:normal}.layui-tree li i{padding-left:6px;color:#333;-moz-user-select:none}.layui-tree li .layui-tree-check{font-size:13px}.layui-tree li .layui-tree-check:hover{color:#009E94}.layui-tree li ul{display:none;margin-left:20px}.layui-tree li .layui-tree-enter{line-height:24px;border:1px dotted #000}.layui-tree-drag{display:none;position:absolute;left:-666px;top:-666px;background-color:#f2f2f2;padding:5px 10px;border:1px dotted #000;white-space:nowrap}.layui-tree-drag i{padding-right:5px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar,.layui-nav-tree .layui-nav-itemed:after{position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s}.layui-nav-bar{z-index:1000}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{content:'';top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{content:'';width:0;height:0;border-style:solid dashed dashed;border-color:#fff transparent transparent;overflow:hidden;cursor:pointer;transition:all .2s;-webkit-transition:all .2s;position:absolute;top:50%;right:3px;margin-top:-3px;border-width:6px;border-top-color:rgba(255,255,255,.7)}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{margin-top:-9px;border-style:dashed dashed solid;border-color:transparent transparent #fff}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #d2d2d2;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#333}.layui-nav .layui-nav-child a:hover{background-color:#f2f2f2;color:#000}.layui-nav-child dd{position:relative}.layui-nav .layui-nav-child dd.layui-this a,.layui-nav-child dd.layui-this{background-color:#5FB878;color:#fff}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:45px}.layui-nav-tree .layui-nav-item a{position:relative;height:45px;line-height:45px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item a:hover{background-color:#4E5465}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child a{height:40px;line-height:40px;color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-tree .layui-nav-more{right:10px}.layui-nav-itemed>.layui-nav-child{display:block;padding:0;background-color:rgba(0,0,0,.3)!important}.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-bg-blue .layui-nav-bar,.layui-bg-blue .layui-nav-itemed:after,.layui-bg-blue .layui-this:after{background-color:#93D1FF}.layui-bg-blue .layui-nav-child dd.layui-this{background-color:#1E9FFF}.layui-bg-blue .layui-nav-itemed>a,.layui-nav-tree.layui-bg-blue .layui-nav-title a,.layui-nav-tree.layui-bg-blue .layui-nav-title a:hover{background-color:#007DDB!important}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#5FB878!important}.layui-breadcrumb a cite{color:#666;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer}.layui-tab-title li a{display:block}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:'';width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#e2e2e2;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:10px}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#f2f2f2}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#5FB878;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#FF5722}.layui-timeline-item:before{content:'';position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:last-child:before{display:none}.layui-timeline-item:first-child:before{display:block}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#FF5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#666}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-8px 6px 0}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\9;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add],.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\9;opacity:1;left:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#e2e2e2;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown]>[carousel-item]>*,.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:9999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-anim{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .3s;-webkit-transition:all .3s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,30px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,30px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout} ================================================ FILE: open-layui-web/src/main/view/static/layui/css/layui.mobile.css ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}html{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0)}a{text-decoration:none;background:0 0}a:active,a:hover{outline:0}table{border-collapse:collapse;border-spacing:0}li{list-style:none}b,strong{font-weight:700}h1,h2,h3,h4,h5,h6{font-weight:500}address,cite,dfn,em,var{font-style:normal}dfn{font-style:italic}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}img{border:0;vertical-align:bottom}.layui-inline,input,label{vertical-align:middle}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;outline:0}button,select{text-transform:none}select{-webkit-appearance:none;border:none}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=1.0.7);src:url(../font/iconfont.eot?v=1.0.7#iefix) format('embedded-opentype'),url(../font/iconfont.woff?v=1.0.7) format('woff'),url(../font/iconfont.ttf?v=1.0.7) format('truetype'),url(../font/iconfont.svg?v=1.0.7#iconfont) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge,.layui-upload-iframe{position:absolute;width:0;height:0}.layui-edge{border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:active{background-color:#d2d2d2!important;color:#fff!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-upload-iframe{border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}@-webkit-keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-left{-webkit-animation-name:layui-m-anim-left;animation-name:layui-m-anim-left}@-webkit-keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-right{-webkit-animation-name:layui-m-anim-right;animation-name:layui-m-anim-right}@-webkit-keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.layui-m-anim-lout{-webkit-animation-name:layui-m-anim-lout;animation-name:layui-m-anim-lout}@-webkit-keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}.layui-m-anim-rout{-webkit-animation-name:layui-m-anim-rout;animation-name:layui-m-anim-rout}.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px} ================================================ FILE: open-layui-web/src/main/view/static/layui/css/modules/code.css ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none} ================================================ FILE: open-layui-web/src/main/view/static/layui/css/modules/laydate/default/laydate.css ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ .laydate-set-ym,.layui-laydate,.layui-laydate *,.layui-laydate-list{box-sizing:border-box}html #layuicss-laydate{display:none;position:absolute;width:1989px}.layui-laydate *{margin:0;padding:0}.layui-laydate{position:absolute;z-index:66666666;margin:5px 0;border-radius:2px;font-size:14px;-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:laydate-upbit;animation-name:laydate-upbit}.layui-laydate-main{width:272px}.layui-laydate-content td,.layui-laydate-header *,.layui-laydate-list li{transition-duration:.3s;-webkit-transition-duration:.3s}@-webkit-keyframes laydate-upbit{from{-webkit-transform:translate3d(0,20px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes laydate-upbit{from{transform:translate3d(0,20px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-laydate-static{position:relative;z-index:0;display:inline-block;margin:0;-webkit-animation:none;animation:none}.laydate-ym-show .laydate-next-m,.laydate-ym-show .laydate-prev-m{display:none!important}.laydate-ym-show .laydate-next-y,.laydate-ym-show .laydate-prev-y{display:inline-block!important}.laydate-time-show .laydate-set-ym span[lay-type=month],.laydate-time-show .laydate-set-ym span[lay-type=year],.laydate-time-show .layui-laydate-header .layui-icon,.laydate-ym-show .laydate-set-ym span[lay-type=month]{display:none!important}.layui-laydate-header{position:relative;line-height:30px;padding:10px 70px 5px}.laydate-set-ym span,.layui-laydate-header i{padding:0 5px;cursor:pointer}.layui-laydate-header *{display:inline-block;vertical-align:bottom}.layui-laydate-header i{position:absolute;top:10px;color:#999;font-size:18px}.layui-laydate-header i.laydate-prev-y{left:15px}.layui-laydate-header i.laydate-prev-m{left:45px}.layui-laydate-header i.laydate-next-y{right:15px}.layui-laydate-header i.laydate-next-m{right:45px}.laydate-set-ym{width:100%;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate-time-text{cursor:default!important}.layui-laydate-content{position:relative;padding:10px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-laydate-content table{border-collapse:collapse;border-spacing:0}.layui-laydate-content td,.layui-laydate-content th{width:36px;height:30px;padding:5px;text-align:center}.layui-laydate-content td{position:relative;cursor:pointer}.laydate-day-mark{position:absolute;left:0;top:0;width:100%;height:100%;line-height:30px;font-size:12px;overflow:hidden}.laydate-day-mark::after{position:absolute;content:'';right:2px;top:2px;width:5px;height:5px;border-radius:50%}.layui-laydate-footer{position:relative;height:46px;line-height:26px;padding:10px 20px}.layui-laydate-footer span{margin-right:15px;display:inline-block;cursor:pointer;font-size:12px}.layui-laydate-footer span:hover{color:#5FB878}.laydate-footer-btns{position:absolute;right:10px;top:10px}.laydate-footer-btns span{height:26px;line-height:26px;margin:0 0 0 -1px;padding:0 10px;border:1px solid #C9C9C9;background-color:#fff;white-space:nowrap;vertical-align:top;border-radius:2px}.layui-laydate-list>li,.layui-laydate-range .layui-laydate-main{display:inline-block;vertical-align:middle}.layui-laydate-list{position:absolute;left:0;top:0;width:100%;height:100%;padding:10px;background-color:#fff}.layui-laydate-list>li{position:relative;width:33.3%;height:36px;line-height:36px;margin:3px 0;text-align:center;cursor:pointer}.laydate-month-list>li{width:25%;margin:17px 0}.laydate-time-list>li{height:100%;margin:0;line-height:normal;cursor:default}.laydate-time-list p{position:relative;top:-4px;line-height:29px}.laydate-time-list ol{height:181px;overflow:hidden}.laydate-time-list>li:hover ol{overflow-y:auto}.laydate-time-list ol li{width:130%;padding-left:33px;line-height:30px;text-align:left;cursor:pointer}.layui-laydate-hint{position:absolute;top:115px;left:50%;width:250px;margin-left:-125px;line-height:20px;padding:15px;text-align:center;font-size:12px}.layui-laydate-range{width:546px}.layui-laydate-range .laydate-main-list-0 .laydate-next-m,.layui-laydate-range .laydate-main-list-0 .laydate-next-y,.layui-laydate-range .laydate-main-list-1 .laydate-prev-m,.layui-laydate-range .laydate-main-list-1 .laydate-prev-y{display:none}.layui-laydate-range .laydate-main-list-1 .layui-laydate-content{border-left:1px solid #e2e2e2}.layui-laydate,.layui-laydate-hint{border:1px solid #d2d2d2;box-shadow:0 2px 4px rgba(0,0,0,.12);background-color:#fff;color:#666}.layui-laydate-header{border-bottom:1px solid #e2e2e2}.layui-laydate-header i:hover,.layui-laydate-header span:hover{color:#5FB878}.layui-laydate-content{border-top:none 0;border-bottom:none 0}.layui-laydate-content th{font-weight:400;color:#333}.layui-laydate-content td{color:#666}.layui-laydate-content td.laydate-selected{background-color:#00F7DE}.laydate-selected:hover{background-color:#00F7DE!important}.layui-laydate-content td:hover,.layui-laydate-list li:hover{background-color:#eaeaea;color:#333}.laydate-time-list li ol{margin:0;padding:0;border:1px solid #e2e2e2;border-left-width:0}.laydate-time-list li:first-child ol{border-left-width:1px}.laydate-time-list>li:hover{background:0 0}.layui-laydate-content .laydate-day-next,.layui-laydate-content .laydate-day-prev{color:#d2d2d2}.laydate-selected.laydate-day-next,.laydate-selected.laydate-day-prev{background-color:#f8f8f8!important}.layui-laydate-footer{border-top:1px solid #e2e2e2}.layui-laydate-hint{color:#FF5722}.laydate-day-mark::after{background-color:#5FB878}.layui-laydate-content td.layui-this .laydate-day-mark::after{display:none}.layui-laydate-footer span[lay-type=date]{color:#5FB878}.layui-laydate .layui-this{background-color:#009688!important;color:#fff!important}.layui-laydate .laydate-disabled,.layui-laydate .laydate-disabled:hover{background:0 0!important;color:#d2d2d2!important;cursor:not-allowed!important;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.laydate-theme-molv{border:none}.laydate-theme-molv.layui-laydate-range{width:548px}.laydate-theme-molv .layui-laydate-main{width:274px}.laydate-theme-molv .layui-laydate-header{border:none;background-color:#009688}.laydate-theme-molv .layui-laydate-header i,.laydate-theme-molv .layui-laydate-header span{color:#f6f6f6}.laydate-theme-molv .layui-laydate-header i:hover,.laydate-theme-molv .layui-laydate-header span:hover{color:#fff}.laydate-theme-molv .layui-laydate-content{border:1px solid #e2e2e2;border-top:none;border-bottom:none}.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left:none}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li,.laydate-theme-grid .layui-laydate-content td,.laydate-theme-grid .layui-laydate-content thead,.laydate-theme-molv .layui-laydate-footer{border:1px solid #e2e2e2}.laydate-theme-grid .laydate-selected,.laydate-theme-grid .laydate-selected:hover{background-color:#f2f2f2!important;color:#009688!important}.laydate-theme-grid .laydate-selected.laydate-day-next,.laydate-theme-grid .laydate-selected.laydate-day-prev{color:#d2d2d2!important}.laydate-theme-grid .laydate-month-list,.laydate-theme-grid .laydate-year-list{margin:1px 0 0 1px}.laydate-theme-grid .laydate-month-list>li,.laydate-theme-grid .laydate-year-list>li{margin:0 -1px -1px 0}.laydate-theme-grid .laydate-year-list>li{height:43px;line-height:43px}.laydate-theme-grid .laydate-month-list>li{height:71px;line-height:71px} ================================================ FILE: open-layui-web/src/main/view/static/layui/css/modules/layer/default/layer.css ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ .layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.layui-layer-title{text-overflow:ellipsis;white-space:nowrap}html #layuicss-layer{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{-webkit-overflow-scrolling:touch;top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(icon.png) no-repeat}.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;background-color:#F8F8F8;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:15px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2E2D3C;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:1px -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:5px 5px 0;padding:0 15px;border:1px solid #dedede;background-color:#fff;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:#1E9FFF;background-color:#1E9FFF;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:260px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;_left:-40px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(loading-2.gif) no-repeat}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:5px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476A7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:5px 10px 10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#E9E7E7;color:#333}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}.layui-layer-iconext{background:url(icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:230px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;overflow:hidden;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:43px;border-left:1px solid #eee;border-right:1px solid #eee;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.layui-this{display:block}.layui-layer-photos{-webkit-animation-duration:.8s;animation-duration:.8s}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}} ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/carousel.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("jquery",function(e){"use strict";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t="carousel",a="layui-this",l=">*[carousel-item]>*",o="layui-carousel-left",r="layui-carousel-right",d="layui-carousel-prev",s="layui-carousel-next",u="layui-carousel-arrow",c="layui-carousel-ind",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr("lay-anim",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['",'"].join(""));n.elem.attr("lay-arrow",n.arrow),n.elem.find("."+u)[0]&&n.elem.find("."+u).remove(),n.elem.append(t),t.on("click",function(){var n=i(this),t=n.attr("lay-type");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['
          ',function(){var i=[];return layui.each(e.elemItem,function(e){i.push("")}),i.join("")}(),"
        "].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+c)[0]&&n.elem.find("."+c).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-(t.height()/2)),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide("add",a-n.index):a/g,">").replace(/'/g,"'").replace(/"/g,""")),c.html('
        1. '+o.replace(/[\r\t\n]+/g,"
        2. ")+"
        "),c.find(">.layui-code-h3")[0]||c.prepend('

        '+(c.attr("lay-title")||e.title||"code")+(e.about?'layui.code':"")+"

        ");var d=c.find(">.layui-code-ol");c.addClass("layui-box layui-code-view"),(c.attr("lay-skin")||e.skin)&&c.addClass("layui-code-"+(c.attr("lay-skin")||e.skin)),(d.find("li").length/100|0)>0&&d.css("margin-left",(d.find("li").length/100|0)+"px"),(c.attr("lay-height")||e.height)&&d.css("max-height",c.attr("lay-height")||e.height)})})}).addcss("modules/code.css","skincodecss"); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/element.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("jquery",function(t){"use strict";var a=layui.$,i=(layui.hint(),layui.device()),e="element",l="layui-this",n="layui-show",s=function(){this.config={}};s.prototype.set=function(t){var i=this;return a.extend(!0,i.config,t),i},s.prototype.on=function(t,a){return layui.onevent.call(this,e,t,a)},s.prototype.tabAdd=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.children(".layui-tab-bar"),o=l.children(".layui-tab-content"),r='
      • "+(i.title||"unnaming")+"
      • ";return s[0]?s.before(r):n.append(r),o.append('
        '+(i.content||"")+"
        "),f.hideTabMore(!0),f.tabAuto(),this},s.prototype.tabDelete=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+i+'"]');return f.tabDelete(null,s),this},s.prototype.tabChange=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+i+'"]');return f.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(t){t=t||{},b.on("click",t.headerElem,function(i){var e=a(this).index();f.tabClick.call(this,i,e,null,t)})},s.prototype.progress=function(t,i){var e="layui-progress",l=a("."+e+"[lay-filter="+t+"]"),n=l.find("."+e+"-bar"),s=n.find("."+e+"-text");return n.css("width",i),s.text(i),this};var o=".layui-nav",r="layui-nav-item",c="layui-nav-bar",u="layui-nav-tree",d="layui-nav-child",y="layui-nav-more",h="layui-anim layui-anim-upbit",f={tabClick:function(t,i,s,o){o=o||{};var r=s||a(this),i=i||r.parent().children("li").index(r),c=o.headerElem?r.parent():r.parents(".layui-tab").eq(0),u=o.bodyElem?a(o.bodyElem):c.children(".layui-tab-content").children(".layui-tab-item"),d=r.find("a"),y=c.attr("lay-filter");"javascript:;"!==d.attr("href")&&"_blank"===d.attr("target")||(r.addClass(l).siblings().removeClass(l),u.eq(i).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,"tab("+y+")",{elem:c,index:i})},tabDelete:function(t,i){var n=i||a(this).parent(),s=n.index(),o=n.parents(".layui-tab").eq(0),r=o.children(".layui-tab-content").children(".layui-tab-item"),c=o.attr("lay-filter");n.hasClass(l)&&(n.next()[0]?f.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&f.tabClick.call(n.prev()[0],null,s-1)),n.remove(),r.eq(s).remove(),setTimeout(function(){f.tabAuto()},50),layui.event.call(this,e,"tabDelete("+c+")",{elem:o,index:s})},tabAuto:function(){var t="layui-tab-more",e="layui-tab-bar",l="layui-tab-close",n=this;a(".layui-tab").each(function(){var s=a(this),o=s.children(".layui-tab-title"),r=(s.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),c=a('');if(n===window&&8!=i.ie&&f.hideTabMore(!0),s.attr("lay-allowClose")&&o.find("li").each(function(){var t=a(this);if(!t.find("."+l)[0]){var i=a('');i.on("click",f.tabDelete),t.append(i)}}),"string"!=typeof s.attr("lay-unauto"))if(o.prop("scrollWidth")>o.outerWidth()+1){if(o.find("."+e)[0])return;o.append(c),s.attr("overflow",""),c.on("click",function(a){o[this.title?"removeClass":"addClass"](t),this.title=this.title?"":"收缩"})}else o.find("."+e).remove(),s.removeAttr("overflow")})},hideTabMore:function(t){var i=a(".layui-tab-title");t!==!0&&"tabmore"===a(t.target).attr("lay-stope")||(i.removeClass("layui-tab-more"),i.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=a(this),i=t.parents(o),n=i.attr("lay-filter"),s=t.parent(),c=t.siblings("."+d),y="string"==typeof s.attr("lay-unselect");"javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||y||c[0]||(i.find("."+l).removeClass(l),s.addClass(l)),i.hasClass(u)&&(c.removeClass(h),c[0]&&(s["none"===c.css("display")?"addClass":"removeClass"](r+"ed"),"all"===i.attr("lay-shrink")&&s.siblings().removeClass(r+"ed"))),layui.event.call(this,e,"nav("+n+")",t)},collapse:function(){var t=a(this),i=t.find(".layui-colla-icon"),l=t.siblings(".layui-colla-content"),s=t.parents(".layui-collapse").eq(0),o=s.attr("lay-filter"),r="none"===l.css("display");if("string"==typeof s.attr("lay-accordion")){var c=s.children(".layui-colla-item").children("."+n);c.siblings(".layui-colla-title").children(".layui-colla-icon").html(""),c.removeClass(n)}l[r?"addClass":"removeClass"](n),i.html(r?"":""),layui.event.call(this,e,"collapse("+o+")",{title:t,content:l,show:r})}};s.prototype.init=function(t,e){var l=function(){return e?'[lay-filter="'+e+'"]':""}(),s={tab:function(){f.tabAuto.call({})},nav:function(){var t=200,e={},s={},p={},b=function(l,o,r){var c=a(this),f=c.find("."+d);o.hasClass(u)?l.css({top:c.position().top,height:c.children("a").outerHeight(),opacity:1}):(f.addClass(h),l.css({left:c.position().left+parseFloat(c.css("marginLeft")),top:c.position().top+c.height()-l.height()}),e[r]=setTimeout(function(){l.css({width:c.width(),opacity:1})},i.ie&&i.ie<10?0:t),clearTimeout(p[r]),"block"===f.css("display")&&clearTimeout(s[r]),s[r]=setTimeout(function(){f.addClass(n),c.find("."+y).addClass(y+"d")},300))};a(o+l).each(function(i){var l=a(this),o=a(''),h=l.find("."+r);l.find("."+c)[0]||(l.append(o),h.on("mouseenter",function(){b.call(this,o,l,i)}).on("mouseleave",function(){l.hasClass(u)||(clearTimeout(s[i]),s[i]=setTimeout(function(){l.find("."+d).removeClass(n),l.find("."+y).removeClass(y+"d")},300))}),l.on("mouseleave",function(){clearTimeout(e[i]),p[i]=setTimeout(function(){l.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},t)})),h.find("a").each(function(){var t=a(this),i=(t.parent(),t.siblings("."+d));i[0]&&!t.children("."+y)[0]&&t.append(''),t.off("click",f.clickThis).on("click",f.clickThis)})})},breadcrumb:function(){var t=".layui-breadcrumb";a(t+l).each(function(){var t=a(this),i="lay-separator",e=t.attr(i)||"/",l=t.find("a");l.next("span["+i+"]")[0]||(l.each(function(t){t!==l.length-1&&a(this).after(""+e+"")}),t.css("visibility","visible"))})},progress:function(){var t="layui-progress";a("."+t+l).each(function(){var i=a(this),e=i.find(".layui-progress-bar"),l=e.attr("lay-percent");e.css("width",function(){return/^.+\/.+$/.test(l)?100*new Function("return "+l)()+"%":l}()),i.attr("lay-showPercent")&&setTimeout(function(){e.html(''+l+"")},350)})},collapse:function(){var t="layui-collapse";a("."+t+l).each(function(){var t=a(this).find(".layui-colla-item");t.each(function(){var t=a(this),i=t.find(".layui-colla-title"),e=t.find(".layui-colla-content"),l="none"===e.css("display");i.find(".layui-colla-icon").remove(),i.append(''+(l?"":"")+""),i.off("click",f.collapse).on("click",f.collapse)})})}};return s[t]?s[t]():layui.each(s,function(t,a){a()})},s.prototype.render=s.prototype.init;var p=new s,b=a(document);p.render();var v=".layui-tab-title li";b.on("click",v,f.tabClick),b.on("click",f.hideTabMore),a(window).on("resize",f.tabAuto),t(e,p)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/flow.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("jquery",function(e){"use strict";var l=layui.$,o=function(e){},t='';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!("isAuto"in e)||e.isAuto,v=e.end||"没有更多了",y=e.scrollElem&&e.scrollElem!==document,d="加载更多",h=l('");f.find(".layui-flow-more")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find("a").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find("a").html(t),"function"==typeof e.done&&e.done(++c,p)};if(g(),h.find("a").on("click",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+" img",scrollElem:e.scrollElem});return s?(m.on("scroll",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop("scrollHeight"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||"img",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr("src")){var m=e.attr("lay-src");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr("src",m).removeAttr("lay-src"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;su)break}};if(f(),!o){var m;n.on("scroll",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e("flow",new o)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/form.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("layer",function(e){"use strict";var i=layui.$,t=layui.layer,a=layui.hint(),n=layui.device(),l="form",r=".layui-form",s="layui-this",c="layui-hide",o="layui-disabled",u=function(){this.config={verify:{required:[/[\S]+/,"必填项不能为空"],phone:[/^1\d{10}$/,"请输入正确的手机号"],email:[/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,"邮箱格式不正确"],url:[/(^#)|(^http(s*):\/\/[^\s]+\.[^\s]+)/,"链接格式不正确"],number:function(e){if(!e||isNaN(e))return"只能填写数字"},date:[/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/,"日期格式不正确"],identity:[/(^\d{15}$)|(^\d{17}(x|X|\d)$)/,"请输入正确的身份证号"]}}};u.prototype.set=function(e){var t=this;return i.extend(!0,t.config,e),t},u.prototype.verify=function(e){var t=this;return i.extend(!0,t.config.verify,e),t},u.prototype.on=function(e,i){return layui.onevent.call(this,l,e,i)},u.prototype.val=function(e,t){var a=i(r+'[lay-filter="'+e+'"]');a.each(function(e,a){var n=i(this);layui.each(t,function(e,i){var t,a=n.find('[name="'+e+'"]');a[0]&&(t=a[0].type,"checkbox"===t?a[0].checked=i:"radio"===t?a.each(function(){this.value===i&&(this.checked=!0)}):a.val(i))})}),f.render(null,e)},u.prototype.render=function(e,t){var n=this,u=i(r+function(){return t?'[lay-filter="'+t+'"]':""}()),d={select:function(){var e,t="请选择",a="layui-form-select",n="layui-select-title",r="layui-select-none",d="",f=u.find("select"),v=function(t,l){i(t.target).parent().hasClass(n)&&!l||(i("."+a).removeClass(a+"ed "+a+"up"),e&&d&&e.val(d)),e=null},h=function(t,u,f){var h,p=i(this),m=t.find("."+n),k=m.find("input"),g=t.find("dl"),x=g.children("dd"),b=this.selectedIndex;if(!u){var C=function(){var e=t.offset().top+t.outerHeight()+5-y.scrollTop(),i=g.outerHeight();b=p[0].selectedIndex,t.addClass(a+"ed"),x.removeClass(c),x.eq(b).addClass(s).siblings().removeClass(s),e+i>y.height()&&e>=i&&t.addClass(a+"up")},w=function(e){t.removeClass(a+"ed "+a+"up"),k.blur(),h=null,e||$(k.val(),function(e){e&&(d=g.find("."+s).html(),k&&k.val(d))})};m.on("click",function(e){t.hasClass(a+"ed")?w():(v(e,!0),C()),g.find("."+r).remove()}),m.find(".layui-edge").on("click",function(){k.focus()}),k.on("keyup",function(e){var i=e.keyCode;9===i&&C()}).on("keydown",function(e){var i=e.keyCode;9===i&&w();var t=function(i,a){var n,l;if(e.preventDefault(),a=function(){return a&&a[0]?a:h&&h[0]?h:x.eq(b)}(),l=a[i](),n=a[i]("dd"),l[0])return h=a[i](),!n[0]||n.hasClass(o)?t(i,h):void n.addClass(s).siblings().removeClass(s)};38===i&&t("prev"),40===i&&t("next"),13===i&&(e.preventDefault(),g.children("dd."+s).trigger("click"))});var $=function(e,t,a){var n=0;layui.each(x,function(){var t=i(this),l=t.text(),r=l.indexOf(e)===-1;(""===e||"blur"===a?e!==l:r)&&n++,"keyup"===a&&t[r?"addClass":"removeClass"](c)});var l=n===x.length;return t(l),l},T=function(e){var i=this.value,t=e.keyCode;return 9!==t&&13!==t&&37!==t&&38!==t&&39!==t&&40!==t&&($(i,function(e){e?g.find("."+r)[0]||g.append('

        无匹配项

        '):g.find("."+r).remove()},"keyup"),void(""===i&&g.find("."+r).remove()))};f&&k.on("keyup",T).on("blur",function(t){var a=p[0].selectedIndex;e=k,d=i(p[0].options[a]).html(),setTimeout(function(){$(k.val(),function(e){d||k.val("")},"blur")},200)}),x.on("click",function(){var e=i(this),a=e.attr("lay-value"),n=p.attr("lay-filter");return!e.hasClass(o)&&(e.hasClass("layui-select-tips")?k.val(""):(k.val(e.text()),e.addClass(s)),e.siblings().removeClass(s),p.val(a).removeClass("layui-form-danger"),layui.event.call(this,l,"select("+n+")",{elem:p[0],value:a,othis:t}),w(!0),!1)}),t.find("dl>dt").on("click",function(e){return!1}),i(document).off("click",v).on("click",v)}};f.each(function(e,l){var r=i(this),c=r.next("."+a),u=this.disabled,d=l.value,f=i(l.options[l.selectedIndex]),v=l.options[0];if("string"==typeof r.attr("lay-ignore"))return r.show();var y="string"==typeof r.attr("lay-search"),p=v?v.value?t:v.innerHTML||t:t,m=i(['
        ','
        ','','
        ','
        ',function(e){var i=[];return layui.each(e,function(e,a){0!==e||a.value?"optgroup"===a.tagName.toLowerCase()?i.push("
        "+a.label+"
        "):i.push('
        '+a.innerHTML+"
        "):i.push('
        '+(a.innerHTML||t)+"
        ")}),0===i.length&&i.push('
        没有选项
        '),i.join("")}(r.find("*"))+"
        ","
        "].join(""));c[0]&&c.remove(),r.after(m),h.call(this,m,u,y)})},checkbox:function(){var e={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],_switch:["layui-form-switch","layui-form-onswitch","switch"]},t=u.find("input[type=checkbox]"),a=function(e,t){var a=i(this);e.on("click",function(){var i=a.attr("lay-filter"),n=(a.attr("lay-text")||"").split("|");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(t[1]).find("em").text(n[1])):(a[0].checked=!0,e.addClass(t[1]).find("em").text(n[0])),layui.event.call(a[0],l,t[2]+"("+i+")",{elem:a[0],value:a[0].value,othis:e}))})};t.each(function(t,n){var l=i(this),r=l.attr("lay-skin"),s=(l.attr("lay-text")||"").split("|"),c=this.disabled;"switch"===r&&(r="_"+r);var u=e[r]||e.checkbox;if("string"==typeof l.attr("lay-ignore"))return l.show();var d=l.next("."+u[0]),f=i(['
        ",function(){var e=n.title.replace(/\s/g,""),i={checkbox:[e?""+n.title+"":"",''].join(""),_switch:""+((n.checked?s[0]:s[1])||"")+""};return i[r]||i.checkbox}(),"
        "].join(""));d[0]&&d.remove(),l.after(f),a.call(this,f,u)})},radio:function(){var e="layui-form-radio",t=["",""],a=u.find("input[type=radio]"),n=function(a){var n=i(this),s="layui-anim-scaleSpring";a.on("click",function(){var c=n[0].name,o=n.parents(r),u=n.attr("lay-filter"),d=o.find("input[name="+c.replace(/(\.|#|\[|\])/g,"\\$1")+"]");n[0].disabled||(layui.each(d,function(){var a=i(this).next("."+e);this.checked=!1,a.removeClass(e+"ed"),a.find(".layui-icon").removeClass(s).html(t[1])}),n[0].checked=!0,a.addClass(e+"ed"),a.find(".layui-icon").addClass(s).html(t[0]),layui.event.call(n[0],l,"radio("+u+")",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=i(this),s=r.next("."+e),c=this.disabled;if("string"==typeof r.attr("lay-ignore"))return r.show();s[0]&&s.remove();var u=i(['
        ',''+t[l.checked?0:1]+"","
        "+function(){var e=l.title||"";return"string"==typeof r.next().attr("lay-radio")&&(e=r.next().html(),r.next().remove()),e}()+"
        ","
        "].join(""));r.after(u),n.call(this,u)})}};return e?d[e]?d[e]():a.error("不支持的"+e+"表单渲染"):layui.each(d,function(e,i){i()}),n};var d=function(){var e=i(this),a=f.config.verify,s=null,c="layui-form-danger",o={},u=e.parents(r),d=u.find("*[lay-verify]"),v=e.parents("form")[0],y=u.find("input,select,textarea"),h=e.attr("lay-filter");if(layui.each(d,function(e,l){var r=i(this),o=r.attr("lay-verify").split("|"),u=r.attr("lay-verType"),d=r.val();if(r.removeClass(c),layui.each(o,function(e,i){var o,f="",v="function"==typeof a[i];if(a[i]){var o=v?f=a[i](d,l):!a[i][0].test(d);if(f=f||a[i][1],o)return"tips"===u?t.tips(f,function(){return"string"==typeof r.attr("lay-ignore")||"select"!==l.tagName.toLowerCase()&&!/^checkbox|radio$/.test(l.type)?r:r.next()}(),{tips:1}):"alert"===u?t.alert(f,{title:"提示",shadeClose:!0}):t.msg(f,{icon:5,shift:6}),n.android||n.ios||l.focus(),r.addClass(c),s=!0}}),s)return s}),s)return!1;var p={};return layui.each(y,function(e,i){if(i.name=(i.name||"").replace(/^\s*|\s*&/,""),i.name){if(/^.*\[\]$/.test(i.name)){var t=i.name.match(/^(.*)\[\]$/g)[0];p[t]=0|p[t],i.name=i.name.replace(/^(.*)\[\]$/,"$1["+p[t]++ +"]")}/^checkbox|radio$/.test(i.type)&&!i.checked||(o[i.name]=i.value)}}),layui.event.call(this,l,"submit("+h+")",{elem:this,form:v,field:o})},f=new u,v=i(document),y=i(window);f.render(),v.on("reset",r,function(){var e=i(this).attr("lay-filter");setTimeout(function(){f.render(null,e)},50)}),v.on("submit",r,d).on("click","*[lay-submit]",d),e(l,f)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/jquery.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&"length"in e&&e.length,n=pe.type(e);return"function"!==n&&!pe.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener("DOMContentLoaded",s),e.removeEventListener("load",s)):(re.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(re.addEventListener||"load"===e.event.type||"complete"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(_e,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n||"false"!==n&&("null"===n?null:+n+""===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if(("data"!==t||!pe.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||"string"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),"object"!=typeof t&&"function"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,"")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?"":"px"),c=(pe.cssNumber[t]||"px"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||".5",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,"globalEval",!t||pe._data(t[r],"globalEval"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,"input"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),"script"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||"")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,"table")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function C(e){return e.type=(null!==pe.find.attr(e,"type"))+"/"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r1&&"string"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,"script"),C),a=s.length;c")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a=0&&n=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||"object"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,"constructor")&&!ce.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?ue[le.call(e)]||"object":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,"ms-").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;iT.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[" "],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),n,s0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h="0",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG("*",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P="sizzle"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),ce=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(oe),de=new RegExp("^"+re+"$"),pe={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ye=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ve=/[+~]/,xe=/'|\\/g,be=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),we=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Te,!1):n.attachEvent&&n.attachEvent("onunload",Te)),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute("id")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&F.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+P+"-]").length||F.push("~="),e.querySelectorAll(":checked").length||F.push(":checked"),e.querySelectorAll("a#"+P+"+*").length||F.push(".#.+[+~]")}),i(function(e){var t=H.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+ne+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),M.push("!=",oe)}),F=F.length&&new RegExp(F.join("|")),M=M.length&&new RegExp(M.join("|")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,"='$1']"),w.matchesSelector&&_&&!X[n+" "]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(be,we),e[3]=(e[3]||e[4]||e[5]||"").replace(be,we),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(ae," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,d,p,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}), l=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[P]?o(n):o.length>1?(i=[e,e,"",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,"$1"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split("").sort(U).join("")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("div"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[":"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Ce=/^.[^:#\[\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t1?pe.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,"string"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,"string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,"parentNode")},parentsUntil:function(e,t,n){return xe(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return xe(e,"nextSibling")},prevAll:function(e){return xe(e,"previousSibling")},nextUntil:function(e,t,n){return xe(e,"nextSibling",n)},prevUntil:function(e,t,n){return xe(e,"previousSibling",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\S+/g;pe.Callbacks=function(e){e="string"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n="",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[["resolve","done",pe.Callbacks("once memory"),"resolved"],["reject","fail",pe.Callbacks("once memory"),"rejected"],["notify","progress",pe.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler("ready"),pe(re).off("ready"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),"complete"===re.readyState||"loading"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener("DOMContentLoaded",s),e.addEventListener("load",s);else{re.attachEvent("onreadystatechange",s),e.attachEvent("onload",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll("left")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst="0"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName("body")[0],n&&n.style&&(t=re.createElement("div"),r=re.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),"undefined"!=typeof t.style.zoom&&(t.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement("div");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+" ").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute("classid")===t)},qe=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,"parsedAttrs"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,"parsedAttrs",!0)}return i}return"object"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks("once memory").add(function(){pe._removeData(e,t+"queue"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length
        a",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName("tbody").length,fe.htmlSerialize=!!e.getElementsByTagName("link").length,fe.html5Clone="<:nav>"!==re.createElement("nav").cloneNode(!0).outerHTML,n.type="checkbox",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML="",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement("input"),n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={option:[1,""],legend:[1,"
        ","
        "],area:[1,"",""],param:[1,"",""],thead:[1,"","
        "],tr:[2,"","
        "],col:[2,"","
        "],td:[3,"","
        "],_default:fe.htmlSerialize?[0,"",""]:[1,"X
        ","
        "]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\w+;/,Ve=/-1&&(h=p.split("."),p=h.shift(),h.sort()),a=p.indexOf(":")<0&&"on"+p,t=t[pe.expando]?t:new pe.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,"events")||{})[t.type]&&pe._data(s,"handle"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,"events")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&("click"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(r=[],n=0;n-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s]","i"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,nt=/\s*$/g,at=p(re),st=at.appendChild(re.createElement("div"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,"<$1>")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,"script"),r.length>0&&g(r,!u&&h(e,"script")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||"undefined"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,""):void 0;if("string"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||["",""])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;nt",t=l.getElementsByTagName("td"),t[0].style.cssText="margin:0;border:0;padding:0;display:none",o=0===t[0].offsetHeight,o&&(t[0].style.display="",t[1].style.display="none",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement("div"),l=re.createElement("div");l.style&&(l.style.cssText="float:left;opacity:.5",fe.opacity="0.5"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",fe.clearCloneStyle="content-box"===l.style.backgroundClip,u=re.createElement("div"),u.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",l.innerHTML="",u.appendChild(l),fe.boxSizing=""===l.style.boxSizing||""===l.style.MozBoxSizing||""===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,""!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+""}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left="fontSize"===t?"1em":a,a=s.pixelLeft+"px",s.left=r,o&&(i.left=o)),void 0===a?a:a+""||"auto"});var yt=/alpha\([^)]*\)/i,vt=/opacity\s*=\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp("^("+Fe+")(.*)$","i"),wt={position:"absolute",visibility:"hidden",display:"block"},Tt={letterSpacing:"0",fontWeight:"400"},Ct=["Webkit","O","Moz","ms"],Et=re.createElement("div").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":fe.cssFloat?"cssFloat":"styleFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,"string"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?"":"px")),fe.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),!(a&&"set"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&"get"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),"normal"===o&&t in Tt&&(o=Tt[t]),""===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each(["height","width"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,"display"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&"border-box"===pe.css(e,"boxSizing",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=pe.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===pe.trim(o.replace(yt,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+" "+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:"inline-block"},gt,[e,"marginRight"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,"marginLeft"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+"px"}),pe.each({margin:"",padding:"",border:"Width"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?"":"px")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=["*"]):e=e.match(De);for(var n,r=0,i=e.length;r
        a",e=n.getElementsByTagName("a")[0],t.setAttribute("type","checkbox"),n.appendChild(t),e=n.getElementsByTagName("a")[0],e.style.cssText="top:1px",fe.getSetAttribute="t"!==n.className,fe.style=/top/.test(e.getAttribute("style")),fe.hrefNormalized="/a"===e.getAttribute("href"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement("form").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement("input"),t.setAttribute("value",""),fe.input=""===t.getAttribute("value"),t.value="t",t.setAttribute("type","radio"),fe.radioValue="t"===t.value}();var Dt=/\r/g,jt=/[\x20\t\r\n\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i="":"number"==typeof i?i+="":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?"":e+""})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(Dt,""):null==n?"":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,"value");return null!=t?t:pe.trim(pe.text(e)).replace(jt," ")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each(["radio","checkbox"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&"radio"===t&&pe.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase("default-"+n)]=e[r]=!1:pe.attr(e,n,""),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase("default-"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase("default-"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,"input")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+="","value"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&""!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,""!==t&&t,n)}},pe.each(["width","height"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(""===n)return e.setAttribute(t,"auto"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+""}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,"tabindex");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),fe.hrefNormalized||pe.each(["href","src"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype="encoding");var Pt=/[\t\r\n\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if("string"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&"boolean"!==n||(t=z(this),t&&pe._data(this,"__className__",t),pe.attr(this,"class",t||e===!1?"":pe._data(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+z(n)+" ").replace(Pt," ").indexOf(t)>-1)return!0;return!1}}),pe.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\?/,$t=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+"");var n,r=null,i=pe.trim(t+"");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,"")}))?Function("return "+i)():pe.error("Invalid JSON: "+t)},pe.parseXML=function(t){var n,r;if(!t||"string"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,"text/xml")):(n=new e.ActiveXObject("Microsoft.XMLDOM"),n.async="false",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName("parsererror").length||pe.error("Invalid XML: "+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\/\//,Gt=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Kt={},Qt={},Zt="*/".concat("*"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:"GET",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Zt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":pe.parseJSON,"text xml":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||"",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader("Last-Modified"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader("etag"),w&&(pe.etag[a]=w)),204===t||"HEAD"===d.type?C="nocontent":304===t?C="notmodified":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C="error",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+"",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?"ajaxSuccess":"ajaxError",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger("ajaxComplete",[T,d]),--pe.active||pe.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks("once memory"),y=d.statusCode||{},v={},x={},b=0,w="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+"").replace(zt,"").replace(Jt,tn[1]+"//"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||"*").toLowerCase().match(De)||[""],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||("http:"===i[1]?"80":"443"))===(tn[3]||("http:"===tn[1]?"80":"443")))),d.data&&d.processData&&"string"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?"&":"?")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,"$1_="+Wt++):a+(It.test(a)?"&":"?")+"_="+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader("If-Modified-Since",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader("If-None-Match",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader("Content-Type",d.contentType),T.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Zt+"; q=0.01":""):d.accepts["*"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w="abort";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger("ajaxSend",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort("timeout")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,"No Transport");return T},getJSON:function(e,t,n){return pe.get(e,t,n,"json")},getScript:function(e,t){return pe.get(e,void 0,t,"script")}}),pe.each(["get","post"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,"body")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\[\]$/,on=/\r?\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join("&").replace(nn,"+")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,"elements");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(":disabled")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent("onunload",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&"withCredentials"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r["X-Requested-With"]||(r["X-Requested-With"]="XMLHttpRequest");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+"");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,"string"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=""}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),pe.ajaxTransport("script",function(e){if(e.crossDomain){var t,n=re.head||pe("head")[0]||re.documentElement;return{send:function(r,i){t=re.createElement("script"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,"success"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\?(?=&|$)|\?\?/;pe.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=fn.pop()||pe.expando+"_"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&dn.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,"$1"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||pe.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),"script"}),pe.parseHTML=function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if("string"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&pe.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?pe("
        ").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,"position"),f=pe(e),d={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=pe.css(e,"top"),u=pe.css(e,"left"),l=("absolute"===c||"fixed"===c)&&pe.inArray("auto",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),"using"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?("undefined"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===pe.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],"html")||(n=e.offset()),n.top+=pe.css(e[0],"borderTopWidth",!0),n.left+=pe.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-pe.css(r,"marginTop",!0),left:t.left-n.left-pe.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){ for(var e=this.offsetParent;e&&!pe.nodeName(e,"html")&&"static"===pe.css(e,"position");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each(["top","left"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+"px":n})}),pe.each({Height:"height",Width:"width"},function(e,t){pe.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),a=n||(r===!0||i===!0?"margin":"border");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e("jquery",pe)}),pe}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/laydate.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;!function(){"use strict";var e=window.layui&&layui.define,t={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,n=t.length-1,a=n;a>0;a--)if("interactive"===t[a].readyState){e=t[a].src;break}return e||t[n].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),getStyle:function(e,t){var n=e.currentStyle?e.currentStyle:window.getComputedStyle(e,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](t)},link:function(e,a,i){if(n.path){var r=document.getElementsByTagName("head")[0],o=document.createElement("link");"string"==typeof a&&(i=a);var s=(i||e).replace(/\.|\//g,""),l="layuicss-"+s,d=0;o.rel="stylesheet",o.href=n.path+e,o.id=l,document.getElementById(l)||r.appendChild(o),"function"==typeof a&&!function c(){return++d>80?window.console&&console.error("laydate.css: Invalid"):void(1989===parseInt(t.getStyle(document.getElementById(l),"width"))?a():setTimeout(c,100))}()}}},n={v:"5.0.9",config:{},index:window.laydate&&window.laydate.v?1e5:0,path:t.getPath,set:function(e){var t=this;return t.config=w.extend({},t.config,e),t},ready:function(a){var i="laydate",r="",o=(e?"modules/laydate/":"theme/")+"default/laydate.css?v="+n.v+r;return e?layui.addcss(o,a,i):t.link(o,a,i),this}},a=function(){var e=this;return{hint:function(t){e.hint.call(e,t)},config:e.config}},i="laydate",r=".layui-laydate",o="layui-this",s="laydate-disabled",l="开始日期超出了结束日期
        建议重新选择",d=[100,2e5],c="layui-laydate-static",m="layui-laydate-list",u="laydate-selected",h="layui-laydate-hint",y="laydate-day-prev",f="laydate-day-next",p="layui-laydate-footer",g=".laydate-btns-confirm",v="laydate-time-text",D=".laydate-btns-time",T=function(e){var t=this;t.index=++n.index,t.config=w.extend({},t.config,n.config,e),n.ready(function(){t.init()})},w=function(e){return new C(e)},C=function(e){for(var t=0,n="object"==typeof e?[e]:(this.selector=e,document.querySelectorAll(e||null));t0)return n[0].getAttribute(e)}():n.each(function(n,a){a.setAttribute(e,t)})},C.prototype.removeAttr=function(e){return this.each(function(t,n){n.removeAttribute(e)})},C.prototype.html=function(e){return this.each(function(t,n){n.innerHTML=e})},C.prototype.val=function(e){return this.each(function(t,n){n.value=e})},C.prototype.append=function(e){return this.each(function(t,n){"object"==typeof e?n.appendChild(e):n.innerHTML=n.innerHTML+e})},C.prototype.remove=function(e){return this.each(function(t,n){e?n.removeChild(e):n.parentNode.removeChild(n)})},C.prototype.on=function(e,t){return this.each(function(n,a){a.attachEvent?a.attachEvent("on"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1)})},C.prototype.off=function(e,t){return this.each(function(n,a){a.detachEvent?a.detachEvent("on"+e,t):a.removeEventListener(e,t,!1)})},T.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},T.prototype.config={type:"date",range:!1,format:"yyyy-MM-dd",value:null,isInitValue:!1,min:"1900-1-1",max:"2099-12-31",trigger:"focus",show:!1,showBottom:!0,btns:["clear","now","confirm"],lang:"cn",theme:"default",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},T.prototype.lang=function(){var e=this,t=e.config,n={cn:{weeks:["日","一","二","三","四","五","六"],time:["时","分","秒"],timeTips:"选择时间",startTime:"开始时间",endTime:"结束时间",dateTips:"返回日期",month:["一","二","三","四","五","六","七","八","九","十","十一","十二"],tools:{confirm:"确定",clear:"清空",now:"现在"}},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"}}};return n[t.lang]||n.cn},T.prototype.init=function(){var e=this,t=e.config,n="yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s",a="static"===t.position,i={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};t.elem=w(t.elem),t.eventElem=w(t.eventElem),t.elem[0]&&(t.range===!0&&(t.range="-"),t.format===i.date&&(t.format=i[t.type]),e.format=t.format.match(new RegExp(n+"|.","g"))||[],e.EXP_IF="",e.EXP_SPLIT="",w.each(e.format,function(t,a){var i=new RegExp(n).test(a)?"\\d{"+function(){return new RegExp(n).test(e.format[0===t?t+1:t-1]||"")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?"1,4":/^y$/.test(a)?"1,308":"1,2"}()+"}":"\\"+a;e.EXP_IF=e.EXP_IF+i,e.EXP_SPLIT=e.EXP_SPLIT+"("+i+")"}),e.EXP_IF=new RegExp("^"+(t.range?e.EXP_IF+"\\s\\"+t.range+"\\s"+e.EXP_IF:e.EXP_IF)+"$"),e.EXP_SPLIT=new RegExp("^"+e.EXP_SPLIT+"$",""),e.isInput(t.elem[0])||"focus"===t.trigger&&(t.trigger="click"),t.elem.attr("lay-key")||(t.elem.attr("lay-key",e.index),t.eventElem.attr("lay-key",e.index)),t.mark=w.extend({},t.calendar&&"cn"===t.lang?{"0-1-1":"元旦","0-2-14":"情人","0-3-8":"妇女","0-3-12":"植树","0-4-1":"愚人","0-5-1":"劳动","0-5-4":"青年","0-6-1":"儿童","0-9-10":"教师","0-9-18":"国耻","0-10-1":"国庆","0-12-25":"圣诞"}:{},t.mark),w.each(["min","max"],function(e,n){var a=[],i=[];if("number"==typeof t[n]){var r=t[n],o=(new Date).getTime(),s=864e5,l=new Date(r?r0)return!0;var a=w.elem("div",{"class":"layui-laydate-header"}),i=[function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-prev-y"});return e.innerHTML="",e}(),function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-prev-m"});return e.innerHTML="",e}(),function(){var e=w.elem("div",{"class":"laydate-set-ym"}),t=w.elem("span"),n=w.elem("span");return e.appendChild(t),e.appendChild(n),e}(),function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-next-m"});return e.innerHTML="",e}(),function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-next-y"});return e.innerHTML="",e}()],d=w.elem("div",{"class":"layui-laydate-content"}),c=w.elem("table"),m=w.elem("thead"),u=w.elem("tr");w.each(i,function(e,t){a.appendChild(t)}),m.appendChild(u),w.each(new Array(6),function(e){var t=c.insertRow(0);w.each(new Array(7),function(a){if(0===e){var i=w.elem("th");i.innerHTML=n.weeks[a],u.appendChild(i)}t.insertCell(a)})}),c.insertBefore(m,c.children[0]),d.appendChild(c),r[e]=w.elem("div",{"class":"layui-laydate-main laydate-main-list-"+e}),r[e].appendChild(a),r[e].appendChild(d),o.push(i),s.push(d),l.push(c)}),w(d).html(function(){var e=[],i=[];return"datetime"===t.type&&e.push(''+n.timeTips+""),w.each(t.btns,function(e,r){var o=n.tools[r]||"btn";t.range&&"now"===r||(a&&"clear"===r&&(o="cn"===t.lang?"重置":"Reset"),i.push(''+o+""))}),e.push('"),e.join("")}()),w.each(r,function(e,t){i.appendChild(t)}),t.showBottom&&i.appendChild(d),/^#/.test(t.theme)){var m=w.elem("style"),u=["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} .layui-this{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,t.theme);"styleSheet"in m?(m.setAttribute("type","text/css"),m.styleSheet.cssText=u):m.innerHTML=u,w(i).addClass("laydate-theme-molv"),i.appendChild(m)}e.remove(T.thisElemDate),a?t.elem.append(i):(document.body.appendChild(i),e.position()),e.checkDate().calendar(),e.changeEvent(),T.thisElemDate=e.elemID,"function"==typeof t.ready&&t.ready(w.extend({},t.dateTime,{month:t.dateTime.month+1}))},T.prototype.remove=function(e){var t=this,n=(t.config,w("#"+(e||t.elemID)));return n.hasClass(c)||t.checkDate(function(){n.remove()}),t},T.prototype.position=function(){var e=this,t=e.config,n=e.bindElem||t.elem[0],a=n.getBoundingClientRect(),i=e.elem.offsetWidth,r=e.elem.offsetHeight,o=function(e){return e=e?"scrollLeft":"scrollTop",document.body[e]|document.documentElement[e]},s=function(e){return document.documentElement[e?"clientWidth":"clientHeight"]},l=5,d=a.left,c=a.bottom;d+i+l>s("width")&&(d=s("width")-i-l),c+r+l>s()&&(c=a.top>r?a.top-r:s()-r,c-=2*l),t.position&&(e.elem.style.position=t.position),e.elem.style.left=d+("fixed"===t.position?0:o(1))+"px",e.elem.style.top=c+("fixed"===t.position?0:o())+"px"},T.prototype.hint=function(e){var t=this,n=(t.config,w.elem("div",{"class":h}));n.innerHTML=e||"",w(t.elem).find("."+h).remove(),t.elem.appendChild(n),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){w(t.elem).find("."+h).remove()},3e3)},T.prototype.getAsYM=function(e,t,n){return n?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},T.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},T.prototype.checkDate=function(e){var t,a,i=this,r=(new Date,i.config),o=r.dateTime=r.dateTime||i.systemDate(),s=i.bindElem||r.elem[0],l=(i.isInput(s)?"val":"html",i.isInput(s)?s.value:"static"===r.position?"":s.innerHTML),c=function(e){e.year>d[1]&&(e.year=d[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=n.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},m=function(e,t,n){var o=["startTime","endTime"];t=(t.match(i.EXP_SPLIT)||[]).slice(1),n=n||0,r.range&&(i[o[n]]=i[o[n]]||{}),w.each(i.format,function(s,l){var c=parseFloat(t[s]);t[s].length必须遵循下述格式:
        "+(r.range?r.format+" "+r.range+" "+r.format:r.format)+"
        已为你重置"),a=!0):l&&l.constructor===Date?r.dateTime=i.systemDate(l):(r.dateTime=i.systemDate(),delete i.startState,delete i.endState,delete i.startDate,delete i.endDate,delete i.startTime,delete i.endTime),c(o),a&&l&&i.setValue(r.range?i.endDate?i.parse():"":i.parse()),e&&e(),i)},T.prototype.mark=function(e,t){var n,a=this,i=a.config;return w.each(i.mark,function(e,a){var i=e.split("-");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(n=a||t[2])}),n&&e.html(''+n+""),a},T.prototype.limit=function(e,t,n,a){var i,r=this,o=r.config,l={},d=o[n>41?"endDate":"dateTime"],c=w.extend({},d,t||{});return w.each({now:c,min:o.min,max:o.max},function(e,t){l[e]=r.newDate(w.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return w.each(a,function(n,a){e[a]=t[a]}),e}())).getTime()}),i=l.nowl.max,e&&e[i?"addClass":"removeClass"](s),i},T.prototype.calendar=function(e){var t,a,i,r=this,s=r.config,l=e||s.dateTime,c=new Date,m=r.lang(),u="date"!==s.type&&"datetime"!==s.type,h=e?1:0,y=w(r.table[h]).find("td"),f=w(r.elemHeader[h][2]).find("span");if(l.yeard[1]&&(l.year=d[1],r.hint("最高只能支持到公元"+d[1]+"年")),r.firstDate||(r.firstDate=w.extend({},l)),c.setFullYear(l.year,l.month,1),t=c.getDay(),a=n.getEndDate(l.month||12,l.year),i=n.getEndDate(l.month+1,l.year),w.each(y,function(e,n){var d=[l.year,l.month],c=0;n=w(n),n.removeAttr("class"),e=t&&e=n.firstDate.year&&(r.month=a.max.month,r.date=a.max.date),n.limit(w(i),r,t),M++}),w(u[f?0:1]).attr("lay-ym",M-8+"-"+T[1]).html(b+p+" - "+(M-1+p))}else if("month"===e)w.each(new Array(12),function(e){var i=w.elem("li",{"lay-ym":e}),s={year:T[0],month:e};e+1==T[1]&&w(i).addClass(o),i.innerHTML=r.month[e]+(f?"月":""),d.appendChild(i),T[0]=n.firstDate.year&&(s.date=a.max.date),n.limit(w(i),s,t)}),w(u[f?0:1]).attr("lay-ym",T[0]+"-"+T[1]).html(T[0]+p);else if("time"===e){var E=function(){w(d).find("ol").each(function(e,a){w(a).find("li").each(function(a,i){n.limit(w(i),[{hours:a},{hours:n[x].hours,minutes:a},{hours:n[x].hours,minutes:n[x].minutes,seconds:a}][e],t,[["hours"],["hours","minutes"],["hours","minutes","seconds"]][e])})}),a.range||n.limit(w(n.footer).find(g),n[x],0,["hours","minutes","seconds"])};a.range?n[x]||(n[x]={hours:0,minutes:0,seconds:0}):n[x]=i,w.each([24,60,60],function(e,t){var a=w.elem("li"),i=["

        "+r.time[e]+"

          "];w.each(new Array(t),function(t){i.push(""+w.digit(t,2)+"")}),a.innerHTML=i.join("")+"
        ",d.appendChild(a)}),E()}if(y&&h.removeChild(y),h.appendChild(d),"year"===e||"month"===e)w(n.elemMain[t]).addClass("laydate-ym-show"),w(d).find("li").on("click",function(){var r=0|w(this).attr("lay-ym");if(!w(this).hasClass(s)){if(0===t)i[e]=r,l&&(n.startDate[e]=r),n.limit(w(n.footer).find(g),null,0);else if(l)n.endDate[e]=r;else{var c="year"===e?n.getAsYM(r,T[1]-1,"sub"):n.getAsYM(T[0],r,"sub");w.extend(i,{year:c[0],month:c[1]})}"year"===a.type||"month"===a.type?(w(d).find("."+o).removeClass(o),w(this).addClass(o),"month"===a.type&&"year"===e&&(n.listYM[t][0]=r,l&&(n[["startDate","endDate"][t]].year=r),n.list("month",t))):(n.checkDate("limit").calendar(),n.closeList()),n.setBtnStatus(),a.range||n.done(null,"change"),w(n.footer).find(D).removeClass(s)}});else{var S=w.elem("span",{"class":v}),k=function(){w(d).find("ol").each(function(e){var t=this,a=w(t).find("li");t.scrollTop=30*(n[x][C[e]]-2),t.scrollTop<=0&&a.each(function(e,n){if(!w(this).hasClass(s))return t.scrollTop=30*(e-2),!0})})},H=w(c[2]).find("."+v);k(),S.innerHTML=a.range?[r.startTime,r.endTime][t]:r.timeTips,w(n.elemMain[t]).addClass("laydate-time-show"),H[0]&&H.remove(),c[2].appendChild(S),w(d).find("ol").each(function(e){var t=this;w(t).find("li").on("click",function(){var r=0|this.innerHTML;w(this).hasClass(s)||(a.range?n[x][C[e]]=r:i[C[e]]=r,w(t).find("."+o).removeClass(o),w(this).addClass(o),E(),k(),(n.endDate||"time"===a.type)&&n.done(null,"change"),n.setBtnStatus())})})}return n},T.prototype.listYM=[],T.prototype.closeList=function(){var e=this;e.config;w.each(e.elemCont,function(t,n){w(this).find("."+m).remove(),w(e.elemMain[t]).removeClass("laydate-ym-show laydate-time-show")}),w(e.elem).find("."+v).remove()},T.prototype.setBtnStatus=function(e,t,n){var a,i=this,r=i.config,o=w(i.footer).find(g),d=r.range&&"date"!==r.type&&"time"!==r.type;d&&(t=t||i.startDate,n=n||i.endDate,a=i.newDate(t).getTime()>i.newDate(n).getTime(),i.limit(null,t)||i.limit(null,n)?o.addClass(s):o[a?"addClass":"removeClass"](s),e&&a&&i.hint("string"==typeof e?l.replace(/日期/g,e):l))},T.prototype.parse=function(e,t){var n=this,a=n.config,i=t||(e?w.extend({},n.endDate,n.endTime):a.range?w.extend({},n.startDate,n.startTime):a.dateTime),r=n.format.concat();return w.each(r,function(e,t){/yyyy|y/.test(t)?r[e]=w.digit(i.year,t.length):/MM|M/.test(t)?r[e]=w.digit(i.month+1,t.length):/dd|d/.test(t)?r[e]=w.digit(i.date,t.length):/HH|H/.test(t)?r[e]=w.digit(i.hours,t.length):/mm|m/.test(t)?r[e]=w.digit(i.minutes,t.length):/ss|s/.test(t)&&(r[e]=w.digit(i.seconds,t.length))}),a.range&&!e?r.join("")+" "+a.range+" "+n.parse(1):r.join("")},T.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},T.prototype.setValue=function(e){var t=this,n=t.config,a=t.bindElem||n.elem[0],i=t.isInput(a)?"val":"html";return"static"===n.position||w(a)[i](e||""),this},T.prototype.stampRange=function(){var e,t,n=this,a=n.config,i=w(n.elem).find("td");if(a.range&&!n.endDate&&w(n.footer).find(g).addClass(s),n.endDate)return e=n.newDate({year:n.startDate.year,month:n.startDate.month,date:n.startDate.date}).getTime(),t=n.newDate({year:n.endDate.year,month:n.endDate.month,date:n.endDate.date}).getTime(),e>t?n.hint(l):void w.each(i,function(a,i){var r=w(i).attr("lay-ymd").split("-"),s=n.newDate({year:r[0],month:r[1]-1,date:r[2]}).getTime();w(i).removeClass(u+" "+o),s!==e&&s!==t||w(i).addClass(w(i).hasClass(y)||w(i).hasClass(f)?u:o),s>e&&s','
        '+f+"
        ",'
        ','',"
        ","
        "].join(""));return l.ie&&l.ie<8?c.removeClass("layui-hide").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass("layui-hide").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e("#"+i[1].attr("textarea"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find("iframe");n.css({height:a.height}).on("load",function(){var o=n.contents(),r=n.prop("contentWindow"),c=o.find("head"),s=e([""].join("")),u=o.find("body");c.append(s),u.attr("contenteditable","true").css({"min-height":a.height}).html(i.value||""),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e("#LAY_layedit_"+t),a=i.prop("contentWindow");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on("keydown",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if("pre"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg("请暂时用shift+enter"),!1}r.execCommand("formatBlock",!1,"

        ")}}),e(n).parents("form").on("submit",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on("paste",function(e){r.execCommand("formatBlock",!1,"

        "),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find("*[style]").each(function(){var t=this.style.textAlign;this.removeAttribute("style"),e(this).css({"text-align":t||""})}),t.find("table").addClass("layui-table"),t.find("script,link").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute("text"),l.selection){var r=a.text||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop("outerHTML")),a.select()}else{var r=a.toString()||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l="layedit-tool-active",n=p(m(a)),o=function(e){return t.find(".layedit-tool-"+e)};i&&i[i.hasClass(l)?"removeClass":"addClass"](l),t.find(">i").removeClass(l),o("unlink").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;"b"!==t&&"strong"!==t||o("b").addClass(l),"i"!==t&&"em"!==t||o("i").addClass(l),"u"===t&&o("u").addClass(l),"strike"===t&&o("d").addClass(l),"p"===t&&("center"===e?o("center").addClass(l):"right"===e?o("right").addClass(l):o("left").addClass(l)),"a"===t&&(o("link").addClass(l),o("unlink").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr("href"),target:l.attr("target")},function(e){var a=l[0];"A"===a.tagName?a.href=e.url:v.call(t,"a",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand("unlink")},face:function(e){x.call(this,function(i){v.call(t,"img",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use("upload",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find("input")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,"img",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||"上传失败")}})})},code:function(e){k.call(o,function(i){v.call(t,"pre",{text:i.code,"lay-lang":i.lang},e)})},help:function(){i.open({type:2,title:"帮助",area:["600px","380px"],shadeClose:!0,shade:.1,skin:"layui-layer-msg",content:["http://www.layui.com/about/layedit/help.html","no"]})}},s=a.find(".layui-layedit-tool"),u=function(){var i=e(this),a=i.attr("layedit-event"),l=i.attr("lay-command");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand("formatBlock",!1,"

        "),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(">i").on("mousedown",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)||u.call(this)}).on("click",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)&&u.call(this)}),o.on("click",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:"LAY_layedit_link",area:"350px",shade:.05,shadeClose:!0,moveType:1,title:"超链接",skin:"layui-layer-msg",content:['

          ','
        • ','','
          ','',"
          ","
        • ",'
        • ','','
          ','",'","
          ","
        • ",'
        • ','','',"
        • ","
        "].join(""),success:function(t,n){var o="submit(layedit-link-yes)";a.render("radio"),t.find(".layui-btn-primary").on("click",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=["[微笑]","[嘻嘻]","[哈哈]","[可爱]","[可怜]","[挖鼻]","[吃惊]","[害羞]","[挤眼]","[闭嘴]","[鄙视]","[爱你]","[泪]","[偷笑]","[亲亲]","[生病]","[太开心]","[白眼]","[右哼哼]","[左哼哼]","[嘘]","[衰]","[委屈]","[吐]","[哈欠]","[抱抱]","[怒]","[疑问]","[馋嘴]","[拜拜]","[思考]","[汗]","[困]","[睡]","[钱]","[失望]","[酷]","[色]","[哼]","[鼓掌]","[晕]","[悲伤]","[抓狂]","[黑线]","[阴险]","[怒骂]","[互粉]","[心]","[伤心]","[猪头]","[熊猫]","[兔子]","[ok]","[耶]","[good]","[NO]","[赞]","[来]","[弱]","[草泥马]","[神马]","[囧]","[浮云]","[给力]","[围观]","[威武]","[奥特曼]","[礼物]","[钟]","[话筒]","[蜡烛]","[蛋糕]"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+"images/face/"+t+".gif"}),e}();return x.hide=x.hide||function(t){"face"!==e(t.target).attr("layedit-event")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('
      • '+e+'
      • ')}),'
          '+t.join("")+"
        "}(),this,{tips:1,time:0,skin:"layui-box layui-util-face",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(".layui-clear>li").on("click",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off("click",x.hide).on("click",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:"LAY_layedit_code",area:"550px",shade:.05,shadeClose:!0,moveType:1,title:"插入代码",skin:"layui-layer-msg",content:['
          ','
        • ','','
          ','","
          ","
        • ",'
        • ','','
          ','',"
          ","
        • ",'
        • ','','',"
        • ","
        "].join(""),success:function(l,n){var o="submit(layedit-code-yes)";a.render("select"),l.find(".layui-btn-primary").on("click",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'',strong:'',italic:'',underline:'',del:'',"|":'',left:'',center:'',right:'',link:'',unlink:'',face:'',image:'',code:'',help:''},w=new c;t(n,w)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/layer.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;!function(e,t){"use strict";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if("interactive"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName("head")[0],s=document.createElement("link");"string"==typeof i&&(n=i);var l=(n||t).replace(/\.|\//g,""),f="layuicss-"+l,c=0;s.rel="stylesheet",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),"function"==typeof i&&!function u(){return++c>80?e.console&&console.error("layer.css: Invalid"):void(1989===parseInt(o.getStyle(document.getElementById(f),"width"))?i():setTimeout(u,100))}()}}},r={v:"3.1.1",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||"ActiveXObject"in e)&&((t.match(/msie\s(\d+)/)||[])[1]||"11")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,"string"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss("modules/layer/"+e.extend):o.link("theme/"+e.extend),this):this},ready:function(e){var t="layer",i="",n=(a?"modules/layer/":"theme/")+"default/layer.css?v="+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a="function"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s="function"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s="function"==typeof n,f=o.config.skin,c=(f?f+" "+f+"-msg":"")||"layui-layer-msg",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+" layui-layer-hui",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+" "+(n.skin||"layui-layer-hui")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];l.anim=["layer-anim-00","layer-anim-01","layer-anim-02","layer-anim-03","layer-anim-04","layer-anim-05","layer-anim-06"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:"信息",offset:"auto",area:"auto",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f="object"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'
        '+(f?r.title[0]:r.title)+"
        ":"";return r.zIndex=s,t([r.shade?'
        ':"",'
        '+(e&&2!=r.type?"":u)+'
        '+(0==r.type&&r.icon!==-1?'':"")+(1==r.type&&e?"":r.content||"")+'
        '+function(){var e=c?'':"";return r.closeBtn&&(e+=''),e}()+""+(r.btn?function(){var e="";"string"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t'+r.btn[t]+"";return'
        '+e+"
        "}():"")+(r.resize?'':"")+"
        "],u,i('
        ')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f="object"==typeof s,c=i("body");if(!t.id||!i("#"+t.id)[0]){switch("string"==typeof t.area&&(t.area="auto"===t.area?["",""]:[t.area,""]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn="btn"in t?t.btn:o.btn[0],r.closeAll("dialog");break;case 2:var s=t.content=f?t.content:[t.content||"http://layer.layui.com","auto"];t.content='';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll("loading");break;case 4:f||(t.content=[t.content,"body"]),t.follow=t.content[1],t.content=t.content[0]+'',delete t.title,t.tips="object"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll("tips")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i("body").append(n[1])}():function(){s.parents("."+l[0])[0]||(s.data("display",s.css("display")).show().addClass("layui-layer-wrap").wrap(n[1]),i("#"+l[0]+a).find("."+l[5]).before(r))}()}():c.append(n[1]),i(".layui-layer-move")[0]||c.append(o.moveElem=u),e.layero=i("#"+l[0]+a),t.scrollbar||l.html.css("overflow","hidden").attr("layer-full",a)}).auto(a),i("#layui-layer-shade"+e.index).css({"background-color":t.shade[1]||"#000",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find("iframe").attr("src",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on("resize",function(){e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u="layer-anim "+l.anim[t.anim];e.layero.addClass(u).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data("isOutAnim",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i("#"+l[0]+e);""===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find("."+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css("padding-top"))))};switch(a.type){case 2:u("iframe");break;default:""===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u("."+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u("."+l[5])):u("."+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o="object"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=n.width()-a[0]:"b"===t.offset?e.offsetTop=n.height()-a[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):"rb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr("minLeft")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i("body"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(".layui-layer-TipsG"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:"auto"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find("."+l[5]).css({"background-color":t.tips[1],"padding-right":t.closeBtn?"30px":""}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(".layui-layer-resize"),c={};return t.move&&l.css("cursor","move"),l.on("mousedown",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css("left")),e.clientY-parseFloat(s.css("top"))],o.moveElem.css("cursor","move").show())}),f.on("mousedown",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css("cursor","se-resize").show()}),a.on("mousemove",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l="fixed"===s.css("position");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;af&&(a=f),ou&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on("mouseup",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find("iframe").on("load",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find("."+l[6]).children("a").on("click",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a["btn"+(e+1)]&&a["btn"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find("."+l[7]).on("click",e),a.shadeClose&&i("#layui-layer-shade"+t.index).on("click",function(){r.close(t.index)}),n.find(".layui-layer-min").on("click",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(".layui-layer-max").on("click",function(){i(this).hasClass("layui-layer-maxmin")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i("select"),function(e,t){var n=i(this);n.parents("."+l[0])[0]||1==n.attr("layer")&&i("."+l[0]).length<1&&n.removeAttr("layer").show(),n=null})},s.pt.IE6=function(e){i("select").each(function(e,t){var n=i(this);n.parents("."+l[0])[0]||"none"===n.css("display")||n.attr({layer:"1"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css("z-index",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on("mousedown",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css("margin-left"))];e.find(".layui-layer-max").addClass("layui-layer-maxmin"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr("layer-full")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty("overflow"):l.html[0].style.removeAttribute("overflow"),l.html.removeAttr("layer-full"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i("."+l[4]).attr("times"),i("#"+l[0]+t).find("iframe").contents().find(e)},r.getFrameIndex=function(e){return i("#"+e).parents("."+l[4]).attr("times")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame("html",e).outerHeight(),n=i("#"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find("."+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find("iframe").css({height:t})}},r.iframeSrc=function(e,t){i("#"+l[0]+e).find("iframe").attr("src",t)},r.style=function(e,t,n){var a=i("#"+l[0]+e),r=a.find(".layui-layer-content"),s=a.attr("type"),f=a.find(l[1]).outerHeight()||0,c=a.find("."+l[6]).outerHeight()||0;a.attr("minLeft");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find("."+l[6]).outerHeight(),s===o.type[2]?a.find("iframe").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom"))}))},r.min=function(e,t){var a=i("#"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr("minLeft")||181*o.minIndex+"px",c=a.css("position");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr("position",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:"fixed",overflow:"hidden"},!0),a.find(".layui-layer-min").hide(),"page"===a.attr("type")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr("minLeft")||o.minIndex++,a.attr("minLeft",f)},r.restore=function(e){var t=i("#"+l[0]+e),n=t.attr("area").split(",");t.attr("type");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===t.attr("type")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i("#"+l[0]+e);o.record(a),l.html.attr("layer-full")||l.html.css("overflow","hidden").attr("layer-full",e),clearTimeout(t),t=setTimeout(function(){var t="fixed"===a.css("position");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(".layui-layer-min").hide()},100)},r.title=function(e,t){var n=i("#"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i("#"+l[0]+e),n=t.attr("type"),a="layer-anim-close";if(t[0]){var s="layui-layer-wrap",f=function(){if(n===o.type[1]&&"object"===t.attr("conType")){t.children(":not(."+l[5]+")").remove();for(var a=t.find("."+s),r=0;r<2;r++)a.unwrap();a.css("display",a.data("display")).removeClass(s)}else{if(n===o.type[2])try{var f=i("#"+l[4]+e)[0];f.contentWindow.document.write(""),f.contentWindow.close(),t.find("."+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML="",t.remove()}"function"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data("isOutAnim")&&t.addClass("layer-anim "+a),i("#layui-layer-moves, #layui-layer-shade"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr("minLeft")&&(o.minIndex--,o.minLeft.push(t.attr("minLeft"))),r.ie&&r.ie<10||!t.data("isOutAnim")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i("."+l[0]),function(){var t=i(this),n=e?t.attr("type")===e:1;n&&r.close(t.attr("times")),n=null})};var f=r.cache||{},c=function(e){return f.skin?" "+f.skin+" "+f.skin+"-"+e:""};r.prompt=function(e,t){var a="";if(e=e||{},"function"==typeof e&&(t=e),e.area){var o=e.area;a='style="width: '+o[0]+"; height: "+o[1]+';"',delete e.area}var s,l=2==e.formType?'":function(){return''}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:["确定","取消"],content:l,skin:"layui-layer-prompt"+c("prompt"),maxWidth:n.width(),success:function(t){s=t.find(".layui-layer-input"),s.val(e.value||"").focus(),"function"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();""===n?s.focus():n.length>(e.maxlength||500)?r.tips("最多输入"+(e.maxlength||500)+"个字数",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n="layui-this",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:"layui-layer-tab"+c("tab"),resize:!1,title:function(){var e=t.length,i=1,a="";if(e>0)for(a=''+t[0].title+"";i"+t[i].title+"";return a}(),content:'
          '+function(){var e=t.length,i=1,a="";if(e>0)for(a='
        • '+(t[0].content||"no content")+"
        • ";i'+(t[i].content||"no content")+"";return a}()+"
        ",success:function(t){var o=t.find(".layui-layer-title").children(),r=t.find(".layui-layer-tabmain").children();o.on("mousedown",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),"function"==typeof e.change&&e.change(o)}),"function"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||"img";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg("没有图片")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr("layer-index",e),u.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(h(),0===u.length)return;if(n||p.on("click",t.img,function(){var e=i(this),n=e.attr("layer-index");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(".layui-layer-imgprev").on("click",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(".layui-layer-imgnext").on("click",function(e){e.preventDefault(),s.imgnext()}),i(document).on("keyup",s.keyup)},s.loadi=r.load(1,{shade:!("shade"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:"layui-layer-photos",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]'+(u[d].alt||
        '+(u.length>1?'':"")+'
        '+(u[d].alt||"")+""+s.imgIndex+"/"+u.length+"
        ",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imguide,.layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
        是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/laypage.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define(function(e){"use strict";var a=document,t="getElementById",n="getElementsByTagName",i="laypage",r="layui-disabled",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups="groups"in a?0|a.groups:5;a.layout="object"==typeof a.layout?a.layout:["prev","page","next"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits="object"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev="prev"in a?a.prev:"上一页",a.next="next"in a?a.next:"下一页";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?''+a.prev+"":""}(),page:function(){var e=[];if(a.count<1)return"";n>1&&a.first!==!1&&0!==t&&e.push(''+(a.first||1)+"");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r2&&e.push('');r<=u;r++)r===a.curr?e.push('"+r+""):e.push(''+r+"");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1…'),0!==t&&e.push(''+(a.last||a.pages)+"")),e.join("")}(),next:function(){return a.next?''+a.next+"":""}(),count:'共 '+a.count+" 条",limit:function(){var e=['"}(),refresh:['','',""].join(""),skip:function(){return['到第','','页',""].join("")}()};return['
        ',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join("")}(),"
        "].join("")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n]("button")[0],l=e[n]("input")[0],p=e[n]("select")[0],c=function(){var e=0|l.value.replace(/\s|\D/g,"");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;oi.pages||(i.curr=e,t.render())});p&&s.on(p,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,"click",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n]("input")[0];t&&s.on(t,"keyup",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\D/.test(n)&&(this.value=n.replace(/\D/,"")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t]("layui-laypage-"+i.index);n.jump(s),i.hash&&!e&&(location.hash="!"+i.hash+"="+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent("on"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/laytpl.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define(function(e){"use strict";var r={open:"{{",close:"}}"},c={exp:function(e){return new RegExp(e,"g")},query:function(e,c,t){var o=["#([\\s\\S])+?","([^{#}])*?"][e||0];return n((c||"")+r.open+o+r.close+(t||""))},escape:function(e){return String(e||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var c="Laytpl Error:";return"object"==typeof console&&console.error(c+e+"\n"+(r||"")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n("^"+r.open+"#",""),l=n(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(n(r.open+"#"),r.open+"# ").replace(n(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(n(r.open+"!(.+?)!"+r.close),function(e){return e=e.replace(n("^"+r.open+"!"),"").replace(n("!"+r.close),"").replace(n(r.open+"|"+r.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(c.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\/g,"")+';view+="'}).replace(c.query(1),function(e){var c='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(n(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),c='"+_escape_('),c+e.replace(/\\/g,"")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error("no data")};var o=function(e){return"string"!=typeof e?c.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v="1.2.0",e("laytpl",o)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/mobile.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define(function(i){i("layui.mobile",layui.v)});layui.define(function(e){"use strict";var r={open:"{{",close:"}}"},c={exp:function(e){return new RegExp(e,"g")},query:function(e,c,t){var o=["#([\\s\\S])+?","([^{#}])*?"][e||0];return n((c||"")+r.open+o+r.close+(t||""))},escape:function(e){return String(e||"").replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var c="Laytpl Error:";return"object"==typeof console&&console.error(c+e+"\n"+(r||"")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n("^"+r.open+"#",""),l=n(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(n(r.open+"#"),r.open+"# ").replace(n(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(n(r.open+"!(.+?)!"+r.close),function(e){return e=e.replace(n("^"+r.open+"!"),"").replace(n("!"+r.close),"").replace(n(r.open+"|"+r.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(c.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\/g,"")+';view+="'}).replace(c.query(1),function(e){var c='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(n(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),c='"+_escape_('),c+e.replace(/\\/g,"")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error("no data")};var o=function(e){return"string"!=typeof e?c.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v="1.2.0",e("laytpl",o)});layui.define(function(e){"use strict";var t=(window,document),i="querySelectorAll",n="getElementsByClassName",a=function(e){return t[i](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var i in e)t[i]=e[i];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var o=0,r=["layui-m-layer"],d=function(e){var t=this;t.config=l.extend(e),t.view()};d.prototype.view=function(){var e=this,i=e.config,s=t.createElement("div");e.id=s.id=r[0]+o,s.setAttribute("class",r[0]+" "+r[0]+(i.type||0)),s.setAttribute("index",o);var l=function(){var e="object"==typeof i.title;return i.title?'

        '+(e?i.title[0]:i.title)+"

        ":""}(),d=function(){"string"==typeof i.btn&&(i.btn=[i.btn]);var e,t=(i.btn||[]).length;return 0!==t&&i.btn?(e=''+i.btn[0]+"",2===t&&(e=''+i.btn[1]+""+e),'
        '+e+"
        "):""}();if(i.fixed||(i.top=i.hasOwnProperty("top")?i.top:100,i.style=i.style||"",i.style+=" top:"+(t.body.scrollTop+i.top)+"px"),2===i.type&&(i.content='

        '+(i.content||"")+"

        "),i.skin&&(i.anim="up"),"msg"===i.skin&&(i.shade=!1),s.innerHTML=(i.shade?"
        ':"")+'
        "+l+'
        '+i.content+"
        "+d+"
        ",!i.type||2===i.type){var y=t[n](r[0]+i.type),u=y.length;u>=1&&c.close(y[0].getAttribute("index"))}document.body.appendChild(s);var m=e.elem=a("#"+e.id)[0];i.success&&i.success(m),e.index=o++,e.action(i,m)},d.prototype.action=function(e,t){var i=this;e.time&&(l.timer[i.index]=setTimeout(function(){c.close(i.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),c.close(i.index)):e.yes?e.yes(i.index):c.close(i.index)};if(e.btn)for(var s=t[n]("layui-m-layerbtn")[0].children,o=s.length,r=0;r0&&e-1 in t)}function s(t){return A.call(t,function(t){return null!=t})}function u(t){return t.length>0?T.fn.concat.apply([],t):t}function c(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function l(t){return t in F?F[t]:F[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function f(t,e){return"number"!=typeof e||k[c(t)]?e:e+"px"}function h(t){var e,n;return $[t]||(e=L.createElement(t),L.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),$[t]=n),$[t]}function p(t){return"children"in t?D.call(t.children):T.map(t.childNodes,function(t){if(1==t.nodeType)return t})}function d(t,e){var n,r=t?t.length:0;for(n=0;n]*>/,R=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,Z=/^(?:body|html)$/i,q=/([A-Z])/g,H=["val","css","html","text","data","width","height","offset"],I=["after","prepend","before","append"],V=L.createElement("table"),_=L.createElement("tr"),B={tr:L.createElement("tbody"),tbody:V,thead:V,tfoot:V,td:_,th:_,"*":L.createElement("div")},U=/complete|loaded|interactive/,X=/^[\w-]*$/,J={},W=J.toString,Y={},G=L.createElement("div"),K={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},Q=Array.isArray||function(t){return t instanceof Array};return Y.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=G).appendChild(t),r=~Y.qsa(i,e).indexOf(t),o&&G.removeChild(t),r},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},N=function(t){return A.call(t,function(e,n){return t.indexOf(e)==n})},Y.fragment=function(t,e,n){var r,i,a;return R.test(t)&&(r=T(L.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(z,"<$1>")),e===E&&(e=M.test(t)&&RegExp.$1),e in B||(e="*"),a=B[e],a.innerHTML=""+t,r=T.each(D.call(a.childNodes),function(){a.removeChild(this)})),o(n)&&(i=T(r),T.each(n,function(t,e){H.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},Y.Z=function(t,e){return new d(t,e)},Y.isZ=function(t){return t instanceof Y.Z},Y.init=function(t,n){var r;if(!t)return Y.Z();if("string"==typeof t)if(t=t.trim(),"<"==t[0]&&M.test(t))r=Y.fragment(t,RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}else{if(e(t))return T(L).ready(t);if(Y.isZ(t))return t;if(Q(t))r=s(t);else if(i(t))r=[t],t=null;else if(M.test(t))r=Y.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==E)return T(n).find(t);r=Y.qsa(L,t)}}return Y.Z(r,t)},T=function(t,e){return Y.init(t,e)},T.extend=function(t){var e,n=D.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){m(t,n,e)}),t},Y.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,a=X.test(o);return t.getElementById&&a&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:D.call(a&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},T.contains=L.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},T.type=t,T.isFunction=e,T.isWindow=n,T.isArray=Q,T.isPlainObject=o,T.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},T.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},T.inArray=function(t,e,n){return O.indexOf.call(e,t,n)},T.camelCase=C,T.trim=function(t){return null==t?"":String.prototype.trim.call(t)},T.uuid=0,T.support={},T.expr={},T.noop=function(){},T.map=function(t,e){var n,r,i,o=[];if(a(t))for(r=0;r=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return O.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return e(t)?this.not(this.not(t)):T(A.call(this,function(e){return Y.matches(e,t)}))},add:function(t,e){return T(N(this.concat(T(t,e))))},is:function(t){return this.length>0&&Y.matches(this[0],t)},not:function(t){var n=[];if(e(t)&&t.call!==E)this.each(function(e){t.call(this,e)||n.push(this)});else{var r="string"==typeof t?this.filter(t):a(t)&&e(t.item)?D.call(t):T(t);this.forEach(function(t){r.indexOf(t)<0&&n.push(t)})}return T(n)},has:function(t){return this.filter(function(){return i(t)?T.contains(this,t):T(this).find(t).size()})},eq:function(t){return t===-1?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!i(t)?t:T(t)},last:function(){var t=this[this.length-1];return t&&!i(t)?t:T(t)},find:function(t){var e,n=this;return e=t?"object"==typeof t?T(t).filter(function(){var t=this;return O.some.call(n,function(e){return T.contains(e,t)})}):1==this.length?T(Y.qsa(this[0],t)):this.map(function(){return Y.qsa(this,t)}):T()},closest:function(t,e){var n=[],i="object"==typeof t&&T(t);return this.each(function(o,a){for(;a&&!(i?i.indexOf(a)>=0:Y.matches(a,t));)a=a!==e&&!r(a)&&a.parentNode;a&&n.indexOf(a)<0&&n.push(a)}),T(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=T.map(n,function(t){if((t=t.parentNode)&&!r(t)&&e.indexOf(t)<0)return e.push(t),t});return v(e,t)},parent:function(t){return v(N(this.pluck("parentNode")),t)},children:function(t){return v(this.map(function(){return p(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||D.call(this.childNodes)})},siblings:function(t){return v(this.map(function(t,e){return A.call(p(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return T.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=h(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var n=e(t);if(this[0]&&!n)var r=T(t).get(0),i=r.parentNode||this.length>1;return this.each(function(e){T(this).wrapAll(n?t.call(this,e):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){T(this[0]).before(t=T(t));for(var e;(e=t.children()).length;)t=e.first();T(t).append(this)}return this},wrapInner:function(t){var n=e(t);return this.each(function(e){var r=T(this),i=r.contents(),o=n?t.call(this,e):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){T(this).replaceWith(T(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var e=T(this);(t===E?"none"==e.css("display"):t)?e.show():e.hide()})},prev:function(t){return T(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return T(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;T(this).empty().append(g(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=g(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,e){var n;return"string"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(i(t))for(j in t)y(this,j,t[j]);else y(this,t,g(this,e,n,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(n=this[0].getAttribute(t))?n:E},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){y(this,t)},this)})},prop:function(t,e){return t=K[t]||t,1 in arguments?this.each(function(n){this[t]=g(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=K[t]||t,this.each(function(){delete this[t]})},data:function(t,e){var n="data-"+t.replace(q,"-$1").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?b(r):E},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each(function(e){this.value=g(this,t,e,this.value)})):this[0]&&(this[0].multiple?T(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var n=T(this),r=g(this,t,e,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)});if(!this.length)return null;if(L.documentElement!==this[0]&&!T.contains(L.documentElement,this[0]))return{top:0,left:0};var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(e,n){if(arguments.length<2){var r=this[0];if("string"==typeof e){if(!r)return;return r.style[C(e)]||getComputedStyle(r,"").getPropertyValue(e)}if(Q(e)){if(!r)return;var i={},o=getComputedStyle(r,"");return T.each(e,function(t,e){i[e]=r.style[C(e)]||o.getPropertyValue(e)}),i}}var a="";if("string"==t(e))n||0===n?a=c(e)+":"+f(e,n):this.each(function(){this.style.removeProperty(c(e))});else for(j in e)e[j]||0===e[j]?a+=c(j)+":"+f(j,e[j])+";":this.each(function(){this.style.removeProperty(c(j))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(T(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&O.some.call(this,function(t){return this.test(x(t))},l(t))},addClass:function(t){return t?this.each(function(e){if("className"in this){S=[];var n=x(this),r=g(this,t,e,n);r.split(/\s+/g).forEach(function(t){T(this).hasClass(t)||S.push(t)},this),S.length&&x(this,n+(n?" ":"")+S.join(" "))}}):this},removeClass:function(t){return this.each(function(e){if("className"in this){if(t===E)return x(this,"");S=x(this),g(this,t,e,S).split(/\s+/g).forEach(function(t){S=S.replace(l(t)," ")}),x(this,S.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=T(this),i=g(this,t,n,x(this));i.split(/\s+/g).forEach(function(t){(e===E?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e="scrollTop"in this[0];return t===E?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e="scrollLeft"in this[0];return t===E?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=Z.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(T(t).css("margin-top"))||0,n.left-=parseFloat(T(t).css("margin-left"))||0,r.top+=parseFloat(T(e[0]).css("border-top-width"))||0,r.left+=parseFloat(T(e[0]).css("border-left-width"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||L.body;t&&!Z.test(t.nodeName)&&"static"==T(t).css("position");)t=t.offsetParent;return t})}},T.fn.detach=T.fn.remove,["width","height"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});T.fn[t]=function(i){var o,a=this[0];return i===E?n(a)?a["inner"+e]:r(a)?a.documentElement["scroll"+e]:(o=this.offset())&&o[t]:this.each(function(e){a=T(this),a.css(t,g(this,i,e,a[t]()))})}}),I.forEach(function(e,n){var r=n%2;T.fn[e]=function(){var e,i,o=T.map(arguments,function(n){var r=[];return e=t(n),"array"==e?(n.forEach(function(t){return t.nodeType!==E?r.push(t):T.zepto.isZ(t)?r=r.concat(t.get()):void(r=r.concat(Y.fragment(t)))}),r):"object"==e||null==n?n:Y.fragment(n)}),a=this.length>1;return o.length<1?this:this.each(function(t,e){i=r?e:e.parentNode,e=0==n?e.nextSibling:1==n?e.firstChild:2==n?e:null;var s=T.contains(L.documentElement,i);o.forEach(function(t){if(a)t=t.cloneNode(!0);else if(!i)return T(t).remove();i.insertBefore(t,e),s&&w(t,function(t){if(!(null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src)){var e=t.ownerDocument?t.ownerDocument.defaultView:window;e.eval.call(e,t.innerHTML)}})})})},T.fn[r?e+"To":"insert"+(n?"Before":"After")]=function(t){return T(t)[e](this),this}}),Y.Z.prototype=d.prototype=T.fn,Y.uniq=N,Y.deserializeValue=b,T.zepto=Y,T}();!function(t){function e(t){return t._zid||(t._zid=h++)}function n(t,n,o,a){if(n=r(n),n.ns)var s=i(n.ns);return(v[e(t)]||[]).filter(function(t){return t&&(!n.e||t.e==n.e)&&(!n.ns||s.test(t.ns))&&(!o||e(t.fn)===e(o))&&(!a||t.sel==a)})}function r(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function i(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function o(t,e){return t.del&&!y&&t.e in x||!!e}function a(t){return b[t]||y&&x[t]||t}function s(n,i,s,u,l,h,p){var d=e(n),m=v[d]||(v[d]=[]);i.split(/\s/).forEach(function(e){if("ready"==e)return t(document).ready(s);var i=r(e);i.fn=s,i.sel=l,i.e in b&&(s=function(e){var n=e.relatedTarget;if(!n||n!==this&&!t.contains(this,n))return i.fn.apply(this,arguments)}),i.del=h;var d=h||s;i.proxy=function(t){if(t=c(t),!t.isImmediatePropagationStopped()){t.data=u;var e=d.apply(n,t._args==f?[t]:[t].concat(t._args));return e===!1&&(t.preventDefault(),t.stopPropagation()),e}},i.i=m.length,m.push(i),"addEventListener"in n&&n.addEventListener(a(i.e),i.proxy,o(i,p))})}function u(t,r,i,s,u){var c=e(t);(r||"").split(/\s/).forEach(function(e){n(t,e,i,s).forEach(function(e){delete v[c][e.i],"removeEventListener"in t&&t.removeEventListener(a(e.e),e.proxy,o(e,u))})})}function c(e,n){return!n&&e.isDefaultPrevented||(n||(n=e),t.each(T,function(t,r){var i=n[t];e[t]=function(){return this[r]=w,i&&i.apply(n,arguments)},e[r]=E}),e.timeStamp||(e.timeStamp=Date.now()),(n.defaultPrevented!==f?n.defaultPrevented:"returnValue"in n?n.returnValue===!1:n.getPreventDefault&&n.getPreventDefault())&&(e.isDefaultPrevented=w)),e}function l(t){var e,n={originalEvent:t};for(e in t)j.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=t.isFunction,m=function(t){return"string"==typeof t},v={},g={},y="onfocusin"in window,x={focus:"focusin",blur:"focusout"},b={mouseenter:"mouseover",mouseleave:"mouseout"};g.click=g.mousedown=g.mouseup=g.mousemove="MouseEvents",t.event={add:s,remove:u},t.proxy=function(n,r){var i=2 in arguments&&p.call(arguments,2);if(d(n)){var o=function(){return n.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=e(n),o}if(m(r))return i?(i.unshift(n[r],n),t.proxy.apply(null,i)):t.proxy(n[r],n);throw new TypeError("expected function")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var w=function(){return!0},E=function(){return!1},j=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,T={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,n,r,i,o){var a,c,h=this;return e&&!m(e)?(t.each(e,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||i===!1||(i=r,r=n,n=f),i!==f&&r!==!1||(i=r,r=f),i===!1&&(i=E),h.each(function(f,h){o&&(a=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(e){var r,o=t(e.target).closest(n,h).get(0);if(o&&o!==h)return r=t.extend(l(e),{currentTarget:o,liveFired:h}),(a||i).apply(o,[r].concat(p.call(arguments,1)))}),s(h,e,i,r,n,c||a)}))},t.fn.off=function(e,n,r){var i=this;return e&&!m(e)?(t.each(e,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||r===!1||(r=n,n=f),r===!1&&(r=E),i.each(function(){u(this,e,r,n)}))},t.fn.trigger=function(e,n){return e=m(e)||t.isPlainObject(e)?t.Event(e):c(e),e._args=n,this.each(function(){e.type in x&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,r){var i,o;return this.each(function(a,s){i=l(m(e)?t.Event(e):e),i._args=r,i.target=s,t.each(n(s,e.type||e),function(t,e){if(o=e.proxy(i),i.isImmediatePropagationStopped())return!1})}),o},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(g[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(e),function(t){function e(e,n,r){var i=t.Event(n);return t(e).trigger(i,r),!i.isDefaultPrevented()}function n(t,n,r,i){if(t.global)return e(n||x,r,i)}function r(e){e.global&&0===t.active++&&n(e,null,"ajaxStart")}function i(e){e.global&&!--t.active&&n(e,null,"ajaxStop")}function o(t,e){var r=e.context;return e.beforeSend.call(r,t,e)!==!1&&n(e,r,"ajaxBeforeSend",[t,e])!==!1&&void n(e,r,"ajaxSend",[t,e])}function a(t,e,r,i){var o=r.context,a="success";r.success.call(o,t,a,e),i&&i.resolveWith(o,[t,a,e]),n(r,o,"ajaxSuccess",[e,r,t]),u(a,e,r)}function s(t,e,r,i,o){var a=i.context;i.error.call(a,r,e,t),o&&o.rejectWith(a,[r,e,t]),n(i,a,"ajaxError",[r,i,t||e]),u(e,r,i)}function u(t,e,r){var o=r.context;r.complete.call(o,e,t),n(r,o,"ajaxComplete",[e,r]),i(r)}function c(t,e,n){if(n.dataFilter==l)return t;var r=n.context;return n.dataFilter.call(r,t,e)}function l(){}function f(t){return t&&(t=t.split(";",2)[0]),t&&(t==T?"html":t==j?"json":w.test(t)?"script":E.test(t)&&"xml")||"text"}function h(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function p(e){e.processData&&e.data&&"string"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&"GET"!=e.type.toUpperCase()&&"jsonp"!=e.dataType||(e.url=h(e.url,e.data),e.data=void 0)}function d(e,n,r,i){return t.isFunction(n)&&(i=r,r=n,n=void 0),t.isFunction(r)||(i=r,r=void 0),{url:e,data:n,success:r,dataType:i}}function m(e,n,r,i){var o,a=t.isArray(n),s=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),i&&(n=r?i:i+"["+(s||"object"==o||"array"==o?n:"")+"]"),!i&&a?e.add(u.name,u.value):"array"==o||!r&&"object"==o?m(e,u,r,n):e.add(n,u)})}var v,g,y=+new Date,x=window.document,b=/)<[^<]*)*<\/script>/gi,w=/^(?:text|application)\/javascript/i,E=/^(?:text|application)\/xml/i,j="application/json",T="text/html",S=/^\s*$/,C=x.createElement("a");C.href=window.location.href,t.active=0,t.ajaxJSONP=function(e,n){if(!("type"in e))return t.ajax(e);var r,i,u=e.jsonpCallback,c=(t.isFunction(u)?u():u)||"Zepto"+y++,l=x.createElement("script"),f=window[c],h=function(e){t(l).triggerHandler("error",e||"abort")},p={abort:h};return n&&n.promise(p),t(l).on("load error",function(o,u){clearTimeout(i),t(l).off().remove(),"error"!=o.type&&r?a(r[0],p,e,n):s(null,u||"error",p,e,n),window[c]=f,r&&t.isFunction(f)&&f(r[0]),f=r=void 0}),o(p,e)===!1?(h("abort"),p):(window[c]=function(){r=arguments},l.src=e.url.replace(/\?(.+)=\?/,"?$1="+c),x.head.appendChild(l),e.timeout>0&&(i=setTimeout(function(){h("timeout")},e.timeout)),p)},t.ajaxSettings={type:"GET",beforeSend:l,success:l,error:l,complete:l,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:j,xml:"application/xml, text/xml",html:T,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:l},t.ajax=function(e){var n,i,u=t.extend({},e||{}),d=t.Deferred&&t.Deferred();for(v in t.ajaxSettings)void 0===u[v]&&(u[v]=t.ajaxSettings[v]);r(u),u.crossDomain||(n=x.createElement("a"),n.href=u.url,n.href=n.href,u.crossDomain=C.protocol+"//"+C.host!=n.protocol+"//"+n.host),u.url||(u.url=window.location.toString()),(i=u.url.indexOf("#"))>-1&&(u.url=u.url.slice(0,i)),p(u);var m=u.dataType,y=/\?.+=\?/.test(u.url);if(y&&(m="jsonp"),u.cache!==!1&&(e&&e.cache===!0||"script"!=m&&"jsonp"!=m)||(u.url=h(u.url,"_="+Date.now())),"jsonp"==m)return y||(u.url=h(u.url,u.jsonp?u.jsonp+"=?":u.jsonp===!1?"":"callback=?")),t.ajaxJSONP(u,d);var b,w=u.accepts[m],E={},j=function(t,e){E[t.toLowerCase()]=[t,e]},T=/^([\w-]+:)\/\//.test(u.url)?RegExp.$1:window.location.protocol,N=u.xhr(),O=N.setRequestHeader;if(d&&d.promise(N),u.crossDomain||j("X-Requested-With","XMLHttpRequest"),j("Accept",w||"*/*"),(w=u.mimeType||w)&&(w.indexOf(",")>-1&&(w=w.split(",",2)[0]),N.overrideMimeType&&N.overrideMimeType(w)),(u.contentType||u.contentType!==!1&&u.data&&"GET"!=u.type.toUpperCase())&&j("Content-Type",u.contentType||"application/x-www-form-urlencoded"),u.headers)for(g in u.headers)j(g,u.headers[g]);if(N.setRequestHeader=j,N.onreadystatechange=function(){if(4==N.readyState){N.onreadystatechange=l,clearTimeout(b);var e,n=!1;if(N.status>=200&&N.status<300||304==N.status||0==N.status&&"file:"==T){if(m=m||f(u.mimeType||N.getResponseHeader("content-type")),"arraybuffer"==N.responseType||"blob"==N.responseType)e=N.response;else{e=N.responseText;try{e=c(e,m,u),"script"==m?(0,eval)(e):"xml"==m?e=N.responseXML:"json"==m&&(e=S.test(e)?null:t.parseJSON(e))}catch(r){n=r}if(n)return s(n,"parsererror",N,u,d)}a(e,N,u,d)}else s(N.statusText||null,N.status?"error":"abort",N,u,d)}},o(N,u)===!1)return N.abort(),s(null,"abort",N,u,d),N;var P=!("async"in u)||u.async;if(N.open(u.type,u.url,P,u.username,u.password),u.xhrFields)for(g in u.xhrFields)N[g]=u.xhrFields[g];for(g in E)O.apply(N,E[g]);return u.timeout>0&&(b=setTimeout(function(){N.onreadystatechange=l,N.abort(),s(null,"timeout",N,u,d)},u.timeout)),N.send(u.data?u.data:null),N},t.get=function(){return t.ajax(d.apply(null,arguments))},t.post=function(){var e=d.apply(null,arguments);return e.type="POST",t.ajax(e)},t.getJSON=function(){var e=d.apply(null,arguments);return e.dataType="json",t.ajax(e)},t.fn.load=function(e,n,r){if(!this.length)return this;var i,o=this,a=e.split(/\s/),s=d(e,n,r),u=s.success;return a.length>1&&(s.url=a[0],i=a[1]),s.success=function(e){o.html(i?t("
        ").html(e.replace(b,"")).find(i):e),u&&u.apply(o,arguments)},t.ajax(s),this};var N=encodeURIComponent;t.param=function(e,n){var r=[];return r.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(N(e)+"="+N(n))},m(r,e,n),r.join("&").replace(/%20/g,"+")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){return t.forEach?t.forEach(i):void r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(t){var e=getComputedStyle;window.getComputedStyle=function(t,n){try{return e(t,n)}catch(r){return null}}}}(),t("zepto",e)});layui.define(["layer-mobile","zepto"],function(e){"use strict";var t=layui.zepto,a=layui["layer-mobile"],i=(layui.device(),"layui-upload-enter"),n="layui-upload-iframe",r={icon:2,shift:6},o={file:"文件",video:"视频",audio:"音频"};a.msg=function(e){return a.open({content:e||"",skin:"msg",time:2})};var s=function(e){this.options=e};s.prototype.init=function(){var e=this,a=e.options,r=t("body"),s=t(a.elem||".layui-upload-file"),u=t('');return t("#"+n)[0]||r.append(u),s.each(function(r,s){s=t(s);var u='
        ',l=s.attr("lay-type")||a.type;a.unwrap||(u='
        '+u+''+(s.attr("lay-title")||a.title||"上传"+(o[l]||"图片"))+"
        "),u=t(u),a.unwrap||u.on("dragover",function(e){e.preventDefault(),t(this).addClass(i)}).on("dragleave",function(){t(this).removeClass(i)}).on("drop",function(){t(this).removeClass(i)}),s.parent("form").attr("target")===n&&(a.unwrap?s.unwrap():(s.parent().next().remove(),s.unwrap().unwrap())),s.wrap(u),s.off("change").on("change",function(){e.action(this,l)})})},s.prototype.action=function(e,i){var o=this,s=o.options,u=e.value,l=t(e),p=l.attr("lay-ext")||s.ext||"";if(u){switch(i){case"file":if(p&&!RegExp("\\w\\.("+p+")$","i").test(escape(u)))return a.msg("不支持该文件格式",r),e.value="";break;case"video":if(!RegExp("\\w\\.("+(p||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(u)))return a.msg("不支持该视频格式",r),e.value="";break;case"audio":if(!RegExp("\\w\\.("+(p||"mp3|wav|mid")+")$","i").test(escape(u)))return a.msg("不支持该音频格式",r),e.value="";break;default:if(!RegExp("\\w\\.("+(p||"jpg|png|gif|bmp|jpeg")+")$","i").test(escape(u)))return a.msg("不支持该图片格式",r),e.value=""}s.before&&s.before(e),l.parent().submit();var c=t("#"+n),f=setInterval(function(){var t;try{t=c.contents().find("body").text()}catch(i){a.msg("上传接口存在跨域",r),clearInterval(f)}if(t){clearInterval(f),c.contents().find("body").html("");try{t=JSON.parse(t)}catch(i){return t={},a.msg("请对上传接口返回JSON字符",r)}"function"==typeof s.success&&s.success(t,e)}},30);e.value=""}},e("upload-mobile",function(e){var t=new s(e=e||{});t.init()})});layui.define(function(i){i("layim-mobile",layui.v)});layui["layui.mobile"]||layui.config({base:layui.cache.dir+"lay/modules/mobile/"}).extend({"layer-mobile":"layer-mobile",zepto:"zepto","upload-mobile":"upload-mobile","layim-mobile":"layim-mobile"}),layui.define(["layer-mobile","zepto","layim-mobile"],function(l){l("mobile",{layer:layui["layer-mobile"],layim:layui["layim-mobile"]})}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/rate.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("jquery",function(e){"use strict";var a=layui.jquery,i={config:{},index:layui.rate?layui.rate.index+1e4:0,set:function(e){var i=this;return i.config=a.extend({},i.config,e),i},on:function(e,a){return layui.onevent.call(this,n,e,a)}},l=function(){var e=this,a=e.config;return{setvalue:function(a){e.setvalue.call(e,a)},config:a}},n="rate",t="layui-rate",o="layui-icon-rate",s="layui-icon-rate-solid",u="layui-icon-rate-half",r="layui-icon-rate-solid layui-icon-rate-half",c="layui-icon-rate-solid layui-icon-rate",f="layui-icon-rate layui-icon-rate-half",v=function(e){var l=this;l.index=++i.index,l.config=a.extend({},l.config,i.config,e),l.render()};v.prototype.config={length:5,text:!1,readonly:!1,half:!1,value:0,theme:""},v.prototype.render=function(){var e=this,i=e.config,l=i.theme?'style="color: '+i.theme+';"':"";i.elem=a(i.elem),parseInt(i.value)!==i.value&&(i.half||(i.value=Math.ceil(i.value)-i.value<.5?Math.ceil(i.value):Math.floor(i.value)));for(var n='
          ",u=1;u<=i.length;u++){var r='
        • ";i.half&&parseInt(i.value)!==i.value&&u==Math.ceil(i.value)?n=n+'
        • ":n+=r}n+="
        "+(i.text?''+i.value+"星":"")+"";var c=i.elem,f=c.next("."+t);f[0]&&f.remove(),e.elemTemp=a(n),i.span=e.elemTemp.next("span"),i.setText&&i.setText(i.value),c.html(e.elemTemp),c.addClass("layui-inline"),i.readonly||e.action()},v.prototype.setvalue=function(e){var a=this,i=a.config;i.value=e,a.render()},v.prototype.action=function(){var e=this,i=e.config,l=e.elemTemp,n=l.find("i").width();l.children("li").each(function(e){var t=e+1,v=a(this);v.on("click",function(e){if(i.value=t,i.half){var o=e.pageX-a(this).offset().left;o<=n/2&&(i.value=i.value-.5)}i.text&&l.next("span").text(i.value+"星"),i.choose&&i.choose(i.value),i.setText&&i.setText(i.value)}),v.on("mousemove",function(e){if(l.find("i").each(function(){a(this).addClass(o).removeClass(r)}),l.find("i:lt("+t+")").each(function(){a(this).addClass(s).removeClass(f)}),i.half){var c=e.pageX-a(this).offset().left;c<=n/2&&v.children("i").addClass(u).removeClass(s)}}),v.on("mouseleave",function(){l.find("i").each(function(){a(this).addClass(o).removeClass(r)}),l.find("i:lt("+Math.floor(i.value)+")").each(function(){a(this).addClass(s).removeClass(f)}),i.half&&parseInt(i.value)!==i.value&&l.children("li:eq("+Math.floor(i.value)+")").children("i").addClass(u).removeClass(c)})})},v.prototype.events=function(){var e=this;e.config},i.render=function(e){var a=new v(e);return l.call(a)},e(n,i)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/table.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define(["laytpl","laypage","layer","form"],function(e){"use strict";var t=layui.$,i=layui.laytpl,a=layui.laypage,l=layui.layer,n=layui.form,o=layui.hint(),r=layui.device(),d={config:{checkName:"LAY_CHECKED",indexName:"LAY_TABLE_INDEX"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,s,e,t)}},c=function(){var e=this,t=e.config,i=t.id;return i&&(c.config[i]=t),{reload:function(t){e.reload.call(e,t)},config:t}},s="table",u=".layui-table",h="layui-hide",f="layui-none",y="layui-table-view",p=".layui-table-header",m=".layui-table-body",v=".layui-table-main",g=".layui-table-fixed",x=".layui-table-fixed-l",b=".layui-table-fixed-r",k=".layui-table-tool",C=".layui-table-page",w=".layui-table-sort",N="layui-table-edit",T="layui-table-hover",F=function(e){var t='{{#if(item2.colspan){}} colspan="{{item2.colspan}}"{{#} if(item2.rowspan){}} rowspan="{{item2.rowspan}}"{{#}}}';return e=e||{},['',"","{{# layui.each(d.data.cols, function(i1, item1){ }}","","{{# layui.each(item1, function(i2, item2){ }}",'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}','{{# if(item2.fixed === "right"){ right = true; } }}',function(){return e.fixed&&"right"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== "right"){ }}':"right"===e.fixed?'{{# if(item2.fixed === "right"){ }}':""}(),'",e.fixed?"{{# }; }}":"","{{# }); }}","","{{# }); }}","","
        ','
        1){ }}","group","{{# } else { }}","{{d.index}}-{{item2.field || i2}}",'{{# if(item2.type !== "normal"){ }}'," laytable-cell-{{ item2.type }}","{{# } }}","{{# } }}",'" {{#if(item2.align){}}align="{{item2.align}}"{{#}}}>','{{# if(item2.type === "checkbox"){ }}','',"{{# } else { }}",'{{item2.title||""}}',"{{# if(!(item2.colspan > 1) && item2.sort){ }}",'',"{{# } }}","{{# } }}","
        ","
        "].join("")},W=['',"","
        "].join(""),z=['
        ',"{{# if(d.data.toolbar){ }}",'
        ',"{{# } }}",'
        ',"{{# var left, right; }}",'
        ',F(),"
        ",'
        ',W,"
        ","{{# if(left){ }}",'
        ','
        ',F({fixed:!0}),"
        ",'
        ',W,"
        ","
        ","{{# }; }}","{{# if(right){ }}",'
        ','
        ',F({fixed:"right"}),'
        ',"
        ",'
        ',W,"
        ","
        ","{{# }; }}","
        ","{{# if(d.data.page){ }}",'
        ','
        ',"
        ","{{# } }}","","
        "].join(""),A=t(window),S=t(document),M=function(e){var i=this;i.index=++d.index,i.config=t.extend({},i.config,d.config,e),i.render()};M.prototype.config={limit:10,loading:!0,cellMinWidth:60,text:{none:"无数据"}},M.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr("id"),a.request=t.extend({pageName:"page",limitName:"limit"},a.request),a.response=t.extend({statusName:"code",statusCode:0,msgName:"msg",dataName:"data",countName:"count"},a.response),"object"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;e.setArea();var l=a.elem,n=l.next("."+y),o=e.elem=t(i(z).render({VIEW_CLASS:y,data:a,index:e.index}));if(a.index=e.index,n[0]&&n.remove(),l.after(o),e.layHeader=o.find(p),e.layMain=o.find(v),e.layBody=o.find(m),e.layFixed=o.find(g),e.layFixLeft=o.find(x),e.layFixRight=o.find(b),e.layTool=o.find(k),e.layPage=o.find(C),e.layTool.html(i(t(a.toolbar).html()||"").render(a)),a.height&&e.fullSize(),a.cols.length>1){var r=e.layFixed.find(p).find("th");r.height(e.layHeader.height()-1-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom")))}e.pullData(e.page),e.events()},M.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,space:15,numbers:40});e.checkbox&&(e.type="checkbox"),e.space&&(e.type="space"),e.type||(e.type="normal"),"normal"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},M.prototype.setArea=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=t.width||function(){var e=function(i){var a,l;i=i||t.elem.parent(),a=i.width();try{l="none"===i.css("display")}catch(n){}return!i[0]||a&&!l?a:e(i.parent())};return e()}();e.eachCols(function(){i++}),o-=function(){return"line"===t.skin||"nob"===t.skin?2:i+1}(),layui.each(t.cols,function(t,i){layui.each(i,function(t,l){var r;return l?(e.initOpts(l),r=l.width||0,void(l.colspan>1||(/\d+%$/.test(r)?l.width=r=Math.floor(parseFloat(r)/100*o):r||(l.width=r=0,a++),n+=r))):void i.splice(t,1)})}),e.autoColNums=a,o>n&&a&&(l=(o-n)/a),layui.each(t.cols,function(e,i){layui.each(i,function(e,i){var a=i.minWidth||t.cellMinWidth;i.colspan>1||0===i.width&&(i.width=Math.floor(l>=a?l:a))})}),t.height&&/^full-\d+$/.test(t.height)&&(e.fullHeightGap=t.height.split("-")[1],t.height=A.height()-e.fullHeightGap)},M.prototype.reload=function(e){var i=this;i.config.data&&i.config.data.constructor===Array&&delete i.config.data,i.config=t.extend({},i.config,e),i.render()},M.prototype.page=1,M.prototype.pullData=function(e,i){var a=this,n=a.config,o=n.request,r=n.response,d=function(){"object"==typeof n.initSort&&a.sort(n.initSort.field,n.initSort.type)};if(a.startTime=(new Date).getTime(),n.url){var c={};c[o.pageName]=e,c[o.limitName]=n.limit;var s=t.extend(c,n.where);n.contentType&&0==n.contentType.indexOf("application/json")&&(s=JSON.stringify(s)),t.ajax({type:n.method||"get",url:n.url,contentType:n.contentType,data:s,dataType:"json",headers:n.headers||{},success:function(t){t[r.statusName]!=r.statusCode?(a.renderForm(),a.layMain.html('
        '+(t[r.msgName]||"返回的数据状态异常")+"
        ")):(a.renderData(t,e,t[r.countName]),d(),n.time=(new Date).getTime()-a.startTime+" ms"),i&&l.close(i),"function"==typeof n.done&&n.done(t,e,t[r.countName])},error:function(e,t){a.layMain.html('
        数据接口请求异常
        '),a.renderForm(),i&&l.close(i)}})}else if(n.data&&n.data.constructor===Array){var u={},h=e*n.limit-n.limit;u[r.dataName]=n.data.concat().splice(h,n.limit),u[r.countName]=n.data.length,a.renderData(u,e,n.data.length),d(),"function"==typeof n.done&&n.done(u,e,u[r.countName])}},M.prototype.eachCols=function(e){var i=t.extend(!0,[],this.config.cols),a=[],l=0;layui.each(i,function(e,t){layui.each(t,function(t,n){if(n.colspan>1){var o=0;l++,n.CHILD_COLS=[],layui.each(i[e+1],function(e,t){t.PARENT_COL||o==n.colspan||(t.PARENT_COL=l,n.CHILD_COLS.push(t),o+=t.colspan>1?t.colspan:1)})}n.PARENT_COL||a.push(n)})});var n=function(t){layui.each(t||a,function(t,i){return i.CHILD_COLS?n(i.CHILD_COLS):void e(t,i)})};n()},M.prototype.renderData=function(e,n,o,r){var c=this,s=c.config,u=e[s.response.dataName]||[],y=[],p=[],m=[],v=function(){return!r&&c.sortKey?c.sort(c.sortKey.field,c.sortKey.sort,!0):(layui.each(u,function(e,a){var l=[],o=[],u=[],h=e+s.limit*(n-1)+1;0!==a.length&&(r||(a[d.config.indexName]=e),c.eachCols(function(e,n){var r=n.field||e,f=a[r];c.getColElem(c.layHeader,r);if(void 0!==f&&null!==f||(f=""),!(n.colspan>1)){var y=['",'
        '+function(){var e=t.extend(!0,{LAY_INDEX:h},a);return"checkbox"===n.type?'":"numbers"===n.type?h:n.toolbar?i(t(n.toolbar).html()||"").render(e):n.templet?function(){return"function"==typeof n.templet?n.templet(e):i(t(n.templet).html()||String(f)).render(e)}():f}(),"
        "].join("");l.push(y),n.fixed&&"right"!==n.fixed&&o.push(y),"right"===n.fixed&&u.push(y)}}),y.push(''+l.join("")+""),p.push(''+o.join("")+""),m.push(''+u.join("")+""))}),c.layBody.scrollTop(0),c.layMain.find("."+f).remove(),c.layMain.find("tbody").html(y.join("")),c.layFixLeft.find("tbody").html(p.join("")),c.layFixRight.find("tbody").html(m.join("")),c.renderForm(),c.syncCheckAll(),c.haveInit?c.scrollPatch():setTimeout(function(){c.scrollPatch()},50),c.haveInit=!0,void l.close(c.tipsIndex))};return c.key=s.id||s.index,d.cache[c.key]=u,c.layPage[0===u.length&&1==n?"addClass":"removeClass"](h),r?v():0===u.length?(c.renderForm(),c.layFixed.remove(),c.layMain.find("tbody").html(""),c.layMain.find("."+f).remove(),c.layMain.append('
        '+s.text.none+"
        ")):(v(),void(s.page&&(s.page=t.extend({elem:"layui-table-page"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:["prev","page","next","skip","count","limit"],prev:'',next:'',jump:function(e,t){t||(c.page=e.curr,s.limit=e.limit,c.pullData(e.curr,c.loading()))}},s.page),s.page.count=o,a.render(s.page))))},M.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(".laytable-cell-"+(a.index+"-"+t)+":eq(0)")},M.prototype.renderForm=function(e){n.render(e,"LAY-table-"+this.index)},M.prototype.sort=function(e,i,a,l){var n,r,c=this,u={},h=c.config,f=h.elem.attr("lay-filter"),y=d.cache[c.key];"string"==typeof e&&c.layHeader.find("th").each(function(i,a){var l=t(this),o=l.data("field");if(o===e)return e=l,n=o,!1});try{var n=n||e.data("field");if(c.sortKey&&!a&&n===c.sortKey.field&&i===c.sortKey.sort)return;var p=c.layHeader.find("th .laytable-cell-"+h.index+"-"+n).find(w);c.layHeader.find("th").find(w).removeAttr("lay-sort"),p.attr("lay-sort",i||null),c.layFixed.find("th")}catch(m){return o.error("Table modules: Did not match to field")}c.sortKey={field:n,sort:i},"asc"===i?r=layui.sort(y,n):"desc"===i?r=layui.sort(y,n,!0):(r=layui.sort(y,d.config.indexName),delete c.sortKey),u[h.response.dataName]=r,c.renderData(u,c.page,c.count,!0),l&&layui.event.call(e,s,"sort("+f+")",{field:n,type:i})},M.prototype.loading=function(){var e=this,t=e.config;if(t.loading&&t.url)return l.msg("数据请求中",{icon:16,offset:[e.elem.offset().top+e.elem.height()/2-35-A.scrollTop()+"px",e.elem.offset().left+e.elem.width()/2-90-A.scrollLeft()+"px"],time:-1,anim:-1,fixed:!1})},M.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=d.cache[i.key];l[e]&&l[e].constructor!==Array&&(l[e][a.checkName]=t)},M.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name="layTableCheckbox"]'),a=function(i){return e.eachCols(function(e,a){"checkbox"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(d.checkStatus(e.key).isAll?(i[0].checked||(i.prop("checked",!0),e.renderForm("checkbox")),a(!0)):(i[0].checked&&(i.prop("checked",!1),e.renderForm("checkbox")),a(!1)))},M.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find("style")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(a,l){if(l.selectorText===".laytable-cell-"+i.index+"-"+e)return t(l),!0})},M.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=A.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css("height",a)),e=parseFloat(a)-parseFloat(t.layHeader.height())-1,i.toolbar&&(e-=t.layTool.outerHeight()),i.page&&(e=e-t.layPage.outerHeight()-1),t.layMain.css("height",e)},M.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement("div"),e.style.width="100px",e.style.height="100px",e.style.overflowY="scroll",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},M.prototype.scrollPatch=function(){var e=this,i=e.layMain.children("table"),a=e.layMain.width()-e.layMain.prop("clientWidth"),l=e.layMain.height()-e.layMain.prop("clientHeight"),n=e.getScrollWidth(e.layMain[0]),o=i.outerWidth()-e.layMain.width();if(e.autoColNums&&o<5&&!e.scrollPatchWStatus){var r=e.layHeader.eq(0).find("thead th:last-child"),d=r.data("field");e.getCssRule(d,function(t){var i=t.style.width||r.outerWidth();t.style.width=parseFloat(i)-n-o+"px",e.layMain.height()-e.layMain.prop("clientHeight")>0&&(t.style.width=parseFloat(t.style.width)-1+"px"),e.scrollPatchWStatus=!0})}if(a&&l){if(!e.elem.find(".layui-table-patch")[0]){var c=t('
        ');c.find("div").css({width:a}),e.layHeader.eq(0).find("thead tr").append(c)}}else e.layHeader.eq(0).find(".layui-table-patch").remove();var s=e.layMain.height(),u=s-l;e.layFixed.find(m).css("height",i.height()>u?u:"auto"),e.layFixRight[o>0?"removeClass":"addClass"](h),e.layFixRight.css("right",a-1)},M.prototype.events=function(){var e,a=this,n=a.config,o=t("body"),c={},u=a.layHeader.find("th"),h=".layui-table-cell",f=n.elem.attr("lay-filter");u.on("mousemove",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.attr("colspan")>1||i.data("unresize")||c.resizeStart||(c.allowResize=i.width()-l<=10,o.css("cursor",c.allowResize?"col-resize":""))}).on("mouseleave",function(){t(this);c.resizeStart||o.css("cursor","")}).on("mousedown",function(e){var i=t(this);if(c.allowResize){var l=i.data("field");e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],a.getCssRule(l,function(e){var t=e.style.width||i.outerWidth();c.rule=e,c.ruleWidth=parseFloat(t),c.minWidth=i.data("minwidth")||n.cellMinWidth})}}),S.on("mousemove",function(t){if(c.resizeStart){if(t.preventDefault(),c.rule){var i=c.ruleWidth+t.clientX-c.offset[0];i');d[0].value=e.data("content")||o.text(),e.find("."+N)[0]||e.append(d),d.focus()}else o.find(".layui-form-switch,.layui-form-checkbox")[0]||Math.round(o.prop("scrollWidth"))>Math.round(o.outerWidth())&&(a.tipsIndex=l.tips(['
        ',o.html(),"
        ",''].join(""),o[0],{tips:[3,""],time:-1,anim:-1,maxWidth:r.ios||r.android?300:600,isOutAnim:!1,skin:"layui-table-tips",success:function(e,t){e.find(".layui-table-tips-c").on("click",function(){l.close(t)})}}))}),a.layBody.on("click","*[lay-event]",function(){var e=t(this),l=e.parents("tr").eq(0).data("index"),n=a.layBody.find('tr[data-index="'+l+'"]'),o="layui-table-click",r=d.cache[a.key][l];layui.event.call(this,s,"tool("+f+")",{data:d.clearCacheKey(r),event:e.attr("lay-event"),tr:n,del:function(){d.cache[a.key][l]=[],n.remove(),a.scrollPatch()},update:function(e){e=e||{},layui.each(e,function(e,l){if(e in r){var o,d=n.children('td[data-field="'+e+'"]');r[e]=l,a.eachCols(function(t,i){i.field==e&&i.templet&&(o=i.templet)}),d.children(h).html(o?i(t(o).html()||l).render(r):l),d.data("content",l)}})}}),n.addClass(o).siblings("tr").removeClass(o)}),a.layMain.on("scroll",function(){var e=t(this),i=e.scrollLeft(),n=e.scrollTop();a.layHeader.scrollLeft(i),a.layFixed.find(m).scrollTop(n),l.close(a.tipsIndex)}),A.on("resize",function(){a.fullSize(),a.scrollPatch()})},d.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter="'+e+'"]':u+"[lay-data]"),n="Table element property lay-data configuration item has a syntax error: ";return l.each(function(){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(r){o.error(n+l)}var c=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr("lay-skin"),size:a.attr("lay-size"),even:"string"==typeof a.attr("lay-even")},d.config,i,l);e&&a.hide(),a.find("thead>tr").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(r){return o.error(n+l)}var d=t.extend({title:a.text(),colspan:a.attr("colspan")||0,rowspan:a.attr("rowspan")||0},l);d.colspan<2&&c.push(d),s.cols[e].push(d)})}),a.find("tbody>tr").each(function(e){var i=t(this),a={};i.children("td").each(function(e,i){var l=t(this),n=l.data("field");if(n)return a[n]=l.html()}),layui.each(c,function(e,t){var l=i.children("td").eq(e);a[t.field]=l.html()}),s.data[e]=a}),d.render(s)}),a},d.checkStatus=function(e){var t=0,i=0,a=[],l=d.cache[e]||[];return layui.each(l,function(e,l){return l.constructor===Array?void i++:void(l[d.config.checkName]&&(t++,a.push(d.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.config={},d.reload=function(e,i){var a=c.config[e];return i=i||{},a?(i.data&&i.data.constructor===Array&&delete a.data,d.render(t.extend(!0,{},a,i))):o.error("The ID option was not found in the table instance")},d.render=function(e){var t=new M(e);return c.call(t)},d.clearCacheKey=function(e){return e=t.extend({},e),delete e[d.config.checkName],delete e[d.config.indexName],e},d.init(),e(s,d)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/tree.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("jquery",function(e){"use strict";var o=layui.$,a=layui.hint(),i="layui-tree-enter",r=function(e){this.options=e},t={arrow:["",""],checkbox:["",""],radio:["",""],branch:["",""],leaf:""};r.prototype.init=function(e){var o=this;e.addClass("layui-box layui-tree"),o.options.skin&&e.addClass("layui-tree-skin-"+o.options.skin),o.tree(e),o.on(e)},r.prototype.tree=function(e,a){var i=this,r=i.options,n=a||r.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('
          '),s=o(["
        • ",function(){return l?''+(n.spread?t.arrow[1]:t.arrow[0])+"":""}(),function(){return r.check?''+("checkbox"===r.check?t.checkbox[0]:"radio"===r.check?t.radio[0]:"")+"":""}(),function(){return'"+(''+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+"")+(""+(n.name||"未命名")+"")}(),"
        • "].join(""));l&&(s.append(c),i.tree(c,n.children)),e.append(s),"function"==typeof r.click&&i.click(s,n),i.spread(s,n),r.drag&&i.drag(s,n)})},r.prototype.click=function(e,o){var a=this,i=a.options;e.children("a").on("click",function(e){layui.stope(e),i.click(o)})},r.prototype.spread=function(e,o){var a=this,i=(a.options,e.children(".layui-tree-spread")),r=e.children("ul"),n=e.children("a"),l=function(){e.data("spread")?(e.data("spread",null),r.removeClass("layui-show"),i.html(t.arrow[0]),n.find(".layui-icon").html(t.branch[0])):(e.data("spread",!0),r.addClass("layui-show"),i.html(t.arrow[1]),n.find(".layui-icon").html(t.branch[1]))};r[0]&&(i.on("click",l),n.on("dblclick",l))},r.prototype.on=function(e){var a=this,r=a.options,t="layui-tree-drag";e.find("i").on("selectstart",function(e){return!1}),r.drag&&o(document).on("mousemove",function(e){var i=a.move;if(i.from){var r=(i.to,o('
          '));e.preventDefault(),o("."+t)[0]||o("body").append(r);var n=o("."+t)[0]?o("."+t):r;n.addClass("layui-show").html(i.from.elem.children("a").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on("mouseup",function(){var e=a.move;e.from&&(e.from.elem.children("a").removeClass(i),e.to&&e.to.elem.children("a").removeClass(i),a.move={},o("."+t).remove())})},r.prototype.move={},r.prototype.drag=function(e,a){var r=this,t=(r.options,e.children("a")),n=function(){var t=o(this),n=r.move;n.from&&(n.to={item:a,elem:e},t.addClass(i))};t.on("mousedown",function(){var o=r.move;o.from={item:a,elem:e}}),t.on("mouseenter",n).on("mousemove",n).on("mouseleave",function(){var e=o(this),a=r.move;a.from&&(delete a.to,e.removeClass(i))})},e("tree",function(e){var i=new r(e=e||{}),t=o(e.elem);return t[0]?void i.init(t):a.error("layui.tree 没有找到"+e.elem+"元素")})}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/upload.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("layer",function(e){"use strict";var i=layui.$,t=layui.layer,n=layui.hint(),a=layui.device(),o={config:{},set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,r,e,i)}},l=function(){var e=this;return{upload:function(i){e.upload.call(e,i)},config:e.config}},r="upload",u="layui-upload-file",c="layui-upload-form",f="layui-upload-iframe",s="layui-upload-choose",p=function(e){var t=this;t.config=i.extend({},t.config,o.config,e),t.render()};p.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",field:"file",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var t=this,e=t.config;e.elem=i(e.elem),e.bindAction=i(e.bindAction),t.file(),t.events()},p.prototype.file=function(){var e=this,t=e.config,n=e.elemFile=i(['"].join("")),o=t.elem.next();(o.hasClass(u)||o.hasClass(c))&&o.remove(),a.ie&&a.ie<10&&t.elem.wrap('
          '),e.isFile()?(e.elemFile=t.elem,t.field=t.elem[0].name):t.elem.after(n),a.ie&&a.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,t=e.config,n=i(''),a=i(['
          ',"
          "].join(""));i("#"+f)[0]||i("body").append(n),t.elem.next().hasClass(f)||(e.elemFile.wrap(a),t.elem.next("."+f).append(function(){var e=[];return layui.each(t.data,function(i,t){t="function"==typeof t?t():t,e.push('')}),e.join("")}()))},p.prototype.msg=function(e){return t.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},p.prototype.preview=function(e){var i=this;window.FileReader&&layui.each(i.chooseFiles,function(i,t){var n=new FileReader;n.readAsDataURL(t),n.onload=function(){e&&e(i,t,this.result)}})},p.prototype.upload=function(e,t){var n,o=this,l=o.config,r=o.elemFile[0],u=function(){var t=0,n=0,a=e||o.files||o.chooseFiles||r.files,u=function(){l.multiple&&t+n===o.fileLength&&"function"==typeof l.allDone&&l.allDone({total:o.fileLength,successful:t,aborted:n})};layui.each(a,function(e,a){var r=new FormData;r.append(l.field,a),layui.each(l.data,function(e,i){i="function"==typeof i?i():i,r.append(e,i)}),i.ajax({url:l.url,type:l.method,data:r,contentType:!1,processData:!1,dataType:"json",headers:l.headers||{},success:function(i){t++,d(e,i),u()},error:function(){n++,o.msg("请求上传接口出现异常"),m(e),u()}})})},c=function(){var e=i("#"+f);o.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var i,t=e.contents().find("body");try{i=t.text()}catch(n){o.msg("获取上传后的响应信息出现异常"),clearInterval(p.timer),m()}i&&(clearInterval(p.timer),t.html(""),d(0,i))},30)},d=function(e,i){if(o.elemFile.next("."+s).remove(),r.value="","object"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},o.msg("请对上传接口返回有效JSON")}"function"==typeof l.done&&l.done(i,e||0,function(e){o.upload(e)})},m=function(e){l.auto&&(r.value=""),"function"==typeof l.error&&l.error(e||0,function(e){o.upload(e)})},h=l.exts,v=function(){var i=[];return layui.each(e||o.chooseFiles,function(e,t){i.push(t.name)}),i}(),g={preview:function(e){o.preview(e)},upload:function(e,i){var t={};t[e]=i,o.upload(t)},pushFile:function(){return o.files=o.files||{},layui.each(o.chooseFiles,function(e,i){o.files[e]=i}),o.files}},y=function(){return"choose"===t?l.choose&&l.choose(g):(l.before&&l.before(g),a.ie?a.ie>9?u():c():void u())};if(v=0===v.length?r.value.match(/[^\/\\]+\..+/g)||[]||"":v,0!==v.length){switch(l.accept){case"file":if(h&&!RegExp("\\w\\.("+h+")$","i").test(escape(v)))return o.msg("选择的文件中包含不支持的格式"),r.value="";break;case"video":if(!RegExp("\\w\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(v)))return o.msg("选择的视频中包含不支持的格式"),r.value="";break;case"audio":if(!RegExp("\\w\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(v)))return o.msg("选择的音频中包含不支持的格式"),r.value="";break;default:if(layui.each(v,function(e,i){RegExp("\\w\\.("+(h||"jpg|png|gif|bmp|jpeg$")+")","i").test(escape(i))||(n=!0)}),n)return o.msg("选择的图片中包含不支持的格式"),r.value=""}if(o.fileLength=function(){var i=0,t=e||o.files||o.chooseFiles||r.files;return layui.each(t,function(){i++}),i}(),l.number&&o.fileLength>l.number)return o.msg("同时最多只能上传的数量为:"+l.number);if(l.size>0&&!(a.ie&&a.ie<10)){var F;if(layui.each(o.chooseFiles,function(e,i){if(i.size>1024*l.size){var t=l.size/1024;t=t>=1?t.toFixed(2)+"MB":l.size+"KB",r.value="",F=t}}),F)return o.msg("文件不能超过"+F)}y()}},p.prototype.events=function(){var e=this,t=e.config,o=function(i){e.chooseFiles={},layui.each(i,function(i,t){var n=(new Date).getTime();e.chooseFiles[n+"-"+i]=t})},l=function(i,n){var a=e.elemFile,o=i.length>1?i.length+"个文件":(i[0]||{}).name||a[0].value.match(/[^\/\\]+\..+/g)||[]||"";a.next().hasClass(s)&&a.next().remove(),e.upload(null,"choose"),e.isFile()||t.choose||a.after(''+o+"")};t.elem.off("upload.start").on("upload.start",function(){var a=i(this),o=a.attr("lay-data");if(o)try{o=new Function("return "+o)(),e.config=i.extend({},t,o)}catch(l){n.error("Upload element property lay-data configuration item has a syntax error: "+o)}e.config.item=a,e.elemFile[0].click()}),a.ie&&a.ie<10||t.elem.off("upload.over").on("upload.over",function(){var e=i(this);e.attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){var e=i(this);e.removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(n,a){var r=i(this),u=a.originalEvent.dataTransfer.files||[];r.removeAttr("lay-over"),o(u),t.auto?e.upload(u):l(u)}),e.elemFile.off("upload.change").on("upload.change",function(){var i=this.files||[];o(i),t.auto?e.upload():l(i)}),t.bindAction.off("upload.action").on("upload.action",function(){e.upload()}),t.elem.data("haveEvents")||(e.elemFile.on("change",function(){i(this).trigger("upload.change")}),t.elem.on("click",function(){e.isFile()||i(this).trigger("upload.start")}),t.drag&&t.elem.on("dragover",function(e){e.preventDefault(),i(this).trigger("upload.over")}).on("dragleave",function(e){i(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),i(this).trigger("upload.drop",e)}),t.bindAction.on("click",function(){i(this).trigger("upload.action")}),t.elem.data("haveEvents",!0))},o.render=function(e){var i=new p(e);return l.call(i)},e(r,o)}); ================================================ FILE: open-layui-web/src/main/view/static/layui/lay/modules/util.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;layui.define("jquery",function(e){"use strict";var t=layui.$,i={fixbar:function(e){var i,o,a="layui-fixbar",r="layui-fixbar-top",n=t(document),l=t("body");e=t.extend({showHeight:200},e),e.bar1=e.bar1===!0?"":e.bar1,e.bar2=e.bar2===!0?"":e.bar2,e.bgcolor=e.bgcolor?"background-color:"+e.bgcolor:"";var c=[e.bar1,e.bar2,""],g=t(['
            ',e.bar1?'
          • '+c[0]+"
          • ":"",e.bar2?'
          • '+c[1]+"
          • ":"",'
          • '+c[2]+"
          • ","
          "].join("")),s=g.find("."+r),u=function(){var t=n.scrollTop();t>=e.showHeight?i||(s.show(),i=1):i&&(s.hide(),i=0)};t("."+a)[0]||("object"==typeof e.css&&g.css(e.css),l.append(g),u(),g.find("li").on("click",function(){var i=t(this),o=i.attr("lay-type");"top"===o&&t("html,body").animate({scrollTop:0},200),e.click&&e.click.call(this,o)}),n.on("scroll",function(){clearTimeout(o),o=setTimeout(function(){u()},100)}))},countdown:function(e,t,i){var o=this,a="function"==typeof t,r=new Date(e).getTime(),n=new Date(!t||a?(new Date).getTime():t).getTime(),l=r-n,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];a&&(i=t);var g=setTimeout(function(){o.countdown(e,n+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,o=[[],[]],a=(new Date).getTime()-new Date(e).getTime();return a>6912e5?(a=new Date(e),o[0][0]=i.digit(a.getFullYear(),4),o[0][1]=i.digit(a.getMonth()+1),o[0][2]=i.digit(a.getDate()),t||(o[1][0]=i.digit(a.getHours()),o[1][1]=i.digit(a.getMinutes()),o[1][2]=i.digit(a.getSeconds())),o[0].join("-")+" "+o[1].join(":")):a>=864e5?(a/1e3/60/60/24|0)+"天前":a>=36e5?(a/1e3/60/60|0)+"小时前":a>=12e4?(a/1e3/60|0)+"分钟前":a<0?"未来":"刚刚"},digit:function(e,t){var i="";e=String(e),t=t||2;for(var o=e.length;o0;r--)if("interactive"===n[r].readyState){e=n[r].src;break}return e||n[o].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),a=function(t){e.console&&console.error&&console.error("Layui hint: "+t)},i="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),u={layer:"modules/layer",laydate:"modules/laydate",laypage:"modules/laypage",laytpl:"modules/laytpl",layim:"modules/layim",layedit:"modules/layedit",form:"modules/form",upload:"modules/upload",tree:"modules/tree",table:"modules/table",element:"modules/element",rate:"modules/rate",carousel:"modules/carousel",flow:"modules/flow",util:"modules/util",code:"modules/code",jquery:"modules/jquery",mobile:"modules/mobile","layui.all":"../layui.all"};o.prototype.cache=n,o.prototype.define=function(e,t){var o=this,r="function"==typeof e,a=function(){var e=function(e,t){layui[e]=t,n.status[e]=!0};return"function"==typeof t&&t(function(o,r){e(o,r),n.callback[o]=function(){t(e)}}),this};return r&&(t=e,e=[]),layui["layui.all"]||!layui["layui.all"]&&layui["layui.mobile"]?a.call(o):(o.use(e,a),o)},o.prototype.use=function(e,o,l){function s(e,t){var o="PLaySTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/;("load"===e.type||o.test((e.currentTarget||e.srcElement).readyState))&&(n.modules[d]=t,f.removeChild(v),function r(){return++m>1e3*n.timeout/4?a(d+" is not a valid module"):void(n.status[d]?c():setTimeout(r,4))}())}function c(){l.push(layui[d]),e.length>1?y.use(e.slice(1),o,l):"function"==typeof o&&o.apply(layui,l)}var y=this,p=n.dir=n.dir?n.dir:r,f=t.getElementsByTagName("head")[0];e="string"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(y.each(e,function(t,n){"jquery"===n&&e.splice(t,1)}),layui.jquery=layui.$=jQuery);var d=e[0],m=0;if(l=l||[],n.host=n.host||(p.match(/\/\/([\s\S]+?)\//)||["//"+location.host+"/"])[0],0===e.length||layui["layui.all"]&&u[d]||!layui["layui.all"]&&layui["layui.mobile"]&&u[d])return c(),y;if(n.modules[d])!function g(){return++m>1e3*n.timeout/4?a(d+" is not a valid module"):void("string"==typeof n.modules[d]&&n.status[d]?c():setTimeout(g,4))}();else{var v=t.createElement("script"),h=(u[d]?p+"lay/":/^\{\/\}/.test(y.modules[d])?"":n.base||"")+(y.modules[d]||d)+".js";h=h.replace(/^\{\/\}/,""),v.async=!0,v.charset="utf-8",v.src=h+function(){var e=n.version===!0?n.v||(new Date).getTime():n.version||"";return e?"?v="+e:""}(),f.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf("[native code")<0||i?v.addEventListener("load",function(e){s(e,h)},!1):v.attachEvent("onreadystatechange",function(e){s(e,h)}),n.modules[d]=h}return y},o.prototype.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?"getPropertyValue":"getAttribute"](n)},o.prototype.link=function(e,o,r){var i=this,u=t.createElement("link"),l=t.getElementsByTagName("head")[0];"string"==typeof o&&(r=o);var s=(r||e).replace(/\.|\//g,""),c=u.id="layuicss-"+s,y=0;return u.rel="stylesheet",u.href=e+(n.debug?"?v="+(new Date).getTime():""),u.media="all",t.getElementById(c)||l.appendChild(u),"function"!=typeof o?i:(function p(){return++y>1e3*n.timeout/100?a(e+" timeout"):void(1989===parseInt(i.getStyle(t.getElementById(c),"width"))?function(){o()}():setTimeout(p,100))}(),i)},n.callback={},o.prototype.factory=function(e){if(layui[e])return"function"==typeof n.callback[e]?n.callback[e]:null},o.prototype.addcss=function(e,t,o){return layui.link(n.dir+"css/"+e,t,o)},o.prototype.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,"function"==typeof t&&t(o)},void(o.onerror=function(e){o.onerror=null,"function"==typeof n&&n(e)}))},o.prototype.config=function(e){e=e||{};for(var t in e)n[t]=e[t];return this},o.prototype.modules=function(){var e={};for(var t in u)e[t]=u[t];return e}(),o.prototype.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?a("模块名 "+n+" 已被占用"):t.modules[n]=e[n];return t},o.prototype.router=function(e){var t=this,e=e||location.hash,n={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(e)?(e=e.replace(/^#\//,""),n.href="/"+e,e=e.replace(/([^#])(#.*$)/,"$1").split("/")||[],t.each(e,function(e,t){/^\w+=/.test(t)?function(){t=t.split("="),n.search[t[0]]=t[1]}():n.path.push(t)}),n):n},o.prototype.data=function(t,n,o){if(t=t||"layui",o=o||localStorage,e.JSON&&e.JSON.parse){if(null===n)return delete o[t];n="object"==typeof n?n:{key:n};try{var r=JSON.parse(o[t])}catch(a){var r={}}return"value"in n&&(r[n.key]=n.value),n.remove&&delete r[n.key],o[t]=JSON.stringify(r),n.key?r[n.key]:r}},o.prototype.sessionData=function(e,t){return this.data(e,t,sessionStorage)},o.prototype.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+"/([^\\s\\_\\-]+)");return e=(n.match(t)||[])[1],e||!1},r={os:function(){return/windows/.test(n)?"windows":/linux/.test(n)?"linux":/iphone|ipod|ipad|ios/.test(n)?"ios":/mac/.test(n)?"mac":void 0}(),ie:function(){return!!(e.ActiveXObject||"ActiveXObject"in e)&&((n.match(/msie\s(\d+)/)||[])[1]||"11")}(),weixin:o("micromessenger")};return t&&!r[t]&&(r[t]=o(t)),r.android=/android/.test(n),r.ios="ios"===r.os,r},o.prototype.hint=function(){return{error:a}},o.prototype.each=function(e,t){var n,o=this;if("function"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;na?1:r/g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var c="Laytpl Error:";return"object"==typeof console&&console.error(c+e+"\n"+(r||"")),c+e}},n=c.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=n("^"+r.open+"#",""),l=n(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(n(r.open+"#"),r.open+"# ").replace(n(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(n(r.open+"!(.+?)!"+r.close),function(e){return e=e.replace(n("^"+r.open+"!"),"").replace(n("!"+r.close),"").replace(n(r.open+"|"+r.close),function(e){return e.replace(/(.)/g,"\\$1")})}).replace(/(?="|')/g,"\\").replace(c.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\/g,"")+';view+="'}).replace(c.query(1),function(e){var c='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(n(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),c='"+_escape_('),c+e.replace(/\\/g,"")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,c.escape)}catch(u){return delete o.cache,c.error(u,p)}},t.pt.render=function(e,r){var n,t=this;return e?(n=t.cache?t.cache(e,c.escape):t.parse(t.tpl,e),r?void r(n):n):c.error("no data")};var o=function(e){return"string"!=typeof e?c.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var c in e)r[c]=e[c]},o.v="1.2.0",e("laytpl",o)});layui.define(function(e){"use strict";var a=document,t="getElementById",n="getElementsByTagName",i="laypage",r="layui-disabled",u=function(e){var a=this;a.config=e||{},a.config.index=++s.index,a.render(!0)};u.prototype.type=function(){var e=this.config;if("object"==typeof e.elem)return void 0===e.elem.length?2:3},u.prototype.view=function(){var e=this,a=e.config,t=a.groups="groups"in a?0|a.groups:5;a.layout="object"==typeof a.layout?a.layout:["prev","page","next"],a.count=0|a.count,a.curr=0|a.curr||1,a.limits="object"==typeof a.limits?a.limits:[10,20,30,40,50],a.limit=0|a.limit||10,a.pages=Math.ceil(a.count/a.limit)||1,a.curr>a.pages&&(a.curr=a.pages),t<0?t=1:t>a.pages&&(t=a.pages),a.prev="prev"in a?a.prev:"上一页",a.next="next"in a?a.next:"下一页";var n=a.pages>t?Math.ceil((a.curr+(t>1?1:0))/(t>0?t:1)):1,i={prev:function(){return a.prev?''+a.prev+"":""}(),page:function(){var e=[];if(a.count<1)return"";n>1&&a.first!==!1&&0!==t&&e.push(''+(a.first||1)+"");var i=Math.floor((t-1)/2),r=n>1?a.curr-i:1,u=n>1?function(){var e=a.curr+(t-i-1);return e>a.pages?a.pages:e}():t;for(u-r2&&e.push('');r<=u;r++)r===a.curr?e.push('"+r+""):e.push(''+r+"");return a.pages>t&&a.pages>u&&a.last!==!1&&(u+1…'),0!==t&&e.push(''+(a.last||a.pages)+"")),e.join("")}(),next:function(){return a.next?''+a.next+"":""}(),count:'共 '+a.count+" 条",limit:function(){var e=['"}(),refresh:['','',""].join(""),skip:function(){return['到第','','页',""].join("")}()};return['
          ',function(){var e=[];return layui.each(a.layout,function(a,t){i[t]&&e.push(i[t])}),e.join("")}(),"
          "].join("")},u.prototype.jump=function(e,a){if(e){var t=this,i=t.config,r=e.children,u=e[n]("button")[0],l=e[n]("input")[0],p=e[n]("select")[0],c=function(){var e=0|l.value.replace(/\s|\D/g,"");e&&(i.curr=e,t.render())};if(a)return c();for(var o=0,y=r.length;oi.pages||(i.curr=e,t.render())});p&&s.on(p,"change",function(){var e=this.value;i.curr*e>i.count&&(i.curr=Math.ceil(i.count/e)),i.limit=e,t.render()}),u&&s.on(u,"click",function(){c()})}},u.prototype.skip=function(e){if(e){var a=this,t=e[n]("input")[0];t&&s.on(t,"keyup",function(t){var n=this.value,i=t.keyCode;/^(37|38|39|40)$/.test(i)||(/\D/.test(n)&&(this.value=n.replace(/\D/,"")),13===i&&a.jump(e,!0))})}},u.prototype.render=function(e){var n=this,i=n.config,r=n.type(),u=n.view();2===r?i.elem&&(i.elem.innerHTML=u):3===r?i.elem.html(u):a[t](i.elem)&&(a[t](i.elem).innerHTML=u),i.jump&&i.jump(i,e);var s=a[t]("layui-laypage-"+i.index);n.jump(s),i.hash&&!e&&(location.hash="!"+i.hash+"="+i.curr),n.skip(s)};var s={render:function(e){var a=new u(e);return a.index},index:layui.laypage?layui.laypage.index+1e4:0,on:function(e,a,t){return e.attachEvent?e.attachEvent("on"+a,function(a){a.target=a.srcElement,t.call(e,a)}):e.addEventListener(a,t,!1),this}};e(i,s)});!function(){"use strict";var e=window.layui&&layui.define,t={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,n=t.length-1,a=n;a>0;a--)if("interactive"===t[a].readyState){e=t[a].src;break}return e||t[n].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),getStyle:function(e,t){var n=e.currentStyle?e.currentStyle:window.getComputedStyle(e,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](t)},link:function(e,a,i){if(n.path){var r=document.getElementsByTagName("head")[0],o=document.createElement("link");"string"==typeof a&&(i=a);var s=(i||e).replace(/\.|\//g,""),l="layuicss-"+s,d=0;o.rel="stylesheet",o.href=n.path+e,o.id=l,document.getElementById(l)||r.appendChild(o),"function"==typeof a&&!function c(){return++d>80?window.console&&console.error("laydate.css: Invalid"):void(1989===parseInt(t.getStyle(document.getElementById(l),"width"))?a():setTimeout(c,100))}()}}},n={v:"5.0.9",config:{},index:window.laydate&&window.laydate.v?1e5:0,path:t.getPath,set:function(e){var t=this;return t.config=w.extend({},t.config,e),t},ready:function(a){var i="laydate",r="",o=(e?"modules/laydate/":"theme/")+"default/laydate.css?v="+n.v+r;return e?layui.addcss(o,a,i):t.link(o,a,i),this}},a=function(){var e=this;return{hint:function(t){e.hint.call(e,t)},config:e.config}},i="laydate",r=".layui-laydate",o="layui-this",s="laydate-disabled",l="开始日期超出了结束日期
          建议重新选择",d=[100,2e5],c="layui-laydate-static",m="layui-laydate-list",u="laydate-selected",h="layui-laydate-hint",y="laydate-day-prev",f="laydate-day-next",p="layui-laydate-footer",g=".laydate-btns-confirm",v="laydate-time-text",D=".laydate-btns-time",T=function(e){var t=this;t.index=++n.index,t.config=w.extend({},t.config,n.config,e),n.ready(function(){t.init()})},w=function(e){return new C(e)},C=function(e){for(var t=0,n="object"==typeof e?[e]:(this.selector=e,document.querySelectorAll(e||null));t0)return n[0].getAttribute(e)}():n.each(function(n,a){a.setAttribute(e,t)})},C.prototype.removeAttr=function(e){return this.each(function(t,n){n.removeAttribute(e)})},C.prototype.html=function(e){return this.each(function(t,n){n.innerHTML=e})},C.prototype.val=function(e){return this.each(function(t,n){n.value=e})},C.prototype.append=function(e){return this.each(function(t,n){"object"==typeof e?n.appendChild(e):n.innerHTML=n.innerHTML+e})},C.prototype.remove=function(e){return this.each(function(t,n){e?n.removeChild(e):n.parentNode.removeChild(n)})},C.prototype.on=function(e,t){return this.each(function(n,a){a.attachEvent?a.attachEvent("on"+e,function(e){e.target=e.srcElement,t.call(a,e)}):a.addEventListener(e,t,!1)})},C.prototype.off=function(e,t){return this.each(function(n,a){a.detachEvent?a.detachEvent("on"+e,t):a.removeEventListener(e,t,!1)})},T.isLeapYear=function(e){return e%4===0&&e%100!==0||e%400===0},T.prototype.config={type:"date",range:!1,format:"yyyy-MM-dd",value:null,isInitValue:!1,min:"1900-1-1",max:"2099-12-31",trigger:"focus",show:!1,showBottom:!0,btns:["clear","now","confirm"],lang:"cn",theme:"default",position:null,calendar:!1,mark:{},zIndex:null,done:null,change:null},T.prototype.lang=function(){var e=this,t=e.config,n={cn:{weeks:["日","一","二","三","四","五","六"],time:["时","分","秒"],timeTips:"选择时间",startTime:"开始时间",endTime:"结束时间",dateTips:"返回日期",month:["一","二","三","四","五","六","七","八","九","十","十一","十二"],tools:{confirm:"确定",clear:"清空",now:"现在"}},en:{weeks:["Su","Mo","Tu","We","Th","Fr","Sa"],time:["Hours","Minutes","Seconds"],timeTips:"Select Time",startTime:"Start Time",endTime:"End Time",dateTips:"Select Date",month:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],tools:{confirm:"Confirm",clear:"Clear",now:"Now"}}};return n[t.lang]||n.cn},T.prototype.init=function(){var e=this,t=e.config,n="yyyy|y|MM|M|dd|d|HH|H|mm|m|ss|s",a="static"===t.position,i={year:"yyyy",month:"yyyy-MM",date:"yyyy-MM-dd",time:"HH:mm:ss",datetime:"yyyy-MM-dd HH:mm:ss"};t.elem=w(t.elem),t.eventElem=w(t.eventElem),t.elem[0]&&(t.range===!0&&(t.range="-"),t.format===i.date&&(t.format=i[t.type]),e.format=t.format.match(new RegExp(n+"|.","g"))||[],e.EXP_IF="",e.EXP_SPLIT="",w.each(e.format,function(t,a){var i=new RegExp(n).test(a)?"\\d{"+function(){return new RegExp(n).test(e.format[0===t?t+1:t-1]||"")?/^yyyy|y$/.test(a)?4:a.length:/^yyyy$/.test(a)?"1,4":/^y$/.test(a)?"1,308":"1,2"}()+"}":"\\"+a;e.EXP_IF=e.EXP_IF+i,e.EXP_SPLIT=e.EXP_SPLIT+"("+i+")"}),e.EXP_IF=new RegExp("^"+(t.range?e.EXP_IF+"\\s\\"+t.range+"\\s"+e.EXP_IF:e.EXP_IF)+"$"),e.EXP_SPLIT=new RegExp("^"+e.EXP_SPLIT+"$",""),e.isInput(t.elem[0])||"focus"===t.trigger&&(t.trigger="click"),t.elem.attr("lay-key")||(t.elem.attr("lay-key",e.index),t.eventElem.attr("lay-key",e.index)),t.mark=w.extend({},t.calendar&&"cn"===t.lang?{"0-1-1":"元旦","0-2-14":"情人","0-3-8":"妇女","0-3-12":"植树","0-4-1":"愚人","0-5-1":"劳动","0-5-4":"青年","0-6-1":"儿童","0-9-10":"教师","0-9-18":"国耻","0-10-1":"国庆","0-12-25":"圣诞"}:{},t.mark),w.each(["min","max"],function(e,n){var a=[],i=[];if("number"==typeof t[n]){var r=t[n],o=(new Date).getTime(),s=864e5,l=new Date(r?r0)return!0;var a=w.elem("div",{"class":"layui-laydate-header"}),i=[function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-prev-y"});return e.innerHTML="",e}(),function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-prev-m"});return e.innerHTML="",e}(),function(){var e=w.elem("div",{"class":"laydate-set-ym"}),t=w.elem("span"),n=w.elem("span");return e.appendChild(t),e.appendChild(n),e}(),function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-next-m"});return e.innerHTML="",e}(),function(){var e=w.elem("i",{"class":"layui-icon laydate-icon laydate-next-y"});return e.innerHTML="",e}()],d=w.elem("div",{"class":"layui-laydate-content"}),c=w.elem("table"),m=w.elem("thead"),u=w.elem("tr");w.each(i,function(e,t){a.appendChild(t)}),m.appendChild(u),w.each(new Array(6),function(e){var t=c.insertRow(0);w.each(new Array(7),function(a){if(0===e){var i=w.elem("th");i.innerHTML=n.weeks[a],u.appendChild(i)}t.insertCell(a)})}),c.insertBefore(m,c.children[0]),d.appendChild(c),r[e]=w.elem("div",{"class":"layui-laydate-main laydate-main-list-"+e}),r[e].appendChild(a),r[e].appendChild(d),o.push(i),s.push(d),l.push(c)}),w(d).html(function(){var e=[],i=[];return"datetime"===t.type&&e.push(''+n.timeTips+""),w.each(t.btns,function(e,r){var o=n.tools[r]||"btn";t.range&&"now"===r||(a&&"clear"===r&&(o="cn"===t.lang?"重置":"Reset"),i.push(''+o+""))}),e.push('"),e.join("")}()),w.each(r,function(e,t){i.appendChild(t)}),t.showBottom&&i.appendChild(d),/^#/.test(t.theme)){var m=w.elem("style"),u=["#{{id}} .layui-laydate-header{background-color:{{theme}};}","#{{id}} .layui-this{background-color:{{theme}} !important;}"].join("").replace(/{{id}}/g,e.elemID).replace(/{{theme}}/g,t.theme);"styleSheet"in m?(m.setAttribute("type","text/css"),m.styleSheet.cssText=u):m.innerHTML=u,w(i).addClass("laydate-theme-molv"),i.appendChild(m)}e.remove(T.thisElemDate),a?t.elem.append(i):(document.body.appendChild(i),e.position()),e.checkDate().calendar(),e.changeEvent(),T.thisElemDate=e.elemID,"function"==typeof t.ready&&t.ready(w.extend({},t.dateTime,{month:t.dateTime.month+1}))},T.prototype.remove=function(e){var t=this,n=(t.config,w("#"+(e||t.elemID)));return n.hasClass(c)||t.checkDate(function(){n.remove()}),t},T.prototype.position=function(){var e=this,t=e.config,n=e.bindElem||t.elem[0],a=n.getBoundingClientRect(),i=e.elem.offsetWidth,r=e.elem.offsetHeight,o=function(e){return e=e?"scrollLeft":"scrollTop",document.body[e]|document.documentElement[e]},s=function(e){return document.documentElement[e?"clientWidth":"clientHeight"]},l=5,d=a.left,c=a.bottom;d+i+l>s("width")&&(d=s("width")-i-l),c+r+l>s()&&(c=a.top>r?a.top-r:s()-r,c-=2*l),t.position&&(e.elem.style.position=t.position),e.elem.style.left=d+("fixed"===t.position?0:o(1))+"px",e.elem.style.top=c+("fixed"===t.position?0:o())+"px"},T.prototype.hint=function(e){var t=this,n=(t.config,w.elem("div",{"class":h}));n.innerHTML=e||"",w(t.elem).find("."+h).remove(),t.elem.appendChild(n),clearTimeout(t.hinTimer),t.hinTimer=setTimeout(function(){w(t.elem).find("."+h).remove()},3e3)},T.prototype.getAsYM=function(e,t,n){return n?t--:t++,t<0&&(t=11,e--),t>11&&(t=0,e++),[e,t]},T.prototype.systemDate=function(e){var t=e||new Date;return{year:t.getFullYear(),month:t.getMonth(),date:t.getDate(),hours:e?e.getHours():0,minutes:e?e.getMinutes():0,seconds:e?e.getSeconds():0}},T.prototype.checkDate=function(e){var t,a,i=this,r=(new Date,i.config),o=r.dateTime=r.dateTime||i.systemDate(),s=i.bindElem||r.elem[0],l=(i.isInput(s)?"val":"html",i.isInput(s)?s.value:"static"===r.position?"":s.innerHTML),c=function(e){e.year>d[1]&&(e.year=d[1],a=!0),e.month>11&&(e.month=11,a=!0),e.hours>23&&(e.hours=0,a=!0),e.minutes>59&&(e.minutes=0,e.hours++,a=!0),e.seconds>59&&(e.seconds=0,e.minutes++,a=!0),t=n.getEndDate(e.month+1,e.year),e.date>t&&(e.date=t,a=!0)},m=function(e,t,n){var o=["startTime","endTime"];t=(t.match(i.EXP_SPLIT)||[]).slice(1),n=n||0,r.range&&(i[o[n]]=i[o[n]]||{}),w.each(i.format,function(s,l){var c=parseFloat(t[s]);t[s].length必须遵循下述格式:
          "+(r.range?r.format+" "+r.range+" "+r.format:r.format)+"
          已为你重置"),a=!0):l&&l.constructor===Date?r.dateTime=i.systemDate(l):(r.dateTime=i.systemDate(),delete i.startState,delete i.endState,delete i.startDate,delete i.endDate,delete i.startTime,delete i.endTime),c(o),a&&l&&i.setValue(r.range?i.endDate?i.parse():"":i.parse()),e&&e(),i)},T.prototype.mark=function(e,t){var n,a=this,i=a.config;return w.each(i.mark,function(e,a){var i=e.split("-");i[0]!=t[0]&&0!=i[0]||i[1]!=t[1]&&0!=i[1]||i[2]!=t[2]||(n=a||t[2])}),n&&e.html(''+n+""),a},T.prototype.limit=function(e,t,n,a){var i,r=this,o=r.config,l={},d=o[n>41?"endDate":"dateTime"],c=w.extend({},d,t||{});return w.each({now:c,min:o.min,max:o.max},function(e,t){l[e]=r.newDate(w.extend({year:t.year,month:t.month,date:t.date},function(){var e={};return w.each(a,function(n,a){e[a]=t[a]}),e}())).getTime()}),i=l.nowl.max,e&&e[i?"addClass":"removeClass"](s),i},T.prototype.calendar=function(e){var t,a,i,r=this,s=r.config,l=e||s.dateTime,c=new Date,m=r.lang(),u="date"!==s.type&&"datetime"!==s.type,h=e?1:0,y=w(r.table[h]).find("td"),f=w(r.elemHeader[h][2]).find("span");if(l.yeard[1]&&(l.year=d[1],r.hint("最高只能支持到公元"+d[1]+"年")),r.firstDate||(r.firstDate=w.extend({},l)),c.setFullYear(l.year,l.month,1),t=c.getDay(),a=n.getEndDate(l.month||12,l.year),i=n.getEndDate(l.month+1,l.year),w.each(y,function(e,n){var d=[l.year,l.month],c=0;n=w(n),n.removeAttr("class"),e=t&&e=n.firstDate.year&&(r.month=a.max.month,r.date=a.max.date),n.limit(w(i),r,t),M++}),w(u[f?0:1]).attr("lay-ym",M-8+"-"+T[1]).html(b+p+" - "+(M-1+p))}else if("month"===e)w.each(new Array(12),function(e){var i=w.elem("li",{"lay-ym":e}),s={year:T[0],month:e};e+1==T[1]&&w(i).addClass(o),i.innerHTML=r.month[e]+(f?"月":""),d.appendChild(i),T[0]=n.firstDate.year&&(s.date=a.max.date),n.limit(w(i),s,t)}),w(u[f?0:1]).attr("lay-ym",T[0]+"-"+T[1]).html(T[0]+p);else if("time"===e){var E=function(){w(d).find("ol").each(function(e,a){w(a).find("li").each(function(a,i){n.limit(w(i),[{hours:a},{hours:n[x].hours,minutes:a},{hours:n[x].hours,minutes:n[x].minutes,seconds:a}][e],t,[["hours"],["hours","minutes"],["hours","minutes","seconds"]][e])})}),a.range||n.limit(w(n.footer).find(g),n[x],0,["hours","minutes","seconds"])};a.range?n[x]||(n[x]={hours:0,minutes:0,seconds:0}):n[x]=i,w.each([24,60,60],function(e,t){var a=w.elem("li"),i=["

          "+r.time[e]+"

            "];w.each(new Array(t),function(t){i.push(""+w.digit(t,2)+"")}),a.innerHTML=i.join("")+"
          ",d.appendChild(a)}),E()}if(y&&h.removeChild(y),h.appendChild(d),"year"===e||"month"===e)w(n.elemMain[t]).addClass("laydate-ym-show"),w(d).find("li").on("click",function(){var r=0|w(this).attr("lay-ym");if(!w(this).hasClass(s)){if(0===t)i[e]=r,l&&(n.startDate[e]=r),n.limit(w(n.footer).find(g),null,0);else if(l)n.endDate[e]=r;else{var c="year"===e?n.getAsYM(r,T[1]-1,"sub"):n.getAsYM(T[0],r,"sub");w.extend(i,{year:c[0],month:c[1]})}"year"===a.type||"month"===a.type?(w(d).find("."+o).removeClass(o),w(this).addClass(o),"month"===a.type&&"year"===e&&(n.listYM[t][0]=r,l&&(n[["startDate","endDate"][t]].year=r),n.list("month",t))):(n.checkDate("limit").calendar(),n.closeList()),n.setBtnStatus(),a.range||n.done(null,"change"),w(n.footer).find(D).removeClass(s)}});else{var S=w.elem("span",{"class":v}),k=function(){w(d).find("ol").each(function(e){var t=this,a=w(t).find("li");t.scrollTop=30*(n[x][C[e]]-2),t.scrollTop<=0&&a.each(function(e,n){if(!w(this).hasClass(s))return t.scrollTop=30*(e-2),!0})})},H=w(c[2]).find("."+v);k(),S.innerHTML=a.range?[r.startTime,r.endTime][t]:r.timeTips,w(n.elemMain[t]).addClass("laydate-time-show"),H[0]&&H.remove(),c[2].appendChild(S),w(d).find("ol").each(function(e){var t=this;w(t).find("li").on("click",function(){var r=0|this.innerHTML;w(this).hasClass(s)||(a.range?n[x][C[e]]=r:i[C[e]]=r,w(t).find("."+o).removeClass(o),w(this).addClass(o),E(),k(),(n.endDate||"time"===a.type)&&n.done(null,"change"),n.setBtnStatus())})})}return n},T.prototype.listYM=[],T.prototype.closeList=function(){var e=this;e.config;w.each(e.elemCont,function(t,n){w(this).find("."+m).remove(),w(e.elemMain[t]).removeClass("laydate-ym-show laydate-time-show")}),w(e.elem).find("."+v).remove()},T.prototype.setBtnStatus=function(e,t,n){var a,i=this,r=i.config,o=w(i.footer).find(g),d=r.range&&"date"!==r.type&&"time"!==r.type;d&&(t=t||i.startDate,n=n||i.endDate,a=i.newDate(t).getTime()>i.newDate(n).getTime(),i.limit(null,t)||i.limit(null,n)?o.addClass(s):o[a?"addClass":"removeClass"](s),e&&a&&i.hint("string"==typeof e?l.replace(/日期/g,e):l))},T.prototype.parse=function(e,t){var n=this,a=n.config,i=t||(e?w.extend({},n.endDate,n.endTime):a.range?w.extend({},n.startDate,n.startTime):a.dateTime),r=n.format.concat();return w.each(r,function(e,t){/yyyy|y/.test(t)?r[e]=w.digit(i.year,t.length):/MM|M/.test(t)?r[e]=w.digit(i.month+1,t.length):/dd|d/.test(t)?r[e]=w.digit(i.date,t.length):/HH|H/.test(t)?r[e]=w.digit(i.hours,t.length):/mm|m/.test(t)?r[e]=w.digit(i.minutes,t.length):/ss|s/.test(t)&&(r[e]=w.digit(i.seconds,t.length))}),a.range&&!e?r.join("")+" "+a.range+" "+n.parse(1):r.join("")},T.prototype.newDate=function(e){return e=e||{},new Date(e.year||1,e.month||0,e.date||1,e.hours||0,e.minutes||0,e.seconds||0)},T.prototype.setValue=function(e){var t=this,n=t.config,a=t.bindElem||n.elem[0],i=t.isInput(a)?"val":"html";return"static"===n.position||w(a)[i](e||""),this},T.prototype.stampRange=function(){var e,t,n=this,a=n.config,i=w(n.elem).find("td");if(a.range&&!n.endDate&&w(n.footer).find(g).addClass(s),n.endDate)return e=n.newDate({year:n.startDate.year,month:n.startDate.month,date:n.startDate.date}).getTime(),t=n.newDate({year:n.endDate.year,month:n.endDate.month,date:n.endDate.date}).getTime(),e>t?n.hint(l):void w.each(i,function(a,i){var r=w(i).attr("lay-ymd").split("-"),s=n.newDate({year:r[0],month:r[1]-1,date:r[2]}).getTime();w(i).removeClass(u+" "+o),s!==e&&s!==t||w(i).addClass(w(i).hasClass(y)||w(i).hasClass(f)?u:o),s>e&&s0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener("DOMContentLoaded",s),e.removeEventListener("load",s)):(re.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(re.addEventListener||"load"===e.event.type||"complete"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(_e,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n||"false"!==n&&("null"===n?null:+n+""===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if(("data"!==t||!pe.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||"string"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),"object"!=typeof t&&"function"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,"")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?"":"px"),c=(pe.cssNumber[t]||"px"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||".5",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,"globalEval",!t||pe._data(t[r],"globalEval"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,"input"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),"script"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||"")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,"table")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function C(e){return e.type=(null!==pe.find.attr(e,"type"))+"/"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r1&&"string"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,"script"),C),a=s.length;c")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a=0&&n=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||"object"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,"constructor")&&!ce.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?ue[le.call(e)]||"object":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,"ms-").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;iT.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[" "],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),n,s0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h="0",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG("*",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P="sizzle"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),ce=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(oe),de=new RegExp("^"+re+"$"),pe={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ye=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ve=/[+~]/,xe=/'|\\/g,be=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),we=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Te,!1):n.attachEvent&&n.attachEvent("onunload",Te)),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute("id")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&F.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+P+"-]").length||F.push("~="),e.querySelectorAll(":checked").length||F.push(":checked"),e.querySelectorAll("a#"+P+"+*").length||F.push(".#.+[+~]")}),i(function(e){var t=H.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+ne+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),M.push("!=",oe)}),F=F.length&&new RegExp(F.join("|")),M=M.length&&new RegExp(M.join("|")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,"='$1']"),w.matchesSelector&&_&&!X[n+" "]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(be,we),e[3]=(e[3]||e[4]||e[5]||"").replace(be,we),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(ae," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,d,p,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}), l=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[P]?o(n):o.length>1?(i=[e,e,"",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,"$1"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split("").sort(U).join("")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("div"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[":"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Ce=/^.[^:#\[\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t1?pe.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,"string"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,"string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,"parentNode")},parentsUntil:function(e,t,n){return xe(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return xe(e,"nextSibling")},prevAll:function(e){return xe(e,"previousSibling")},nextUntil:function(e,t,n){return xe(e,"nextSibling",n)},prevUntil:function(e,t,n){return xe(e,"previousSibling",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\S+/g;pe.Callbacks=function(e){e="string"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n="",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[["resolve","done",pe.Callbacks("once memory"),"resolved"],["reject","fail",pe.Callbacks("once memory"),"rejected"],["notify","progress",pe.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler("ready"),pe(re).off("ready"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),"complete"===re.readyState||"loading"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener("DOMContentLoaded",s),e.addEventListener("load",s);else{re.attachEvent("onreadystatechange",s),e.attachEvent("onload",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll("left")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst="0"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName("body")[0],n&&n.style&&(t=re.createElement("div"),r=re.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),"undefined"!=typeof t.style.zoom&&(t.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement("div");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+" ").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute("classid")===t)},qe=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,"parsedAttrs"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,"parsedAttrs",!0)}return i}return"object"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks("once memory").add(function(){pe._removeData(e,t+"queue"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length
          a",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName("tbody").length,fe.htmlSerialize=!!e.getElementsByTagName("link").length,fe.html5Clone="<:nav>"!==re.createElement("nav").cloneNode(!0).outerHTML,n.type="checkbox",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML="",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement("input"),n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={option:[1,""],legend:[1,"
          ","
          "],area:[1,"",""],param:[1,"",""],thead:[1,"","
          "],tr:[2,"","
          "],col:[2,"","
          "],td:[3,"","
          "],_default:fe.htmlSerialize?[0,"",""]:[1,"X
          ","
          "]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|&#?\w+;/,Ve=/-1&&(h=p.split("."),p=h.shift(),h.sort()),a=p.indexOf(":")<0&&"on"+p,t=t[pe.expando]?t:new pe.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,"events")||{})[t.type]&&pe._data(s,"handle"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,"events")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&("click"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(r=[],n=0;n-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s]","i"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,nt=/\s*$/g,at=p(re),st=at.appendChild(re.createElement("div"));pe.extend({htmlPrefilter:function(e){return e.replace(tt,"<$1>")},clone:function(e,t,n){var r,i,o,a,s,u=pe.contains(e.ownerDocument,e);if(fe.html5Clone||pe.isXMLDoc(e)||!et.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(st.innerHTML=e.outerHTML,st.removeChild(o=st.firstChild)),!(fe.noCloneEvent&&fe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||pe.isXMLDoc(e)))for(r=h(o),s=h(e),a=0;null!=(i=s[a]);++a)r[a]&&k(i,r[a]);if(t)if(n)for(s=s||h(e),r=r||h(o),a=0;null!=(i=s[a]);a++)N(i,r[a]);else N(e,o);return r=h(o,"script"),r.length>0&&g(r,!u&&h(e,"script")),r=s=i=null,o},cleanData:function(e,t){for(var n,r,i,o,a=0,s=pe.expando,u=pe.cache,l=fe.attributes,c=pe.event.special;null!=(n=e[a]);a++)if((t||He(n))&&(i=n[s],o=i&&u[i])){if(o.events)for(r in o.events)c[r]?pe.event.remove(n,r):pe.removeEvent(n,r,o.handle);u[i]&&(delete u[i],l||"undefined"==typeof n.removeAttribute?n[s]=void 0:n.removeAttribute(s),ne.push(i))}}}),pe.fn.extend({domManip:S,detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return Pe(this,function(e){return void 0===e?pe.text(this):this.empty().append((this[0]&&this[0].ownerDocument||re).createTextNode(e))},null,e,arguments.length)},append:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.appendChild(e)}})},prepend:function(){return S(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=T(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return S(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&pe.cleanData(h(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&pe.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return pe.clone(this,e,t)})},html:function(e){return Pe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ze,""):void 0;if("string"==typeof e&&!nt.test(e)&&(fe.htmlSerialize||!et.test(e))&&(fe.leadingWhitespace||!$e.test(e))&&!Xe[(We.exec(e)||["",""])[1].toLowerCase()]){e=pe.htmlPrefilter(e);try{for(;nt",t=l.getElementsByTagName("td"),t[0].style.cssText="margin:0;border:0;padding:0;display:none",o=0===t[0].offsetHeight,o&&(t[0].style.display="",t[1].style.display="none",o=0===t[0].offsetHeight)),f.removeChild(u)}var n,r,i,o,a,s,u=re.createElement("div"),l=re.createElement("div");l.style&&(l.style.cssText="float:left;opacity:.5",fe.opacity="0.5"===l.style.opacity,fe.cssFloat=!!l.style.cssFloat,l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",fe.clearCloneStyle="content-box"===l.style.backgroundClip,u=re.createElement("div"),u.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",l.innerHTML="",u.appendChild(l),fe.boxSizing=""===l.style.boxSizing||""===l.style.MozBoxSizing||""===l.style.WebkitBoxSizing,pe.extend(fe,{reliableHiddenOffsets:function(){return null==n&&t(),o},boxSizingReliable:function(){return null==n&&t(),i},pixelMarginRight:function(){return null==n&&t(),r},pixelPosition:function(){return null==n&&t(),n},reliableMarginRight:function(){return null==n&&t(),a},reliableMarginLeft:function(){return null==n&&t(),s}}))}();var ht,gt,mt=/^(top|right|bottom|left)$/;e.getComputedStyle?(ht=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n.getPropertyValue(t)||n[t]:void 0,""!==a&&void 0!==a||pe.contains(e.ownerDocument,e)||(a=pe.style(e,t)),n&&!fe.pixelMarginRight()&&ft.test(a)&&ct.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o),void 0===a?a:a+""}):pt.currentStyle&&(ht=function(e){return e.currentStyle},gt=function(e,t,n){var r,i,o,a,s=e.style;return n=n||ht(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),ft.test(a)&&!mt.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left="fontSize"===t?"1em":a,a=s.pixelLeft+"px",s.left=r,o&&(i.left=o)),void 0===a?a:a+""||"auto"});var yt=/alpha\([^)]*\)/i,vt=/opacity\s*=\s*([^)]*)/i,xt=/^(none|table(?!-c[ea]).+)/,bt=new RegExp("^("+Fe+")(.*)$","i"),wt={position:"absolute",visibility:"hidden",display:"block"},Tt={letterSpacing:"0",fontWeight:"400"},Ct=["Webkit","O","Moz","ms"],Et=re.createElement("div").style;pe.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=gt(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":fe.cssFloat?"cssFloat":"styleFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=pe.camelCase(t),u=e.style;if(t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:u[t];if(o=typeof n,"string"===o&&(i=Me.exec(n))&&i[1]&&(n=d(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(pe.cssNumber[s]?"":"px")),fe.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),!(a&&"set"in a&&void 0===(n=a.set(e,n,r)))))try{u[t]=n}catch(l){}}},css:function(e,t,n,r){var i,o,a,s=pe.camelCase(t);return t=pe.cssProps[s]||(pe.cssProps[s]=H(s)||s),a=pe.cssHooks[t]||pe.cssHooks[s],a&&"get"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=gt(e,t,r)),"normal"===o&&t in Tt&&(o=Tt[t]),""===n||n?(i=parseFloat(o),n===!0||isFinite(i)?i||0:o):o}}),pe.each(["height","width"],function(e,t){pe.cssHooks[t]={get:function(e,n,r){if(n)return xt.test(pe.css(e,"display"))&&0===e.offsetWidth?dt(e,wt,function(){return M(e,t,r)}):M(e,t,r)},set:function(e,n,r){var i=r&&ht(e);return _(e,n,r?F(e,t,r,fe.boxSizing&&"border-box"===pe.css(e,"boxSizing",!1,i),i):0)}}}),fe.opacity||(pe.cssHooks.opacity={get:function(e,t){return vt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=pe.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===pe.trim(o.replace(yt,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=yt.test(o)?o.replace(yt,i):o+" "+i)}}),pe.cssHooks.marginRight=L(fe.reliableMarginRight,function(e,t){if(t)return dt(e,{display:"inline-block"},gt,[e,"marginRight"])}),pe.cssHooks.marginLeft=L(fe.reliableMarginLeft,function(e,t){if(t)return(parseFloat(gt(e,"marginLeft"))||(pe.contains(e.ownerDocument,e)?e.getBoundingClientRect().left-dt(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}):0))+"px"}),pe.each({margin:"",padding:"",border:"Width"},function(e,t){pe.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+Oe[r]+t]=o[r]||o[r-2]||o[0];return i}},ct.test(e)||(pe.cssHooks[e+t].set=_)}),pe.fn.extend({css:function(e,t){return Pe(this,function(e,t,n){var r,i,o={},a=0;if(pe.isArray(t)){for(r=ht(e),i=t.length;a1)},show:function(){return q(this,!0)},hide:function(){return q(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Re(this)?pe(this).show():pe(this).hide()})}}),pe.Tween=O,O.prototype={constructor:O,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||pe.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(pe.cssNumber[n]?"":"px")},cur:function(){var e=O.propHooks[this.prop];return e&&e.get?e.get(this):O.propHooks._default.get(this)},run:function(e){var t,n=O.propHooks[this.prop];return this.options.duration?this.pos=t=pe.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):O.propHooks._default.set(this),this}},O.prototype.init.prototype=O.prototype,O.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=pe.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){pe.fx.step[e.prop]?pe.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[pe.cssProps[e.prop]]&&!pe.cssHooks[e.prop]?e.elem[e.prop]=e.now:pe.style(e.elem,e.prop,e.now+e.unit)}}},O.propHooks.scrollTop=O.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},pe.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},pe.fx=O.prototype.init,pe.fx.step={};var Nt,kt,St=/^(?:toggle|show|hide)$/,At=/queueHooks$/;pe.Animation=pe.extend($,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return d(n.elem,e,Me.exec(t),n),n}]},tweener:function(e,t){pe.isFunction(e)?(t=e,e=["*"]):e=e.match(De);for(var n,r=0,i=e.length;r
          a",e=n.getElementsByTagName("a")[0],t.setAttribute("type","checkbox"),n.appendChild(t),e=n.getElementsByTagName("a")[0],e.style.cssText="top:1px",fe.getSetAttribute="t"!==n.className,fe.style=/top/.test(e.getAttribute("style")),fe.hrefNormalized="/a"===e.getAttribute("href"),fe.checkOn=!!t.value,fe.optSelected=i.selected,fe.enctype=!!re.createElement("form").enctype,r.disabled=!0,fe.optDisabled=!i.disabled,t=re.createElement("input"),t.setAttribute("value",""),fe.input=""===t.getAttribute("value"),t.value="t",t.setAttribute("type","radio"),fe.radioValue="t"===t.value}();var Dt=/\r/g,jt=/[\x20\t\r\n\f]+/g;pe.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=pe.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,pe(this).val()):e,null==i?i="":"number"==typeof i?i+="":pe.isArray(i)&&(i=pe.map(i,function(e){return null==e?"":e+""})),t=pe.valHooks[this.type]||pe.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return t=pe.valHooks[i.type]||pe.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(Dt,""):null==n?"":n)}}}),pe.extend({valHooks:{option:{get:function(e){var t=pe.find.attr(e,"value");return null!=t?t:pe.trim(pe.text(e)).replace(jt," ")}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||i<0,a=o?null:[],s=o?i+1:r.length,u=i<0?s:o?i:0;u-1)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),pe.each(["radio","checkbox"],function(){pe.valHooks[this]={set:function(e,t){if(pe.isArray(t))return e.checked=pe.inArray(pe(e).val(),t)>-1}},fe.checkOn||(pe.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Lt,Ht,qt=pe.expr.attrHandle,_t=/^(?:checked|selected)$/i,Ft=fe.getSetAttribute,Mt=fe.input;pe.fn.extend({attr:function(e,t){return Pe(this,pe.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){pe.removeAttr(this,e)})}}),pe.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?pe.prop(e,t,n):(1===o&&pe.isXMLDoc(e)||(t=t.toLowerCase(),i=pe.attrHooks[t]||(pe.expr.match.bool.test(t)?Ht:Lt)),void 0!==n?null===n?void pe.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:(r=pe.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!fe.radioValue&&"radio"===t&&pe.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(De);if(o&&1===e.nodeType)for(;n=o[i++];)r=pe.propFix[n]||n,pe.expr.match.bool.test(n)?Mt&&Ft||!_t.test(n)?e[r]=!1:e[pe.camelCase("default-"+n)]=e[r]=!1:pe.attr(e,n,""),e.removeAttribute(Ft?n:r)}}),Ht={set:function(e,t,n){return t===!1?pe.removeAttr(e,n):Mt&&Ft||!_t.test(n)?e.setAttribute(!Ft&&pe.propFix[n]||n,n):e[pe.camelCase("default-"+n)]=e[n]=!0,n}},pe.each(pe.expr.match.bool.source.match(/\w+/g),function(e,t){var n=qt[t]||pe.find.attr;Mt&&Ft||!_t.test(t)?qt[t]=function(e,t,r){var i,o;return r||(o=qt[t],qt[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,qt[t]=o),i}:qt[t]=function(e,t,n){if(!n)return e[pe.camelCase("default-"+t)]?t.toLowerCase():null}}),Mt&&Ft||(pe.attrHooks.value={set:function(e,t,n){return pe.nodeName(e,"input")?void(e.defaultValue=t):Lt&&Lt.set(e,t,n)}}),Ft||(Lt={set:function(e,t,n){var r=e.getAttributeNode(n);if(r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+="","value"===n||t===e.getAttribute(n))return t}},qt.id=qt.name=qt.coords=function(e,t,n){var r;if(!n)return(r=e.getAttributeNode(t))&&""!==r.value?r.value:null},pe.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);if(n&&n.specified)return n.value},set:Lt.set},pe.attrHooks.contenteditable={set:function(e,t,n){Lt.set(e,""!==t&&t,n)}},pe.each(["width","height"],function(e,t){pe.attrHooks[t]={set:function(e,n){if(""===n)return e.setAttribute(t,"auto"),n}}})),fe.style||(pe.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+""}});var Ot=/^(?:input|select|textarea|button|object)$/i,Rt=/^(?:a|area)$/i;pe.fn.extend({prop:function(e,t){return Pe(this,pe.prop,e,t,arguments.length>1)},removeProp:function(e){return e=pe.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),pe.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&pe.isXMLDoc(e)||(t=pe.propFix[t]||t,i=pe.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=pe.find.attr(e,"tabindex");return t?parseInt(t,10):Ot.test(e.nodeName)||Rt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),fe.hrefNormalized||pe.each(["href","src"],function(e,t){pe.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),fe.optSelected||(pe.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),pe.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){pe.propFix[this.toLowerCase()]=this}),fe.enctype||(pe.propFix.enctype="encoding");var Pt=/[\t\r\n\f]/g;pe.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).addClass(e.call(this,t,z(this)))});if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(pe.isFunction(e))return this.each(function(t){pe(this).removeClass(e.call(this,t,z(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(De)||[];n=this[u++];)if(i=z(n),r=1===n.nodeType&&(" "+i+" ").replace(Pt," ")){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");s=pe.trim(r),i!==s&&pe.attr(n,"class",s)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):pe.isFunction(e)?this.each(function(n){pe(this).toggleClass(e.call(this,n,z(this),t),t)}):this.each(function(){var t,r,i,o;if("string"===n)for(r=0,i=pe(this),o=e.match(De)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&"boolean"!==n||(t=z(this),t&&pe._data(this,"__className__",t),pe.attr(this,"class",t||e===!1?"":pe._data(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+z(n)+" ").replace(Pt," ").indexOf(t)>-1)return!0;return!1}}),pe.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){pe.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),pe.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}});var Bt=e.location,Wt=pe.now(),It=/\?/,$t=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;pe.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+"");var n,r=null,i=pe.trim(t+"");return i&&!pe.trim(i.replace($t,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,"")}))?Function("return "+i)():pe.error("Invalid JSON: "+t)},pe.parseXML=function(t){var n,r;if(!t||"string"!=typeof t)return null;try{e.DOMParser?(r=new e.DOMParser,n=r.parseFromString(t,"text/xml")):(n=new e.ActiveXObject("Microsoft.XMLDOM"),n.async="false",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName("parsererror").length||pe.error("Invalid XML: "+t),n};var zt=/#.*$/,Xt=/([?&])_=[^&]*/,Ut=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Vt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Yt=/^(?:GET|HEAD)$/,Jt=/^\/\//,Gt=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Kt={},Qt={},Zt="*/".concat("*"),en=Bt.href,tn=Gt.exec(en.toLowerCase())||[];pe.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:en,type:"GET",isLocal:Vt.test(tn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Zt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":pe.parseJSON,"text xml":pe.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?V(V(e,pe.ajaxSettings),t):V(pe.ajaxSettings,e)},ajaxPrefilter:X(Kt),ajaxTransport:X(Qt),ajax:function(t,n){function r(t,n,r,i){var o,f,v,x,w,C=n;2!==b&&(b=2,u&&e.clearTimeout(u),c=void 0,s=i||"",T.readyState=t>0?4:0,o=t>=200&&t<300||304===t,r&&(x=Y(d,T,r)),x=J(d,x,T,o),o?(d.ifModified&&(w=T.getResponseHeader("Last-Modified"),w&&(pe.lastModified[a]=w),w=T.getResponseHeader("etag"),w&&(pe.etag[a]=w)),204===t||"HEAD"===d.type?C="nocontent":304===t?C="notmodified":(C=x.state,f=x.data,v=x.error,o=!v)):(v=C,!t&&C||(C="error",t<0&&(t=0))),T.status=t,T.statusText=(n||C)+"",o?g.resolveWith(p,[f,C,T]):g.rejectWith(p,[T,C,v]),T.statusCode(y),y=void 0,l&&h.trigger(o?"ajaxSuccess":"ajaxError",[T,d,o?f:v]),m.fireWith(p,[T,C]),l&&(h.trigger("ajaxComplete",[T,d]),--pe.active||pe.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,d=pe.ajaxSetup({},n),p=d.context||d,h=d.context&&(p.nodeType||p.jquery)?pe(p):pe.event,g=pe.Deferred(),m=pe.Callbacks("once memory"),y=d.statusCode||{},v={},x={},b=0,w="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!f)for(f={};t=Ut.exec(s);)f[t[1].toLowerCase()]=t[2];t=f[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?s:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=x[n]=x[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(b<2)for(t in e)y[t]=[y[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||w;return c&&c.abort(t),r(0,t),this}};if(g.promise(T).complete=m.add,T.success=T.done,T.error=T.fail,d.url=((t||d.url||en)+"").replace(zt,"").replace(Jt,tn[1]+"//"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=pe.trim(d.dataType||"*").toLowerCase().match(De)||[""],null==d.crossDomain&&(i=Gt.exec(d.url.toLowerCase()),d.crossDomain=!(!i||i[1]===tn[1]&&i[2]===tn[2]&&(i[3]||("http:"===i[1]?"80":"443"))===(tn[3]||("http:"===tn[1]?"80":"443")))),d.data&&d.processData&&"string"!=typeof d.data&&(d.data=pe.param(d.data,d.traditional)),U(Kt,d,n,T),2===b)return T;l=pe.event&&d.global,l&&0===pe.active++&&pe.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!Yt.test(d.type),a=d.url,d.hasContent||(d.data&&(a=d.url+=(It.test(a)?"&":"?")+d.data,delete d.data),d.cache===!1&&(d.url=Xt.test(a)?a.replace(Xt,"$1_="+Wt++):a+(It.test(a)?"&":"?")+"_="+Wt++)),d.ifModified&&(pe.lastModified[a]&&T.setRequestHeader("If-Modified-Since",pe.lastModified[a]),pe.etag[a]&&T.setRequestHeader("If-None-Match",pe.etag[a])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&T.setRequestHeader("Content-Type",d.contentType),T.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Zt+"; q=0.01":""):d.accepts["*"]);for(o in d.headers)T.setRequestHeader(o,d.headers[o]);if(d.beforeSend&&(d.beforeSend.call(p,T,d)===!1||2===b))return T.abort();w="abort";for(o in{success:1,error:1,complete:1})T[o](d[o]);if(c=U(Qt,d,n,T)){if(T.readyState=1,l&&h.trigger("ajaxSend",[T,d]),2===b)return T;d.async&&d.timeout>0&&(u=e.setTimeout(function(){T.abort("timeout")},d.timeout));try{b=1,c.send(v,r)}catch(C){if(!(b<2))throw C;r(-1,C)}}else r(-1,"No Transport");return T},getJSON:function(e,t,n){return pe.get(e,t,n,"json")},getScript:function(e,t){return pe.get(e,void 0,t,"script")}}),pe.each(["get","post"],function(e,t){pe[t]=function(e,n,r,i){return pe.isFunction(n)&&(i=i||r,r=n,n=void 0),pe.ajax(pe.extend({url:e,type:t,dataType:i,data:n,success:r},pe.isPlainObject(e)&&e))}}),pe._evalUrl=function(e){return pe.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},pe.fn.extend({wrapAll:function(e){if(pe.isFunction(e))return this.each(function(t){pe(this).wrapAll(e.call(this,t))});if(this[0]){var t=pe(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return pe.isFunction(e)?this.each(function(t){pe(this).wrapInner(e.call(this,t))}):this.each(function(){var t=pe(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=pe.isFunction(e);return this.each(function(n){pe(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){pe.nodeName(this,"body")||pe(this).replaceWith(this.childNodes)}).end()}}),pe.expr.filters.hidden=function(e){return fe.reliableHiddenOffsets()?e.offsetWidth<=0&&e.offsetHeight<=0&&!e.getClientRects().length:K(e)},pe.expr.filters.visible=function(e){return!pe.expr.filters.hidden(e)};var nn=/%20/g,rn=/\[\]$/,on=/\r?\n/g,an=/^(?:submit|button|image|reset|file)$/i,sn=/^(?:input|select|textarea|keygen)/i;pe.param=function(e,t){var n,r=[],i=function(e,t){t=pe.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(void 0===t&&(t=pe.ajaxSettings&&pe.ajaxSettings.traditional),pe.isArray(e)||e.jquery&&!pe.isPlainObject(e))pe.each(e,function(){i(this.name,this.value)});else for(n in e)Q(n,e[n],t,i);return r.join("&").replace(nn,"+")},pe.fn.extend({serialize:function(){return pe.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=pe.prop(this,"elements");return e?pe.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!pe(this).is(":disabled")&&sn.test(this.nodeName)&&!an.test(e)&&(this.checked||!Be.test(e))}).map(function(e,t){var n=pe(this).val();return null==n?null:pe.isArray(n)?pe.map(n,function(e){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),pe.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return this.isLocal?ee():re.documentMode>8?Z():/^(get|post|head|put|delete|options)$/i.test(this.type)&&Z()||ee()}:Z;var un=0,ln={},cn=pe.ajaxSettings.xhr();e.attachEvent&&e.attachEvent("onunload",function(){for(var e in ln)ln[e](void 0,!0)}),fe.cors=!!cn&&"withCredentials"in cn,cn=fe.ajax=!!cn,cn&&pe.ajaxTransport(function(t){if(!t.crossDomain||fe.cors){var n;return{send:function(r,i){var o,a=t.xhr(),s=++un;if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)a[o]=t.xhrFields[o];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||r["X-Requested-With"]||(r["X-Requested-With"]="XMLHttpRequest");for(o in r)void 0!==r[o]&&a.setRequestHeader(o,r[o]+"");a.send(t.hasContent&&t.data||null),n=function(e,r){var o,u,l;if(n&&(r||4===a.readyState))if(delete ln[s],n=void 0,a.onreadystatechange=pe.noop,r)4!==a.readyState&&a.abort();else{l={},o=a.status,"string"==typeof a.responseText&&(l.text=a.responseText);try{u=a.statusText}catch(c){u=""}o||!t.isLocal||t.crossDomain?1223===o&&(o=204):o=l.text?200:404}l&&i(o,u,l,a.getAllResponseHeaders())},t.async?4===a.readyState?e.setTimeout(n):a.onreadystatechange=ln[s]=n:n()},abort:function(){n&&n(void 0,!0)}}}}),pe.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return pe.globalEval(e),e}}}),pe.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),pe.ajaxTransport("script",function(e){if(e.crossDomain){var t,n=re.head||pe("head")[0]||re.documentElement;return{send:function(r,i){t=re.createElement("script"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,"success"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var fn=[],dn=/(=)\?(?=&|$)|\?\?/;pe.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=fn.pop()||pe.expando+"_"+Wt++;return this[e]=!0,e}}),pe.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(dn.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&dn.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=pe.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(dn,"$1"+i):t.jsonp!==!1&&(t.url+=(It.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||pe.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?pe(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,fn.push(i)),a&&pe.isFunction(o)&&o(a[0]),a=o=void 0}),"script"}),pe.parseHTML=function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||re;var r=Te.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=y([e],t,i),i&&i.length&&pe(i).remove(),pe.merge([],r.childNodes))};var pn=pe.fn.load;return pe.fn.load=function(e,t,n){if("string"!=typeof e&&pn)return pn.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=pe.trim(e.slice(s,e.length)),e=e.slice(0,s)),pe.isFunction(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&pe.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?pe("
          ").append(pe.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},pe.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){pe.fn[t]=function(e){return this.on(t,e)}}),pe.expr.filters.animated=function(e){return pe.grep(pe.timers,function(t){return e===t.elem}).length},pe.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=pe.css(e,"position"),f=pe(e),d={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=pe.css(e,"top"),u=pe.css(e,"left"),l=("absolute"===c||"fixed"===c)&&pe.inArray("auto",[o,u])>-1,l?(r=f.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),pe.isFunction(t)&&(t=t.call(e,n,pe.extend({},s))),null!=t.top&&(d.top=t.top-s.top+a),null!=t.left&&(d.left=t.left-s.left+i),"using"in t?t.using.call(e,d):f.css(d)}},pe.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){pe.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,pe.contains(t,i)?("undefined"!=typeof i.getBoundingClientRect&&(r=i.getBoundingClientRect()),n=te(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===pe.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),pe.nodeName(e[0],"html")||(n=e.offset()),n.top+=pe.css(e[0],"borderTopWidth",!0),n.left+=pe.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-pe.css(r,"marginTop",!0),left:t.left-n.left-pe.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){ for(var e=this.offsetParent;e&&!pe.nodeName(e,"html")&&"static"===pe.css(e,"position");)e=e.offsetParent;return e||pt})}}),pe.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n=/Y/.test(t);pe.fn[e]=function(r){return Pe(this,function(e,r,i){var o=te(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?pe(o).scrollLeft():i,n?i:pe(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),pe.each(["top","left"],function(e,t){pe.cssHooks[t]=L(fe.pixelPosition,function(e,n){if(n)return n=gt(e,t),ft.test(n)?pe(e).position()[t]+"px":n})}),pe.each({Height:"height",Width:"width"},function(e,t){pe.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){pe.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),a=n||(r===!0||i===!0?"margin":"border");return Pe(this,function(t,n,r){var i;return pe.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):void 0===r?pe.css(t,n,a):pe.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),pe.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),pe.fn.size=function(){return this.length},pe.fn.andSelf=pe.fn.addBack,layui.define(function(e){layui.$=pe,e("jquery",pe)}),pe});!function(e,t){"use strict";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if("interactive"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName("head")[0],s=document.createElement("link");"string"==typeof i&&(n=i);var l=(n||t).replace(/\.|\//g,""),f="layuicss-"+l,c=0;s.rel="stylesheet",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),"function"==typeof i&&!function u(){return++c>80?e.console&&console.error("layer.css: Invalid"):void(1989===parseInt(o.getStyle(document.getElementById(f),"width"))?i():setTimeout(u,100))}()}}},r={v:"3.1.1",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||"ActiveXObject"in e)&&((t.match(/msie\s(\d+)/)||[])[1]||"11")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,"string"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss("modules/layer/"+e.extend):o.link("theme/"+e.extend),this):this},ready:function(e){var t="layer",i="",n=(a?"modules/layer/":"theme/")+"default/layer.css?v="+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a="function"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s="function"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s="function"==typeof n,f=o.config.skin,c=(f?f+" "+f+"-msg":"")||"layui-layer-msg",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+" layui-layer-hui",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+" "+(n.skin||"layui-layer-hui")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];l.anim=["layer-anim-00","layer-anim-01","layer-anim-02","layer-anim-03","layer-anim-04","layer-anim-05","layer-anim-06"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:"信息",offset:"auto",area:"auto",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f="object"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'
          '+(f?r.title[0]:r.title)+"
          ":"";return r.zIndex=s,t([r.shade?'
          ':"",'
          '+(e&&2!=r.type?"":u)+'
          '+(0==r.type&&r.icon!==-1?'':"")+(1==r.type&&e?"":r.content||"")+'
          '+function(){var e=c?'':"";return r.closeBtn&&(e+=''),e}()+""+(r.btn?function(){var e="";"string"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t'+r.btn[t]+"";return'
          '+e+"
          "}():"")+(r.resize?'':"")+"
          "],u,i('
          ')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f="object"==typeof s,c=i("body");if(!t.id||!i("#"+t.id)[0]){switch("string"==typeof t.area&&(t.area="auto"===t.area?["",""]:[t.area,""]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn="btn"in t?t.btn:o.btn[0],r.closeAll("dialog");break;case 2:var s=t.content=f?t.content:[t.content||"http://layer.layui.com","auto"];t.content='';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll("loading");break;case 4:f||(t.content=[t.content,"body"]),t.follow=t.content[1],t.content=t.content[0]+'',delete t.title,t.tips="object"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll("tips")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i("body").append(n[1])}():function(){s.parents("."+l[0])[0]||(s.data("display",s.css("display")).show().addClass("layui-layer-wrap").wrap(n[1]),i("#"+l[0]+a).find("."+l[5]).before(r))}()}():c.append(n[1]),i(".layui-layer-move")[0]||c.append(o.moveElem=u),e.layero=i("#"+l[0]+a),t.scrollbar||l.html.css("overflow","hidden").attr("layer-full",a)}).auto(a),i("#layui-layer-shade"+e.index).css({"background-color":t.shade[1]||"#000",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find("iframe").attr("src",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on("resize",function(){e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u="layer-anim "+l.anim[t.anim];e.layero.addClass(u).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data("isOutAnim",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i("#"+l[0]+e);""===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find("."+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css("padding-top"))))};switch(a.type){case 2:u("iframe");break;default:""===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u("."+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u("."+l[5])):u("."+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o="object"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=n.width()-a[0]:"b"===t.offset?e.offsetTop=n.height()-a[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):"rb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr("minLeft")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i("body"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(".layui-layer-TipsG"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:"auto"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find("."+l[5]).css({"background-color":t.tips[1],"padding-right":t.closeBtn?"30px":""}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(".layui-layer-resize"),c={};return t.move&&l.css("cursor","move"),l.on("mousedown",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css("left")),e.clientY-parseFloat(s.css("top"))],o.moveElem.css("cursor","move").show())}),f.on("mousedown",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css("cursor","se-resize").show()}),a.on("mousemove",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l="fixed"===s.css("position");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;af&&(a=f),ou&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on("mouseup",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find("iframe").on("load",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find("."+l[6]).children("a").on("click",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a["btn"+(e+1)]&&a["btn"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find("."+l[7]).on("click",e),a.shadeClose&&i("#layui-layer-shade"+t.index).on("click",function(){r.close(t.index)}),n.find(".layui-layer-min").on("click",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(".layui-layer-max").on("click",function(){i(this).hasClass("layui-layer-maxmin")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i("select"),function(e,t){var n=i(this);n.parents("."+l[0])[0]||1==n.attr("layer")&&i("."+l[0]).length<1&&n.removeAttr("layer").show(),n=null})},s.pt.IE6=function(e){i("select").each(function(e,t){var n=i(this);n.parents("."+l[0])[0]||"none"===n.css("display")||n.attr({layer:"1"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css("z-index",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on("mousedown",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css("margin-left"))];e.find(".layui-layer-max").addClass("layui-layer-maxmin"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr("layer-full")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty("overflow"):l.html[0].style.removeAttribute("overflow"),l.html.removeAttr("layer-full"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i("."+l[4]).attr("times"),i("#"+l[0]+t).find("iframe").contents().find(e)},r.getFrameIndex=function(e){return i("#"+e).parents("."+l[4]).attr("times")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame("html",e).outerHeight(),n=i("#"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find("."+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find("iframe").css({height:t})}},r.iframeSrc=function(e,t){i("#"+l[0]+e).find("iframe").attr("src",t)},r.style=function(e,t,n){var a=i("#"+l[0]+e),r=a.find(".layui-layer-content"),s=a.attr("type"),f=a.find(l[1]).outerHeight()||0,c=a.find("."+l[6]).outerHeight()||0;a.attr("minLeft");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find("."+l[6]).outerHeight(),s===o.type[2]?a.find("iframe").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom"))}))},r.min=function(e,t){var a=i("#"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr("minLeft")||181*o.minIndex+"px",c=a.css("position");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr("position",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:"fixed",overflow:"hidden"},!0),a.find(".layui-layer-min").hide(),"page"===a.attr("type")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr("minLeft")||o.minIndex++,a.attr("minLeft",f)},r.restore=function(e){var t=i("#"+l[0]+e),n=t.attr("area").split(",");t.attr("type");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===t.attr("type")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i("#"+l[0]+e);o.record(a),l.html.attr("layer-full")||l.html.css("overflow","hidden").attr("layer-full",e),clearTimeout(t),t=setTimeout(function(){var t="fixed"===a.css("position");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(".layui-layer-min").hide()},100)},r.title=function(e,t){var n=i("#"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i("#"+l[0]+e),n=t.attr("type"),a="layer-anim-close";if(t[0]){var s="layui-layer-wrap",f=function(){if(n===o.type[1]&&"object"===t.attr("conType")){t.children(":not(."+l[5]+")").remove();for(var a=t.find("."+s),r=0;r<2;r++)a.unwrap();a.css("display",a.data("display")).removeClass(s)}else{if(n===o.type[2])try{var f=i("#"+l[4]+e)[0];f.contentWindow.document.write(""),f.contentWindow.close(),t.find("."+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML="",t.remove()}"function"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data("isOutAnim")&&t.addClass("layer-anim "+a),i("#layui-layer-moves, #layui-layer-shade"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr("minLeft")&&(o.minIndex--,o.minLeft.push(t.attr("minLeft"))),r.ie&&r.ie<10||!t.data("isOutAnim")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i("."+l[0]),function(){var t=i(this),n=e?t.attr("type")===e:1;n&&r.close(t.attr("times")),n=null})};var f=r.cache||{},c=function(e){return f.skin?" "+f.skin+" "+f.skin+"-"+e:""};r.prompt=function(e,t){var a="";if(e=e||{},"function"==typeof e&&(t=e),e.area){var o=e.area;a='style="width: '+o[0]+"; height: "+o[1]+';"',delete e.area}var s,l=2==e.formType?'":function(){return''}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:["确定","取消"],content:l,skin:"layui-layer-prompt"+c("prompt"),maxWidth:n.width(),success:function(t){s=t.find(".layui-layer-input"),s.val(e.value||"").focus(),"function"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();""===n?s.focus():n.length>(e.maxlength||500)?r.tips("最多输入"+(e.maxlength||500)+"个字数",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n="layui-this",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:"layui-layer-tab"+c("tab"),resize:!1,title:function(){var e=t.length,i=1,a="";if(e>0)for(a=''+t[0].title+"";i"+t[i].title+"";return a}(),content:'
            '+function(){var e=t.length,i=1,a="";if(e>0)for(a='
          • '+(t[0].content||"no content")+"
          • ";i'+(t[i].content||"no content")+"";return a}()+"
          ",success:function(t){var o=t.find(".layui-layer-title").children(),r=t.find(".layui-layer-tabmain").children();o.on("mousedown",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),"function"==typeof e.change&&e.change(o)}),"function"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||"img";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg("没有图片")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr("layer-index",e),u.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(h(),0===u.length)return;if(n||p.on("click",t.img,function(){var e=i(this),n=e.attr("layer-index");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(".layui-layer-imgprev").on("click",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(".layui-layer-imgnext").on("click",function(e){e.preventDefault(),s.imgnext()}),i(document).on("keyup",s.keyup)},s.loadi=r.load(1,{shade:!("shade"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:"layui-layer-photos",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]'+(u[d].alt||
          '+(u.length>1?'':"")+'
          '+(u[d].alt||"")+""+s.imgIndex+"/"+u.length+"
          ",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imguide,.layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
          是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window);layui.define("jquery",function(t){"use strict";var a=layui.$,i=(layui.hint(),layui.device()),e="element",l="layui-this",n="layui-show",s=function(){this.config={}};s.prototype.set=function(t){var i=this;return a.extend(!0,i.config,t),i},s.prototype.on=function(t,a){return layui.onevent.call(this,e,t,a)},s.prototype.tabAdd=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.children(".layui-tab-bar"),o=l.children(".layui-tab-content"),r='
        • "+(i.title||"unnaming")+"
        • ";return s[0]?s.before(r):n.append(r),o.append('
          '+(i.content||"")+"
          "),f.hideTabMore(!0),f.tabAuto(),this},s.prototype.tabDelete=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+i+'"]');return f.tabDelete(null,s),this},s.prototype.tabChange=function(t,i){var e=".layui-tab-title",l=a(".layui-tab[lay-filter="+t+"]"),n=l.children(e),s=n.find('>li[lay-id="'+i+'"]');return f.tabClick.call(s[0],null,null,s),this},s.prototype.tab=function(t){t=t||{},b.on("click",t.headerElem,function(i){var e=a(this).index();f.tabClick.call(this,i,e,null,t)})},s.prototype.progress=function(t,i){var e="layui-progress",l=a("."+e+"[lay-filter="+t+"]"),n=l.find("."+e+"-bar"),s=n.find("."+e+"-text");return n.css("width",i),s.text(i),this};var o=".layui-nav",r="layui-nav-item",c="layui-nav-bar",u="layui-nav-tree",d="layui-nav-child",y="layui-nav-more",h="layui-anim layui-anim-upbit",f={tabClick:function(t,i,s,o){o=o||{};var r=s||a(this),i=i||r.parent().children("li").index(r),c=o.headerElem?r.parent():r.parents(".layui-tab").eq(0),u=o.bodyElem?a(o.bodyElem):c.children(".layui-tab-content").children(".layui-tab-item"),d=r.find("a"),y=c.attr("lay-filter");"javascript:;"!==d.attr("href")&&"_blank"===d.attr("target")||(r.addClass(l).siblings().removeClass(l),u.eq(i).addClass(n).siblings().removeClass(n)),layui.event.call(this,e,"tab("+y+")",{elem:c,index:i})},tabDelete:function(t,i){var n=i||a(this).parent(),s=n.index(),o=n.parents(".layui-tab").eq(0),r=o.children(".layui-tab-content").children(".layui-tab-item"),c=o.attr("lay-filter");n.hasClass(l)&&(n.next()[0]?f.tabClick.call(n.next()[0],null,s+1):n.prev()[0]&&f.tabClick.call(n.prev()[0],null,s-1)),n.remove(),r.eq(s).remove(),setTimeout(function(){f.tabAuto()},50),layui.event.call(this,e,"tabDelete("+c+")",{elem:o,index:s})},tabAuto:function(){var t="layui-tab-more",e="layui-tab-bar",l="layui-tab-close",n=this;a(".layui-tab").each(function(){var s=a(this),o=s.children(".layui-tab-title"),r=(s.children(".layui-tab-content").children(".layui-tab-item"),'lay-stope="tabmore"'),c=a('');if(n===window&&8!=i.ie&&f.hideTabMore(!0),s.attr("lay-allowClose")&&o.find("li").each(function(){var t=a(this);if(!t.find("."+l)[0]){var i=a('');i.on("click",f.tabDelete),t.append(i)}}),"string"!=typeof s.attr("lay-unauto"))if(o.prop("scrollWidth")>o.outerWidth()+1){if(o.find("."+e)[0])return;o.append(c),s.attr("overflow",""),c.on("click",function(a){o[this.title?"removeClass":"addClass"](t),this.title=this.title?"":"收缩"})}else o.find("."+e).remove(),s.removeAttr("overflow")})},hideTabMore:function(t){var i=a(".layui-tab-title");t!==!0&&"tabmore"===a(t.target).attr("lay-stope")||(i.removeClass("layui-tab-more"),i.find(".layui-tab-bar").attr("title",""))},clickThis:function(){var t=a(this),i=t.parents(o),n=i.attr("lay-filter"),s=t.parent(),c=t.siblings("."+d),y="string"==typeof s.attr("lay-unselect");"javascript:;"!==t.attr("href")&&"_blank"===t.attr("target")||y||c[0]||(i.find("."+l).removeClass(l),s.addClass(l)),i.hasClass(u)&&(c.removeClass(h),c[0]&&(s["none"===c.css("display")?"addClass":"removeClass"](r+"ed"),"all"===i.attr("lay-shrink")&&s.siblings().removeClass(r+"ed"))),layui.event.call(this,e,"nav("+n+")",t)},collapse:function(){var t=a(this),i=t.find(".layui-colla-icon"),l=t.siblings(".layui-colla-content"),s=t.parents(".layui-collapse").eq(0),o=s.attr("lay-filter"),r="none"===l.css("display");if("string"==typeof s.attr("lay-accordion")){var c=s.children(".layui-colla-item").children("."+n);c.siblings(".layui-colla-title").children(".layui-colla-icon").html(""),c.removeClass(n)}l[r?"addClass":"removeClass"](n),i.html(r?"":""),layui.event.call(this,e,"collapse("+o+")",{title:t,content:l,show:r})}};s.prototype.init=function(t,e){var l=function(){return e?'[lay-filter="'+e+'"]':""}(),s={tab:function(){f.tabAuto.call({})},nav:function(){var t=200,e={},s={},p={},b=function(l,o,r){var c=a(this),f=c.find("."+d);o.hasClass(u)?l.css({top:c.position().top,height:c.children("a").outerHeight(),opacity:1}):(f.addClass(h),l.css({left:c.position().left+parseFloat(c.css("marginLeft")),top:c.position().top+c.height()-l.height()}),e[r]=setTimeout(function(){l.css({width:c.width(),opacity:1})},i.ie&&i.ie<10?0:t),clearTimeout(p[r]),"block"===f.css("display")&&clearTimeout(s[r]),s[r]=setTimeout(function(){f.addClass(n),c.find("."+y).addClass(y+"d")},300))};a(o+l).each(function(i){var l=a(this),o=a(''),h=l.find("."+r);l.find("."+c)[0]||(l.append(o),h.on("mouseenter",function(){b.call(this,o,l,i)}).on("mouseleave",function(){l.hasClass(u)||(clearTimeout(s[i]),s[i]=setTimeout(function(){l.find("."+d).removeClass(n),l.find("."+y).removeClass(y+"d")},300))}),l.on("mouseleave",function(){clearTimeout(e[i]),p[i]=setTimeout(function(){l.hasClass(u)?o.css({height:0,top:o.position().top+o.height()/2,opacity:0}):o.css({width:0,left:o.position().left+o.width()/2,opacity:0})},t)})),h.find("a").each(function(){var t=a(this),i=(t.parent(),t.siblings("."+d));i[0]&&!t.children("."+y)[0]&&t.append(''),t.off("click",f.clickThis).on("click",f.clickThis)})})},breadcrumb:function(){var t=".layui-breadcrumb";a(t+l).each(function(){var t=a(this),i="lay-separator",e=t.attr(i)||"/",l=t.find("a");l.next("span["+i+"]")[0]||(l.each(function(t){t!==l.length-1&&a(this).after(""+e+"")}),t.css("visibility","visible"))})},progress:function(){var t="layui-progress";a("."+t+l).each(function(){var i=a(this),e=i.find(".layui-progress-bar"),l=e.attr("lay-percent");e.css("width",function(){return/^.+\/.+$/.test(l)?100*new Function("return "+l)()+"%":l}()),i.attr("lay-showPercent")&&setTimeout(function(){e.html(''+l+"")},350)})},collapse:function(){var t="layui-collapse";a("."+t+l).each(function(){var t=a(this).find(".layui-colla-item");t.each(function(){var t=a(this),i=t.find(".layui-colla-title"),e=t.find(".layui-colla-content"),l="none"===e.css("display");i.find(".layui-colla-icon").remove(),i.append(''+(l?"":"")+""),i.off("click",f.collapse).on("click",f.collapse)})})}};return s[t]?s[t]():layui.each(s,function(t,a){a()})},s.prototype.render=s.prototype.init;var p=new s,b=a(document);p.render();var v=".layui-tab-title li";b.on("click",v,f.tabClick),b.on("click",f.hideTabMore),a(window).on("resize",f.tabAuto),t(e,p)});layui.define("layer",function(e){"use strict";var i=layui.$,t=layui.layer,n=layui.hint(),a=layui.device(),o={config:{},set:function(e){var t=this;return t.config=i.extend({},t.config,e),t},on:function(e,i){return layui.onevent.call(this,r,e,i)}},l=function(){var e=this;return{upload:function(i){e.upload.call(e,i)},config:e.config}},r="upload",u="layui-upload-file",c="layui-upload-form",f="layui-upload-iframe",s="layui-upload-choose",p=function(e){var t=this;t.config=i.extend({},t.config,o.config,e),t.render()};p.prototype.config={accept:"images",exts:"",auto:!0,bindAction:"",url:"",field:"file",method:"post",data:{},drag:!0,size:0,number:0,multiple:!1},p.prototype.render=function(e){var t=this,e=t.config;e.elem=i(e.elem),e.bindAction=i(e.bindAction),t.file(),t.events()},p.prototype.file=function(){var e=this,t=e.config,n=e.elemFile=i(['"].join("")),o=t.elem.next();(o.hasClass(u)||o.hasClass(c))&&o.remove(),a.ie&&a.ie<10&&t.elem.wrap('
          '),e.isFile()?(e.elemFile=t.elem,t.field=t.elem[0].name):t.elem.after(n),a.ie&&a.ie<10&&e.initIE()},p.prototype.initIE=function(){var e=this,t=e.config,n=i(''),a=i(['
          ',"
          "].join(""));i("#"+f)[0]||i("body").append(n),t.elem.next().hasClass(f)||(e.elemFile.wrap(a),t.elem.next("."+f).append(function(){var e=[];return layui.each(t.data,function(i,t){t="function"==typeof t?t():t,e.push('')}),e.join("")}()))},p.prototype.msg=function(e){return t.msg(e,{icon:2,shift:6})},p.prototype.isFile=function(){var e=this.config.elem[0];if(e)return"input"===e.tagName.toLocaleLowerCase()&&"file"===e.type},p.prototype.preview=function(e){var i=this;window.FileReader&&layui.each(i.chooseFiles,function(i,t){var n=new FileReader;n.readAsDataURL(t),n.onload=function(){e&&e(i,t,this.result)}})},p.prototype.upload=function(e,t){var n,o=this,l=o.config,r=o.elemFile[0],u=function(){var t=0,n=0,a=e||o.files||o.chooseFiles||r.files,u=function(){l.multiple&&t+n===o.fileLength&&"function"==typeof l.allDone&&l.allDone({total:o.fileLength,successful:t,aborted:n})};layui.each(a,function(e,a){var r=new FormData;r.append(l.field,a),layui.each(l.data,function(e,i){i="function"==typeof i?i():i,r.append(e,i)}),i.ajax({url:l.url,type:l.method,data:r,contentType:!1,processData:!1,dataType:"json",headers:l.headers||{},success:function(i){t++,d(e,i),u()},error:function(){n++,o.msg("请求上传接口出现异常"),m(e),u()}})})},c=function(){var e=i("#"+f);o.elemFile.parent().submit(),clearInterval(p.timer),p.timer=setInterval(function(){var i,t=e.contents().find("body");try{i=t.text()}catch(n){o.msg("获取上传后的响应信息出现异常"),clearInterval(p.timer),m()}i&&(clearInterval(p.timer),t.html(""),d(0,i))},30)},d=function(e,i){if(o.elemFile.next("."+s).remove(),r.value="","object"!=typeof i)try{i=JSON.parse(i)}catch(t){return i={},o.msg("请对上传接口返回有效JSON")}"function"==typeof l.done&&l.done(i,e||0,function(e){o.upload(e)})},m=function(e){l.auto&&(r.value=""),"function"==typeof l.error&&l.error(e||0,function(e){o.upload(e)})},h=l.exts,v=function(){var i=[];return layui.each(e||o.chooseFiles,function(e,t){i.push(t.name)}),i}(),g={preview:function(e){o.preview(e)},upload:function(e,i){var t={};t[e]=i,o.upload(t)},pushFile:function(){return o.files=o.files||{},layui.each(o.chooseFiles,function(e,i){o.files[e]=i}),o.files}},y=function(){return"choose"===t?l.choose&&l.choose(g):(l.before&&l.before(g),a.ie?a.ie>9?u():c():void u())};if(v=0===v.length?r.value.match(/[^\/\\]+\..+/g)||[]||"":v,0!==v.length){switch(l.accept){case"file":if(h&&!RegExp("\\w\\.("+h+")$","i").test(escape(v)))return o.msg("选择的文件中包含不支持的格式"),r.value="";break;case"video":if(!RegExp("\\w\\.("+(h||"avi|mp4|wma|rmvb|rm|flash|3gp|flv")+")$","i").test(escape(v)))return o.msg("选择的视频中包含不支持的格式"),r.value="";break;case"audio":if(!RegExp("\\w\\.("+(h||"mp3|wav|mid")+")$","i").test(escape(v)))return o.msg("选择的音频中包含不支持的格式"),r.value="";break;default:if(layui.each(v,function(e,i){RegExp("\\w\\.("+(h||"jpg|png|gif|bmp|jpeg$")+")","i").test(escape(i))||(n=!0)}),n)return o.msg("选择的图片中包含不支持的格式"),r.value=""}if(o.fileLength=function(){var i=0,t=e||o.files||o.chooseFiles||r.files;return layui.each(t,function(){i++}),i}(),l.number&&o.fileLength>l.number)return o.msg("同时最多只能上传的数量为:"+l.number);if(l.size>0&&!(a.ie&&a.ie<10)){var F;if(layui.each(o.chooseFiles,function(e,i){if(i.size>1024*l.size){var t=l.size/1024;t=t>=1?t.toFixed(2)+"MB":l.size+"KB",r.value="",F=t}}),F)return o.msg("文件不能超过"+F)}y()}},p.prototype.events=function(){var e=this,t=e.config,o=function(i){e.chooseFiles={},layui.each(i,function(i,t){var n=(new Date).getTime();e.chooseFiles[n+"-"+i]=t})},l=function(i,n){var a=e.elemFile,o=i.length>1?i.length+"个文件":(i[0]||{}).name||a[0].value.match(/[^\/\\]+\..+/g)||[]||"";a.next().hasClass(s)&&a.next().remove(),e.upload(null,"choose"),e.isFile()||t.choose||a.after(''+o+"")};t.elem.off("upload.start").on("upload.start",function(){var a=i(this),o=a.attr("lay-data");if(o)try{o=new Function("return "+o)(),e.config=i.extend({},t,o)}catch(l){n.error("Upload element property lay-data configuration item has a syntax error: "+o)}e.config.item=a,e.elemFile[0].click()}),a.ie&&a.ie<10||t.elem.off("upload.over").on("upload.over",function(){var e=i(this);e.attr("lay-over","")}).off("upload.leave").on("upload.leave",function(){var e=i(this);e.removeAttr("lay-over")}).off("upload.drop").on("upload.drop",function(n,a){var r=i(this),u=a.originalEvent.dataTransfer.files||[];r.removeAttr("lay-over"),o(u),t.auto?e.upload(u):l(u)}),e.elemFile.off("upload.change").on("upload.change",function(){var i=this.files||[];o(i),t.auto?e.upload():l(i)}),t.bindAction.off("upload.action").on("upload.action",function(){e.upload()}),t.elem.data("haveEvents")||(e.elemFile.on("change",function(){i(this).trigger("upload.change")}),t.elem.on("click",function(){e.isFile()||i(this).trigger("upload.start")}),t.drag&&t.elem.on("dragover",function(e){e.preventDefault(),i(this).trigger("upload.over")}).on("dragleave",function(e){i(this).trigger("upload.leave")}).on("drop",function(e){e.preventDefault(),i(this).trigger("upload.drop",e)}),t.bindAction.on("click",function(){i(this).trigger("upload.action")}),t.elem.data("haveEvents",!0))},o.render=function(e){var i=new p(e);return l.call(i)},e(r,o)});layui.define("layer",function(e){"use strict";var i=layui.$,t=layui.layer,a=layui.hint(),n=layui.device(),l="form",r=".layui-form",s="layui-this",c="layui-hide",o="layui-disabled",u=function(){this.config={verify:{required:[/[\S]+/,"必填项不能为空"],phone:[/^1\d{10}$/,"请输入正确的手机号"],email:[/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,"邮箱格式不正确"],url:[/(^#)|(^http(s*):\/\/[^\s]+\.[^\s]+)/,"链接格式不正确"],number:function(e){if(!e||isNaN(e))return"只能填写数字"},date:[/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/,"日期格式不正确"],identity:[/(^\d{15}$)|(^\d{17}(x|X|\d)$)/,"请输入正确的身份证号"]}}};u.prototype.set=function(e){var t=this;return i.extend(!0,t.config,e),t},u.prototype.verify=function(e){var t=this;return i.extend(!0,t.config.verify,e),t},u.prototype.on=function(e,i){return layui.onevent.call(this,l,e,i)},u.prototype.val=function(e,t){var a=i(r+'[lay-filter="'+e+'"]');a.each(function(e,a){var n=i(this);layui.each(t,function(e,i){var t,a=n.find('[name="'+e+'"]');a[0]&&(t=a[0].type,"checkbox"===t?a[0].checked=i:"radio"===t?a.each(function(){this.value===i&&(this.checked=!0)}):a.val(i))})}),f.render(null,e)},u.prototype.render=function(e,t){var n=this,u=i(r+function(){return t?'[lay-filter="'+t+'"]':""}()),d={select:function(){var e,t="请选择",a="layui-form-select",n="layui-select-title",r="layui-select-none",d="",f=u.find("select"),v=function(t,l){i(t.target).parent().hasClass(n)&&!l||(i("."+a).removeClass(a+"ed "+a+"up"),e&&d&&e.val(d)),e=null},h=function(t,u,f){var h,p=i(this),m=t.find("."+n),k=m.find("input"),g=t.find("dl"),x=g.children("dd"),b=this.selectedIndex;if(!u){var C=function(){var e=t.offset().top+t.outerHeight()+5-y.scrollTop(),i=g.outerHeight();b=p[0].selectedIndex,t.addClass(a+"ed"),x.removeClass(c),x.eq(b).addClass(s).siblings().removeClass(s),e+i>y.height()&&e>=i&&t.addClass(a+"up")},w=function(e){t.removeClass(a+"ed "+a+"up"),k.blur(),h=null,e||$(k.val(),function(e){e&&(d=g.find("."+s).html(),k&&k.val(d))})};m.on("click",function(e){t.hasClass(a+"ed")?w():(v(e,!0),C()),g.find("."+r).remove()}),m.find(".layui-edge").on("click",function(){k.focus()}),k.on("keyup",function(e){var i=e.keyCode;9===i&&C()}).on("keydown",function(e){var i=e.keyCode;9===i&&w();var t=function(i,a){var n,l;if(e.preventDefault(),a=function(){return a&&a[0]?a:h&&h[0]?h:x.eq(b)}(),l=a[i](),n=a[i]("dd"),l[0])return h=a[i](),!n[0]||n.hasClass(o)?t(i,h):void n.addClass(s).siblings().removeClass(s)};38===i&&t("prev"),40===i&&t("next"),13===i&&(e.preventDefault(),g.children("dd."+s).trigger("click"))});var $=function(e,t,a){var n=0;layui.each(x,function(){var t=i(this),l=t.text(),r=l.indexOf(e)===-1;(""===e||"blur"===a?e!==l:r)&&n++,"keyup"===a&&t[r?"addClass":"removeClass"](c)});var l=n===x.length;return t(l),l},T=function(e){var i=this.value,t=e.keyCode;return 9!==t&&13!==t&&37!==t&&38!==t&&39!==t&&40!==t&&($(i,function(e){e?g.find("."+r)[0]||g.append('

          无匹配项

          '):g.find("."+r).remove()},"keyup"),void(""===i&&g.find("."+r).remove()))};f&&k.on("keyup",T).on("blur",function(t){var a=p[0].selectedIndex;e=k,d=i(p[0].options[a]).html(),setTimeout(function(){$(k.val(),function(e){d||k.val("")},"blur")},200)}),x.on("click",function(){var e=i(this),a=e.attr("lay-value"),n=p.attr("lay-filter");return!e.hasClass(o)&&(e.hasClass("layui-select-tips")?k.val(""):(k.val(e.text()),e.addClass(s)),e.siblings().removeClass(s),p.val(a).removeClass("layui-form-danger"),layui.event.call(this,l,"select("+n+")",{elem:p[0],value:a,othis:t}),w(!0),!1)}),t.find("dl>dt").on("click",function(e){return!1}),i(document).off("click",v).on("click",v)}};f.each(function(e,l){var r=i(this),c=r.next("."+a),u=this.disabled,d=l.value,f=i(l.options[l.selectedIndex]),v=l.options[0];if("string"==typeof r.attr("lay-ignore"))return r.show();var y="string"==typeof r.attr("lay-search"),p=v?v.value?t:v.innerHTML||t:t,m=i(['
          ','
          ','','
          ','
          ',function(e){var i=[];return layui.each(e,function(e,a){0!==e||a.value?"optgroup"===a.tagName.toLowerCase()?i.push("
          "+a.label+"
          "):i.push('
          '+a.innerHTML+"
          "):i.push('
          '+(a.innerHTML||t)+"
          ")}),0===i.length&&i.push('
          没有选项
          '),i.join("")}(r.find("*"))+"
          ","
          "].join(""));c[0]&&c.remove(),r.after(m),h.call(this,m,u,y)})},checkbox:function(){var e={checkbox:["layui-form-checkbox","layui-form-checked","checkbox"],_switch:["layui-form-switch","layui-form-onswitch","switch"]},t=u.find("input[type=checkbox]"),a=function(e,t){var a=i(this);e.on("click",function(){var i=a.attr("lay-filter"),n=(a.attr("lay-text")||"").split("|");a[0].disabled||(a[0].checked?(a[0].checked=!1,e.removeClass(t[1]).find("em").text(n[1])):(a[0].checked=!0,e.addClass(t[1]).find("em").text(n[0])),layui.event.call(a[0],l,t[2]+"("+i+")",{elem:a[0],value:a[0].value,othis:e}))})};t.each(function(t,n){var l=i(this),r=l.attr("lay-skin"),s=(l.attr("lay-text")||"").split("|"),c=this.disabled;"switch"===r&&(r="_"+r);var u=e[r]||e.checkbox;if("string"==typeof l.attr("lay-ignore"))return l.show();var d=l.next("."+u[0]),f=i(['
          ",function(){var e=n.title.replace(/\s/g,""),i={checkbox:[e?""+n.title+"":"",''].join(""),_switch:""+((n.checked?s[0]:s[1])||"")+""};return i[r]||i.checkbox}(),"
          "].join(""));d[0]&&d.remove(),l.after(f),a.call(this,f,u)})},radio:function(){var e="layui-form-radio",t=["",""],a=u.find("input[type=radio]"),n=function(a){var n=i(this),s="layui-anim-scaleSpring";a.on("click",function(){var c=n[0].name,o=n.parents(r),u=n.attr("lay-filter"),d=o.find("input[name="+c.replace(/(\.|#|\[|\])/g,"\\$1")+"]");n[0].disabled||(layui.each(d,function(){var a=i(this).next("."+e);this.checked=!1,a.removeClass(e+"ed"),a.find(".layui-icon").removeClass(s).html(t[1])}),n[0].checked=!0,a.addClass(e+"ed"),a.find(".layui-icon").addClass(s).html(t[0]),layui.event.call(n[0],l,"radio("+u+")",{elem:n[0],value:n[0].value,othis:a}))})};a.each(function(a,l){var r=i(this),s=r.next("."+e),c=this.disabled;if("string"==typeof r.attr("lay-ignore"))return r.show();s[0]&&s.remove();var u=i(['
          ',''+t[l.checked?0:1]+"","
          "+function(){var e=l.title||"";return"string"==typeof r.next().attr("lay-radio")&&(e=r.next().html(),r.next().remove()),e}()+"
          ","
          "].join(""));r.after(u),n.call(this,u)})}};return e?d[e]?d[e]():a.error("不支持的"+e+"表单渲染"):layui.each(d,function(e,i){i()}),n};var d=function(){var e=i(this),a=f.config.verify,s=null,c="layui-form-danger",o={},u=e.parents(r),d=u.find("*[lay-verify]"),v=e.parents("form")[0],y=u.find("input,select,textarea"),h=e.attr("lay-filter");if(layui.each(d,function(e,l){var r=i(this),o=r.attr("lay-verify").split("|"),u=r.attr("lay-verType"),d=r.val();if(r.removeClass(c),layui.each(o,function(e,i){var o,f="",v="function"==typeof a[i];if(a[i]){var o=v?f=a[i](d,l):!a[i][0].test(d);if(f=f||a[i][1],o)return"tips"===u?t.tips(f,function(){return"string"==typeof r.attr("lay-ignore")||"select"!==l.tagName.toLowerCase()&&!/^checkbox|radio$/.test(l.type)?r:r.next()}(),{tips:1}):"alert"===u?t.alert(f,{title:"提示",shadeClose:!0}):t.msg(f,{icon:5,shift:6}),n.android||n.ios||l.focus(),r.addClass(c),s=!0}}),s)return s}),s)return!1;var p={};return layui.each(y,function(e,i){if(i.name=(i.name||"").replace(/^\s*|\s*&/,""),i.name){if(/^.*\[\]$/.test(i.name)){var t=i.name.match(/^(.*)\[\]$/g)[0];p[t]=0|p[t],i.name=i.name.replace(/^(.*)\[\]$/,"$1["+p[t]++ +"]")}/^checkbox|radio$/.test(i.type)&&!i.checked||(o[i.name]=i.value)}}),layui.event.call(this,l,"submit("+h+")",{elem:this,form:v,field:o})},f=new u,v=i(document),y=i(window);f.render(),v.on("reset",r,function(){var e=i(this).attr("lay-filter");setTimeout(function(){f.render(null,e)},50)}),v.on("submit",r,d).on("click","*[lay-submit]",d),e(l,f)});layui.define("jquery",function(e){"use strict";var o=layui.$,a=layui.hint(),i="layui-tree-enter",r=function(e){this.options=e},t={arrow:["",""],checkbox:["",""],radio:["",""],branch:["",""],leaf:""};r.prototype.init=function(e){var o=this;e.addClass("layui-box layui-tree"),o.options.skin&&e.addClass("layui-tree-skin-"+o.options.skin),o.tree(e),o.on(e)},r.prototype.tree=function(e,a){var i=this,r=i.options,n=a||r.nodes;layui.each(n,function(a,n){var l=n.children&&n.children.length>0,c=o('
            '),s=o(["
          • ",function(){return l?''+(n.spread?t.arrow[1]:t.arrow[0])+"":""}(),function(){return r.check?''+("checkbox"===r.check?t.checkbox[0]:"radio"===r.check?t.radio[0]:"")+"":""}(),function(){return'"+(''+(l?n.spread?t.branch[1]:t.branch[0]:t.leaf)+"")+(""+(n.name||"未命名")+"")}(),"
          • "].join(""));l&&(s.append(c),i.tree(c,n.children)),e.append(s),"function"==typeof r.click&&i.click(s,n),i.spread(s,n),r.drag&&i.drag(s,n)})},r.prototype.click=function(e,o){var a=this,i=a.options;e.children("a").on("click",function(e){layui.stope(e),i.click(o)})},r.prototype.spread=function(e,o){var a=this,i=(a.options,e.children(".layui-tree-spread")),r=e.children("ul"),n=e.children("a"),l=function(){e.data("spread")?(e.data("spread",null),r.removeClass("layui-show"),i.html(t.arrow[0]),n.find(".layui-icon").html(t.branch[0])):(e.data("spread",!0),r.addClass("layui-show"),i.html(t.arrow[1]),n.find(".layui-icon").html(t.branch[1]))};r[0]&&(i.on("click",l),n.on("dblclick",l))},r.prototype.on=function(e){var a=this,r=a.options,t="layui-tree-drag";e.find("i").on("selectstart",function(e){return!1}),r.drag&&o(document).on("mousemove",function(e){var i=a.move;if(i.from){var r=(i.to,o('
            '));e.preventDefault(),o("."+t)[0]||o("body").append(r);var n=o("."+t)[0]?o("."+t):r;n.addClass("layui-show").html(i.from.elem.children("a").html()),n.css({left:e.pageX+10,top:e.pageY+10})}}).on("mouseup",function(){var e=a.move;e.from&&(e.from.elem.children("a").removeClass(i),e.to&&e.to.elem.children("a").removeClass(i),a.move={},o("."+t).remove())})},r.prototype.move={},r.prototype.drag=function(e,a){var r=this,t=(r.options,e.children("a")),n=function(){var t=o(this),n=r.move;n.from&&(n.to={item:a,elem:e},t.addClass(i))};t.on("mousedown",function(){var o=r.move;o.from={item:a,elem:e}}),t.on("mouseenter",n).on("mousemove",n).on("mouseleave",function(){var e=o(this),a=r.move;a.from&&(delete a.to,e.removeClass(i))})},e("tree",function(e){var i=new r(e=e||{}),t=o(e.elem);return t[0]?void i.init(t):a.error("layui.tree 没有找到"+e.elem+"元素")})});layui.define(["laytpl","laypage","layer","form"],function(e){"use strict";var t=layui.$,i=layui.laytpl,a=layui.laypage,l=layui.layer,n=layui.form,o=layui.hint(),r=layui.device(),d={config:{checkName:"LAY_CHECKED",indexName:"LAY_TABLE_INDEX"},cache:{},index:layui.table?layui.table.index+1e4:0,set:function(e){var i=this;return i.config=t.extend({},i.config,e),i},on:function(e,t){return layui.onevent.call(this,s,e,t)}},c=function(){var e=this,t=e.config,i=t.id;return i&&(c.config[i]=t),{reload:function(t){e.reload.call(e,t)},config:t}},s="table",u=".layui-table",h="layui-hide",f="layui-none",y="layui-table-view",p=".layui-table-header",m=".layui-table-body",v=".layui-table-main",g=".layui-table-fixed",x=".layui-table-fixed-l",b=".layui-table-fixed-r",k=".layui-table-tool",C=".layui-table-page",w=".layui-table-sort",N="layui-table-edit",T="layui-table-hover",F=function(e){var t='{{#if(item2.colspan){}} colspan="{{item2.colspan}}"{{#} if(item2.rowspan){}} rowspan="{{item2.rowspan}}"{{#}}}';return e=e||{},['',"","{{# layui.each(d.data.cols, function(i1, item1){ }}","","{{# layui.each(item1, function(i2, item2){ }}",'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}','{{# if(item2.fixed === "right"){ right = true; } }}',function(){return e.fixed&&"right"!==e.fixed?'{{# if(item2.fixed && item2.fixed !== "right"){ }}':"right"===e.fixed?'{{# if(item2.fixed === "right"){ }}':""}(),'",e.fixed?"{{# }; }}":"","{{# }); }}","","{{# }); }}","","
            ','
            1){ }}","group","{{# } else { }}","{{d.index}}-{{item2.field || i2}}",'{{# if(item2.type !== "normal"){ }}'," laytable-cell-{{ item2.type }}","{{# } }}","{{# } }}",'" {{#if(item2.align){}}align="{{item2.align}}"{{#}}}>','{{# if(item2.type === "checkbox"){ }}','',"{{# } else { }}",'{{item2.title||""}}',"{{# if(!(item2.colspan > 1) && item2.sort){ }}",'',"{{# } }}","{{# } }}","
            ","
            "].join("")},W=['',"","
            "].join(""),z=['
            ',"{{# if(d.data.toolbar){ }}",'
            ',"{{# } }}",'
            ',"{{# var left, right; }}",'
            ',F(),"
            ",'
            ',W,"
            ","{{# if(left){ }}",'
            ','
            ',F({fixed:!0}),"
            ",'
            ',W,"
            ","
            ","{{# }; }}","{{# if(right){ }}",'
            ','
            ',F({fixed:"right"}),'
            ',"
            ",'
            ',W,"
            ","
            ","{{# }; }}","
            ","{{# if(d.data.page){ }}",'
            ','
            ',"
            ","{{# } }}","","
            "].join(""),A=t(window),S=t(document),M=function(e){var i=this;i.index=++d.index,i.config=t.extend({},i.config,d.config,e),i.render()};M.prototype.config={limit:10,loading:!0,cellMinWidth:60,text:{none:"无数据"}},M.prototype.render=function(){var e=this,a=e.config;if(a.elem=t(a.elem),a.where=a.where||{},a.id=a.id||a.elem.attr("id"),a.request=t.extend({pageName:"page",limitName:"limit"},a.request),a.response=t.extend({statusName:"code",statusCode:0,msgName:"msg",dataName:"data",countName:"count"},a.response),"object"==typeof a.page&&(a.limit=a.page.limit||a.limit,a.limits=a.page.limits||a.limits,e.page=a.page.curr=a.page.curr||1,delete a.page.elem,delete a.page.jump),!a.elem[0])return e;e.setArea();var l=a.elem,n=l.next("."+y),o=e.elem=t(i(z).render({VIEW_CLASS:y,data:a,index:e.index}));if(a.index=e.index,n[0]&&n.remove(),l.after(o),e.layHeader=o.find(p),e.layMain=o.find(v),e.layBody=o.find(m),e.layFixed=o.find(g),e.layFixLeft=o.find(x),e.layFixRight=o.find(b),e.layTool=o.find(k),e.layPage=o.find(C),e.layTool.html(i(t(a.toolbar).html()||"").render(a)),a.height&&e.fullSize(),a.cols.length>1){var r=e.layFixed.find(p).find("th");r.height(e.layHeader.height()-1-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom")))}e.pullData(e.page),e.events()},M.prototype.initOpts=function(e){var t=this,i=(t.config,{checkbox:48,space:15,numbers:40});e.checkbox&&(e.type="checkbox"),e.space&&(e.type="space"),e.type||(e.type="normal"),"normal"!==e.type&&(e.unresize=!0,e.width=e.width||i[e.type])},M.prototype.setArea=function(){var e=this,t=e.config,i=0,a=0,l=0,n=0,o=t.width||function(){var e=function(i){var a,l;i=i||t.elem.parent(),a=i.width();try{l="none"===i.css("display")}catch(n){}return!i[0]||a&&!l?a:e(i.parent())};return e()}();e.eachCols(function(){i++}),o-=function(){return"line"===t.skin||"nob"===t.skin?2:i+1}(),layui.each(t.cols,function(t,i){layui.each(i,function(t,l){var r;return l?(e.initOpts(l),r=l.width||0,void(l.colspan>1||(/\d+%$/.test(r)?l.width=r=Math.floor(parseFloat(r)/100*o):r||(l.width=r=0,a++),n+=r))):void i.splice(t,1)})}),e.autoColNums=a,o>n&&a&&(l=(o-n)/a),layui.each(t.cols,function(e,i){layui.each(i,function(e,i){var a=i.minWidth||t.cellMinWidth;i.colspan>1||0===i.width&&(i.width=Math.floor(l>=a?l:a))})}),t.height&&/^full-\d+$/.test(t.height)&&(e.fullHeightGap=t.height.split("-")[1],t.height=A.height()-e.fullHeightGap)},M.prototype.reload=function(e){var i=this;i.config.data&&i.config.data.constructor===Array&&delete i.config.data,i.config=t.extend({},i.config,e),i.render()},M.prototype.page=1,M.prototype.pullData=function(e,i){var a=this,n=a.config,o=n.request,r=n.response,d=function(){"object"==typeof n.initSort&&a.sort(n.initSort.field,n.initSort.type)};if(a.startTime=(new Date).getTime(),n.url){var c={};c[o.pageName]=e,c[o.limitName]=n.limit;var s=t.extend(c,n.where);n.contentType&&0==n.contentType.indexOf("application/json")&&(s=JSON.stringify(s)),t.ajax({type:n.method||"get",url:n.url,contentType:n.contentType,data:s,dataType:"json",headers:n.headers||{},success:function(t){t[r.statusName]!=r.statusCode?(a.renderForm(),a.layMain.html('
            '+(t[r.msgName]||"返回的数据状态异常")+"
            ")):(a.renderData(t,e,t[r.countName]),d(),n.time=(new Date).getTime()-a.startTime+" ms"),i&&l.close(i),"function"==typeof n.done&&n.done(t,e,t[r.countName])},error:function(e,t){a.layMain.html('
            数据接口请求异常
            '),a.renderForm(),i&&l.close(i)}})}else if(n.data&&n.data.constructor===Array){var u={},h=e*n.limit-n.limit;u[r.dataName]=n.data.concat().splice(h,n.limit),u[r.countName]=n.data.length,a.renderData(u,e,n.data.length),d(),"function"==typeof n.done&&n.done(u,e,u[r.countName])}},M.prototype.eachCols=function(e){var i=t.extend(!0,[],this.config.cols),a=[],l=0;layui.each(i,function(e,t){layui.each(t,function(t,n){if(n.colspan>1){var o=0;l++,n.CHILD_COLS=[],layui.each(i[e+1],function(e,t){t.PARENT_COL||o==n.colspan||(t.PARENT_COL=l,n.CHILD_COLS.push(t),o+=t.colspan>1?t.colspan:1)})}n.PARENT_COL||a.push(n)})});var n=function(t){layui.each(t||a,function(t,i){return i.CHILD_COLS?n(i.CHILD_COLS):void e(t,i)})};n()},M.prototype.renderData=function(e,n,o,r){var c=this,s=c.config,u=e[s.response.dataName]||[],y=[],p=[],m=[],v=function(){return!r&&c.sortKey?c.sort(c.sortKey.field,c.sortKey.sort,!0):(layui.each(u,function(e,a){var l=[],o=[],u=[],h=e+s.limit*(n-1)+1;0!==a.length&&(r||(a[d.config.indexName]=e),c.eachCols(function(e,n){var r=n.field||e,f=a[r];c.getColElem(c.layHeader,r);if(void 0!==f&&null!==f||(f=""),!(n.colspan>1)){var y=['",'
            '+function(){var e=t.extend(!0,{LAY_INDEX:h},a);return"checkbox"===n.type?'":"numbers"===n.type?h:n.toolbar?i(t(n.toolbar).html()||"").render(e):n.templet?function(){return"function"==typeof n.templet?n.templet(e):i(t(n.templet).html()||String(f)).render(e)}():f}(),"
            "].join("");l.push(y),n.fixed&&"right"!==n.fixed&&o.push(y),"right"===n.fixed&&u.push(y)}}),y.push(''+l.join("")+""),p.push(''+o.join("")+""),m.push(''+u.join("")+""))}),c.layBody.scrollTop(0),c.layMain.find("."+f).remove(),c.layMain.find("tbody").html(y.join("")),c.layFixLeft.find("tbody").html(p.join("")),c.layFixRight.find("tbody").html(m.join("")),c.renderForm(),c.syncCheckAll(),c.haveInit?c.scrollPatch():setTimeout(function(){c.scrollPatch()},50),c.haveInit=!0,void l.close(c.tipsIndex))};return c.key=s.id||s.index,d.cache[c.key]=u,c.layPage[0===u.length&&1==n?"addClass":"removeClass"](h),r?v():0===u.length?(c.renderForm(),c.layFixed.remove(),c.layMain.find("tbody").html(""),c.layMain.find("."+f).remove(),c.layMain.append('
            '+s.text.none+"
            ")):(v(),void(s.page&&(s.page=t.extend({elem:"layui-table-page"+s.index,count:o,limit:s.limit,limits:s.limits||[10,20,30,40,50,60,70,80,90],groups:3,layout:["prev","page","next","skip","count","limit"],prev:'',next:'',jump:function(e,t){t||(c.page=e.curr,s.limit=e.limit,c.pullData(e.curr,c.loading()))}},s.page),s.page.count=o,a.render(s.page))))},M.prototype.getColElem=function(e,t){var i=this,a=i.config;return e.eq(0).find(".laytable-cell-"+(a.index+"-"+t)+":eq(0)")},M.prototype.renderForm=function(e){n.render(e,"LAY-table-"+this.index)},M.prototype.sort=function(e,i,a,l){var n,r,c=this,u={},h=c.config,f=h.elem.attr("lay-filter"),y=d.cache[c.key];"string"==typeof e&&c.layHeader.find("th").each(function(i,a){var l=t(this),o=l.data("field");if(o===e)return e=l,n=o,!1});try{var n=n||e.data("field");if(c.sortKey&&!a&&n===c.sortKey.field&&i===c.sortKey.sort)return;var p=c.layHeader.find("th .laytable-cell-"+h.index+"-"+n).find(w);c.layHeader.find("th").find(w).removeAttr("lay-sort"),p.attr("lay-sort",i||null),c.layFixed.find("th")}catch(m){return o.error("Table modules: Did not match to field")}c.sortKey={field:n,sort:i},"asc"===i?r=layui.sort(y,n):"desc"===i?r=layui.sort(y,n,!0):(r=layui.sort(y,d.config.indexName),delete c.sortKey),u[h.response.dataName]=r,c.renderData(u,c.page,c.count,!0),l&&layui.event.call(e,s,"sort("+f+")",{field:n,type:i})},M.prototype.loading=function(){var e=this,t=e.config;if(t.loading&&t.url)return l.msg("数据请求中",{icon:16,offset:[e.elem.offset().top+e.elem.height()/2-35-A.scrollTop()+"px",e.elem.offset().left+e.elem.width()/2-90-A.scrollLeft()+"px"],time:-1,anim:-1,fixed:!1})},M.prototype.setCheckData=function(e,t){var i=this,a=i.config,l=d.cache[i.key];l[e]&&l[e].constructor!==Array&&(l[e][a.checkName]=t)},M.prototype.syncCheckAll=function(){var e=this,t=e.config,i=e.layHeader.find('input[name="layTableCheckbox"]'),a=function(i){return e.eachCols(function(e,a){"checkbox"===a.type&&(a[t.checkName]=i)}),i};i[0]&&(d.checkStatus(e.key).isAll?(i[0].checked||(i.prop("checked",!0),e.renderForm("checkbox")),a(!0)):(i[0].checked&&(i.prop("checked",!1),e.renderForm("checkbox")),a(!1)))},M.prototype.getCssRule=function(e,t){var i=this,a=i.elem.find("style")[0],l=a.sheet||a.styleSheet||{},n=l.cssRules||l.rules;layui.each(n,function(a,l){if(l.selectorText===".laytable-cell-"+i.index+"-"+e)return t(l),!0})},M.prototype.fullSize=function(){var e,t=this,i=t.config,a=i.height;t.fullHeightGap&&(a=A.height()-t.fullHeightGap,a<135&&(a=135),t.elem.css("height",a)),e=parseFloat(a)-parseFloat(t.layHeader.height())-1,i.toolbar&&(e-=t.layTool.outerHeight()),i.page&&(e=e-t.layPage.outerHeight()-1),t.layMain.css("height",e)},M.prototype.getScrollWidth=function(e){var t=0;return e?t=e.offsetWidth-e.clientWidth:(e=document.createElement("div"),e.style.width="100px",e.style.height="100px",e.style.overflowY="scroll",document.body.appendChild(e),t=e.offsetWidth-e.clientWidth,document.body.removeChild(e)),t},M.prototype.scrollPatch=function(){var e=this,i=e.layMain.children("table"),a=e.layMain.width()-e.layMain.prop("clientWidth"),l=e.layMain.height()-e.layMain.prop("clientHeight"),n=e.getScrollWidth(e.layMain[0]),o=i.outerWidth()-e.layMain.width();if(e.autoColNums&&o<5&&!e.scrollPatchWStatus){var r=e.layHeader.eq(0).find("thead th:last-child"),d=r.data("field");e.getCssRule(d,function(t){var i=t.style.width||r.outerWidth();t.style.width=parseFloat(i)-n-o+"px",e.layMain.height()-e.layMain.prop("clientHeight")>0&&(t.style.width=parseFloat(t.style.width)-1+"px"),e.scrollPatchWStatus=!0})}if(a&&l){if(!e.elem.find(".layui-table-patch")[0]){var c=t('
            ');c.find("div").css({width:a}),e.layHeader.eq(0).find("thead tr").append(c)}}else e.layHeader.eq(0).find(".layui-table-patch").remove();var s=e.layMain.height(),u=s-l;e.layFixed.find(m).css("height",i.height()>u?u:"auto"),e.layFixRight[o>0?"removeClass":"addClass"](h),e.layFixRight.css("right",a-1)},M.prototype.events=function(){var e,a=this,n=a.config,o=t("body"),c={},u=a.layHeader.find("th"),h=".layui-table-cell",f=n.elem.attr("lay-filter");u.on("mousemove",function(e){var i=t(this),a=i.offset().left,l=e.clientX-a;i.attr("colspan")>1||i.data("unresize")||c.resizeStart||(c.allowResize=i.width()-l<=10,o.css("cursor",c.allowResize?"col-resize":""))}).on("mouseleave",function(){t(this);c.resizeStart||o.css("cursor","")}).on("mousedown",function(e){var i=t(this);if(c.allowResize){var l=i.data("field");e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],a.getCssRule(l,function(e){var t=e.style.width||i.outerWidth();c.rule=e,c.ruleWidth=parseFloat(t),c.minWidth=i.data("minwidth")||n.cellMinWidth})}}),S.on("mousemove",function(t){if(c.resizeStart){if(t.preventDefault(),c.rule){var i=c.ruleWidth+t.clientX-c.offset[0];i');d[0].value=e.data("content")||o.text(),e.find("."+N)[0]||e.append(d),d.focus()}else o.find(".layui-form-switch,.layui-form-checkbox")[0]||Math.round(o.prop("scrollWidth"))>Math.round(o.outerWidth())&&(a.tipsIndex=l.tips(['
            ',o.html(),"
            ",''].join(""),o[0],{tips:[3,""],time:-1,anim:-1,maxWidth:r.ios||r.android?300:600,isOutAnim:!1,skin:"layui-table-tips",success:function(e,t){e.find(".layui-table-tips-c").on("click",function(){l.close(t)})}}))}),a.layBody.on("click","*[lay-event]",function(){var e=t(this),l=e.parents("tr").eq(0).data("index"),n=a.layBody.find('tr[data-index="'+l+'"]'),o="layui-table-click",r=d.cache[a.key][l];layui.event.call(this,s,"tool("+f+")",{data:d.clearCacheKey(r),event:e.attr("lay-event"),tr:n,del:function(){d.cache[a.key][l]=[],n.remove(),a.scrollPatch()},update:function(e){e=e||{},layui.each(e,function(e,l){if(e in r){var o,d=n.children('td[data-field="'+e+'"]');r[e]=l,a.eachCols(function(t,i){i.field==e&&i.templet&&(o=i.templet)}),d.children(h).html(o?i(t(o).html()||l).render(r):l),d.data("content",l)}})}}),n.addClass(o).siblings("tr").removeClass(o)}),a.layMain.on("scroll",function(){var e=t(this),i=e.scrollLeft(),n=e.scrollTop();a.layHeader.scrollLeft(i),a.layFixed.find(m).scrollTop(n),l.close(a.tipsIndex)}),A.on("resize",function(){a.fullSize(),a.scrollPatch()})},d.init=function(e,i){i=i||{};var a=this,l=t(e?'table[lay-filter="'+e+'"]':u+"[lay-data]"),n="Table element property lay-data configuration item has a syntax error: ";return l.each(function(){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(r){o.error(n+l)}var c=[],s=t.extend({elem:this,cols:[],data:[],skin:a.attr("lay-skin"),size:a.attr("lay-size"),even:"string"==typeof a.attr("lay-even")},d.config,i,l);e&&a.hide(),a.find("thead>tr").each(function(e){s.cols[e]=[],t(this).children().each(function(i){var a=t(this),l=a.attr("lay-data");try{l=new Function("return "+l)()}catch(r){return o.error(n+l)}var d=t.extend({title:a.text(),colspan:a.attr("colspan")||0,rowspan:a.attr("rowspan")||0},l);d.colspan<2&&c.push(d),s.cols[e].push(d)})}),a.find("tbody>tr").each(function(e){var i=t(this),a={};i.children("td").each(function(e,i){var l=t(this),n=l.data("field");if(n)return a[n]=l.html()}),layui.each(c,function(e,t){var l=i.children("td").eq(e);a[t.field]=l.html()}),s.data[e]=a}),d.render(s)}),a},d.checkStatus=function(e){var t=0,i=0,a=[],l=d.cache[e]||[];return layui.each(l,function(e,l){return l.constructor===Array?void i++:void(l[d.config.checkName]&&(t++,a.push(d.clearCacheKey(l))))}),{data:a,isAll:!!l.length&&t===l.length-i}},c.config={},d.reload=function(e,i){var a=c.config[e];return i=i||{},a?(i.data&&i.data.constructor===Array&&delete a.data,d.render(t.extend(!0,{},a,i))):o.error("The ID option was not found in the table instance")},d.render=function(e){var t=new M(e);return c.call(t)},d.clearCacheKey=function(e){return e=t.extend({},e),delete e[d.config.checkName],delete e[d.config.indexName],e},d.init(),e(s,d)});layui.define("jquery",function(e){"use strict";var i=layui.$,n=(layui.hint(),layui.device(),{config:{},set:function(e){var n=this;return n.config=i.extend({},n.config,e),n},on:function(e,i){return layui.onevent.call(this,t,e,i)}}),t="carousel",a="layui-this",l=">*[carousel-item]>*",o="layui-carousel-left",r="layui-carousel-right",d="layui-carousel-prev",s="layui-carousel-next",u="layui-carousel-arrow",c="layui-carousel-ind",m=function(e){var t=this;t.config=i.extend({},t.config,n.config,e),t.render()};m.prototype.config={width:"600px",height:"280px",full:!1,arrow:"hover",indicator:"inside",autoplay:!0,interval:3e3,anim:"",trigger:"click",index:0},m.prototype.render=function(){var e=this,n=e.config;n.elem=i(n.elem),n.elem[0]&&(e.elemItem=n.elem.find(l),n.index<0&&(n.index=0),n.index>=e.elemItem.length&&(n.index=e.elemItem.length-1),n.interval<800&&(n.interval=800),n.full?n.elem.css({position:"fixed",width:"100%",height:"100%",zIndex:9999}):n.elem.css({width:n.width,height:n.height}),n.elem.attr("lay-anim",n.anim),e.elemItem.eq(n.index).addClass(a),e.elemItem.length<=1||(e.indicator(),e.arrow(),e.autoplay(),e.events()))},m.prototype.reload=function(e){var n=this;clearInterval(n.timer),n.config=i.extend({},n.config,e),n.render()},m.prototype.prevIndex=function(){var e=this,i=e.config,n=i.index-1;return n<0&&(n=e.elemItem.length-1),n},m.prototype.nextIndex=function(){var e=this,i=e.config,n=i.index+1;return n>=e.elemItem.length&&(n=0),n},m.prototype.addIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index+e,n.index>=i.elemItem.length&&(n.index=0)},m.prototype.subIndex=function(e){var i=this,n=i.config;e=e||1,n.index=n.index-e,n.index<0&&(n.index=i.elemItem.length-1)},m.prototype.autoplay=function(){var e=this,i=e.config;i.autoplay&&(e.timer=setInterval(function(){e.slide()},i.interval))},m.prototype.arrow=function(){var e=this,n=e.config,t=i(['",'"].join(""));n.elem.attr("lay-arrow",n.arrow),n.elem.find("."+u)[0]&&n.elem.find("."+u).remove(),n.elem.append(t),t.on("click",function(){var n=i(this),t=n.attr("lay-type");e.slide(t)})},m.prototype.indicator=function(){var e=this,n=e.config,t=e.elemInd=i(['
              ',function(){var i=[];return layui.each(e.elemItem,function(e){i.push("")}),i.join("")}(),"
            "].join(""));n.elem.attr("lay-indicator",n.indicator),n.elem.find("."+c)[0]&&n.elem.find("."+c).remove(),n.elem.append(t),"updown"===n.anim&&t.css("margin-top",-(t.height()/2)),t.find("li").on("hover"===n.trigger?"mouseover":n.trigger,function(){var t=i(this),a=t.index();a>n.index?e.slide("add",a-n.index):a',e.bar1?'
          • '+c[0]+"
          • ":"",e.bar2?'
          • '+c[1]+"
          • ":"",'
          • '+c[2]+"
          • ",""].join("")),s=g.find("."+r),u=function(){var t=n.scrollTop();t>=e.showHeight?i||(s.show(),i=1):i&&(s.hide(),i=0)};t("."+a)[0]||("object"==typeof e.css&&g.css(e.css),l.append(g),u(),g.find("li").on("click",function(){var i=t(this),o=i.attr("lay-type");"top"===o&&t("html,body").animate({scrollTop:0},200),e.click&&e.click.call(this,o)}),n.on("scroll",function(){clearTimeout(o),o=setTimeout(function(){u()},100)}))},countdown:function(e,t,i){var o=this,a="function"==typeof t,r=new Date(e).getTime(),n=new Date(!t||a?(new Date).getTime():t).getTime(),l=r-n,c=[Math.floor(l/864e5),Math.floor(l/36e5)%24,Math.floor(l/6e4)%60,Math.floor(l/1e3)%60];a&&(i=t);var g=setTimeout(function(){o.countdown(e,n+1e3,i)},1e3);return i&&i(l>0?c:[0,0,0,0],t,g),l<=0&&clearTimeout(g),g},timeAgo:function(e,t){var i=this,o=[[],[]],a=(new Date).getTime()-new Date(e).getTime();return a>6912e5?(a=new Date(e),o[0][0]=i.digit(a.getFullYear(),4),o[0][1]=i.digit(a.getMonth()+1),o[0][2]=i.digit(a.getDate()),t||(o[1][0]=i.digit(a.getHours()),o[1][1]=i.digit(a.getMinutes()),o[1][2]=i.digit(a.getSeconds())),o[0].join("-")+" "+o[1].join(":")):a>=864e5?(a/1e3/60/60/24|0)+"天前":a>=36e5?(a/1e3/60/60|0)+"小时前":a>=12e4?(a/1e3/60|0)+"分钟前":a<0?"未来":"刚刚"},digit:function(e,t){var i="";e=String(e),t=t||2;for(var o=e.length;o';o.prototype.load=function(e){var o,i,n,r,a=this,c=0;e=e||{};var f=l(e.elem);if(f[0]){var m=l(e.scrollElem||document),u=e.mb||50,s=!("isAuto"in e)||e.isAuto,v=e.end||"没有更多了",y=e.scrollElem&&e.scrollElem!==document,d="加载更多",h=l('");f.find(".layui-flow-more")[0]||f.append(h);var p=function(e,t){e=l(e),h.before(e),t=0==t||null,t?h.html(v):h.find("a").html(d),i=t,o=null,n&&n()},g=function(){o=!0,h.find("a").html(t),"function"==typeof e.done&&e.done(++c,p)};if(g(),h.find("a").on("click",function(){l(this);i||o||g()}),e.isLazyimg)var n=a.lazyimg({elem:e.elem+" img",scrollElem:e.scrollElem});return s?(m.on("scroll",function(){var e=l(this),t=e.scrollTop();r&&clearTimeout(r),i||(r=setTimeout(function(){var i=y?e.height():l(window).height(),n=y?e.prop("scrollHeight"):document.documentElement.scrollHeight;n-t-i<=u&&(o||g())},100))}),a):a}},o.prototype.lazyimg=function(e){var o,t=this,i=0;e=e||{};var n=l(e.scrollElem||document),r=e.elem||"img",a=e.scrollElem&&e.scrollElem!==document,c=function(e,l){var o=n.scrollTop(),r=o+l,c=a?function(){return e.offset().top-n.offset().top+o}():e.offset().top;if(c>=o&&c<=r&&!e.attr("src")){var m=e.attr("lay-src");layui.img(m,function(){var l=t.lazyimg.elem.eq(i);e.attr("src",m).removeAttr("lay-src"),l[0]&&f(l),i++})}},f=function(e,o){var f=a?(o||n).height():l(window).height(),m=n.scrollTop(),u=m+f;if(t.lazyimg.elem=l(r),e)c(e,f);else for(var s=0;su)break}};if(f(),!o){var m;n.on("scroll",function(){var e=l(this);m&&clearTimeout(m),m=setTimeout(function(){f(null,e)},50)}),o=!0}return f},e("flow",new o)});layui.define(["layer","form"],function(t){"use strict";var e=layui.$,i=layui.layer,a=layui.form,l=(layui.hint(),layui.device()),n="layedit",o="layui-show",r="layui-disabled",c=function(){var t=this;t.index=0,t.config={tool:["strong","italic","underline","del","|","left","center","right","|","link","unlink","face","image"],hideTool:[],height:280}};c.prototype.set=function(t){var i=this;return e.extend(!0,i.config,t),i},c.prototype.on=function(t,e){return layui.onevent(n,t,e)},c.prototype.build=function(t,i){i=i||{};var a=this,n=a.config,r="layui-layedit",c=e("string"==typeof t?"#"+t:t),u="LAY_layedit_"+ ++a.index,d=c.next("."+r),y=e.extend({},n,i),f=function(){var t=[],e={};return layui.each(y.hideTool,function(t,i){e[i]=!0}),layui.each(y.tool,function(i,a){C[a]&&!e[a]&&t.push(C[a])}),t.join("")}(),m=e(['
            ','
            '+f+"
            ",'
            ','',"
            ","
            "].join(""));return l.ie&&l.ie<8?c.removeClass("layui-hide").addClass(o):(d[0]&&d.remove(),s.call(a,m,c[0],y),c.addClass("layui-hide").after(m),a.index)},c.prototype.getContent=function(t){var e=u(t);if(e[0])return d(e[0].document.body.innerHTML)},c.prototype.getText=function(t){var i=u(t);if(i[0])return e(i[0].document.body).text()},c.prototype.setContent=function(t,i,a){var l=u(t);l[0]&&(a?e(l[0].document.body).append(i):e(l[0].document.body).html(i),layedit.sync(t))},c.prototype.sync=function(t){var i=u(t);if(i[0]){var a=e("#"+i[1].attr("textarea"));a.val(d(i[0].document.body.innerHTML))}},c.prototype.getSelection=function(t){var e=u(t);if(e[0]){var i=m(e[0].document);return document.selection?i.text:i.toString()}};var s=function(t,i,a){var l=this,n=t.find("iframe");n.css({height:a.height}).on("load",function(){var o=n.contents(),r=n.prop("contentWindow"),c=o.find("head"),s=e([""].join("")),u=o.find("body");c.append(s),u.attr("contenteditable","true").css({"min-height":a.height}).html(i.value||""),y.apply(l,[r,n,i,a]),g.call(l,r,t,a)})},u=function(t){var i=e("#LAY_layedit_"+t),a=i.prop("contentWindow");return[a,i]},d=function(t){return 8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),t},y=function(t,a,n,o){var r=t.document,c=e(r.body);c.on("keydown",function(t){var e=t.keyCode;if(13===e){var a=m(r),l=p(a),n=l.parentNode;if("pre"===n.tagName.toLowerCase()){if(t.shiftKey)return;return i.msg("请暂时用shift+enter"),!1}r.execCommand("formatBlock",!1,"

            ")}}),e(n).parents("form").on("submit",function(){var t=c.html();8==l.ie&&(t=t.replace(/<.+>/g,function(t){return t.toLowerCase()})),n.value=t}),c.on("paste",function(e){r.execCommand("formatBlock",!1,"

            "),setTimeout(function(){f.call(t,c),n.value=c.html()},100)})},f=function(t){var i=this;i.document;t.find("*[style]").each(function(){var t=this.style.textAlign;this.removeAttribute("style"),e(this).css({"text-align":t||""})}),t.find("table").addClass("layui-table"),t.find("script,link").remove()},m=function(t){return t.selection?t.selection.createRange():t.getSelection().getRangeAt(0)},p=function(t){return t.endContainer||t.parentElement().childNodes[0]},v=function(t,i,a){var l=this.document,n=document.createElement(t);for(var o in i)n.setAttribute(o,i[o]);if(n.removeAttribute("text"),l.selection){var r=a.text||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.pasteHTML(e(n).prop("outerHTML")),a.select()}else{var r=a.toString()||i.text;if("a"===t&&!r)return;r&&(n.innerHTML=r),a.deleteContents(),a.insertNode(n)}},h=function(t,i){var a=this.document,l="layedit-tool-active",n=p(m(a)),o=function(e){return t.find(".layedit-tool-"+e)};i&&i[i.hasClass(l)?"removeClass":"addClass"](l),t.find(">i").removeClass(l),o("unlink").addClass(r),e(n).parents().each(function(){var t=this.tagName.toLowerCase(),e=this.style.textAlign;"b"!==t&&"strong"!==t||o("b").addClass(l),"i"!==t&&"em"!==t||o("i").addClass(l),"u"===t&&o("u").addClass(l),"strike"===t&&o("d").addClass(l),"p"===t&&("center"===e?o("center").addClass(l):"right"===e?o("right").addClass(l):o("left").addClass(l)),"a"===t&&(o("link").addClass(l),o("unlink").removeClass(r))})},g=function(t,a,l){var n=t.document,o=e(n.body),c={link:function(i){var a=p(i),l=e(a).parent();b.call(o,{href:l.attr("href"),target:l.attr("target")},function(e){var a=l[0];"A"===a.tagName?a.href=e.url:v.call(t,"a",{target:e.target,href:e.url,text:e.url},i)})},unlink:function(t){n.execCommand("unlink")},face:function(e){x.call(this,function(i){v.call(t,"img",{src:i.src,alt:i.alt},e)})},image:function(a){var n=this;layui.use("upload",function(o){var r=l.uploadImage||{};o.render({url:r.url,method:r.type,elem:e(n).find("input")[0],done:function(e){0==e.code?(e.data=e.data||{},v.call(t,"img",{src:e.data.src,alt:e.data.title},a)):i.msg(e.msg||"上传失败")}})})},code:function(e){k.call(o,function(i){v.call(t,"pre",{text:i.code,"lay-lang":i.lang},e)})},help:function(){i.open({type:2,title:"帮助",area:["600px","380px"],shadeClose:!0,shade:.1,skin:"layui-layer-msg",content:["http://www.layui.com/about/layedit/help.html","no"]})}},s=a.find(".layui-layedit-tool"),u=function(){var i=e(this),a=i.attr("layedit-event"),l=i.attr("lay-command");if(!i.hasClass(r)){o.focus();var u=m(n);u.commonAncestorContainer;l?(n.execCommand(l),/justifyLeft|justifyCenter|justifyRight/.test(l)&&n.execCommand("formatBlock",!1,"

            "),setTimeout(function(){o.focus()},10)):c[a]&&c[a].call(this,u),h.call(t,s,i)}},d=/image/;s.find(">i").on("mousedown",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)||u.call(this)}).on("click",function(){var t=e(this),i=t.attr("layedit-event");d.test(i)&&u.call(this)}),o.on("click",function(){h.call(t,s),i.close(x.index)})},b=function(t,e){var l=this,n=i.open({type:1,id:"LAY_layedit_link",area:"350px",shade:.05,shadeClose:!0,moveType:1,title:"超链接",skin:"layui-layer-msg",content:['

              ','
            • ','','
              ','',"
              ","
            • ",'
            • ','','
              ','",'","
              ","
            • ",'
            • ','','',"
            • ","
            "].join(""),success:function(t,n){var o="submit(layedit-link-yes)";a.render("radio"),t.find(".layui-btn-primary").on("click",function(){i.close(n),l.focus()}),a.on(o,function(t){i.close(b.index),e&&e(t.field)})}});b.index=n},x=function(t){var a=function(){var t=["[微笑]","[嘻嘻]","[哈哈]","[可爱]","[可怜]","[挖鼻]","[吃惊]","[害羞]","[挤眼]","[闭嘴]","[鄙视]","[爱你]","[泪]","[偷笑]","[亲亲]","[生病]","[太开心]","[白眼]","[右哼哼]","[左哼哼]","[嘘]","[衰]","[委屈]","[吐]","[哈欠]","[抱抱]","[怒]","[疑问]","[馋嘴]","[拜拜]","[思考]","[汗]","[困]","[睡]","[钱]","[失望]","[酷]","[色]","[哼]","[鼓掌]","[晕]","[悲伤]","[抓狂]","[黑线]","[阴险]","[怒骂]","[互粉]","[心]","[伤心]","[猪头]","[熊猫]","[兔子]","[ok]","[耶]","[good]","[NO]","[赞]","[来]","[弱]","[草泥马]","[神马]","[囧]","[浮云]","[给力]","[围观]","[威武]","[奥特曼]","[礼物]","[钟]","[话筒]","[蜡烛]","[蛋糕]"],e={};return layui.each(t,function(t,i){e[i]=layui.cache.dir+"images/face/"+t+".gif"}),e}();return x.hide=x.hide||function(t){"face"!==e(t.target).attr("layedit-event")&&i.close(x.index)},x.index=i.tips(function(){var t=[];return layui.each(a,function(e,i){t.push('
          • '+e+'
          • ')}),'
              '+t.join("")+"
            "}(),this,{tips:1,time:0,skin:"layui-box layui-util-face",maxWidth:500,success:function(l,n){l.css({marginTop:-4,marginLeft:-10}).find(".layui-clear>li").on("click",function(){t&&t({src:a[this.title],alt:this.title}),i.close(n)}),e(document).off("click",x.hide).on("click",x.hide)}})},k=function(t){var e=this,l=i.open({type:1,id:"LAY_layedit_code",area:"550px",shade:.05,shadeClose:!0,moveType:1,title:"插入代码",skin:"layui-layer-msg",content:['
              ','
            • ','','
              ','","
              ","
            • ",'
            • ','','
              ','',"
              ","
            • ",'
            • ','','',"
            • ","
            "].join(""),success:function(l,n){var o="submit(layedit-code-yes)";a.render("select"),l.find(".layui-btn-primary").on("click",function(){i.close(n),e.focus()}),a.on(o,function(e){i.close(k.index),t&&t(e.field)})}});k.index=l},C={html:'',strong:'',italic:'',underline:'',del:'',"|":'',left:'',center:'',right:'',link:'',unlink:'',face:'',image:'',code:'',help:''},w=new c;t(n,w)});layui.define("jquery",function(e){"use strict";var a=layui.$,l="http://www.layui.com/doc/modules/code.html";e("code",function(e){var t=[];e=e||{},e.elem=a(e.elem||".layui-code"),e.about=!("about"in e)||e.about,e.elem.each(function(){t.push(this)}),layui.each(t.reverse(),function(t,i){var c=a(i),o=c.html();(c.attr("lay-encode")||e.encode)&&(o=o.replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")),c.html('
            1. '+o.replace(/[\r\t\n]+/g,"
            2. ")+"
            "),c.find(">.layui-code-h3")[0]||c.prepend('

            '+(c.attr("lay-title")||e.title||"code")+(e.about?'layui.code':"")+"

            ");var d=c.find(">.layui-code-ol");c.addClass("layui-box layui-code-view"),(c.attr("lay-skin")||e.skin)&&c.addClass("layui-code-"+(c.attr("lay-skin")||e.skin)),(d.find("li").length/100|0)>0&&d.css("margin-left",(d.find("li").length/100|0)+"px"),(c.attr("lay-height")||e.height)&&d.css("max-height",c.attr("lay-height")||e.height)})})}).addcss("modules/code.css","skincodecss"); ================================================ FILE: open-layui-web/src/main/view/static/layui/layui.js ================================================ /** layui-v2.3.0-rc1 MIT License By https://www.layui.com */ ;!function(e){"use strict";var t=document,n={modules:{},status:{},timeout:10,event:{}},o=function(){this.v="2.3.0-rc1"},r=function(){var e=t.currentScript?t.currentScript.src:function(){for(var e,n=t.scripts,o=n.length-1,r=o;r>0;r--)if("interactive"===n[r].readyState){e=n[r].src;break}return e||n[o].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),a=function(t){e.console&&console.error&&console.error("Layui hint: "+t)},i="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),u={layer:"modules/layer",laydate:"modules/laydate",laypage:"modules/laypage",laytpl:"modules/laytpl",layim:"modules/layim",layedit:"modules/layedit",form:"modules/form",upload:"modules/upload",tree:"modules/tree",table:"modules/table",element:"modules/element",rate:"modules/rate",carousel:"modules/carousel",flow:"modules/flow",util:"modules/util",code:"modules/code",jquery:"modules/jquery",mobile:"modules/mobile","layui.all":"../layui.all"};o.prototype.cache=n,o.prototype.define=function(e,t){var o=this,r="function"==typeof e,a=function(){var e=function(e,t){layui[e]=t,n.status[e]=!0};return"function"==typeof t&&t(function(o,r){e(o,r),n.callback[o]=function(){t(e)}}),this};return r&&(t=e,e=[]),layui["layui.all"]||!layui["layui.all"]&&layui["layui.mobile"]?a.call(o):(o.use(e,a),o)},o.prototype.use=function(e,o,l){function s(e,t){var o="PLaySTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/;("load"===e.type||o.test((e.currentTarget||e.srcElement).readyState))&&(n.modules[d]=t,f.removeChild(v),function r(){return++m>1e3*n.timeout/4?a(d+" is not a valid module"):void(n.status[d]?c():setTimeout(r,4))}())}function c(){l.push(layui[d]),e.length>1?y.use(e.slice(1),o,l):"function"==typeof o&&o.apply(layui,l)}var y=this,p=n.dir=n.dir?n.dir:r,f=t.getElementsByTagName("head")[0];e="string"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(y.each(e,function(t,n){"jquery"===n&&e.splice(t,1)}),layui.jquery=layui.$=jQuery);var d=e[0],m=0;if(l=l||[],n.host=n.host||(p.match(/\/\/([\s\S]+?)\//)||["//"+location.host+"/"])[0],0===e.length||layui["layui.all"]&&u[d]||!layui["layui.all"]&&layui["layui.mobile"]&&u[d])return c(),y;if(n.modules[d])!function g(){return++m>1e3*n.timeout/4?a(d+" is not a valid module"):void("string"==typeof n.modules[d]&&n.status[d]?c():setTimeout(g,4))}();else{var v=t.createElement("script"),h=(u[d]?p+"lay/":/^\{\/\}/.test(y.modules[d])?"":n.base||"")+(y.modules[d]||d)+".js";h=h.replace(/^\{\/\}/,""),v.async=!0,v.charset="utf-8",v.src=h+function(){var e=n.version===!0?n.v||(new Date).getTime():n.version||"";return e?"?v="+e:""}(),f.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf("[native code")<0||i?v.addEventListener("load",function(e){s(e,h)},!1):v.attachEvent("onreadystatechange",function(e){s(e,h)}),n.modules[d]=h}return y},o.prototype.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?"getPropertyValue":"getAttribute"](n)},o.prototype.link=function(e,o,r){var i=this,u=t.createElement("link"),l=t.getElementsByTagName("head")[0];"string"==typeof o&&(r=o);var s=(r||e).replace(/\.|\//g,""),c=u.id="layuicss-"+s,y=0;return u.rel="stylesheet",u.href=e+(n.debug?"?v="+(new Date).getTime():""),u.media="all",t.getElementById(c)||l.appendChild(u),"function"!=typeof o?i:(function p(){return++y>1e3*n.timeout/100?a(e+" timeout"):void(1989===parseInt(i.getStyle(t.getElementById(c),"width"))?function(){o()}():setTimeout(p,100))}(),i)},n.callback={},o.prototype.factory=function(e){if(layui[e])return"function"==typeof n.callback[e]?n.callback[e]:null},o.prototype.addcss=function(e,t,o){return layui.link(n.dir+"css/"+e,t,o)},o.prototype.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,"function"==typeof t&&t(o)},void(o.onerror=function(e){o.onerror=null,"function"==typeof n&&n(e)}))},o.prototype.config=function(e){e=e||{};for(var t in e)n[t]=e[t];return this},o.prototype.modules=function(){var e={};for(var t in u)e[t]=u[t];return e}(),o.prototype.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?a("模块名 "+n+" 已被占用"):t.modules[n]=e[n];return t},o.prototype.router=function(e){var t=this,e=e||location.hash,n={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(e)?(e=e.replace(/^#\//,""),n.href="/"+e,e=e.replace(/([^#])(#.*$)/,"$1").split("/")||[],t.each(e,function(e,t){/^\w+=/.test(t)?function(){t=t.split("="),n.search[t[0]]=t[1]}():n.path.push(t)}),n):n},o.prototype.data=function(t,n,o){if(t=t||"layui",o=o||localStorage,e.JSON&&e.JSON.parse){if(null===n)return delete o[t];n="object"==typeof n?n:{key:n};try{var r=JSON.parse(o[t])}catch(a){var r={}}return"value"in n&&(r[n.key]=n.value),n.remove&&delete r[n.key],o[t]=JSON.stringify(r),n.key?r[n.key]:r}},o.prototype.sessionData=function(e,t){return this.data(e,t,sessionStorage)},o.prototype.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+"/([^\\s\\_\\-]+)");return e=(n.match(t)||[])[1],e||!1},r={os:function(){return/windows/.test(n)?"windows":/linux/.test(n)?"linux":/iphone|ipod|ipad|ios/.test(n)?"ios":/mac/.test(n)?"mac":void 0}(),ie:function(){return!!(e.ActiveXObject||"ActiveXObject"in e)&&((n.match(/msie\s(\d+)/)||[])[1]||"11")}(),weixin:o("micromessenger")};return t&&!r[t]&&(r[t]=o(t)),r.android=/android/.test(n),r.ios="ios"===r.os,r},o.prototype.hint=function(){return{error:a}},o.prototype.each=function(e,t){var n,o=this;if("function"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;na?1:r .col, .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-first { -ms-flex-order: -1; order: -1; } .order-1 { -ms-flex-order: 1; order: 1; } .order-2 { -ms-flex-order: 2; order: 2; } .order-3 { -ms-flex-order: 3; order: 3; } .order-4 { -ms-flex-order: 4; order: 4; } .order-5 { -ms-flex-order: 5; order: 5; } .order-6 { -ms-flex-order: 6; order: 6; } .order-7 { -ms-flex-order: 7; order: 7; } .order-8 { -ms-flex-order: 8; order: 8; } .order-9 { -ms-flex-order: 9; order: 9; } .order-10 { -ms-flex-order: 10; order: 10; } .order-11 { -ms-flex-order: 11; order: 11; } .order-12 { -ms-flex-order: 12; order: 12; } .offset-1 { margin-left: 8.333333%; } .offset-2 { margin-left: 16.666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.333333%; } .offset-5 { margin-left: 41.666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.333333%; } .offset-8 { margin-left: 66.666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.333333%; } .offset-11 { margin-left: 91.666667%; } @media (min-width: 576px) { .col-sm { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-sm-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-sm-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-sm-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-sm-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-sm-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-sm-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-sm-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-sm-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-sm-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-sm-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-sm-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-sm-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-sm-first { -ms-flex-order: -1; order: -1; } .order-sm-1 { -ms-flex-order: 1; order: 1; } .order-sm-2 { -ms-flex-order: 2; order: 2; } .order-sm-3 { -ms-flex-order: 3; order: 3; } .order-sm-4 { -ms-flex-order: 4; order: 4; } .order-sm-5 { -ms-flex-order: 5; order: 5; } .order-sm-6 { -ms-flex-order: 6; order: 6; } .order-sm-7 { -ms-flex-order: 7; order: 7; } .order-sm-8 { -ms-flex-order: 8; order: 8; } .order-sm-9 { -ms-flex-order: 9; order: 9; } .order-sm-10 { -ms-flex-order: 10; order: 10; } .order-sm-11 { -ms-flex-order: 11; order: 11; } .order-sm-12 { -ms-flex-order: 12; order: 12; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.333333%; } .offset-sm-2 { margin-left: 16.666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.333333%; } .offset-sm-5 { margin-left: 41.666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.333333%; } .offset-sm-8 { margin-left: 66.666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.333333%; } .offset-sm-11 { margin-left: 91.666667%; } } @media (min-width: 768px) { .col-md { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-md-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-md-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-md-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-md-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-md-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-md-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-md-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-md-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-md-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-md-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-md-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-md-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-md-first { -ms-flex-order: -1; order: -1; } .order-md-1 { -ms-flex-order: 1; order: 1; } .order-md-2 { -ms-flex-order: 2; order: 2; } .order-md-3 { -ms-flex-order: 3; order: 3; } .order-md-4 { -ms-flex-order: 4; order: 4; } .order-md-5 { -ms-flex-order: 5; order: 5; } .order-md-6 { -ms-flex-order: 6; order: 6; } .order-md-7 { -ms-flex-order: 7; order: 7; } .order-md-8 { -ms-flex-order: 8; order: 8; } .order-md-9 { -ms-flex-order: 9; order: 9; } .order-md-10 { -ms-flex-order: 10; order: 10; } .order-md-11 { -ms-flex-order: 11; order: 11; } .order-md-12 { -ms-flex-order: 12; order: 12; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.333333%; } .offset-md-2 { margin-left: 16.666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.333333%; } .offset-md-5 { margin-left: 41.666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.333333%; } .offset-md-8 { margin-left: 66.666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.333333%; } .offset-md-11 { margin-left: 91.666667%; } } @media (min-width: 992px) { .col-lg { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-lg-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-lg-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-lg-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-lg-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-lg-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-lg-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-lg-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-lg-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-lg-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-lg-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-lg-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-lg-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-lg-first { -ms-flex-order: -1; order: -1; } .order-lg-1 { -ms-flex-order: 1; order: 1; } .order-lg-2 { -ms-flex-order: 2; order: 2; } .order-lg-3 { -ms-flex-order: 3; order: 3; } .order-lg-4 { -ms-flex-order: 4; order: 4; } .order-lg-5 { -ms-flex-order: 5; order: 5; } .order-lg-6 { -ms-flex-order: 6; order: 6; } .order-lg-7 { -ms-flex-order: 7; order: 7; } .order-lg-8 { -ms-flex-order: 8; order: 8; } .order-lg-9 { -ms-flex-order: 9; order: 9; } .order-lg-10 { -ms-flex-order: 10; order: 10; } .order-lg-11 { -ms-flex-order: 11; order: 11; } .order-lg-12 { -ms-flex-order: 12; order: 12; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.333333%; } .offset-lg-2 { margin-left: 16.666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.333333%; } .offset-lg-5 { margin-left: 41.666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.333333%; } .offset-lg-8 { margin-left: 66.666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.333333%; } .offset-lg-11 { margin-left: 91.666667%; } } @media (min-width: 1200px) { .col-xl { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-xl-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-xl-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-xl-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-xl-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-xl-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-xl-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-xl-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-xl-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-xl-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-xl-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-xl-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-xl-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-xl-first { -ms-flex-order: -1; order: -1; } .order-xl-1 { -ms-flex-order: 1; order: 1; } .order-xl-2 { -ms-flex-order: 2; order: 2; } .order-xl-3 { -ms-flex-order: 3; order: 3; } .order-xl-4 { -ms-flex-order: 4; order: 4; } .order-xl-5 { -ms-flex-order: 5; order: 5; } .order-xl-6 { -ms-flex-order: 6; order: 6; } .order-xl-7 { -ms-flex-order: 7; order: 7; } .order-xl-8 { -ms-flex-order: 8; order: 8; } .order-xl-9 { -ms-flex-order: 9; order: 9; } .order-xl-10 { -ms-flex-order: 10; order: 10; } .order-xl-11 { -ms-flex-order: 11; order: 11; } .order-xl-12 { -ms-flex-order: 12; order: 12; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.333333%; } .offset-xl-2 { margin-left: 16.666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.333333%; } .offset-xl-5 { margin-left: 41.666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.333333%; } .offset-xl-8 { margin-left: 66.666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.333333%; } .offset-xl-11 { margin-left: 91.666667%; } } .flex-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } @media (min-width: 576px) { .flex-sm-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-sm-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-sm-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-sm-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-sm-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-sm-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-sm-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-sm-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-sm-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-sm-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-sm-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-sm-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-sm-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-sm-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-sm-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-sm-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-sm-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-sm-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-sm-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-sm-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-sm-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-sm-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-sm-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-sm-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-sm-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-sm-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-sm-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-sm-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 768px) { .flex-md-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-md-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-md-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-md-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-md-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-md-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-md-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-md-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-md-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-md-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-md-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-md-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-md-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-md-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-md-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-md-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-md-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-md-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-md-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-md-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-md-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-md-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-md-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-md-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-md-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-md-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-md-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-md-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-md-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 992px) { .flex-lg-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-lg-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-lg-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-lg-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-lg-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-lg-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-lg-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-lg-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-lg-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-lg-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-lg-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-lg-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-lg-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-lg-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-lg-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-lg-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-lg-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-lg-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-lg-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-lg-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-lg-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-lg-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-lg-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-lg-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-lg-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-lg-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-lg-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-lg-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 1200px) { .flex-xl-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-xl-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-xl-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-xl-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-xl-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-xl-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-xl-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-xl-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-xl-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-xl-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-xl-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-xl-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-xl-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-xl-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-xl-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-xl-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-xl-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-xl-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-xl-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-xl-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-xl-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-xl-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-xl-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-xl-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-xl-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-xl-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-xl-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-xl-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } /*# sourceMappingURL=bootstrap-grid.css.map */ ================================================ FILE: open-layui-web/src/main/view/static/lib/bootstrap/css/bootstrap-reboot.css ================================================ /*! * Bootstrap Reboot v4.0.0-beta.2 (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors * Copyright 2011-2017 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) */ *, *::before, *::after { box-sizing: border-box; } html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -ms-overflow-style: scrollbar; -webkit-tap-highlight-color: transparent; } @-ms-viewport { width: device-width; } article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: left; background-color: #fff; } [tabindex="-1"]:focus { outline: none !important; } hr { box-sizing: content-box; height: 0; overflow: visible; } h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-original-title] { text-decoration: underline; -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; border-bottom: 0; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: .5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } dfn { font-style: italic; } b, strong { font-weight: bolder; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } a { color: #007bff; text-decoration: none; background-color: transparent; -webkit-text-decoration-skip: objects; } a:hover { color: #0056b3; text-decoration: underline; } a:not([href]):not([tabindex]) { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus { outline: 0; } pre, code, kbd, samp { font-family: monospace, monospace; font-size: 1em; } pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; -ms-overflow-style: scrollbar; } figure { margin: 0 0 1rem; } img { vertical-align: middle; border-style: none; } svg:not(:root) { overflow: hidden; } a, area, button, [role="button"], input:not([type="range"]), label, select, summary, textarea { -ms-touch-action: manipulation; touch-action: manipulation; } table { border-collapse: collapse; } caption { padding-top: 0.75rem; padding-bottom: 0.75rem; color: #868e96; text-align: left; caption-side: bottom; } th { text-align: inherit; } label { display: inline-block; margin-bottom: .5rem; } button { border-radius: 0; } button:focus { outline: 1px dotted; outline: 5px auto -webkit-focus-ring-color; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, input { overflow: visible; } button, select { text-transform: none; } button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } input[type="radio"], input[type="checkbox"] { box-sizing: border-box; padding: 0; } input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"] { -webkit-appearance: listbox; } textarea { overflow: auto; resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; max-width: 100%; padding: 0; margin-bottom: .5rem; font-size: 1.5rem; line-height: inherit; color: inherit; white-space: normal; } progress { vertical-align: baseline; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { outline-offset: -2px; -webkit-appearance: none; } [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } summary { display: list-item; } template { display: none; } [hidden] { display: none !important; } /*# sourceMappingURL=bootstrap-reboot.css.map */ ================================================ FILE: open-layui-web/src/main/view/static/lib/bootstrap/css/bootstrap.css ================================================ /*! * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors * Copyright 2011-2017 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ :root { --blue: #007bff; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #dc3545; --orange: #fd7e14; --yellow: #ffc107; --green: #28a745; --teal: #20c997; --cyan: #17a2b8; --white: #fff; --gray: #868e96; --gray-dark: #343a40; --primary: #007bff; --secondary: #868e96; --success: #28a745; --info: #17a2b8; --warning: #ffc107; --danger: #dc3545; --light: #f8f9fa; --dark: #343a40; --breakpoint-xs: 0; --breakpoint-sm: 576px; --breakpoint-md: 768px; --breakpoint-lg: 992px; --breakpoint-xl: 1200px; --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --font-family-monospace: "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } @media print { *, *::before, *::after { text-shadow: none !important; box-shadow: none !important; } a, a:visited { text-decoration: underline; } abbr[title]::after { content: " (" attr(title) ")"; } pre { white-space: pre-wrap !important; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } .navbar { display: none; } .badge { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordered td { border: 1px solid #ddd !important; } } *, *::before, *::after { box-sizing: border-box; } html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -ms-overflow-style: scrollbar; -webkit-tap-highlight-color: transparent; } @-ms-viewport { width: device-width; } article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: left; background-color: #fff; } [tabindex="-1"]:focus { outline: none !important; } hr { box-sizing: content-box; height: 0; overflow: visible; } h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-original-title] { text-decoration: underline; -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; border-bottom: 0; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: .5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } dfn { font-style: italic; } b, strong { font-weight: bolder; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } a { color: #007bff; text-decoration: none; background-color: transparent; -webkit-text-decoration-skip: objects; } a:hover { color: #0056b3; text-decoration: underline; } a:not([href]):not([tabindex]) { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus { outline: 0; } pre, code, kbd, samp { font-family: monospace, monospace; font-size: 1em; } pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; -ms-overflow-style: scrollbar; } figure { margin: 0 0 1rem; } img { vertical-align: middle; border-style: none; } svg:not(:root) { overflow: hidden; } a, area, button, [role="button"], input:not([type="range"]), label, select, summary, textarea { -ms-touch-action: manipulation; touch-action: manipulation; } table { border-collapse: collapse; } caption { padding-top: 0.75rem; padding-bottom: 0.75rem; color: #868e96; text-align: left; caption-side: bottom; } th { text-align: inherit; } label { display: inline-block; margin-bottom: .5rem; } button { border-radius: 0; } button:focus { outline: 1px dotted; outline: 5px auto -webkit-focus-ring-color; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, input { overflow: visible; } button, select { text-transform: none; } button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } input[type="radio"], input[type="checkbox"] { box-sizing: border-box; padding: 0; } input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"] { -webkit-appearance: listbox; } textarea { overflow: auto; resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; max-width: 100%; padding: 0; margin-bottom: .5rem; font-size: 1.5rem; line-height: inherit; color: inherit; white-space: normal; } progress { vertical-align: baseline; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { outline-offset: -2px; -webkit-appearance: none; } [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } summary { display: list-item; } template { display: none; } [hidden] { display: none !important; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { margin-bottom: 0.5rem; font-family: inherit; font-weight: 500; line-height: 1.2; color: inherit; } h1, .h1 { font-size: 2.5rem; } h2, .h2 { font-size: 2rem; } h3, .h3 { font-size: 1.75rem; } h4, .h4 { font-size: 1.5rem; } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: 6rem; font-weight: 300; line-height: 1.2; } .display-2 { font-size: 5.5rem; font-weight: 300; line-height: 1.2; } .display-3 { font-size: 4.5rem; font-weight: 300; line-height: 1.2; } .display-4 { font-size: 3.5rem; font-weight: 300; line-height: 1.2; } hr { margin-top: 1rem; margin-bottom: 1rem; border: 0; border-top: 1px solid rgba(0, 0, 0, 0.1); } small, .small { font-size: 80%; font-weight: 400; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-right: 5px; } .initialism { font-size: 90%; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote-footer { display: block; font-size: 80%; color: #868e96; } .blockquote-footer::before { content: "\2014 \00A0"; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid #ddd; border-radius: 0.25rem; transition: all 0.2s ease-in-out; max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 90%; color: #868e96; } code, kbd, pre, samp { font-family: "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } code { padding: 0.2rem 0.4rem; font-size: 90%; color: #bd4147; background-color: #f8f9fa; border-radius: 0.25rem; } a > code { padding: 0; color: inherit; background-color: inherit; } kbd { padding: 0.2rem 0.4rem; font-size: 90%; color: #fff; background-color: #212529; border-radius: 0.2rem; } kbd kbd { padding: 0; font-size: 100%; font-weight: 700; } pre { display: block; margin-top: 0; margin-bottom: 1rem; font-size: 90%; color: #212529; } pre code { padding: 0; font-size: inherit; color: inherit; background-color: transparent; border-radius: 0; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container { max-width: 540px; } } @media (min-width: 768px) { .container { max-width: 720px; } } @media (min-width: 992px) { .container { max-width: 960px; } } @media (min-width: 1200px) { .container { max-width: 1140px; } } .container-fluid { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; } .no-gutters { margin-right: 0; margin-left: 0; } .no-gutters > .col, .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-first { -ms-flex-order: -1; order: -1; } .order-1 { -ms-flex-order: 1; order: 1; } .order-2 { -ms-flex-order: 2; order: 2; } .order-3 { -ms-flex-order: 3; order: 3; } .order-4 { -ms-flex-order: 4; order: 4; } .order-5 { -ms-flex-order: 5; order: 5; } .order-6 { -ms-flex-order: 6; order: 6; } .order-7 { -ms-flex-order: 7; order: 7; } .order-8 { -ms-flex-order: 8; order: 8; } .order-9 { -ms-flex-order: 9; order: 9; } .order-10 { -ms-flex-order: 10; order: 10; } .order-11 { -ms-flex-order: 11; order: 11; } .order-12 { -ms-flex-order: 12; order: 12; } .offset-1 { margin-left: 8.333333%; } .offset-2 { margin-left: 16.666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.333333%; } .offset-5 { margin-left: 41.666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.333333%; } .offset-8 { margin-left: 66.666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.333333%; } .offset-11 { margin-left: 91.666667%; } @media (min-width: 576px) { .col-sm { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-sm-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-sm-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-sm-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-sm-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-sm-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-sm-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-sm-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-sm-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-sm-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-sm-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-sm-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-sm-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-sm-first { -ms-flex-order: -1; order: -1; } .order-sm-1 { -ms-flex-order: 1; order: 1; } .order-sm-2 { -ms-flex-order: 2; order: 2; } .order-sm-3 { -ms-flex-order: 3; order: 3; } .order-sm-4 { -ms-flex-order: 4; order: 4; } .order-sm-5 { -ms-flex-order: 5; order: 5; } .order-sm-6 { -ms-flex-order: 6; order: 6; } .order-sm-7 { -ms-flex-order: 7; order: 7; } .order-sm-8 { -ms-flex-order: 8; order: 8; } .order-sm-9 { -ms-flex-order: 9; order: 9; } .order-sm-10 { -ms-flex-order: 10; order: 10; } .order-sm-11 { -ms-flex-order: 11; order: 11; } .order-sm-12 { -ms-flex-order: 12; order: 12; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.333333%; } .offset-sm-2 { margin-left: 16.666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.333333%; } .offset-sm-5 { margin-left: 41.666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.333333%; } .offset-sm-8 { margin-left: 66.666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.333333%; } .offset-sm-11 { margin-left: 91.666667%; } } @media (min-width: 768px) { .col-md { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-md-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-md-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-md-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-md-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-md-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-md-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-md-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-md-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-md-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-md-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-md-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-md-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-md-first { -ms-flex-order: -1; order: -1; } .order-md-1 { -ms-flex-order: 1; order: 1; } .order-md-2 { -ms-flex-order: 2; order: 2; } .order-md-3 { -ms-flex-order: 3; order: 3; } .order-md-4 { -ms-flex-order: 4; order: 4; } .order-md-5 { -ms-flex-order: 5; order: 5; } .order-md-6 { -ms-flex-order: 6; order: 6; } .order-md-7 { -ms-flex-order: 7; order: 7; } .order-md-8 { -ms-flex-order: 8; order: 8; } .order-md-9 { -ms-flex-order: 9; order: 9; } .order-md-10 { -ms-flex-order: 10; order: 10; } .order-md-11 { -ms-flex-order: 11; order: 11; } .order-md-12 { -ms-flex-order: 12; order: 12; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.333333%; } .offset-md-2 { margin-left: 16.666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.333333%; } .offset-md-5 { margin-left: 41.666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.333333%; } .offset-md-8 { margin-left: 66.666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.333333%; } .offset-md-11 { margin-left: 91.666667%; } } @media (min-width: 992px) { .col-lg { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-lg-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-lg-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-lg-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-lg-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-lg-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-lg-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-lg-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-lg-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-lg-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-lg-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-lg-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-lg-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-lg-first { -ms-flex-order: -1; order: -1; } .order-lg-1 { -ms-flex-order: 1; order: 1; } .order-lg-2 { -ms-flex-order: 2; order: 2; } .order-lg-3 { -ms-flex-order: 3; order: 3; } .order-lg-4 { -ms-flex-order: 4; order: 4; } .order-lg-5 { -ms-flex-order: 5; order: 5; } .order-lg-6 { -ms-flex-order: 6; order: 6; } .order-lg-7 { -ms-flex-order: 7; order: 7; } .order-lg-8 { -ms-flex-order: 8; order: 8; } .order-lg-9 { -ms-flex-order: 9; order: 9; } .order-lg-10 { -ms-flex-order: 10; order: 10; } .order-lg-11 { -ms-flex-order: 11; order: 11; } .order-lg-12 { -ms-flex-order: 12; order: 12; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.333333%; } .offset-lg-2 { margin-left: 16.666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.333333%; } .offset-lg-5 { margin-left: 41.666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.333333%; } .offset-lg-8 { margin-left: 66.666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.333333%; } .offset-lg-11 { margin-left: 91.666667%; } } @media (min-width: 1200px) { .col-xl { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-xl-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-xl-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-xl-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-xl-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-xl-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-xl-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-xl-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-xl-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-xl-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-xl-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-xl-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-xl-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-xl-first { -ms-flex-order: -1; order: -1; } .order-xl-1 { -ms-flex-order: 1; order: 1; } .order-xl-2 { -ms-flex-order: 2; order: 2; } .order-xl-3 { -ms-flex-order: 3; order: 3; } .order-xl-4 { -ms-flex-order: 4; order: 4; } .order-xl-5 { -ms-flex-order: 5; order: 5; } .order-xl-6 { -ms-flex-order: 6; order: 6; } .order-xl-7 { -ms-flex-order: 7; order: 7; } .order-xl-8 { -ms-flex-order: 8; order: 8; } .order-xl-9 { -ms-flex-order: 9; order: 9; } .order-xl-10 { -ms-flex-order: 10; order: 10; } .order-xl-11 { -ms-flex-order: 11; order: 11; } .order-xl-12 { -ms-flex-order: 12; order: 12; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.333333%; } .offset-xl-2 { margin-left: 16.666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.333333%; } .offset-xl-5 { margin-left: 41.666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.333333%; } .offset-xl-8 { margin-left: 66.666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.333333%; } .offset-xl-11 { margin-left: 91.666667%; } } .table { width: 100%; max-width: 100%; margin-bottom: 1rem; background-color: transparent; } .table th, .table td { padding: 0.75rem; vertical-align: top; border-top: 1px solid #e9ecef; } .table thead th { vertical-align: bottom; border-bottom: 2px solid #e9ecef; } .table tbody + tbody { border-top: 2px solid #e9ecef; } .table .table { background-color: #fff; } .table-sm th, .table-sm td { padding: 0.3rem; } .table-bordered { border: 1px solid #e9ecef; } .table-bordered th, .table-bordered td { border: 1px solid #e9ecef; } .table-bordered thead th, .table-bordered thead td { border-bottom-width: 2px; } .table-striped tbody tr:nth-of-type(odd) { background-color: rgba(0, 0, 0, 0.05); } .table-hover tbody tr:hover { background-color: rgba(0, 0, 0, 0.075); } .table-primary, .table-primary > th, .table-primary > td { background-color: #b8daff; } .table-hover .table-primary:hover { background-color: #9fcdff; } .table-hover .table-primary:hover > td, .table-hover .table-primary:hover > th { background-color: #9fcdff; } .table-secondary, .table-secondary > th, .table-secondary > td { background-color: #dddfe2; } .table-hover .table-secondary:hover { background-color: #cfd2d6; } .table-hover .table-secondary:hover > td, .table-hover .table-secondary:hover > th { background-color: #cfd2d6; } .table-success, .table-success > th, .table-success > td { background-color: #c3e6cb; } .table-hover .table-success:hover { background-color: #b1dfbb; } .table-hover .table-success:hover > td, .table-hover .table-success:hover > th { background-color: #b1dfbb; } .table-info, .table-info > th, .table-info > td { background-color: #bee5eb; } .table-hover .table-info:hover { background-color: #abdde5; } .table-hover .table-info:hover > td, .table-hover .table-info:hover > th { background-color: #abdde5; } .table-warning, .table-warning > th, .table-warning > td { background-color: #ffeeba; } .table-hover .table-warning:hover { background-color: #ffe8a1; } .table-hover .table-warning:hover > td, .table-hover .table-warning:hover > th { background-color: #ffe8a1; } .table-danger, .table-danger > th, .table-danger > td { background-color: #f5c6cb; } .table-hover .table-danger:hover { background-color: #f1b0b7; } .table-hover .table-danger:hover > td, .table-hover .table-danger:hover > th { background-color: #f1b0b7; } .table-light, .table-light > th, .table-light > td { background-color: #fdfdfe; } .table-hover .table-light:hover { background-color: #ececf6; } .table-hover .table-light:hover > td, .table-hover .table-light:hover > th { background-color: #ececf6; } .table-dark, .table-dark > th, .table-dark > td { background-color: #c6c8ca; } .table-hover .table-dark:hover { background-color: #b9bbbe; } .table-hover .table-dark:hover > td, .table-hover .table-dark:hover > th { background-color: #b9bbbe; } .table-active, .table-active > th, .table-active > td { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover > td, .table-hover .table-active:hover > th { background-color: rgba(0, 0, 0, 0.075); } .table .thead-dark th { color: #fff; background-color: #212529; border-color: #32383e; } .table .thead-light th { color: #495057; background-color: #e9ecef; border-color: #e9ecef; } .table-dark { color: #fff; background-color: #212529; } .table-dark th, .table-dark td, .table-dark thead th { border-color: #32383e; } .table-dark.table-bordered { border: 0; } .table-dark.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255, 255, 255, 0.05); } .table-dark.table-hover tbody tr:hover { background-color: rgba(255, 255, 255, 0.075); } @media (max-width: 575px) { .table-responsive-sm { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-sm.table-bordered { border: 0; } } @media (max-width: 767px) { .table-responsive-md { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-md.table-bordered { border: 0; } } @media (max-width: 991px) { .table-responsive-lg { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-lg.table-bordered { border: 0; } } @media (max-width: 1199px) { .table-responsive-xl { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-xl.table-bordered { border: 0; } } .table-responsive { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive.table-bordered { border: 0; } .form-control { display: block; width: 100%; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; color: #495057; background-color: #fff; background-image: none; background-clip: padding-box; border: 1px solid #ced4da; border-radius: 0.25rem; transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; } .form-control::-ms-expand { background-color: transparent; border: 0; } .form-control:focus { color: #495057; background-color: #fff; border-color: #80bdff; outline: none; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .form-control::-webkit-input-placeholder { color: #868e96; opacity: 1; } .form-control:-ms-input-placeholder { color: #868e96; opacity: 1; } .form-control::-ms-input-placeholder { color: #868e96; opacity: 1; } .form-control::placeholder { color: #868e96; opacity: 1; } .form-control:disabled, .form-control[readonly] { background-color: #e9ecef; opacity: 1; } select.form-control:not([size]):not([multiple]) { height: calc(2.25rem + 2px); } select.form-control:focus::-ms-value { color: #495057; background-color: #fff; } .form-control-file, .form-control-range { display: block; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; line-height: 1.5; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; line-height: 1.5; } .col-form-legend { padding-top: 0.375rem; padding-bottom: 0.375rem; margin-bottom: 0; font-size: 1rem; } .form-control-plaintext { padding-top: 0.375rem; padding-bottom: 0.375rem; margin-bottom: 0; line-height: 1.5; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control, .input-group-sm > .form-control-plaintext.input-group-addon, .input-group-sm > .input-group-btn > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control, .input-group-lg > .form-control-plaintext.input-group-addon, .input-group-lg > .input-group-btn > .form-control-plaintext.btn { padding-right: 0; padding-left: 0; } .form-control-sm, .input-group-sm > .form-control, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]), .input-group-sm > select.input-group-addon:not([size]):not([multiple]), .input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) { height: calc(1.8125rem + 2px); } .form-control-lg, .input-group-lg > .form-control, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]), .input-group-lg > select.input-group-addon:not([size]):not([multiple]), .input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) { height: calc(2.875rem + 2px); } .form-group { margin-bottom: 1rem; } .form-text { display: block; margin-top: 0.25rem; } .form-row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -5px; margin-left: -5px; } .form-row > .col, .form-row > [class*="col-"] { padding-right: 5px; padding-left: 5px; } .form-check { position: relative; display: block; margin-bottom: 0.5rem; } .form-check.disabled .form-check-label { color: #868e96; } .form-check-label { padding-left: 1.25rem; margin-bottom: 0; } .form-check-input { position: absolute; margin-top: 0.25rem; margin-left: -1.25rem; } .form-check-inline { display: inline-block; margin-right: 0.75rem; } .form-check-inline .form-check-label { vertical-align: middle; } .valid-feedback { display: none; margin-top: .25rem; font-size: .875rem; color: #28a745; } .valid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; width: 250px; padding: .5rem; margin-top: .1rem; font-size: .875rem; line-height: 1; color: #fff; background-color: rgba(40, 167, 69, 0.8); border-radius: .2rem; } .was-validated .form-control:valid, .form-control.is-valid, .was-validated .custom-select:valid, .custom-select.is-valid { border-color: #28a745; } .was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated .custom-select:valid:focus, .custom-select.is-valid:focus { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .was-validated .form-control:valid ~ .valid-feedback, .was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback, .form-control.is-valid ~ .valid-tooltip, .was-validated .custom-select:valid ~ .valid-feedback, .was-validated .custom-select:valid ~ .valid-tooltip, .custom-select.is-valid ~ .valid-feedback, .custom-select.is-valid ~ .valid-tooltip { display: block; } .was-validated .form-check-input:valid + .form-check-label, .form-check-input.is-valid + .form-check-label { color: #28a745; } .was-validated .custom-control-input:valid ~ .custom-control-indicator, .custom-control-input.is-valid ~ .custom-control-indicator { background-color: rgba(40, 167, 69, 0.25); } .was-validated .custom-control-input:valid ~ .custom-control-description, .custom-control-input.is-valid ~ .custom-control-description { color: #28a745; } .was-validated .custom-file-input:valid ~ .custom-file-control, .custom-file-input.is-valid ~ .custom-file-control { border-color: #28a745; } .was-validated .custom-file-input:valid ~ .custom-file-control::before, .custom-file-input.is-valid ~ .custom-file-control::before { border-color: inherit; } .was-validated .custom-file-input:valid:focus, .custom-file-input.is-valid:focus { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .invalid-feedback { display: none; margin-top: .25rem; font-size: .875rem; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; width: 250px; padding: .5rem; margin-top: .1rem; font-size: .875rem; line-height: 1; color: #fff; background-color: rgba(220, 53, 69, 0.8); border-radius: .2rem; } .was-validated .form-control:invalid, .form-control.is-invalid, .was-validated .custom-select:invalid, .custom-select.is-invalid { border-color: #dc3545; } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .was-validated .form-control:invalid ~ .invalid-feedback, .was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback, .form-control.is-invalid ~ .invalid-tooltip, .was-validated .custom-select:invalid ~ .invalid-feedback, .was-validated .custom-select:invalid ~ .invalid-tooltip, .custom-select.is-invalid ~ .invalid-feedback, .custom-select.is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-check-input:invalid + .form-check-label, .form-check-input.is-invalid + .form-check-label { color: #dc3545; } .was-validated .custom-control-input:invalid ~ .custom-control-indicator, .custom-control-input.is-invalid ~ .custom-control-indicator { background-color: rgba(220, 53, 69, 0.25); } .was-validated .custom-control-input:invalid ~ .custom-control-description, .custom-control-input.is-invalid ~ .custom-control-description { color: #dc3545; } .was-validated .custom-file-input:invalid ~ .custom-file-control, .custom-file-input.is-invalid ~ .custom-file-control { border-color: #dc3545; } .was-validated .custom-file-input:invalid ~ .custom-file-control::before, .custom-file-input.is-invalid ~ .custom-file-control::before { border-color: inherit; } .was-validated .custom-file-input:invalid:focus, .custom-file-input.is-invalid:focus { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .form-inline { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; } .form-inline .form-check { width: 100%; } @media (min-width: 576px) { .form-inline label { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; margin-bottom: 0; } .form-inline .form-group { display: -ms-flexbox; display: flex; -ms-flex: 0 0 auto; flex: 0 0 auto; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; margin-bottom: 0; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .form-control-plaintext { display: inline-block; } .form-inline .input-group { width: auto; } .form-inline .form-check { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: auto; margin-top: 0; margin-bottom: 0; } .form-inline .form-check-label { padding-left: 0; } .form-inline .form-check-input { position: relative; margin-top: 0; margin-right: 0.25rem; margin-left: 0; } .form-inline .custom-control { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; padding-left: 0; } .form-inline .custom-control-indicator { position: static; display: inline-block; margin-right: 0.25rem; vertical-align: text-bottom; } .form-inline .has-feedback .form-control-feedback { top: 0; } } .btn { display: inline-block; font-weight: 400; text-align: center; white-space: nowrap; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border: 1px solid transparent; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; border-radius: 0.25rem; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .btn:focus, .btn:hover { text-decoration: none; } .btn:focus, .btn.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .btn.disabled, .btn:disabled { opacity: .65; } .btn:not([disabled]):not(.disabled):active, .btn:not([disabled]):not(.disabled).active { background-image: none; } a.btn.disabled, fieldset[disabled] a.btn { pointer-events: none; } .btn-primary { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-primary:hover { color: #fff; background-color: #0069d9; border-color: #0062cc; } .btn-primary:focus, .btn-primary.focus { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-primary.disabled, .btn-primary:disabled { background-color: #007bff; border-color: #007bff; } .btn-primary:not([disabled]):not(.disabled):active, .btn-primary:not([disabled]):not(.disabled).active, .show > .btn-primary.dropdown-toggle { color: #fff; background-color: #0062cc; border-color: #005cbf; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-secondary { color: #fff; background-color: #868e96; border-color: #868e96; } .btn-secondary:hover { color: #fff; background-color: #727b84; border-color: #6c757d; } .btn-secondary:focus, .btn-secondary.focus { box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-secondary.disabled, .btn-secondary:disabled { background-color: #868e96; border-color: #868e96; } .btn-secondary:not([disabled]):not(.disabled):active, .btn-secondary:not([disabled]):not(.disabled).active, .show > .btn-secondary.dropdown-toggle { color: #fff; background-color: #6c757d; border-color: #666e76; box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-success { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-success:hover { color: #fff; background-color: #218838; border-color: #1e7e34; } .btn-success:focus, .btn-success.focus { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-success.disabled, .btn-success:disabled { background-color: #28a745; border-color: #28a745; } .btn-success:not([disabled]):not(.disabled):active, .btn-success:not([disabled]):not(.disabled).active, .show > .btn-success.dropdown-toggle { color: #fff; background-color: #1e7e34; border-color: #1c7430; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-info { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-info:hover { color: #fff; background-color: #138496; border-color: #117a8b; } .btn-info:focus, .btn-info.focus { box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-info.disabled, .btn-info:disabled { background-color: #17a2b8; border-color: #17a2b8; } .btn-info:not([disabled]):not(.disabled):active, .btn-info:not([disabled]):not(.disabled).active, .show > .btn-info.dropdown-toggle { color: #fff; background-color: #117a8b; border-color: #10707f; box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-warning { color: #111; background-color: #ffc107; border-color: #ffc107; } .btn-warning:hover { color: #111; background-color: #e0a800; border-color: #d39e00; } .btn-warning:focus, .btn-warning.focus { box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-warning.disabled, .btn-warning:disabled { background-color: #ffc107; border-color: #ffc107; } .btn-warning:not([disabled]):not(.disabled):active, .btn-warning:not([disabled]):not(.disabled).active, .show > .btn-warning.dropdown-toggle { color: #111; background-color: #d39e00; border-color: #c69500; box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-danger { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-danger:hover { color: #fff; background-color: #c82333; border-color: #bd2130; } .btn-danger:focus, .btn-danger.focus { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-danger.disabled, .btn-danger:disabled { background-color: #dc3545; border-color: #dc3545; } .btn-danger:not([disabled]):not(.disabled):active, .btn-danger:not([disabled]):not(.disabled).active, .show > .btn-danger.dropdown-toggle { color: #fff; background-color: #bd2130; border-color: #b21f2d; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-light { color: #111; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:hover { color: #111; background-color: #e2e6ea; border-color: #dae0e5; } .btn-light:focus, .btn-light.focus { box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-light.disabled, .btn-light:disabled { background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:not([disabled]):not(.disabled):active, .btn-light:not([disabled]):not(.disabled).active, .show > .btn-light.dropdown-toggle { color: #111; background-color: #dae0e5; border-color: #d3d9df; box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-dark { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-dark:hover { color: #fff; background-color: #23272b; border-color: #1d2124; } .btn-dark:focus, .btn-dark.focus { box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-dark.disabled, .btn-dark:disabled { background-color: #343a40; border-color: #343a40; } .btn-dark:not([disabled]):not(.disabled):active, .btn-dark:not([disabled]):not(.disabled).active, .show > .btn-dark.dropdown-toggle { color: #fff; background-color: #1d2124; border-color: #171a1d; box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-outline-primary { color: #007bff; background-color: transparent; background-image: none; border-color: #007bff; } .btn-outline-primary:hover { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:focus, .btn-outline-primary.focus { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-outline-primary.disabled, .btn-outline-primary:disabled { color: #007bff; background-color: transparent; } .btn-outline-primary:not([disabled]):not(.disabled):active, .btn-outline-primary:not([disabled]):not(.disabled).active, .show > .btn-outline-primary.dropdown-toggle { color: #fff; background-color: #007bff; border-color: #007bff; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-outline-secondary { color: #868e96; background-color: transparent; background-image: none; border-color: #868e96; } .btn-outline-secondary:hover { color: #fff; background-color: #868e96; border-color: #868e96; } .btn-outline-secondary:focus, .btn-outline-secondary.focus { box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-outline-secondary.disabled, .btn-outline-secondary:disabled { color: #868e96; background-color: transparent; } .btn-outline-secondary:not([disabled]):not(.disabled):active, .btn-outline-secondary:not([disabled]):not(.disabled).active, .show > .btn-outline-secondary.dropdown-toggle { color: #fff; background-color: #868e96; border-color: #868e96; box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-outline-success { color: #28a745; background-color: transparent; background-image: none; border-color: #28a745; } .btn-outline-success:hover { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:focus, .btn-outline-success.focus { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-outline-success.disabled, .btn-outline-success:disabled { color: #28a745; background-color: transparent; } .btn-outline-success:not([disabled]):not(.disabled):active, .btn-outline-success:not([disabled]):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { color: #fff; background-color: #28a745; border-color: #28a745; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-outline-info { color: #17a2b8; background-color: transparent; background-image: none; border-color: #17a2b8; } .btn-outline-info:hover { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:focus, .btn-outline-info.focus { box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-outline-info.disabled, .btn-outline-info:disabled { color: #17a2b8; background-color: transparent; } .btn-outline-info:not([disabled]):not(.disabled):active, .btn-outline-info:not([disabled]):not(.disabled).active, .show > .btn-outline-info.dropdown-toggle { color: #fff; background-color: #17a2b8; border-color: #17a2b8; box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-outline-warning { color: #ffc107; background-color: transparent; background-image: none; border-color: #ffc107; } .btn-outline-warning:hover { color: #fff; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:focus, .btn-outline-warning.focus { box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-outline-warning.disabled, .btn-outline-warning:disabled { color: #ffc107; background-color: transparent; } .btn-outline-warning:not([disabled]):not(.disabled):active, .btn-outline-warning:not([disabled]):not(.disabled).active, .show > .btn-outline-warning.dropdown-toggle { color: #fff; background-color: #ffc107; border-color: #ffc107; box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-outline-danger { color: #dc3545; background-color: transparent; background-image: none; border-color: #dc3545; } .btn-outline-danger:hover { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:focus, .btn-outline-danger.focus { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-outline-danger.disabled, .btn-outline-danger:disabled { color: #dc3545; background-color: transparent; } .btn-outline-danger:not([disabled]):not(.disabled):active, .btn-outline-danger:not([disabled]):not(.disabled).active, .show > .btn-outline-danger.dropdown-toggle { color: #fff; background-color: #dc3545; border-color: #dc3545; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-outline-light { color: #f8f9fa; background-color: transparent; background-image: none; border-color: #f8f9fa; } .btn-outline-light:hover { color: #212529; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:focus, .btn-outline-light.focus { box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #f8f9fa; background-color: transparent; } .btn-outline-light:not([disabled]):not(.disabled):active, .btn-outline-light:not([disabled]):not(.disabled).active, .show > .btn-outline-light.dropdown-toggle { color: #212529; background-color: #f8f9fa; border-color: #f8f9fa; box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-outline-dark { color: #343a40; background-color: transparent; background-image: none; border-color: #343a40; } .btn-outline-dark:hover { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:focus, .btn-outline-dark.focus { box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-outline-dark.disabled, .btn-outline-dark:disabled { color: #343a40; background-color: transparent; } .btn-outline-dark:not([disabled]):not(.disabled):active, .btn-outline-dark:not([disabled]):not(.disabled).active, .show > .btn-outline-dark.dropdown-toggle { color: #fff; background-color: #343a40; border-color: #343a40; box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-link { font-weight: 400; color: #007bff; background-color: transparent; } .btn-link:hover { color: #0056b3; text-decoration: underline; background-color: transparent; border-color: transparent; } .btn-link:focus, .btn-link.focus { border-color: transparent; box-shadow: none; } .btn-link:disabled, .btn-link.disabled { color: #868e96; } .btn-lg, .btn-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .btn-sm, .btn-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .btn-block { display: block; width: 100%; } .btn-block + .btn-block { margin-top: 0.5rem; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { opacity: 0; transition: opacity 0.15s linear; } .fade.show { opacity: 1; } .collapse { display: none; } .collapse.show { display: block; } tr.collapse.show { display: table-row; } tbody.collapse.show { display: table-row-group; } .collapsing { position: relative; height: 0; overflow: hidden; transition: height 0.35s ease; } .dropup, .dropdown { position: relative; } .dropdown-toggle::after { display: inline-block; width: 0; height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-right: 0.3em solid transparent; border-bottom: 0; border-left: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 10rem; padding: 0.5rem 0; margin: 0.125rem 0 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 0.25rem; } .dropup .dropdown-menu { margin-top: 0; margin-bottom: 0.125rem; } .dropup .dropdown-toggle::after { display: inline-block; width: 0; height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-right: 0.3em solid transparent; border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-divider { height: 0; margin: 0.5rem 0; overflow: hidden; border-top: 1px solid #e9ecef; } .dropdown-item { display: block; width: 100%; padding: 0.25rem 1.5rem; clear: both; font-weight: 400; color: #212529; text-align: inherit; white-space: nowrap; background: none; border: 0; } .dropdown-item:focus, .dropdown-item:hover { color: #16181b; text-decoration: none; background-color: #f8f9fa; } .dropdown-item.active, .dropdown-item:active { color: #fff; text-decoration: none; background-color: #007bff; } .dropdown-item.disabled, .dropdown-item:disabled { color: #868e96; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: 0.5rem 1.5rem; margin-bottom: 0; font-size: 0.875rem; color: #868e96; white-space: nowrap; } .btn-group, .btn-group-vertical { position: relative; display: -ms-inline-flexbox; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; -ms-flex: 0 1 auto; flex: 0 1 auto; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover { z-index: 2; } .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 2; } .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group, .btn-group-vertical .btn + .btn, .btn-group-vertical .btn + .btn-group, .btn-group-vertical .btn-group + .btn, .btn-group-vertical .btn-group + .btn-group { margin-left: -1px; } .btn-toolbar { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-pack: start; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { border-radius: 0; } .btn-group > .btn:first-child { margin-left: 0; } .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:last-child:not(:first-child), .btn-group > .dropdown-toggle:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group > .btn-group { float: left; } .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn + .dropdown-toggle-split { padding-right: 0.5625rem; padding-left: 0.5625rem; } .btn + .dropdown-toggle-split::after { margin-left: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-right: 0.375rem; padding-left: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-right: 0.75rem; padding-left: 0.75rem; } .btn-group-vertical { -ms-flex-direction: column; flex-direction: column; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: center; justify-content: center; } .btn-group-vertical .btn, .btn-group-vertical .btn-group { width: 100%; } .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { margin-top: -1px; margin-left: 0; } .btn-group-vertical > .btn:not(:first-child):not(:last-child) { border-radius: 0; } .btn-group-vertical > .btn:first-child:not(:last-child) { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:last-child:not(:first-child) { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { border-top-left-radius: 0; border-top-right-radius: 0; } [data-toggle="buttons"] > .btn input[type="radio"], [data-toggle="buttons"] > .btn input[type="checkbox"], [data-toggle="buttons"] > .btn-group > .btn input[type="radio"], [data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .input-group { position: relative; display: -ms-flexbox; display: flex; -ms-flex-align: stretch; align-items: stretch; width: 100%; } .input-group .form-control { position: relative; z-index: 2; -ms-flex: 1 1 auto; flex: 1 1 auto; width: 1%; margin-bottom: 0; } .input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover { z-index: 3; } .input-group-addon, .input-group-btn, .input-group .form-control { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; } .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child), .input-group .form-control:not(:first-child):not(:last-child) { border-radius: 0; } .input-group-addon, .input-group-btn { white-space: nowrap; } .input-group-addon { padding: 0.375rem 0.75rem; margin-bottom: 0; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; text-align: center; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.25rem; } .input-group-addon.form-control-sm, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .input-group-addon.btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.2rem; } .input-group-addon.form-control-lg, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .input-group-addon.btn { padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.3rem; } .input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] { margin-top: 0; } .input-group .form-control:not(:last-child), .input-group-addon:not(:last-child), .input-group-btn:not(:last-child) > .btn, .input-group-btn:not(:last-child) > .btn-group > .btn, .input-group-btn:not(:last-child) > .dropdown-toggle, .input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle), .input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group-addon:not(:last-child) { border-right: 0; } .input-group .form-control:not(:first-child), .input-group-addon:not(:first-child), .input-group-btn:not(:first-child) > .btn, .input-group-btn:not(:first-child) > .btn-group > .btn, .input-group-btn:not(:first-child) > .dropdown-toggle, .input-group-btn:not(:last-child) > .btn:not(:first-child), .input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .form-control + .input-group-addon:not(:first-child) { border-left: 0; } .input-group-btn { position: relative; -ms-flex-align: stretch; align-items: stretch; font-size: 0; white-space: nowrap; } .input-group-btn > .btn { position: relative; } .input-group-btn > .btn + .btn { margin-left: -1px; } .input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover { z-index: 3; } .input-group-btn:first-child > .btn + .btn { margin-left: 0; } .input-group-btn:not(:last-child) > .btn, .input-group-btn:not(:last-child) > .btn-group { margin-right: -1px; } .input-group-btn:not(:first-child) > .btn, .input-group-btn:not(:first-child) > .btn-group { z-index: 2; margin-left: 0; } .input-group-btn:not(:first-child) > .btn:first-child, .input-group-btn:not(:first-child) > .btn-group:first-child { margin-left: -1px; } .input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover, .input-group-btn:not(:first-child) > .btn-group:focus, .input-group-btn:not(:first-child) > .btn-group:active, .input-group-btn:not(:first-child) > .btn-group:hover { z-index: 3; } .custom-control { position: relative; display: -ms-inline-flexbox; display: inline-flex; min-height: 1.5rem; padding-left: 1.5rem; margin-right: 1rem; } .custom-control-input { position: absolute; z-index: -1; opacity: 0; } .custom-control-input:checked ~ .custom-control-indicator { color: #fff; background-color: #007bff; } .custom-control-input:focus ~ .custom-control-indicator { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input:active ~ .custom-control-indicator { color: #fff; background-color: #b3d7ff; } .custom-control-input:disabled ~ .custom-control-indicator { background-color: #e9ecef; } .custom-control-input:disabled ~ .custom-control-description { color: #868e96; } .custom-control-indicator { position: absolute; top: 0.25rem; left: 0; display: block; width: 1rem; height: 1rem; pointer-events: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: #ddd; background-repeat: no-repeat; background-position: center center; background-size: 50% 50%; } .custom-checkbox .custom-control-indicator { border-radius: 0.25rem; } .custom-checkbox .custom-control-input:checked ~ .custom-control-indicator { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator { background-color: #007bff; background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); } .custom-radio .custom-control-indicator { border-radius: 50%; } .custom-radio .custom-control-input:checked ~ .custom-control-indicator { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); } .custom-controls-stacked { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; } .custom-controls-stacked .custom-control { margin-bottom: 0.25rem; } .custom-controls-stacked .custom-control + .custom-control { margin-left: 0; } .custom-select { display: inline-block; max-width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 1.75rem 0.375rem 0.75rem; line-height: 1.5; color: #495057; vertical-align: middle; background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; background-size: 8px 10px; border: 1px solid #ced4da; border-radius: 0.25rem; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-select:focus { border-color: #80bdff; outline: none; } .custom-select:focus::-ms-value { color: #495057; background-color: #fff; } .custom-select[multiple] { height: auto; background-image: none; } .custom-select:disabled { color: #868e96; background-color: #e9ecef; } .custom-select::-ms-expand { opacity: 0; } .custom-select-sm { height: calc(1.8125rem + 2px); padding-top: 0.375rem; padding-bottom: 0.375rem; font-size: 75%; } .custom-file { position: relative; display: inline-block; max-width: 100%; height: calc(2.25rem + 2px); margin-bottom: 0; } .custom-file-input { min-width: 14rem; max-width: 100%; height: calc(2.25rem + 2px); margin: 0; opacity: 0; } .custom-file-input:focus ~ .custom-file-control { box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #007bff; } .custom-file-control { position: absolute; top: 0; right: 0; left: 0; z-index: 5; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; pointer-events: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; } .custom-file-control:lang(en):empty::after { content: "Choose file..."; } .custom-file-control::before { position: absolute; top: -1px; right: -1px; bottom: -1px; z-index: 6; display: block; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0 0.25rem 0.25rem 0; } .custom-file-control:lang(en)::before { content: "Browse"; } .nav { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: 0.5rem 1rem; } .nav-link:focus, .nav-link:hover { text-decoration: none; } .nav-link.disabled { color: #868e96; } .nav-tabs { border-bottom: 1px solid #ddd; } .nav-tabs .nav-item { margin-bottom: -1px; } .nav-tabs .nav-link { border: 1px solid transparent; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { border-color: #e9ecef #e9ecef #ddd; } .nav-tabs .nav-link.disabled { color: #868e96; background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: #495057; background-color: #fff; border-color: #ddd #ddd #fff; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .nav-pills .nav-link { border-radius: 0.25rem; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: #fff; background-color: #007bff; } .nav-fill .nav-item { -ms-flex: 1 1 auto; flex: 1 1 auto; text-align: center; } .nav-justified .nav-item { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; text-align: center; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { position: relative; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; padding: 0.5rem 1rem; } .navbar > .container, .navbar > .container-fluid { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; } .navbar-brand { display: inline-block; padding-top: 0.3125rem; padding-bottom: 0.3125rem; margin-right: 1rem; font-size: 1.25rem; line-height: inherit; white-space: nowrap; } .navbar-brand:focus, .navbar-brand:hover { text-decoration: none; } .navbar-nav { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; list-style: none; } .navbar-nav .nav-link { padding-right: 0; padding-left: 0; } .navbar-nav .dropdown-menu { position: static; float: none; } .navbar-text { display: inline-block; padding-top: 0.5rem; padding-bottom: 0.5rem; } .navbar-collapse { -ms-flex-preferred-size: 100%; flex-basis: 100%; -ms-flex-positive: 1; flex-grow: 1; -ms-flex-align: center; align-items: center; } .navbar-toggler { padding: 0.25rem 0.75rem; font-size: 1.25rem; line-height: 1; background: transparent; border: 1px solid transparent; border-radius: 0.25rem; } .navbar-toggler:focus, .navbar-toggler:hover { text-decoration: none; } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; content: ""; background: no-repeat center center; background-size: 100% 100%; } @media (max-width: 575px) { .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 576px) { .navbar-expand-sm { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-sm .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-sm .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } .navbar-expand-sm .dropup .dropdown-menu { top: auto; bottom: 100%; } } @media (max-width: 767px) { .navbar-expand-md > .container, .navbar-expand-md > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 768px) { .navbar-expand-md { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-md .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-md .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-md > .container, .navbar-expand-md > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-md .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } .navbar-expand-md .dropup .dropdown-menu { top: auto; bottom: 100%; } } @media (max-width: 991px) { .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 992px) { .navbar-expand-lg { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-lg .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-lg .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } .navbar-expand-lg .dropup .dropdown-menu { top: auto; bottom: 100%; } } @media (max-width: 1199px) { .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 1200px) { .navbar-expand-xl { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-xl .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-xl .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } .navbar-expand-xl .dropup .dropdown-menu { top: auto; bottom: 100%; } } .navbar-expand { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand > .container, .navbar-expand > .container-fluid { padding-right: 0; padding-left: 0; } .navbar-expand .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand > .container, .navbar-expand > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-expand .dropup .dropdown-menu { top: auto; bottom: 100%; } .navbar-light .navbar-brand { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-nav .nav-link { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { color: rgba(0, 0, 0, 0.7); } .navbar-light .navbar-nav .nav-link.disabled { color: rgba(0, 0, 0, 0.3); } .navbar-light .navbar-nav .show > .nav-link, .navbar-light .navbar-nav .active > .nav-link, .navbar-light .navbar-nav .nav-link.show, .navbar-light .navbar-nav .nav-link.active { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-toggler { color: rgba(0, 0, 0, 0.5); border-color: rgba(0, 0, 0, 0.1); } .navbar-light .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-light .navbar-text { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-text a { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-text a:focus, .navbar-light .navbar-text a:hover { color: rgba(0, 0, 0, 0.9); } .navbar-dark .navbar-brand { color: #fff; } .navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { color: #fff; } .navbar-dark .navbar-nav .nav-link { color: rgba(255, 255, 255, 0.5); } .navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-nav .nav-link.disabled { color: rgba(255, 255, 255, 0.25); } .navbar-dark .navbar-nav .show > .nav-link, .navbar-dark .navbar-nav .active > .nav-link, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .nav-link.active { color: #fff; } .navbar-dark .navbar-toggler { color: rgba(255, 255, 255, 0.5); border-color: rgba(255, 255, 255, 0.1); } .navbar-dark .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-dark .navbar-text { color: rgba(255, 255, 255, 0.5); } .navbar-dark .navbar-text a { color: #fff; } .navbar-dark .navbar-text a:focus, .navbar-dark .navbar-text a:hover { color: #fff; } .card { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; min-width: 0; word-wrap: break-word; background-color: #fff; background-clip: border-box; border: 1px solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; } .card > hr { margin-right: 0; margin-left: 0; } .card > .list-group:first-child .list-group-item:first-child { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .card > .list-group:last-child .list-group-item:last-child { border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .card-body { -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 1.25rem; } .card-title { margin-bottom: 0.75rem; } .card-subtitle { margin-top: -0.375rem; margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link:hover { text-decoration: none; } .card-link + .card-link { margin-left: 1.25rem; } .card-header { padding: 0.75rem 1.25rem; margin-bottom: 0; background-color: rgba(0, 0, 0, 0.03); border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .card-header:first-child { border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; } .card-header + .list-group .list-group-item:first-child { border-top: 0; } .card-footer { padding: 0.75rem 1.25rem; background-color: rgba(0, 0, 0, 0.03); border-top: 1px solid rgba(0, 0, 0, 0.125); } .card-footer:last-child { border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); } .card-header-tabs { margin-right: -0.625rem; margin-bottom: -0.75rem; margin-left: -0.625rem; border-bottom: 0; } .card-header-pills { margin-right: -0.625rem; margin-left: -0.625rem; } .card-img-overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; padding: 1.25rem; } .card-img { width: 100%; border-radius: calc(0.25rem - 1px); } .card-img-top { width: 100%; border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .card-img-bottom { width: 100%; border-bottom-right-radius: calc(0.25rem - 1px); border-bottom-left-radius: calc(0.25rem - 1px); } .card-deck { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; } .card-deck .card { margin-bottom: 15px; } @media (min-width: 576px) { .card-deck { -ms-flex-flow: row wrap; flex-flow: row wrap; margin-right: -15px; margin-left: -15px; } .card-deck .card { display: -ms-flexbox; display: flex; -ms-flex: 1 0 0%; flex: 1 0 0%; -ms-flex-direction: column; flex-direction: column; margin-right: 15px; margin-bottom: 0; margin-left: 15px; } } .card-group { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; } .card-group .card { margin-bottom: 15px; } @media (min-width: 576px) { .card-group { -ms-flex-flow: row wrap; flex-flow: row wrap; } .card-group .card { -ms-flex: 1 0 0%; flex: 1 0 0%; margin-bottom: 0; } .card-group .card + .card { margin-left: 0; border-left: 0; } .card-group .card:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group .card:first-child .card-img-top { border-top-right-radius: 0; } .card-group .card:first-child .card-img-bottom { border-bottom-right-radius: 0; } .card-group .card:last-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group .card:last-child .card-img-top { border-top-left-radius: 0; } .card-group .card:last-child .card-img-bottom { border-bottom-left-radius: 0; } .card-group .card:only-child { border-radius: 0.25rem; } .card-group .card:only-child .card-img-top { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .card-group .card:only-child .card-img-bottom { border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .card-group .card:not(:first-child):not(:last-child):not(:only-child) { border-radius: 0; } .card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top, .card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom { border-radius: 0; } } .card-columns .card { margin-bottom: 0.75rem; } @media (min-width: 576px) { .card-columns { -webkit-column-count: 3; column-count: 3; -webkit-column-gap: 1.25rem; column-gap: 1.25rem; } .card-columns .card { display: inline-block; width: 100%; } } .breadcrumb { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 0.75rem 1rem; margin-bottom: 1rem; list-style: none; background-color: #e9ecef; border-radius: 0.25rem; } .breadcrumb-item + .breadcrumb-item::before { display: inline-block; padding-right: 0.5rem; padding-left: 0.5rem; color: #868e96; content: "/"; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: underline; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: none; } .breadcrumb-item.active { color: #868e96; } .pagination { display: -ms-flexbox; display: flex; padding-left: 0; list-style: none; border-radius: 0.25rem; } .page-item:first-child .page-link { margin-left: 0; border-top-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .page-item:last-child .page-link { border-top-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } .page-item.active .page-link { z-index: 2; color: #fff; background-color: #007bff; border-color: #007bff; } .page-item.disabled .page-link { color: #868e96; pointer-events: none; background-color: #fff; border-color: #ddd; } .page-link { position: relative; display: block; padding: 0.5rem 0.75rem; margin-left: -1px; line-height: 1.25; color: #007bff; background-color: #fff; border: 1px solid #ddd; } .page-link:focus, .page-link:hover { color: #0056b3; text-decoration: none; background-color: #e9ecef; border-color: #ddd; } .pagination-lg .page-link { padding: 0.75rem 1.5rem; font-size: 1.25rem; line-height: 1.5; } .pagination-lg .page-item:first-child .page-link { border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } .pagination-lg .page-item:last-child .page-link { border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; } .pagination-sm .page-link { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; } .pagination-sm .page-item:first-child .page-link { border-top-left-radius: 0.2rem; border-bottom-left-radius: 0.2rem; } .pagination-sm .page-item:last-child .page-link { border-top-right-radius: 0.2rem; border-bottom-right-radius: 0.2rem; } .badge { display: inline-block; padding: 0.25em 0.4em; font-size: 75%; font-weight: 700; line-height: 1; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .badge-pill { padding-right: 0.6em; padding-left: 0.6em; border-radius: 10rem; } .badge-primary { color: #fff; background-color: #007bff; } .badge-primary[href]:focus, .badge-primary[href]:hover { color: #fff; text-decoration: none; background-color: #0062cc; } .badge-secondary { color: #fff; background-color: #868e96; } .badge-secondary[href]:focus, .badge-secondary[href]:hover { color: #fff; text-decoration: none; background-color: #6c757d; } .badge-success { color: #fff; background-color: #28a745; } .badge-success[href]:focus, .badge-success[href]:hover { color: #fff; text-decoration: none; background-color: #1e7e34; } .badge-info { color: #fff; background-color: #17a2b8; } .badge-info[href]:focus, .badge-info[href]:hover { color: #fff; text-decoration: none; background-color: #117a8b; } .badge-warning { color: #111; background-color: #ffc107; } .badge-warning[href]:focus, .badge-warning[href]:hover { color: #111; text-decoration: none; background-color: #d39e00; } .badge-danger { color: #fff; background-color: #dc3545; } .badge-danger[href]:focus, .badge-danger[href]:hover { color: #fff; text-decoration: none; background-color: #bd2130; } .badge-light { color: #111; background-color: #f8f9fa; } .badge-light[href]:focus, .badge-light[href]:hover { color: #111; text-decoration: none; background-color: #dae0e5; } .badge-dark { color: #fff; background-color: #343a40; } .badge-dark[href]:focus, .badge-dark[href]:hover { color: #fff; text-decoration: none; background-color: #1d2124; } .jumbotron { padding: 2rem 1rem; margin-bottom: 2rem; background-color: #e9ecef; border-radius: 0.3rem; } @media (min-width: 576px) { .jumbotron { padding: 4rem 2rem; } } .jumbotron-fluid { padding-right: 0; padding-left: 0; border-radius: 0; } .alert { position: relative; padding: 0.75rem 1.25rem; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 0.25rem; } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible .close { position: absolute; top: 0; right: 0; padding: 0.75rem 1.25rem; color: inherit; } .alert-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-primary hr { border-top-color: #9fcdff; } .alert-primary .alert-link { color: #002752; } .alert-secondary { color: #464a4e; background-color: #e7e8ea; border-color: #dddfe2; } .alert-secondary hr { border-top-color: #cfd2d6; } .alert-secondary .alert-link { color: #2e3133; } .alert-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-success hr { border-top-color: #b1dfbb; } .alert-success .alert-link { color: #0b2e13; } .alert-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-info hr { border-top-color: #abdde5; } .alert-info .alert-link { color: #062c33; } .alert-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-warning hr { border-top-color: #ffe8a1; } .alert-warning .alert-link { color: #533f03; } .alert-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-danger hr { border-top-color: #f1b0b7; } .alert-danger .alert-link { color: #491217; } .alert-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-light hr { border-top-color: #ececf6; } .alert-light .alert-link { color: #686868; } .alert-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-dark hr { border-top-color: #b9bbbe; } .alert-dark .alert-link { color: #040505; } @-webkit-keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } .progress { display: -ms-flexbox; display: flex; height: 1rem; overflow: hidden; font-size: 0.75rem; background-color: #e9ecef; border-radius: 0.25rem; } .progress-bar { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; color: #fff; background-color: #007bff; } .progress-bar-striped { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: 1rem 1rem; } .progress-bar-animated { -webkit-animation: progress-bar-stripes 1s linear infinite; animation: progress-bar-stripes 1s linear infinite; } .media { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; } .media-body { -ms-flex: 1; flex: 1; } .list-group { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; } .list-group-item-action { width: 100%; color: #495057; text-align: inherit; } .list-group-item-action:focus, .list-group-item-action:hover { color: #495057; text-decoration: none; background-color: #f8f9fa; } .list-group-item-action:active { color: #212529; background-color: #e9ecef; } .list-group-item { position: relative; display: block; padding: 0.75rem 1.25rem; margin-bottom: -1px; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); } .list-group-item:first-child { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .list-group-item:last-child { margin-bottom: 0; border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .list-group-item:focus, .list-group-item:hover { text-decoration: none; } .list-group-item.disabled, .list-group-item:disabled { color: #868e96; background-color: #fff; } .list-group-item.active { z-index: 2; color: #fff; background-color: #007bff; border-color: #007bff; } .list-group-flush .list-group-item { border-right: 0; border-left: 0; border-radius: 0; } .list-group-flush:first-child .list-group-item:first-child { border-top: 0; } .list-group-flush:last-child .list-group-item:last-child { border-bottom: 0; } .list-group-item-primary { color: #004085; background-color: #b8daff; } a.list-group-item-primary, button.list-group-item-primary { color: #004085; } a.list-group-item-primary:focus, a.list-group-item-primary:hover, button.list-group-item-primary:focus, button.list-group-item-primary:hover { color: #004085; background-color: #9fcdff; } a.list-group-item-primary.active, button.list-group-item-primary.active { color: #fff; background-color: #004085; border-color: #004085; } .list-group-item-secondary { color: #464a4e; background-color: #dddfe2; } a.list-group-item-secondary, button.list-group-item-secondary { color: #464a4e; } a.list-group-item-secondary:focus, a.list-group-item-secondary:hover, button.list-group-item-secondary:focus, button.list-group-item-secondary:hover { color: #464a4e; background-color: #cfd2d6; } a.list-group-item-secondary.active, button.list-group-item-secondary.active { color: #fff; background-color: #464a4e; border-color: #464a4e; } .list-group-item-success { color: #155724; background-color: #c3e6cb; } a.list-group-item-success, button.list-group-item-success { color: #155724; } a.list-group-item-success:focus, a.list-group-item-success:hover, button.list-group-item-success:focus, button.list-group-item-success:hover { color: #155724; background-color: #b1dfbb; } a.list-group-item-success.active, button.list-group-item-success.active { color: #fff; background-color: #155724; border-color: #155724; } .list-group-item-info { color: #0c5460; background-color: #bee5eb; } a.list-group-item-info, button.list-group-item-info { color: #0c5460; } a.list-group-item-info:focus, a.list-group-item-info:hover, button.list-group-item-info:focus, button.list-group-item-info:hover { color: #0c5460; background-color: #abdde5; } a.list-group-item-info.active, button.list-group-item-info.active { color: #fff; background-color: #0c5460; border-color: #0c5460; } .list-group-item-warning { color: #856404; background-color: #ffeeba; } a.list-group-item-warning, button.list-group-item-warning { color: #856404; } a.list-group-item-warning:focus, a.list-group-item-warning:hover, button.list-group-item-warning:focus, button.list-group-item-warning:hover { color: #856404; background-color: #ffe8a1; } a.list-group-item-warning.active, button.list-group-item-warning.active { color: #fff; background-color: #856404; border-color: #856404; } .list-group-item-danger { color: #721c24; background-color: #f5c6cb; } a.list-group-item-danger, button.list-group-item-danger { color: #721c24; } a.list-group-item-danger:focus, a.list-group-item-danger:hover, button.list-group-item-danger:focus, button.list-group-item-danger:hover { color: #721c24; background-color: #f1b0b7; } a.list-group-item-danger.active, button.list-group-item-danger.active { color: #fff; background-color: #721c24; border-color: #721c24; } .list-group-item-light { color: #818182; background-color: #fdfdfe; } a.list-group-item-light, button.list-group-item-light { color: #818182; } a.list-group-item-light:focus, a.list-group-item-light:hover, button.list-group-item-light:focus, button.list-group-item-light:hover { color: #818182; background-color: #ececf6; } a.list-group-item-light.active, button.list-group-item-light.active { color: #fff; background-color: #818182; border-color: #818182; } .list-group-item-dark { color: #1b1e21; background-color: #c6c8ca; } a.list-group-item-dark, button.list-group-item-dark { color: #1b1e21; } a.list-group-item-dark:focus, a.list-group-item-dark:hover, button.list-group-item-dark:focus, button.list-group-item-dark:hover { color: #1b1e21; background-color: #b9bbbe; } a.list-group-item-dark.active, button.list-group-item-dark.active { color: #fff; background-color: #1b1e21; border-color: #1b1e21; } .close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:focus, .close:hover { color: #000; text-decoration: none; opacity: .75; } button.close { padding: 0; background: transparent; border: 0; -webkit-appearance: none; } .modal-open { overflow: hidden; } .modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1050; display: none; overflow: hidden; outline: 0; } .modal.fade .modal-dialog { transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; -webkit-transform: translate(0, -25%); transform: translate(0, -25%); } .modal.show .modal-dialog { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .modal-open .modal { overflow-x: hidden; overflow-y: auto; } .modal-dialog { position: relative; width: auto; margin: 10px; pointer-events: none; } .modal-content { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; pointer-events: auto; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; outline: 0; } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: 0.5; } .modal-header { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: justify; justify-content: space-between; padding: 15px; border-bottom: 1px solid #e9ecef; border-top-left-radius: 0.3rem; border-top-right-radius: 0.3rem; } .modal-header .close { padding: 15px; margin: -15px -15px -15px auto; } .modal-title { margin-bottom: 0; line-height: 1.5; } .modal-body { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 15px; } .modal-footer { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: end; justify-content: flex-end; padding: 15px; border-top: 1px solid #e9ecef; } .modal-footer > :not(:first-child) { margin-left: .25rem; } .modal-footer > :not(:last-child) { margin-right: .25rem; } .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } @media (min-width: 576px) { .modal-dialog { max-width: 500px; margin: 30px auto; } .modal-sm { max-width: 300px; } } @media (min-width: 992px) { .modal-lg { max-width: 800px; } } .tooltip { position: absolute; z-index: 1070; display: block; margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: 0.9; } .tooltip .arrow { position: absolute; display: block; width: 5px; height: 5px; } .tooltip .arrow::before { position: absolute; border-color: transparent; border-style: solid; } .tooltip.bs-tooltip-top, .tooltip.bs-tooltip-auto[x-placement^="top"] { padding: 5px 0; } .tooltip.bs-tooltip-top .arrow, .tooltip.bs-tooltip-auto[x-placement^="top"] .arrow { bottom: 0; } .tooltip.bs-tooltip-top .arrow::before, .tooltip.bs-tooltip-auto[x-placement^="top"] .arrow::before { margin-left: -3px; content: ""; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.bs-tooltip-right, .tooltip.bs-tooltip-auto[x-placement^="right"] { padding: 0 5px; } .tooltip.bs-tooltip-right .arrow, .tooltip.bs-tooltip-auto[x-placement^="right"] .arrow { left: 0; } .tooltip.bs-tooltip-right .arrow::before, .tooltip.bs-tooltip-auto[x-placement^="right"] .arrow::before { margin-top: -3px; content: ""; border-width: 5px 5px 5px 0; border-right-color: #000; } .tooltip.bs-tooltip-bottom, .tooltip.bs-tooltip-auto[x-placement^="bottom"] { padding: 5px 0; } .tooltip.bs-tooltip-bottom .arrow, .tooltip.bs-tooltip-auto[x-placement^="bottom"] .arrow { top: 0; } .tooltip.bs-tooltip-bottom .arrow::before, .tooltip.bs-tooltip-auto[x-placement^="bottom"] .arrow::before { margin-left: -3px; content: ""; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bs-tooltip-left, .tooltip.bs-tooltip-auto[x-placement^="left"] { padding: 0 5px; } .tooltip.bs-tooltip-left .arrow, .tooltip.bs-tooltip-auto[x-placement^="left"] .arrow { right: 0; } .tooltip.bs-tooltip-left .arrow::before, .tooltip.bs-tooltip-auto[x-placement^="left"] .arrow::before { right: 0; margin-top: -3px; content: ""; border-width: 5px 0 5px 5px; border-left-color: #000; } .tooltip-inner { max-width: 200px; padding: 3px 8px; color: #fff; text-align: center; background-color: #000; border-radius: 0.25rem; } .popover { position: absolute; top: 0; left: 0; z-index: 1060; display: block; max-width: 276px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; } .popover .arrow { position: absolute; display: block; width: 0.8rem; height: 0.4rem; } .popover .arrow::before, .popover .arrow::after { position: absolute; display: block; border-color: transparent; border-style: solid; } .popover .arrow::before { content: ""; border-width: 0.8rem; } .popover .arrow::after { content: ""; border-width: 0.8rem; } .popover.bs-popover-top, .popover.bs-popover-auto[x-placement^="top"] { margin-bottom: 0.8rem; } .popover.bs-popover-top .arrow, .popover.bs-popover-auto[x-placement^="top"] .arrow { bottom: 0; } .popover.bs-popover-top .arrow::before, .popover.bs-popover-auto[x-placement^="top"] .arrow::before, .popover.bs-popover-top .arrow::after, .popover.bs-popover-auto[x-placement^="top"] .arrow::after { border-bottom-width: 0; } .popover.bs-popover-top .arrow::before, .popover.bs-popover-auto[x-placement^="top"] .arrow::before { bottom: -0.8rem; margin-left: -0.8rem; border-top-color: rgba(0, 0, 0, 0.25); } .popover.bs-popover-top .arrow::after, .popover.bs-popover-auto[x-placement^="top"] .arrow::after { bottom: calc((0.8rem - 1px) * -1); margin-left: -0.8rem; border-top-color: #fff; } .popover.bs-popover-right, .popover.bs-popover-auto[x-placement^="right"] { margin-left: 0.8rem; } .popover.bs-popover-right .arrow, .popover.bs-popover-auto[x-placement^="right"] .arrow { left: 0; } .popover.bs-popover-right .arrow::before, .popover.bs-popover-auto[x-placement^="right"] .arrow::before, .popover.bs-popover-right .arrow::after, .popover.bs-popover-auto[x-placement^="right"] .arrow::after { margin-top: -0.8rem; border-left-width: 0; } .popover.bs-popover-right .arrow::before, .popover.bs-popover-auto[x-placement^="right"] .arrow::before { left: -0.8rem; border-right-color: rgba(0, 0, 0, 0.25); } .popover.bs-popover-right .arrow::after, .popover.bs-popover-auto[x-placement^="right"] .arrow::after { left: calc((0.8rem - 1px) * -1); border-right-color: #fff; } .popover.bs-popover-bottom, .popover.bs-popover-auto[x-placement^="bottom"] { margin-top: 0.8rem; } .popover.bs-popover-bottom .arrow, .popover.bs-popover-auto[x-placement^="bottom"] .arrow { top: 0; } .popover.bs-popover-bottom .arrow::before, .popover.bs-popover-auto[x-placement^="bottom"] .arrow::before, .popover.bs-popover-bottom .arrow::after, .popover.bs-popover-auto[x-placement^="bottom"] .arrow::after { margin-left: -0.8rem; border-top-width: 0; } .popover.bs-popover-bottom .arrow::before, .popover.bs-popover-auto[x-placement^="bottom"] .arrow::before { top: -0.8rem; border-bottom-color: rgba(0, 0, 0, 0.25); } .popover.bs-popover-bottom .arrow::after, .popover.bs-popover-auto[x-placement^="bottom"] .arrow::after { top: calc((0.8rem - 1px) * -1); border-bottom-color: #fff; } .popover.bs-popover-bottom .popover-header::before, .popover.bs-popover-auto[x-placement^="bottom"] .popover-header::before { position: absolute; top: 0; left: 50%; display: block; width: 20px; margin-left: -10px; content: ""; border-bottom: 1px solid #f7f7f7; } .popover.bs-popover-left, .popover.bs-popover-auto[x-placement^="left"] { margin-right: 0.8rem; } .popover.bs-popover-left .arrow, .popover.bs-popover-auto[x-placement^="left"] .arrow { right: 0; } .popover.bs-popover-left .arrow::before, .popover.bs-popover-auto[x-placement^="left"] .arrow::before, .popover.bs-popover-left .arrow::after, .popover.bs-popover-auto[x-placement^="left"] .arrow::after { margin-top: -0.8rem; border-right-width: 0; } .popover.bs-popover-left .arrow::before, .popover.bs-popover-auto[x-placement^="left"] .arrow::before { right: -0.8rem; border-left-color: rgba(0, 0, 0, 0.25); } .popover.bs-popover-left .arrow::after, .popover.bs-popover-auto[x-placement^="left"] .arrow::after { right: calc((0.8rem - 1px) * -1); border-left-color: #fff; } .popover-header { padding: 0.5rem 0.75rem; margin-bottom: 0; font-size: 1rem; color: inherit; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .popover-header:empty { display: none; } .popover-body { padding: 0.5rem 0.75rem; color: #212529; } .carousel { position: relative; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-item { position: relative; display: none; -ms-flex-align: center; align-items: center; width: 100%; transition: -webkit-transform 0.6s ease; transition: transform 0.6s ease; transition: transform 0.6s ease, -webkit-transform 0.6s ease; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next, .carousel-item-prev { position: absolute; top: 0; } .carousel-item-next.carousel-item-left, .carousel-item-prev.carousel-item-right { -webkit-transform: translateX(0); transform: translateX(0); } @supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { .carousel-item-next.carousel-item-left, .carousel-item-prev.carousel-item-right { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .carousel-item-next, .active.carousel-item-right { -webkit-transform: translateX(100%); transform: translateX(100%); } @supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { .carousel-item-next, .active.carousel-item-right { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); } } .carousel-item-prev, .active.carousel-item-left { -webkit-transform: translateX(-100%); transform: translateX(-100%); } @supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { .carousel-item-prev, .active.carousel-item-left { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: 15%; color: #fff; text-align: center; opacity: 0.5; } .carousel-control-prev:focus, .carousel-control-prev:hover, .carousel-control-next:focus, .carousel-control-next:hover { color: #fff; text-decoration: none; outline: 0; opacity: .9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 20px; height: 20px; background: transparent no-repeat center center; background-size: 100% 100%; } .carousel-control-prev-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); } .carousel-indicators { position: absolute; right: 0; bottom: 10px; left: 0; z-index: 15; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; padding-left: 0; margin-right: 15%; margin-left: 15%; list-style: none; } .carousel-indicators li { position: relative; -ms-flex: 0 1 auto; flex: 0 1 auto; width: 30px; height: 3px; margin-right: 3px; margin-left: 3px; text-indent: -999px; background-color: rgba(255, 255, 255, 0.5); } .carousel-indicators li::before { position: absolute; top: -10px; left: 0; display: inline-block; width: 100%; height: 10px; content: ""; } .carousel-indicators li::after { position: absolute; bottom: -10px; left: 0; display: inline-block; width: 100%; height: 10px; content: ""; } .carousel-indicators .active { background-color: #fff; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .bg-primary { background-color: #007bff !important; } a.bg-primary:focus, a.bg-primary:hover { background-color: #0062cc !important; } .bg-secondary { background-color: #868e96 !important; } a.bg-secondary:focus, a.bg-secondary:hover { background-color: #6c757d !important; } .bg-success { background-color: #28a745 !important; } a.bg-success:focus, a.bg-success:hover { background-color: #1e7e34 !important; } .bg-info { background-color: #17a2b8 !important; } a.bg-info:focus, a.bg-info:hover { background-color: #117a8b !important; } .bg-warning { background-color: #ffc107 !important; } a.bg-warning:focus, a.bg-warning:hover { background-color: #d39e00 !important; } .bg-danger { background-color: #dc3545 !important; } a.bg-danger:focus, a.bg-danger:hover { background-color: #bd2130 !important; } .bg-light { background-color: #f8f9fa !important; } a.bg-light:focus, a.bg-light:hover { background-color: #dae0e5 !important; } .bg-dark { background-color: #343a40 !important; } a.bg-dark:focus, a.bg-dark:hover { background-color: #1d2124 !important; } .bg-white { background-color: #fff !important; } .bg-transparent { background-color: transparent !important; } .border { border: 1px solid #e9ecef !important; } .border-0 { border: 0 !important; } .border-top-0 { border-top: 0 !important; } .border-right-0 { border-right: 0 !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-left-0 { border-left: 0 !important; } .border-primary { border-color: #007bff !important; } .border-secondary { border-color: #868e96 !important; } .border-success { border-color: #28a745 !important; } .border-info { border-color: #17a2b8 !important; } .border-warning { border-color: #ffc107 !important; } .border-danger { border-color: #dc3545 !important; } .border-light { border-color: #f8f9fa !important; } .border-dark { border-color: #343a40 !important; } .border-white { border-color: #fff !important; } .rounded { border-radius: 0.25rem !important; } .rounded-top { border-top-left-radius: 0.25rem !important; border-top-right-radius: 0.25rem !important; } .rounded-right { border-top-right-radius: 0.25rem !important; border-bottom-right-radius: 0.25rem !important; } .rounded-bottom { border-bottom-right-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-left { border-top-left-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-circle { border-radius: 50% !important; } .rounded-0 { border-radius: 0 !important; } .clearfix::after { display: block; clear: both; content: ""; } .d-none { display: none !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: -ms-flexbox !important; display: flex !important; } .d-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } @media (min-width: 576px) { .d-sm-none { display: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: -ms-flexbox !important; display: flex !important; } .d-sm-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 768px) { .d-md-none { display: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: -ms-flexbox !important; display: flex !important; } .d-md-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 992px) { .d-lg-none { display: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: -ms-flexbox !important; display: flex !important; } .d-lg-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 1200px) { .d-xl-none { display: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: -ms-flexbox !important; display: flex !important; } .d-xl-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } .d-print-block { display: none !important; } @media print { .d-print-block { display: block !important; } } .d-print-inline { display: none !important; } @media print { .d-print-inline { display: inline !important; } } .d-print-inline-block { display: none !important; } @media print { .d-print-inline-block { display: inline-block !important; } } @media print { .d-print-none { display: none !important; } } .embed-responsive { position: relative; display: block; width: 100%; padding: 0; overflow: hidden; } .embed-responsive::before { display: block; content: ""; } .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, .embed-responsive object, .embed-responsive video { position: absolute; top: 0; bottom: 0; left: 0; width: 100%; height: 100%; border: 0; } .embed-responsive-21by9::before { padding-top: 42.857143%; } .embed-responsive-16by9::before { padding-top: 56.25%; } .embed-responsive-4by3::before { padding-top: 75%; } .embed-responsive-1by1::before { padding-top: 100%; } .flex-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } @media (min-width: 576px) { .flex-sm-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-sm-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-sm-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-sm-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-sm-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-sm-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-sm-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-sm-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-sm-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-sm-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-sm-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-sm-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-sm-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-sm-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-sm-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-sm-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-sm-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-sm-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-sm-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-sm-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-sm-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-sm-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-sm-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-sm-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-sm-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-sm-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-sm-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-sm-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 768px) { .flex-md-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-md-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-md-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-md-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-md-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-md-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-md-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-md-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-md-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-md-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-md-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-md-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-md-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-md-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-md-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-md-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-md-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-md-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-md-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-md-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-md-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-md-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-md-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-md-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-md-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-md-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-md-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-md-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-md-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 992px) { .flex-lg-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-lg-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-lg-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-lg-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-lg-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-lg-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-lg-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-lg-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-lg-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-lg-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-lg-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-lg-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-lg-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-lg-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-lg-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-lg-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-lg-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-lg-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-lg-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-lg-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-lg-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-lg-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-lg-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-lg-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-lg-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-lg-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-lg-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-lg-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 1200px) { .flex-xl-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-xl-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-xl-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-xl-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-xl-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-xl-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-xl-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-xl-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-xl-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-xl-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-xl-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-xl-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-xl-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-xl-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-xl-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-xl-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-xl-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-xl-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-xl-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-xl-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-xl-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-xl-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-xl-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-xl-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-xl-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-xl-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-xl-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-xl-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } .float-left { float: left !important; } .float-right { float: right !important; } .float-none { float: none !important; } @media (min-width: 576px) { .float-sm-left { float: left !important; } .float-sm-right { float: right !important; } .float-sm-none { float: none !important; } } @media (min-width: 768px) { .float-md-left { float: left !important; } .float-md-right { float: right !important; } .float-md-none { float: none !important; } } @media (min-width: 992px) { .float-lg-left { float: left !important; } .float-lg-right { float: right !important; } .float-lg-none { float: none !important; } } @media (min-width: 1200px) { .float-xl-left { float: left !important; } .float-xl-right { float: right !important; } .float-xl-none { float: none !important; } } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } @supports ((position: -webkit-sticky) or (position: sticky)) { .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; -webkit-clip-path: inset(50%); clip-path: inset(50%); border: 0; } .sr-only-focusable:active, .sr-only-focusable:focus { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; -webkit-clip-path: none; clip-path: none; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .mw-100 { max-width: 100% !important; } .mh-100 { max-height: 100% !important; } .m-0 { margin: 0 !important; } .mt-0, .my-0 { margin-top: 0 !important; } .mr-0, .mx-0 { margin-right: 0 !important; } .mb-0, .my-0 { margin-bottom: 0 !important; } .ml-0, .mx-0 { margin-left: 0 !important; } .m-1 { margin: 0.25rem !important; } .mt-1, .my-1 { margin-top: 0.25rem !important; } .mr-1, .mx-1 { margin-right: 0.25rem !important; } .mb-1, .my-1 { margin-bottom: 0.25rem !important; } .ml-1, .mx-1 { margin-left: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .mt-2, .my-2 { margin-top: 0.5rem !important; } .mr-2, .mx-2 { margin-right: 0.5rem !important; } .mb-2, .my-2 { margin-bottom: 0.5rem !important; } .ml-2, .mx-2 { margin-left: 0.5rem !important; } .m-3 { margin: 1rem !important; } .mt-3, .my-3 { margin-top: 1rem !important; } .mr-3, .mx-3 { margin-right: 1rem !important; } .mb-3, .my-3 { margin-bottom: 1rem !important; } .ml-3, .mx-3 { margin-left: 1rem !important; } .m-4 { margin: 1.5rem !important; } .mt-4, .my-4 { margin-top: 1.5rem !important; } .mr-4, .mx-4 { margin-right: 1.5rem !important; } .mb-4, .my-4 { margin-bottom: 1.5rem !important; } .ml-4, .mx-4 { margin-left: 1.5rem !important; } .m-5 { margin: 3rem !important; } .mt-5, .my-5 { margin-top: 3rem !important; } .mr-5, .mx-5 { margin-right: 3rem !important; } .mb-5, .my-5 { margin-bottom: 3rem !important; } .ml-5, .mx-5 { margin-left: 3rem !important; } .p-0 { padding: 0 !important; } .pt-0, .py-0 { padding-top: 0 !important; } .pr-0, .px-0 { padding-right: 0 !important; } .pb-0, .py-0 { padding-bottom: 0 !important; } .pl-0, .px-0 { padding-left: 0 !important; } .p-1 { padding: 0.25rem !important; } .pt-1, .py-1 { padding-top: 0.25rem !important; } .pr-1, .px-1 { padding-right: 0.25rem !important; } .pb-1, .py-1 { padding-bottom: 0.25rem !important; } .pl-1, .px-1 { padding-left: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .pt-2, .py-2 { padding-top: 0.5rem !important; } .pr-2, .px-2 { padding-right: 0.5rem !important; } .pb-2, .py-2 { padding-bottom: 0.5rem !important; } .pl-2, .px-2 { padding-left: 0.5rem !important; } .p-3 { padding: 1rem !important; } .pt-3, .py-3 { padding-top: 1rem !important; } .pr-3, .px-3 { padding-right: 1rem !important; } .pb-3, .py-3 { padding-bottom: 1rem !important; } .pl-3, .px-3 { padding-left: 1rem !important; } .p-4 { padding: 1.5rem !important; } .pt-4, .py-4 { padding-top: 1.5rem !important; } .pr-4, .px-4 { padding-right: 1.5rem !important; } .pb-4, .py-4 { padding-bottom: 1.5rem !important; } .pl-4, .px-4 { padding-left: 1.5rem !important; } .p-5 { padding: 3rem !important; } .pt-5, .py-5 { padding-top: 3rem !important; } .pr-5, .px-5 { padding-right: 3rem !important; } .pb-5, .py-5 { padding-bottom: 3rem !important; } .pl-5, .px-5 { padding-left: 3rem !important; } .m-auto { margin: auto !important; } .mt-auto, .my-auto { margin-top: auto !important; } .mr-auto, .mx-auto { margin-right: auto !important; } .mb-auto, .my-auto { margin-bottom: auto !important; } .ml-auto, .mx-auto { margin-left: auto !important; } @media (min-width: 576px) { .m-sm-0 { margin: 0 !important; } .mt-sm-0, .my-sm-0 { margin-top: 0 !important; } .mr-sm-0, .mx-sm-0 { margin-right: 0 !important; } .mb-sm-0, .my-sm-0 { margin-bottom: 0 !important; } .ml-sm-0, .mx-sm-0 { margin-left: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .mt-sm-1, .my-sm-1 { margin-top: 0.25rem !important; } .mr-sm-1, .mx-sm-1 { margin-right: 0.25rem !important; } .mb-sm-1, .my-sm-1 { margin-bottom: 0.25rem !important; } .ml-sm-1, .mx-sm-1 { margin-left: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .mt-sm-2, .my-sm-2 { margin-top: 0.5rem !important; } .mr-sm-2, .mx-sm-2 { margin-right: 0.5rem !important; } .mb-sm-2, .my-sm-2 { margin-bottom: 0.5rem !important; } .ml-sm-2, .mx-sm-2 { margin-left: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .mt-sm-3, .my-sm-3 { margin-top: 1rem !important; } .mr-sm-3, .mx-sm-3 { margin-right: 1rem !important; } .mb-sm-3, .my-sm-3 { margin-bottom: 1rem !important; } .ml-sm-3, .mx-sm-3 { margin-left: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .mt-sm-4, .my-sm-4 { margin-top: 1.5rem !important; } .mr-sm-4, .mx-sm-4 { margin-right: 1.5rem !important; } .mb-sm-4, .my-sm-4 { margin-bottom: 1.5rem !important; } .ml-sm-4, .mx-sm-4 { margin-left: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .mt-sm-5, .my-sm-5 { margin-top: 3rem !important; } .mr-sm-5, .mx-sm-5 { margin-right: 3rem !important; } .mb-sm-5, .my-sm-5 { margin-bottom: 3rem !important; } .ml-sm-5, .mx-sm-5 { margin-left: 3rem !important; } .p-sm-0 { padding: 0 !important; } .pt-sm-0, .py-sm-0 { padding-top: 0 !important; } .pr-sm-0, .px-sm-0 { padding-right: 0 !important; } .pb-sm-0, .py-sm-0 { padding-bottom: 0 !important; } .pl-sm-0, .px-sm-0 { padding-left: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .pt-sm-1, .py-sm-1 { padding-top: 0.25rem !important; } .pr-sm-1, .px-sm-1 { padding-right: 0.25rem !important; } .pb-sm-1, .py-sm-1 { padding-bottom: 0.25rem !important; } .pl-sm-1, .px-sm-1 { padding-left: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .pt-sm-2, .py-sm-2 { padding-top: 0.5rem !important; } .pr-sm-2, .px-sm-2 { padding-right: 0.5rem !important; } .pb-sm-2, .py-sm-2 { padding-bottom: 0.5rem !important; } .pl-sm-2, .px-sm-2 { padding-left: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .pt-sm-3, .py-sm-3 { padding-top: 1rem !important; } .pr-sm-3, .px-sm-3 { padding-right: 1rem !important; } .pb-sm-3, .py-sm-3 { padding-bottom: 1rem !important; } .pl-sm-3, .px-sm-3 { padding-left: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .pt-sm-4, .py-sm-4 { padding-top: 1.5rem !important; } .pr-sm-4, .px-sm-4 { padding-right: 1.5rem !important; } .pb-sm-4, .py-sm-4 { padding-bottom: 1.5rem !important; } .pl-sm-4, .px-sm-4 { padding-left: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .pt-sm-5, .py-sm-5 { padding-top: 3rem !important; } .pr-sm-5, .px-sm-5 { padding-right: 3rem !important; } .pb-sm-5, .py-sm-5 { padding-bottom: 3rem !important; } .pl-sm-5, .px-sm-5 { padding-left: 3rem !important; } .m-sm-auto { margin: auto !important; } .mt-sm-auto, .my-sm-auto { margin-top: auto !important; } .mr-sm-auto, .mx-sm-auto { margin-right: auto !important; } .mb-sm-auto, .my-sm-auto { margin-bottom: auto !important; } .ml-sm-auto, .mx-sm-auto { margin-left: auto !important; } } @media (min-width: 768px) { .m-md-0 { margin: 0 !important; } .mt-md-0, .my-md-0 { margin-top: 0 !important; } .mr-md-0, .mx-md-0 { margin-right: 0 !important; } .mb-md-0, .my-md-0 { margin-bottom: 0 !important; } .ml-md-0, .mx-md-0 { margin-left: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .mt-md-1, .my-md-1 { margin-top: 0.25rem !important; } .mr-md-1, .mx-md-1 { margin-right: 0.25rem !important; } .mb-md-1, .my-md-1 { margin-bottom: 0.25rem !important; } .ml-md-1, .mx-md-1 { margin-left: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .mt-md-2, .my-md-2 { margin-top: 0.5rem !important; } .mr-md-2, .mx-md-2 { margin-right: 0.5rem !important; } .mb-md-2, .my-md-2 { margin-bottom: 0.5rem !important; } .ml-md-2, .mx-md-2 { margin-left: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .mt-md-3, .my-md-3 { margin-top: 1rem !important; } .mr-md-3, .mx-md-3 { margin-right: 1rem !important; } .mb-md-3, .my-md-3 { margin-bottom: 1rem !important; } .ml-md-3, .mx-md-3 { margin-left: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .mt-md-4, .my-md-4 { margin-top: 1.5rem !important; } .mr-md-4, .mx-md-4 { margin-right: 1.5rem !important; } .mb-md-4, .my-md-4 { margin-bottom: 1.5rem !important; } .ml-md-4, .mx-md-4 { margin-left: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .mt-md-5, .my-md-5 { margin-top: 3rem !important; } .mr-md-5, .mx-md-5 { margin-right: 3rem !important; } .mb-md-5, .my-md-5 { margin-bottom: 3rem !important; } .ml-md-5, .mx-md-5 { margin-left: 3rem !important; } .p-md-0 { padding: 0 !important; } .pt-md-0, .py-md-0 { padding-top: 0 !important; } .pr-md-0, .px-md-0 { padding-right: 0 !important; } .pb-md-0, .py-md-0 { padding-bottom: 0 !important; } .pl-md-0, .px-md-0 { padding-left: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .pt-md-1, .py-md-1 { padding-top: 0.25rem !important; } .pr-md-1, .px-md-1 { padding-right: 0.25rem !important; } .pb-md-1, .py-md-1 { padding-bottom: 0.25rem !important; } .pl-md-1, .px-md-1 { padding-left: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .pt-md-2, .py-md-2 { padding-top: 0.5rem !important; } .pr-md-2, .px-md-2 { padding-right: 0.5rem !important; } .pb-md-2, .py-md-2 { padding-bottom: 0.5rem !important; } .pl-md-2, .px-md-2 { padding-left: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .pt-md-3, .py-md-3 { padding-top: 1rem !important; } .pr-md-3, .px-md-3 { padding-right: 1rem !important; } .pb-md-3, .py-md-3 { padding-bottom: 1rem !important; } .pl-md-3, .px-md-3 { padding-left: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .pt-md-4, .py-md-4 { padding-top: 1.5rem !important; } .pr-md-4, .px-md-4 { padding-right: 1.5rem !important; } .pb-md-4, .py-md-4 { padding-bottom: 1.5rem !important; } .pl-md-4, .px-md-4 { padding-left: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .pt-md-5, .py-md-5 { padding-top: 3rem !important; } .pr-md-5, .px-md-5 { padding-right: 3rem !important; } .pb-md-5, .py-md-5 { padding-bottom: 3rem !important; } .pl-md-5, .px-md-5 { padding-left: 3rem !important; } .m-md-auto { margin: auto !important; } .mt-md-auto, .my-md-auto { margin-top: auto !important; } .mr-md-auto, .mx-md-auto { margin-right: auto !important; } .mb-md-auto, .my-md-auto { margin-bottom: auto !important; } .ml-md-auto, .mx-md-auto { margin-left: auto !important; } } @media (min-width: 992px) { .m-lg-0 { margin: 0 !important; } .mt-lg-0, .my-lg-0 { margin-top: 0 !important; } .mr-lg-0, .mx-lg-0 { margin-right: 0 !important; } .mb-lg-0, .my-lg-0 { margin-bottom: 0 !important; } .ml-lg-0, .mx-lg-0 { margin-left: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .mt-lg-1, .my-lg-1 { margin-top: 0.25rem !important; } .mr-lg-1, .mx-lg-1 { margin-right: 0.25rem !important; } .mb-lg-1, .my-lg-1 { margin-bottom: 0.25rem !important; } .ml-lg-1, .mx-lg-1 { margin-left: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .mt-lg-2, .my-lg-2 { margin-top: 0.5rem !important; } .mr-lg-2, .mx-lg-2 { margin-right: 0.5rem !important; } .mb-lg-2, .my-lg-2 { margin-bottom: 0.5rem !important; } .ml-lg-2, .mx-lg-2 { margin-left: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .mt-lg-3, .my-lg-3 { margin-top: 1rem !important; } .mr-lg-3, .mx-lg-3 { margin-right: 1rem !important; } .mb-lg-3, .my-lg-3 { margin-bottom: 1rem !important; } .ml-lg-3, .mx-lg-3 { margin-left: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .mt-lg-4, .my-lg-4 { margin-top: 1.5rem !important; } .mr-lg-4, .mx-lg-4 { margin-right: 1.5rem !important; } .mb-lg-4, .my-lg-4 { margin-bottom: 1.5rem !important; } .ml-lg-4, .mx-lg-4 { margin-left: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .mt-lg-5, .my-lg-5 { margin-top: 3rem !important; } .mr-lg-5, .mx-lg-5 { margin-right: 3rem !important; } .mb-lg-5, .my-lg-5 { margin-bottom: 3rem !important; } .ml-lg-5, .mx-lg-5 { margin-left: 3rem !important; } .p-lg-0 { padding: 0 !important; } .pt-lg-0, .py-lg-0 { padding-top: 0 !important; } .pr-lg-0, .px-lg-0 { padding-right: 0 !important; } .pb-lg-0, .py-lg-0 { padding-bottom: 0 !important; } .pl-lg-0, .px-lg-0 { padding-left: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .pt-lg-1, .py-lg-1 { padding-top: 0.25rem !important; } .pr-lg-1, .px-lg-1 { padding-right: 0.25rem !important; } .pb-lg-1, .py-lg-1 { padding-bottom: 0.25rem !important; } .pl-lg-1, .px-lg-1 { padding-left: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .pt-lg-2, .py-lg-2 { padding-top: 0.5rem !important; } .pr-lg-2, .px-lg-2 { padding-right: 0.5rem !important; } .pb-lg-2, .py-lg-2 { padding-bottom: 0.5rem !important; } .pl-lg-2, .px-lg-2 { padding-left: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .pt-lg-3, .py-lg-3 { padding-top: 1rem !important; } .pr-lg-3, .px-lg-3 { padding-right: 1rem !important; } .pb-lg-3, .py-lg-3 { padding-bottom: 1rem !important; } .pl-lg-3, .px-lg-3 { padding-left: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .pt-lg-4, .py-lg-4 { padding-top: 1.5rem !important; } .pr-lg-4, .px-lg-4 { padding-right: 1.5rem !important; } .pb-lg-4, .py-lg-4 { padding-bottom: 1.5rem !important; } .pl-lg-4, .px-lg-4 { padding-left: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .pt-lg-5, .py-lg-5 { padding-top: 3rem !important; } .pr-lg-5, .px-lg-5 { padding-right: 3rem !important; } .pb-lg-5, .py-lg-5 { padding-bottom: 3rem !important; } .pl-lg-5, .px-lg-5 { padding-left: 3rem !important; } .m-lg-auto { margin: auto !important; } .mt-lg-auto, .my-lg-auto { margin-top: auto !important; } .mr-lg-auto, .mx-lg-auto { margin-right: auto !important; } .mb-lg-auto, .my-lg-auto { margin-bottom: auto !important; } .ml-lg-auto, .mx-lg-auto { margin-left: auto !important; } } @media (min-width: 1200px) { .m-xl-0 { margin: 0 !important; } .mt-xl-0, .my-xl-0 { margin-top: 0 !important; } .mr-xl-0, .mx-xl-0 { margin-right: 0 !important; } .mb-xl-0, .my-xl-0 { margin-bottom: 0 !important; } .ml-xl-0, .mx-xl-0 { margin-left: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .mt-xl-1, .my-xl-1 { margin-top: 0.25rem !important; } .mr-xl-1, .mx-xl-1 { margin-right: 0.25rem !important; } .mb-xl-1, .my-xl-1 { margin-bottom: 0.25rem !important; } .ml-xl-1, .mx-xl-1 { margin-left: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .mt-xl-2, .my-xl-2 { margin-top: 0.5rem !important; } .mr-xl-2, .mx-xl-2 { margin-right: 0.5rem !important; } .mb-xl-2, .my-xl-2 { margin-bottom: 0.5rem !important; } .ml-xl-2, .mx-xl-2 { margin-left: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .mt-xl-3, .my-xl-3 { margin-top: 1rem !important; } .mr-xl-3, .mx-xl-3 { margin-right: 1rem !important; } .mb-xl-3, .my-xl-3 { margin-bottom: 1rem !important; } .ml-xl-3, .mx-xl-3 { margin-left: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .mt-xl-4, .my-xl-4 { margin-top: 1.5rem !important; } .mr-xl-4, .mx-xl-4 { margin-right: 1.5rem !important; } .mb-xl-4, .my-xl-4 { margin-bottom: 1.5rem !important; } .ml-xl-4, .mx-xl-4 { margin-left: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .mt-xl-5, .my-xl-5 { margin-top: 3rem !important; } .mr-xl-5, .mx-xl-5 { margin-right: 3rem !important; } .mb-xl-5, .my-xl-5 { margin-bottom: 3rem !important; } .ml-xl-5, .mx-xl-5 { margin-left: 3rem !important; } .p-xl-0 { padding: 0 !important; } .pt-xl-0, .py-xl-0 { padding-top: 0 !important; } .pr-xl-0, .px-xl-0 { padding-right: 0 !important; } .pb-xl-0, .py-xl-0 { padding-bottom: 0 !important; } .pl-xl-0, .px-xl-0 { padding-left: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .pt-xl-1, .py-xl-1 { padding-top: 0.25rem !important; } .pr-xl-1, .px-xl-1 { padding-right: 0.25rem !important; } .pb-xl-1, .py-xl-1 { padding-bottom: 0.25rem !important; } .pl-xl-1, .px-xl-1 { padding-left: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .pt-xl-2, .py-xl-2 { padding-top: 0.5rem !important; } .pr-xl-2, .px-xl-2 { padding-right: 0.5rem !important; } .pb-xl-2, .py-xl-2 { padding-bottom: 0.5rem !important; } .pl-xl-2, .px-xl-2 { padding-left: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .pt-xl-3, .py-xl-3 { padding-top: 1rem !important; } .pr-xl-3, .px-xl-3 { padding-right: 1rem !important; } .pb-xl-3, .py-xl-3 { padding-bottom: 1rem !important; } .pl-xl-3, .px-xl-3 { padding-left: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .pt-xl-4, .py-xl-4 { padding-top: 1.5rem !important; } .pr-xl-4, .px-xl-4 { padding-right: 1.5rem !important; } .pb-xl-4, .py-xl-4 { padding-bottom: 1.5rem !important; } .pl-xl-4, .px-xl-4 { padding-left: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .pt-xl-5, .py-xl-5 { padding-top: 3rem !important; } .pr-xl-5, .px-xl-5 { padding-right: 3rem !important; } .pb-xl-5, .py-xl-5 { padding-bottom: 3rem !important; } .pl-xl-5, .px-xl-5 { padding-left: 3rem !important; } .m-xl-auto { margin: auto !important; } .mt-xl-auto, .my-xl-auto { margin-top: auto !important; } .mr-xl-auto, .mx-xl-auto { margin-right: auto !important; } .mb-xl-auto, .my-xl-auto { margin-bottom: auto !important; } .ml-xl-auto, .mx-xl-auto { margin-left: auto !important; } } .text-justify { text-align: justify !important; } .text-nowrap { white-space: nowrap !important; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-left { text-align: left !important; } .text-right { text-align: right !important; } .text-center { text-align: center !important; } @media (min-width: 576px) { .text-sm-left { text-align: left !important; } .text-sm-right { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .text-md-left { text-align: left !important; } .text-md-right { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .text-lg-left { text-align: left !important; } .text-lg-right { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .text-xl-left { text-align: left !important; } .text-xl-right { text-align: right !important; } .text-xl-center { text-align: center !important; } } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .font-weight-light { font-weight: 300 !important; } .font-weight-normal { font-weight: 400 !important; } .font-weight-bold { font-weight: 700 !important; } .font-italic { font-style: italic !important; } .text-white { color: #fff !important; } .text-primary { color: #007bff !important; } a.text-primary:focus, a.text-primary:hover { color: #0062cc !important; } .text-secondary { color: #868e96 !important; } a.text-secondary:focus, a.text-secondary:hover { color: #6c757d !important; } .text-success { color: #28a745 !important; } a.text-success:focus, a.text-success:hover { color: #1e7e34 !important; } .text-info { color: #17a2b8 !important; } a.text-info:focus, a.text-info:hover { color: #117a8b !important; } .text-warning { color: #ffc107 !important; } a.text-warning:focus, a.text-warning:hover { color: #d39e00 !important; } .text-danger { color: #dc3545 !important; } a.text-danger:focus, a.text-danger:hover { color: #bd2130 !important; } .text-light { color: #f8f9fa !important; } a.text-light:focus, a.text-light:hover { color: #dae0e5 !important; } .text-dark { color: #343a40 !important; } a.text-dark:focus, a.text-dark:hover { color: #1d2124 !important; } .text-muted { color: #868e96 !important; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } /*# sourceMappingURL=bootstrap.css.map */ ================================================ FILE: open-layui-web/src/main/view/static/lib/bootstrap/js/bootstrap.bundle.js ================================================ /*! * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ var bootstrap = (function (exports,$) { 'use strict'; $ = $ && $.hasOwnProperty('default') ? $['default'] : $; /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): util.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Util = function () { /** * ------------------------------------------------------------------------ * Private TransitionEnd Helpers * ------------------------------------------------------------------------ */ var transition = false; var MAX_UID = 1000000; var TransitionEndEvent = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', transition: 'transitionend' // shoutout AngusCroll (https://goo.gl/pxwQGp) }; function toType(obj) { return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } function getSpecialTransitionEndEvent() { return { bindType: transition.end, delegateType: transition.end, handle: function handle(event) { if ($(event.target).is(this)) { return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params } return undefined; // eslint-disable-line no-undefined } }; } function transitionEndTest() { if (window.QUnit) { return false; } var el = document.createElement('bootstrap'); for (var name in TransitionEndEvent) { if (typeof el.style[name] !== 'undefined') { return { end: TransitionEndEvent[name] }; } } return false; } function transitionEndEmulator(duration) { var _this = this; var called = false; $(this).one(Util.TRANSITION_END, function () { called = true; }); setTimeout(function () { if (!called) { Util.triggerTransitionEnd(_this); } }, duration); return this; } function setTransitionEndSupport() { transition = transitionEndTest(); $.fn.emulateTransitionEnd = transitionEndEmulator; if (Util.supportsTransitionEnd()) { $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); } } /** * -------------------------------------------------------------------------- * Public Util Api * -------------------------------------------------------------------------- */ var Util = { TRANSITION_END: 'bsTransitionEnd', getUID: function getUID(prefix) { do { // eslint-disable-next-line no-bitwise prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here } while (document.getElementById(prefix)); return prefix; }, getSelectorFromElement: function getSelectorFromElement(element) { var selector = element.getAttribute('data-target'); if (!selector || selector === '#') { selector = element.getAttribute('href') || ''; } try { var $selector = $(document).find(selector); return $selector.length > 0 ? selector : null; } catch (error) { return null; } }, reflow: function reflow(element) { return element.offsetHeight; }, triggerTransitionEnd: function triggerTransitionEnd(element) { $(element).trigger(transition.end); }, supportsTransitionEnd: function supportsTransitionEnd() { return Boolean(transition); }, isElement: function isElement(obj) { return (obj[0] || obj).nodeType; }, typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { for (var property in configTypes) { if (Object.prototype.hasOwnProperty.call(configTypes, property)) { var expectedTypes = configTypes[property]; var value = config[property]; var valueType = value && Util.isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); } } } } }; setTransitionEndSupport(); return Util; }($); function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var createClass = _createClass; function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var inheritsLoose = _inheritsLoose; /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Alert = function () { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'alert'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.alert'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var TRANSITION_DURATION = 150; var Selector = { DISMISS: '[data-dismiss="alert"]' }; var Event = { CLOSE: "close" + EVENT_KEY, CLOSED: "closed" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { ALERT: 'alert', FADE: 'fade', SHOW: 'show' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Alert = /*#__PURE__*/ function () { function Alert(element) { this._element = element; } // getters var _proto = Alert.prototype; // public _proto.close = function close(element) { element = element || this._element; var rootElement = this._getRootElement(element); var customEvent = this._triggerCloseEvent(rootElement); if (customEvent.isDefaultPrevented()) { return; } this._removeElement(rootElement); }; _proto.dispose = function dispose() { $.removeData(this._element, DATA_KEY); this._element = null; }; // private _proto._getRootElement = function _getRootElement(element) { var selector = Util.getSelectorFromElement(element); var parent = false; if (selector) { parent = $(selector)[0]; } if (!parent) { parent = $(element).closest("." + ClassName.ALERT)[0]; } return parent; }; _proto._triggerCloseEvent = function _triggerCloseEvent(element) { var closeEvent = $.Event(Event.CLOSE); $(element).trigger(closeEvent); return closeEvent; }; _proto._removeElement = function _removeElement(element) { var _this = this; $(element).removeClass(ClassName.SHOW); if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) { this._destroyElement(element); return; } $(element).one(Util.TRANSITION_END, function (event) { return _this._destroyElement(element, event); }).emulateTransitionEnd(TRANSITION_DURATION); }; _proto._destroyElement = function _destroyElement(element) { $(element).detach().trigger(Event.CLOSED).remove(); }; // static Alert._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var $element = $(this); var data = $element.data(DATA_KEY); if (!data) { data = new Alert(this); $element.data(DATA_KEY, data); } if (config === 'close') { data[config](this); } }); }; Alert._handleDismiss = function _handleDismiss(alertInstance) { return function (event) { if (event) { event.preventDefault(); } alertInstance.close(this); }; }; createClass(Alert, null, [{ key: "VERSION", get: function get() { return VERSION; } }]); return Alert; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Alert._jQueryInterface; $.fn[NAME].Constructor = Alert; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Alert._jQueryInterface; }; return Alert; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Button = function () { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'button'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.button'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var ClassName = { ACTIVE: 'active', BUTTON: 'btn', FOCUS: 'focus' }; var Selector = { DATA_TOGGLE_CARROT: '[data-toggle^="button"]', DATA_TOGGLE: '[data-toggle="buttons"]', INPUT: 'input', ACTIVE: '.active', BUTTON: '.btn' }; var Event = { CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY) /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Button = /*#__PURE__*/ function () { function Button(element) { this._element = element; } // getters var _proto = Button.prototype; // public _proto.toggle = function toggle() { var triggerChangeEvent = true; var addAriaPressed = true; var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0]; if (rootElement) { var input = $(this._element).find(Selector.INPUT)[0]; if (input) { if (input.type === 'radio') { if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) { triggerChangeEvent = false; } else { var activeElement = $(rootElement).find(Selector.ACTIVE)[0]; if (activeElement) { $(activeElement).removeClass(ClassName.ACTIVE); } } } if (triggerChangeEvent) { if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) { return; } input.checked = !$(this._element).hasClass(ClassName.ACTIVE); $(input).trigger('change'); } input.focus(); addAriaPressed = false; } } if (addAriaPressed) { this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE)); } if (triggerChangeEvent) { $(this._element).toggleClass(ClassName.ACTIVE); } }; _proto.dispose = function dispose() { $.removeData(this._element, DATA_KEY); this._element = null; }; // static Button._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $(this).data(DATA_KEY); if (!data) { data = new Button(this); $(this).data(DATA_KEY, data); } if (config === 'toggle') { data[config](); } }); }; createClass(Button, null, [{ key: "VERSION", get: function get() { return VERSION; } }]); return Button; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { event.preventDefault(); var button = event.target; if (!$(button).hasClass(ClassName.BUTTON)) { button = $(button).closest(Selector.BUTTON); } Button._jQueryInterface.call($(button), 'toggle'); }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { var button = $(event.target).closest(Selector.BUTTON)[0]; $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Button._jQueryInterface; $.fn[NAME].Constructor = Button; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Button._jQueryInterface; }; return Button; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Carousel = function () { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'carousel'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.carousel'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var TRANSITION_DURATION = 600; var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch var Default = { interval: 5000, keyboard: true, slide: false, pause: 'hover', wrap: true }; var DefaultType = { interval: '(number|boolean)', keyboard: 'boolean', slide: '(boolean|string)', pause: '(string|boolean)', wrap: 'boolean' }; var Direction = { NEXT: 'next', PREV: 'prev', LEFT: 'left', RIGHT: 'right' }; var Event = { SLIDE: "slide" + EVENT_KEY, SLID: "slid" + EVENT_KEY, KEYDOWN: "keydown" + EVENT_KEY, MOUSEENTER: "mouseenter" + EVENT_KEY, MOUSELEAVE: "mouseleave" + EVENT_KEY, TOUCHEND: "touchend" + EVENT_KEY, LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { CAROUSEL: 'carousel', ACTIVE: 'active', SLIDE: 'slide', RIGHT: 'carousel-item-right', LEFT: 'carousel-item-left', NEXT: 'carousel-item-next', PREV: 'carousel-item-prev', ITEM: 'carousel-item' }; var Selector = { ACTIVE: '.active', ACTIVE_ITEM: '.active.carousel-item', ITEM: '.carousel-item', NEXT_PREV: '.carousel-item-next, .carousel-item-prev', INDICATORS: '.carousel-indicators', DATA_SLIDE: '[data-slide], [data-slide-to]', DATA_RIDE: '[data-ride="carousel"]' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Carousel = /*#__PURE__*/ function () { function Carousel(element, config) { this._items = null; this._interval = null; this._activeElement = null; this._isPaused = false; this._isSliding = false; this.touchTimeout = null; this._config = this._getConfig(config); this._element = $(element)[0]; this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0]; this._addEventListeners(); } // getters var _proto = Carousel.prototype; // public _proto.next = function next() { if (!this._isSliding) { this._slide(Direction.NEXT); } }; _proto.nextWhenVisible = function nextWhenVisible() { // Don't call next when the page isn't visible // or the carousel or its parent isn't visible if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') { this.next(); } }; _proto.prev = function prev() { if (!this._isSliding) { this._slide(Direction.PREV); } }; _proto.pause = function pause(event) { if (!event) { this._isPaused = true; } if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) { Util.triggerTransitionEnd(this._element); this.cycle(true); } clearInterval(this._interval); this._interval = null; }; _proto.cycle = function cycle(event) { if (!event) { this._isPaused = false; } if (this._interval) { clearInterval(this._interval); this._interval = null; } if (this._config.interval && !this._isPaused) { this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); } }; _proto.to = function to(index) { var _this = this; this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0]; var activeIndex = this._getItemIndex(this._activeElement); if (index > this._items.length - 1 || index < 0) { return; } if (this._isSliding) { $(this._element).one(Event.SLID, function () { return _this.to(index); }); return; } if (activeIndex === index) { this.pause(); this.cycle(); return; } var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; this._slide(direction, this._items[index]); }; _proto.dispose = function dispose() { $(this._element).off(EVENT_KEY); $.removeData(this._element, DATA_KEY); this._items = null; this._config = null; this._element = null; this._interval = null; this._isPaused = null; this._isSliding = null; this._activeElement = null; this._indicatorsElement = null; }; // private _proto._getConfig = function _getConfig(config) { config = $.extend({}, Default, config); Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._addEventListeners = function _addEventListeners() { var _this2 = this; if (this._config.keyboard) { $(this._element).on(Event.KEYDOWN, function (event) { return _this2._keydown(event); }); } if (this._config.pause === 'hover') { $(this._element).on(Event.MOUSEENTER, function (event) { return _this2.pause(event); }).on(Event.MOUSELEAVE, function (event) { return _this2.cycle(event); }); if ('ontouchstart' in document.documentElement) { // if it's a touch-enabled device, mouseenter/leave are fired as // part of the mouse compatibility events on first tap - the carousel // would stop cycling until user tapped out of it; // here, we listen for touchend, explicitly pause the carousel // (as if it's the second time we tap on it, mouseenter compat event // is NOT fired) and after a timeout (to allow for mouse compatibility // events to fire) we explicitly restart cycling $(this._element).on(Event.TOUCHEND, function () { _this2.pause(); if (_this2.touchTimeout) { clearTimeout(_this2.touchTimeout); } _this2.touchTimeout = setTimeout(function (event) { return _this2.cycle(event); }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval); }); } } }; _proto._keydown = function _keydown(event) { if (/input|textarea/i.test(event.target.tagName)) { return; } switch (event.which) { case ARROW_LEFT_KEYCODE: event.preventDefault(); this.prev(); break; case ARROW_RIGHT_KEYCODE: event.preventDefault(); this.next(); break; default: return; } }; _proto._getItemIndex = function _getItemIndex(element) { this._items = $.makeArray($(element).parent().find(Selector.ITEM)); return this._items.indexOf(element); }; _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) { var isNextDirection = direction === Direction.NEXT; var isPrevDirection = direction === Direction.PREV; var activeIndex = this._getItemIndex(activeElement); var lastItemIndex = this._items.length - 1; var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; if (isGoingToWrap && !this._config.wrap) { return activeElement; } var delta = direction === Direction.PREV ? -1 : 1; var itemIndex = (activeIndex + delta) % this._items.length; return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; }; _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { var targetIndex = this._getItemIndex(relatedTarget); var fromIndex = this._getItemIndex($(this._element).find(Selector.ACTIVE_ITEM)[0]); var slideEvent = $.Event(Event.SLIDE, { relatedTarget: relatedTarget, direction: eventDirectionName, from: fromIndex, to: targetIndex }); $(this._element).trigger(slideEvent); return slideEvent; }; _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { if (this._indicatorsElement) { $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE); var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; if (nextIndicator) { $(nextIndicator).addClass(ClassName.ACTIVE); } } }; _proto._slide = function _slide(direction, element) { var _this3 = this; var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0]; var activeElementIndex = this._getItemIndex(activeElement); var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); var nextElementIndex = this._getItemIndex(nextElement); var isCycling = Boolean(this._interval); var directionalClassName; var orderClassName; var eventDirectionName; if (direction === Direction.NEXT) { directionalClassName = ClassName.LEFT; orderClassName = ClassName.NEXT; eventDirectionName = Direction.LEFT; } else { directionalClassName = ClassName.RIGHT; orderClassName = ClassName.PREV; eventDirectionName = Direction.RIGHT; } if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) { this._isSliding = false; return; } var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); if (slideEvent.isDefaultPrevented()) { return; } if (!activeElement || !nextElement) { // some weirdness is happening, so we bail return; } this._isSliding = true; if (isCycling) { this.pause(); } this._setActiveIndicatorElement(nextElement); var slidEvent = $.Event(Event.SLID, { relatedTarget: nextElement, direction: eventDirectionName, from: activeElementIndex, to: nextElementIndex }); if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) { $(nextElement).addClass(orderClassName); Util.reflow(nextElement); $(activeElement).addClass(directionalClassName); $(nextElement).addClass(directionalClassName); $(activeElement).one(Util.TRANSITION_END, function () { $(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE); $(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName); _this3._isSliding = false; setTimeout(function () { return $(_this3._element).trigger(slidEvent); }, 0); }).emulateTransitionEnd(TRANSITION_DURATION); } else { $(activeElement).removeClass(ClassName.ACTIVE); $(nextElement).addClass(ClassName.ACTIVE); this._isSliding = false; $(this._element).trigger(slidEvent); } if (isCycling) { this.cycle(); } }; // static Carousel._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $(this).data(DATA_KEY); var _config = $.extend({}, Default, $(this).data()); if (typeof config === 'object') { $.extend(_config, config); } var action = typeof config === 'string' ? config : _config.slide; if (!data) { data = new Carousel(this, _config); $(this).data(DATA_KEY, data); } if (typeof config === 'number') { data.to(config); } else if (typeof action === 'string') { if (typeof data[action] === 'undefined') { throw new Error("No method named \"" + action + "\""); } data[action](); } else if (_config.interval) { data.pause(); data.cycle(); } }); }; Carousel._dataApiClickHandler = function _dataApiClickHandler(event) { var selector = Util.getSelectorFromElement(this); if (!selector) { return; } var target = $(selector)[0]; if (!target || !$(target).hasClass(ClassName.CAROUSEL)) { return; } var config = $.extend({}, $(target).data(), $(this).data()); var slideIndex = this.getAttribute('data-slide-to'); if (slideIndex) { config.interval = false; } Carousel._jQueryInterface.call($(target), config); if (slideIndex) { $(target).data(DATA_KEY).to(slideIndex); } event.preventDefault(); }; createClass(Carousel, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }]); return Carousel; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler); $(window).on(Event.LOAD_DATA_API, function () { $(Selector.DATA_RIDE).each(function () { var $carousel = $(this); Carousel._jQueryInterface.call($carousel, $carousel.data()); }); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Carousel._jQueryInterface; $.fn[NAME].Constructor = Carousel; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Carousel._jQueryInterface; }; return Carousel; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Collapse = function () { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'collapse'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.collapse'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var TRANSITION_DURATION = 600; var Default = { toggle: true, parent: '' }; var DefaultType = { toggle: 'boolean', parent: '(string|element)' }; var Event = { SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { SHOW: 'show', COLLAPSE: 'collapse', COLLAPSING: 'collapsing', COLLAPSED: 'collapsed' }; var Dimension = { WIDTH: 'width', HEIGHT: 'height' }; var Selector = { ACTIVES: '.show, .collapsing', DATA_TOGGLE: '[data-toggle="collapse"]' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Collapse = /*#__PURE__*/ function () { function Collapse(element, config) { this._isTransitioning = false; this._element = element; this._config = this._getConfig(config); this._triggerArray = $.makeArray($("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); var tabToggles = $(Selector.DATA_TOGGLE); for (var i = 0; i < tabToggles.length; i++) { var elem = tabToggles[i]; var selector = Util.getSelectorFromElement(elem); if (selector !== null && $(selector).filter(element).length > 0) { this._triggerArray.push(elem); } } this._parent = this._config.parent ? this._getParent() : null; if (!this._config.parent) { this._addAriaAndCollapsedClass(this._element, this._triggerArray); } if (this._config.toggle) { this.toggle(); } } // getters var _proto = Collapse.prototype; // public _proto.toggle = function toggle() { if ($(this._element).hasClass(ClassName.SHOW)) { this.hide(); } else { this.show(); } }; _proto.show = function show() { var _this = this; if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) { return; } var actives; var activesData; if (this._parent) { actives = $.makeArray($(this._parent).children().children(Selector.ACTIVES)); if (!actives.length) { actives = null; } } if (actives) { activesData = $(actives).data(DATA_KEY); if (activesData && activesData._isTransitioning) { return; } } var startEvent = $.Event(Event.SHOW); $(this._element).trigger(startEvent); if (startEvent.isDefaultPrevented()) { return; } if (actives) { Collapse._jQueryInterface.call($(actives), 'hide'); if (!activesData) { $(actives).data(DATA_KEY, null); } } var dimension = this._getDimension(); $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); this._element.style[dimension] = 0; if (this._triggerArray.length) { $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); } this.setTransitioning(true); var complete = function complete() { $(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW); _this._element.style[dimension] = ''; _this.setTransitioning(false); $(_this._element).trigger(Event.SHOWN); }; if (!Util.supportsTransitionEnd()) { complete(); return; } var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); var scrollSize = "scroll" + capitalizedDimension; $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); this._element.style[dimension] = this._element[scrollSize] + "px"; }; _proto.hide = function hide() { var _this2 = this; if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) { return; } var startEvent = $.Event(Event.HIDE); $(this._element).trigger(startEvent); if (startEvent.isDefaultPrevented()) { return; } var dimension = this._getDimension(); this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; Util.reflow(this._element); $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); if (this._triggerArray.length) { for (var i = 0; i < this._triggerArray.length; i++) { var trigger = this._triggerArray[i]; var selector = Util.getSelectorFromElement(trigger); if (selector !== null) { var $elem = $(selector); if (!$elem.hasClass(ClassName.SHOW)) { $(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); } } } } this.setTransitioning(true); var complete = function complete() { _this2.setTransitioning(false); $(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN); }; this._element.style[dimension] = ''; if (!Util.supportsTransitionEnd()) { complete(); return; } $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); }; _proto.setTransitioning = function setTransitioning(isTransitioning) { this._isTransitioning = isTransitioning; }; _proto.dispose = function dispose() { $.removeData(this._element, DATA_KEY); this._config = null; this._parent = null; this._element = null; this._triggerArray = null; this._isTransitioning = null; }; // private _proto._getConfig = function _getConfig(config) { config = $.extend({}, Default, config); config.toggle = Boolean(config.toggle); // coerce string values Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._getDimension = function _getDimension() { var hasWidth = $(this._element).hasClass(Dimension.WIDTH); return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; }; _proto._getParent = function _getParent() { var _this3 = this; var parent = null; if (Util.isElement(this._config.parent)) { parent = this._config.parent; // it's a jQuery object if (typeof this._config.parent.jquery !== 'undefined') { parent = this._config.parent[0]; } } else { parent = $(this._config.parent)[0]; } var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; $(parent).find(selector).each(function (i, element) { _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); }); return parent; }; _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { if (element) { var isOpen = $(element).hasClass(ClassName.SHOW); if (triggerArray.length) { $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); } } }; // static Collapse._getTargetFromElement = function _getTargetFromElement(element) { var selector = Util.getSelectorFromElement(element); return selector ? $(selector)[0] : null; }; Collapse._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var $this = $(this); var data = $this.data(DATA_KEY); var _config = $.extend({}, Default, $this.data(), typeof config === 'object' && config); if (!data && _config.toggle && /show|hide/.test(config)) { _config.toggle = false; } if (!data) { data = new Collapse(this, _config); $this.data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; createClass(Collapse, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }]); return Collapse; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { // preventDefault only for elements (which change the URL) not inside the collapsible element if (event.currentTarget.tagName === 'A') { event.preventDefault(); } var $trigger = $(this); var selector = Util.getSelectorFromElement(this); $(selector).each(function () { var $target = $(this); var data = $target.data(DATA_KEY); var config = data ? 'toggle' : $trigger.data(); Collapse._jQueryInterface.call($target, config); }); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Collapse._jQueryInterface; $.fn[NAME].Constructor = Collapse; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Collapse._jQueryInterface; }; return Collapse; }($); /**! * @fileOverview Kickass library to create and place poppers near their reference elements. * @version 1.12.5 * @license * Copyright (c) 2016 Federico Zivolo and contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ var nativeHints = ['native code', '[object MutationObserverConstructor]']; /** * Determine if a function is implemented natively (as opposed to a polyfill). * @method * @memberof Popper.Utils * @argument {Function | undefined} fn the function to check * @returns {Boolean} */ var isNative = (function (fn) { return nativeHints.some(function (hint) { return (fn || '').toString().indexOf(hint) > -1; }); }); var isBrowser = typeof window !== 'undefined'; var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; var timeoutDuration = 0; for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) { if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { timeoutDuration = 1; break; } } function microtaskDebounce(fn) { var scheduled = false; var i = 0; var elem = document.createElement('span'); // MutationObserver provides a mechanism for scheduling microtasks, which // are scheduled *before* the next task. This gives us a way to debounce // a function but ensure it's called *before* the next paint. var observer = new MutationObserver(function () { fn(); scheduled = false; }); observer.observe(elem, { attributes: true }); return function () { if (!scheduled) { scheduled = true; elem.setAttribute('x-index', i); i = i + 1; // don't use compund (+=) because it doesn't get optimized in V8 } }; } function taskDebounce(fn) { var scheduled = false; return function () { if (!scheduled) { scheduled = true; setTimeout(function () { scheduled = false; fn(); }, timeoutDuration); } }; } // It's common for MutationObserver polyfills to be seen in the wild, however // these rely on Mutation Events which only occur when an element is connected // to the DOM. The algorithm used in this module does not use a connected element, // and so we must ensure that a *native* MutationObserver is available. var supportsNativeMutationObserver = isBrowser && isNative(window.MutationObserver); /** * Create a debounced version of a method, that's asynchronously deferred * but called in the minimum time possible. * * @method * @memberof Popper.Utils * @argument {Function} fn * @returns {Function} */ var debounce = supportsNativeMutationObserver ? microtaskDebounce : taskDebounce; /** * Check if the given variable is a function * @method * @memberof Popper.Utils * @argument {Any} functionToCheck - variable to check * @returns {Boolean} answer to: is a function? */ function isFunction(functionToCheck) { var getType = {}; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; } /** * Get CSS computed property of the given element * @method * @memberof Popper.Utils * @argument {Eement} element * @argument {String} property */ function getStyleComputedProperty(element, property) { if (element.nodeType !== 1) { return []; } // NOTE: 1 DOM access here var css = window.getComputedStyle(element, null); return property ? css[property] : css; } /** * Returns the parentNode or the host of the element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} parent */ function getParentNode(element) { if (element.nodeName === 'HTML') { return element; } return element.parentNode || element.host; } /** * Returns the scrolling parent of the given element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} scroll parent */ function getScrollParent(element) { // Return body, `getScroll` will take care to get the correct `scrollTop` from it if (!element || ['HTML', 'BODY', '#document'].indexOf(element.nodeName) !== -1) { return window.document.body; } // Firefox want us to check `-x` and `-y` variations as well var _getStyleComputedProp = getStyleComputedProperty(element), overflow = _getStyleComputedProp.overflow, overflowX = _getStyleComputedProp.overflowX, overflowY = _getStyleComputedProp.overflowY; if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) { return element; } return getScrollParent(getParentNode(element)); } /** * Returns the offset parent of the given element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} offset parent */ function getOffsetParent(element) { // NOTE: 1 DOM access here var offsetParent = element && element.offsetParent; var nodeName = offsetParent && offsetParent.nodeName; if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { return window.document.documentElement; } // .offsetParent will return the closest TD or TABLE in case // no offsetParent is present, I hate this job... if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') { return getOffsetParent(offsetParent); } return offsetParent; } function isOffsetContainer(element) { var nodeName = element.nodeName; if (nodeName === 'BODY') { return false; } return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element; } /** * Finds the root node (document, shadowDOM root) of the given element * @method * @memberof Popper.Utils * @argument {Element} node * @returns {Element} root node */ function getRoot(node) { if (node.parentNode !== null) { return getRoot(node.parentNode); } return node; } /** * Finds the offset parent common to the two provided nodes * @method * @memberof Popper.Utils * @argument {Element} element1 * @argument {Element} element2 * @returns {Element} common offset parent */ function findCommonOffsetParent(element1, element2) { // This check is needed to avoid errors in case one of the elements isn't defined for any reason if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { return window.document.documentElement; } // Here we make sure to give as "start" the element that comes first in the DOM var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING; var start = order ? element1 : element2; var end = order ? element2 : element1; // Get common ancestor container var range = document.createRange(); range.setStart(start, 0); range.setEnd(end, 0); var commonAncestorContainer = range.commonAncestorContainer; // Both nodes are inside #document if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) { if (isOffsetContainer(commonAncestorContainer)) { return commonAncestorContainer; } return getOffsetParent(commonAncestorContainer); } // one of the nodes is inside shadowDOM, find which one var element1root = getRoot(element1); if (element1root.host) { return findCommonOffsetParent(element1root.host, element2); } else { return findCommonOffsetParent(element1, getRoot(element2).host); } } /** * Gets the scroll value of the given element in the given side (top and left) * @method * @memberof Popper.Utils * @argument {Element} element * @argument {String} side `top` or `left` * @returns {number} amount of scrolled pixels */ function getScroll(element) { var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top'; var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; var nodeName = element.nodeName; if (nodeName === 'BODY' || nodeName === 'HTML') { var html = window.document.documentElement; var scrollingElement = window.document.scrollingElement || html; return scrollingElement[upperSide]; } return element[upperSide]; } /* * Sum or subtract the element scroll values (left and top) from a given rect object * @method * @memberof Popper.Utils * @param {Object} rect - Rect object you want to change * @param {HTMLElement} element - The element from the function reads the scroll values * @param {Boolean} subtract - set to true if you want to subtract the scroll values * @return {Object} rect - The modifier rect object */ function includeScroll(rect, element) { var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var scrollTop = getScroll(element, 'top'); var scrollLeft = getScroll(element, 'left'); var modifier = subtract ? -1 : 1; rect.top += scrollTop * modifier; rect.bottom += scrollTop * modifier; rect.left += scrollLeft * modifier; rect.right += scrollLeft * modifier; return rect; } /* * Helper to detect borders of a given element * @method * @memberof Popper.Utils * @param {CSSStyleDeclaration} styles * Result of `getStyleComputedProperty` on the given element * @param {String} axis - `x` or `y` * @return {number} borders - The borders size of the given axis */ function getBordersSize(styles, axis) { var sideA = axis === 'x' ? 'Left' : 'Top'; var sideB = sideA === 'Left' ? 'Right' : 'Bottom'; return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0]; } /** * Tells if you are running Internet Explorer 10 * @method * @memberof Popper.Utils * @returns {Boolean} isIE10 */ var isIE10 = undefined; var isIE10$1 = function () { if (isIE10 === undefined) { isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1; } return isIE10; }; function getSize(axis, body, html, computedStyle) { return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0); } function getWindowSizes() { var body = window.document.body; var html = window.document.documentElement; var computedStyle = isIE10$1() && window.getComputedStyle(html); return { height: getSize('Height', body, html, computedStyle), width: getSize('Width', body, html, computedStyle) }; } var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass$1 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends$1 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** * Given element offsets, generate an output similar to getBoundingClientRect * @method * @memberof Popper.Utils * @argument {Object} offsets * @returns {Object} ClientRect like output */ function getClientRect(offsets) { return _extends$1({}, offsets, { right: offsets.left + offsets.width, bottom: offsets.top + offsets.height }); } /** * Get bounding client rect of given element * @method * @memberof Popper.Utils * @param {HTMLElement} element * @return {Object} client rect */ function getBoundingClientRect(element) { var rect = {}; // IE10 10 FIX: Please, don't ask, the element isn't // considered in DOM in some circumstances... // This isn't reproducible in IE10 compatibility mode of IE11 if (isIE10$1()) { try { rect = element.getBoundingClientRect(); var scrollTop = getScroll(element, 'top'); var scrollLeft = getScroll(element, 'left'); rect.top += scrollTop; rect.left += scrollLeft; rect.bottom += scrollTop; rect.right += scrollLeft; } catch (err) {} } else { rect = element.getBoundingClientRect(); } var result = { left: rect.left, top: rect.top, width: rect.right - rect.left, height: rect.bottom - rect.top }; // subtract scrollbar size from sizes var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {}; var width = sizes.width || element.clientWidth || result.right - result.left; var height = sizes.height || element.clientHeight || result.bottom - result.top; var horizScrollbar = element.offsetWidth - width; var vertScrollbar = element.offsetHeight - height; // if an hypothetical scrollbar is detected, we must be sure it's not a `border` // we make this check conditional for performance reasons if (horizScrollbar || vertScrollbar) { var styles = getStyleComputedProperty(element); horizScrollbar -= getBordersSize(styles, 'x'); vertScrollbar -= getBordersSize(styles, 'y'); result.width -= horizScrollbar; result.height -= vertScrollbar; } return getClientRect(result); } function getOffsetRectRelativeToArbitraryNode(children, parent) { var isIE10 = isIE10$1(); var isHTML = parent.nodeName === 'HTML'; var childrenRect = getBoundingClientRect(children); var parentRect = getBoundingClientRect(parent); var scrollParent = getScrollParent(children); var styles = getStyleComputedProperty(parent); var borderTopWidth = +styles.borderTopWidth.split('px')[0]; var borderLeftWidth = +styles.borderLeftWidth.split('px')[0]; var offsets = getClientRect({ top: childrenRect.top - parentRect.top - borderTopWidth, left: childrenRect.left - parentRect.left - borderLeftWidth, width: childrenRect.width, height: childrenRect.height }); offsets.marginTop = 0; offsets.marginLeft = 0; // Subtract margins of documentElement in case it's being used as parent // we do this only on HTML because it's the only element that behaves // differently when margins are applied to it. The margins are included in // the box of the documentElement, in the other cases not. if (!isIE10 && isHTML) { var marginTop = +styles.marginTop.split('px')[0]; var marginLeft = +styles.marginLeft.split('px')[0]; offsets.top -= borderTopWidth - marginTop; offsets.bottom -= borderTopWidth - marginTop; offsets.left -= borderLeftWidth - marginLeft; offsets.right -= borderLeftWidth - marginLeft; // Attach marginTop and marginLeft because in some circumstances we may need them offsets.marginTop = marginTop; offsets.marginLeft = marginLeft; } if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') { offsets = includeScroll(offsets, parent); } return offsets; } function getViewportOffsetRectRelativeToArtbitraryNode(element) { var html = window.document.documentElement; var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); var width = Math.max(html.clientWidth, window.innerWidth || 0); var height = Math.max(html.clientHeight, window.innerHeight || 0); var scrollTop = getScroll(html); var scrollLeft = getScroll(html, 'left'); var offset = { top: scrollTop - relativeOffset.top + relativeOffset.marginTop, left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, width: width, height: height }; return getClientRect(offset); } /** * Check if the given element is fixed or is inside a fixed parent * @method * @memberof Popper.Utils * @argument {Element} element * @argument {Element} customContainer * @returns {Boolean} answer to "isFixed?" */ function isFixed(element) { var nodeName = element.nodeName; if (nodeName === 'BODY' || nodeName === 'HTML') { return false; } if (getStyleComputedProperty(element, 'position') === 'fixed') { return true; } return isFixed(getParentNode(element)); } /** * Computed the boundaries limits and return them * @method * @memberof Popper.Utils * @param {HTMLElement} popper * @param {HTMLElement} reference * @param {number} padding * @param {HTMLElement} boundariesElement - Element used to define the boundaries * @returns {Object} Coordinates of the boundaries */ function getBoundaries(popper, reference, padding, boundariesElement) { // NOTE: 1 DOM access here var boundaries = { top: 0, left: 0 }; var offsetParent = findCommonOffsetParent(popper, reference); // Handle viewport case if (boundariesElement === 'viewport') { boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent); } else { // Handle other cases based on DOM element used as boundaries var boundariesNode = void 0; if (boundariesElement === 'scrollParent') { boundariesNode = getScrollParent(getParentNode(popper)); if (boundariesNode.nodeName === 'BODY') { boundariesNode = window.document.documentElement; } } else if (boundariesElement === 'window') { boundariesNode = window.document.documentElement; } else { boundariesNode = boundariesElement; } var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent); // In case of HTML, we need a different computation if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { var _getWindowSizes = getWindowSizes(), height = _getWindowSizes.height, width = _getWindowSizes.width; boundaries.top += offsets.top - offsets.marginTop; boundaries.bottom = height + offsets.top; boundaries.left += offsets.left - offsets.marginLeft; boundaries.right = width + offsets.left; } else { // for all the other DOM elements, this one is good boundaries = offsets; } } // Add paddings boundaries.left += padding; boundaries.top += padding; boundaries.right -= padding; boundaries.bottom -= padding; return boundaries; } function getArea(_ref) { var width = _ref.width, height = _ref.height; return width * height; } /** * Utility used to transform the `auto` placement to the placement with more * available space. * @method * @memberof Popper.Utils * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) { var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; if (placement.indexOf('auto') === -1) { return placement; } var boundaries = getBoundaries(popper, reference, padding, boundariesElement); var rects = { top: { width: boundaries.width, height: refRect.top - boundaries.top }, right: { width: boundaries.right - refRect.right, height: boundaries.height }, bottom: { width: boundaries.width, height: boundaries.bottom - refRect.bottom }, left: { width: refRect.left - boundaries.left, height: boundaries.height } }; var sortedAreas = Object.keys(rects).map(function (key) { return _extends$1({ key: key }, rects[key], { area: getArea(rects[key]) }); }).sort(function (a, b) { return b.area - a.area; }); var filteredAreas = sortedAreas.filter(function (_ref2) { var width = _ref2.width, height = _ref2.height; return width >= popper.clientWidth && height >= popper.clientHeight; }); var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key; var variation = placement.split('-')[1]; return computedPlacement + (variation ? '-' + variation : ''); } /** * Get offsets to the reference element * @method * @memberof Popper.Utils * @param {Object} state * @param {Element} popper - the popper element * @param {Element} reference - the reference element (the popper will be relative to this) * @returns {Object} An object containing the offsets which will be applied to the popper */ function getReferenceOffsets(state, popper, reference) { var commonOffsetParent = findCommonOffsetParent(popper, reference); return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent); } /** * Get the outer sizes of the given element (offset size + margins) * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Object} object containing width and height properties */ function getOuterSizes(element) { var styles = window.getComputedStyle(element); var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom); var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight); var result = { width: element.offsetWidth + y, height: element.offsetHeight + x }; return result; } /** * Get the opposite placement of the given one * @method * @memberof Popper.Utils * @argument {String} placement * @returns {String} flipped placement */ function getOppositePlacement(placement) { var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; return placement.replace(/left|right|bottom|top/g, function (matched) { return hash[matched]; }); } /** * Get offsets to the popper * @method * @memberof Popper.Utils * @param {Object} position - CSS position the Popper will get applied * @param {HTMLElement} popper - the popper element * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) * @param {String} placement - one of the valid placement options * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper */ function getPopperOffsets(popper, referenceOffsets, placement) { placement = placement.split('-')[0]; // Get popper node sizes var popperRect = getOuterSizes(popper); // Add position, width and height to our offsets object var popperOffsets = { width: popperRect.width, height: popperRect.height }; // depending by the popper placement we have to compute its offsets slightly differently var isHoriz = ['right', 'left'].indexOf(placement) !== -1; var mainSide = isHoriz ? 'top' : 'left'; var secondarySide = isHoriz ? 'left' : 'top'; var measurement = isHoriz ? 'height' : 'width'; var secondaryMeasurement = !isHoriz ? 'height' : 'width'; popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2; if (placement === secondarySide) { popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; } else { popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)]; } return popperOffsets; } /** * Mimics the `find` method of Array * @method * @memberof Popper.Utils * @argument {Array} arr * @argument prop * @argument value * @returns index or -1 */ function find(arr, check) { // use native find if supported if (Array.prototype.find) { return arr.find(check); } // use `filter` to obtain the same behavior of `find` return arr.filter(check)[0]; } /** * Return the index of the matching object * @method * @memberof Popper.Utils * @argument {Array} arr * @argument prop * @argument value * @returns index or -1 */ function findIndex(arr, prop, value) { // use native findIndex if supported if (Array.prototype.findIndex) { return arr.findIndex(function (cur) { return cur[prop] === value; }); } // use `find` + `indexOf` if `findIndex` isn't supported var match = find(arr, function (obj) { return obj[prop] === value; }); return arr.indexOf(match); } /** * Loop trough the list of modifiers and run them in order, * each of them will then edit the data object. * @method * @memberof Popper.Utils * @param {dataObject} data * @param {Array} modifiers * @param {String} ends - Optional modifier name used as stopper * @returns {dataObject} */ function runModifiers(modifiers, data, ends) { var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends)); modifiersToRun.forEach(function (modifier) { if (modifier.function) { console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); } var fn = modifier.function || modifier.fn; if (modifier.enabled && isFunction(fn)) { // Add properties to offsets to make them a complete clientRect object // we do this before each modifier to make sure the previous one doesn't // mess with these values data.offsets.popper = getClientRect(data.offsets.popper); data.offsets.reference = getClientRect(data.offsets.reference); data = fn(data, modifier); } }); return data; } /** * Updates the position of the popper, computing the new offsets and applying * the new style.
            * Prefer `scheduleUpdate` over `update` because of performance reasons. * @method * @memberof Popper */ function update() { // if popper is destroyed, don't perform any further update if (this.state.isDestroyed) { return; } var data = { instance: this, styles: {}, arrowStyles: {}, attributes: {}, flipped: false, offsets: {} }; // compute reference element offsets data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference); // compute auto placement, store placement inside the data object, // modifiers will be able to edit `placement` if needed // and refer to originalPlacement to know the original value data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); // store the computed placement inside `originalPlacement` data.originalPlacement = data.placement; // compute the popper offsets data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement); data.offsets.popper.position = 'absolute'; // run the modifiers data = runModifiers(this.modifiers, data); // the first `update` will call `onCreate` callback // the other ones will call `onUpdate` callback if (!this.state.isCreated) { this.state.isCreated = true; this.options.onCreate(data); } else { this.options.onUpdate(data); } } /** * Helper used to know if the given modifier is enabled. * @method * @memberof Popper.Utils * @returns {Boolean} */ function isModifierEnabled(modifiers, modifierName) { return modifiers.some(function (_ref) { var name = _ref.name, enabled = _ref.enabled; return enabled && name === modifierName; }); } /** * Get the prefixed supported property name * @method * @memberof Popper.Utils * @argument {String} property (camelCase) * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) */ function getSupportedPropertyName(property) { var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; var upperProp = property.charAt(0).toUpperCase() + property.slice(1); for (var i = 0; i < prefixes.length - 1; i++) { var prefix = prefixes[i]; var toCheck = prefix ? '' + prefix + upperProp : property; if (typeof window.document.body.style[toCheck] !== 'undefined') { return toCheck; } } return null; } /** * Destroy the popper * @method * @memberof Popper */ function destroy() { this.state.isDestroyed = true; // touch DOM only if `applyStyle` modifier is enabled if (isModifierEnabled(this.modifiers, 'applyStyle')) { this.popper.removeAttribute('x-placement'); this.popper.style.left = ''; this.popper.style.position = ''; this.popper.style.top = ''; this.popper.style[getSupportedPropertyName('transform')] = ''; } this.disableEventListeners(); // remove the popper if user explicity asked for the deletion on destroy // do not use `remove` because IE11 doesn't support it if (this.options.removeOnDestroy) { this.popper.parentNode.removeChild(this.popper); } return this; } function attachToScrollParents(scrollParent, event, callback, scrollParents) { var isBody = scrollParent.nodeName === 'BODY'; var target = isBody ? window : scrollParent; target.addEventListener(event, callback, { passive: true }); if (!isBody) { attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); } scrollParents.push(target); } /** * Setup needed event listeners used to update the popper position * @method * @memberof Popper.Utils * @private */ function setupEventListeners(reference, options, state, updateBound) { // Resize event listener on window state.updateBound = updateBound; window.addEventListener('resize', state.updateBound, { passive: true }); // Scroll event listener on scroll parents var scrollElement = getScrollParent(reference); attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); state.scrollElement = scrollElement; state.eventsEnabled = true; return state; } /** * It will add resize/scroll events and start recalculating * position of the popper element when they are triggered. * @method * @memberof Popper */ function enableEventListeners() { if (!this.state.eventsEnabled) { this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate); } } /** * Remove event listeners used to update the popper position * @method * @memberof Popper.Utils * @private */ function removeEventListeners(reference, state) { // Remove resize event listener on window window.removeEventListener('resize', state.updateBound); // Remove scroll event listener on scroll parents state.scrollParents.forEach(function (target) { target.removeEventListener('scroll', state.updateBound); }); // Reset state state.updateBound = null; state.scrollParents = []; state.scrollElement = null; state.eventsEnabled = false; return state; } /** * It will remove resize/scroll events and won't recalculate popper position * when they are triggered. It also won't trigger onUpdate callback anymore, * unless you call `update` method manually. * @method * @memberof Popper */ function disableEventListeners() { if (this.state.eventsEnabled) { window.cancelAnimationFrame(this.scheduleUpdate); this.state = removeEventListeners(this.reference, this.state); } } /** * Tells if a given input is a number * @method * @memberof Popper.Utils * @param {*} input to check * @return {Boolean} */ function isNumeric(n) { return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); } /** * Set the style to the given popper * @method * @memberof Popper.Utils * @argument {Element} element - Element to apply the style to * @argument {Object} styles * Object with a list of properties and values which will be applied to the element */ function setStyles(element, styles) { Object.keys(styles).forEach(function (prop) { var unit = ''; // add unit if the value is numeric and is one of the following if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { unit = 'px'; } element.style[prop] = styles[prop] + unit; }); } /** * Set the attributes to the given popper * @method * @memberof Popper.Utils * @argument {Element} element - Element to apply the attributes to * @argument {Object} styles * Object with a list of properties and values which will be applied to the element */ function setAttributes(element, attributes) { Object.keys(attributes).forEach(function (prop) { var value = attributes[prop]; if (value !== false) { element.setAttribute(prop, attributes[prop]); } else { element.removeAttribute(prop); } }); } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} data.styles - List of style properties - values to apply to popper element * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element * @argument {Object} options - Modifiers configuration and options * @returns {Object} The same data object */ function applyStyle(data) { // any property present in `data.styles` will be applied to the popper, // in this way we can make the 3rd party modifiers add custom styles to it // Be aware, modifiers could override the properties defined in the previous // lines of this modifier! setStyles(data.instance.popper, data.styles); // any property present in `data.attributes` will be applied to the popper, // they will be set as HTML attributes of the element setAttributes(data.instance.popper, data.attributes); // if arrowElement is defined and arrowStyles has some properties if (data.arrowElement && Object.keys(data.arrowStyles).length) { setStyles(data.arrowElement, data.arrowStyles); } return data; } /** * Set the x-placement attribute before everything else because it could be used * to add margins to the popper margins needs to be calculated to get the * correct popper offsets. * @method * @memberof Popper.modifiers * @param {HTMLElement} reference - The reference element used to position the popper * @param {HTMLElement} popper - The HTML element used as popper. * @param {Object} options - Popper.js options */ function applyStyleOnLoad(reference, popper, options, modifierOptions, state) { // compute reference element offsets var referenceOffsets = getReferenceOffsets(state, popper, reference); // compute auto placement, store placement inside the data object, // modifiers will be able to edit `placement` if needed // and refer to originalPlacement to know the original value var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding); popper.setAttribute('x-placement', placement); // Apply `position` to popper before anything else because // without the position applied we can't guarantee correct computations setStyles(popper, { position: 'absolute' }); return options; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function computeStyle(data, options) { var x = options.x, y = options.y; var popper = data.offsets.popper; // Remove this legacy support in Popper.js v2 var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) { return modifier.name === 'applyStyle'; }).gpuAcceleration; if (legacyGpuAccelerationOption !== undefined) { console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!'); } var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration; var offsetParent = getOffsetParent(data.instance.popper); var offsetParentRect = getBoundingClientRect(offsetParent); // Styles var styles = { position: popper.position }; // floor sides to avoid blurry text var offsets = { left: Math.floor(popper.left), top: Math.floor(popper.top), bottom: Math.floor(popper.bottom), right: Math.floor(popper.right) }; var sideA = x === 'bottom' ? 'top' : 'bottom'; var sideB = y === 'right' ? 'left' : 'right'; // if gpuAcceleration is set to `true` and transform is supported, // we use `translate3d` to apply the position to the popper we // automatically use the supported prefixed version if needed var prefixedProperty = getSupportedPropertyName('transform'); // now, let's make a step back and look at this code closely (wtf?) // If the content of the popper grows once it's been positioned, it // may happen that the popper gets misplaced because of the new content // overflowing its reference element // To avoid this problem, we provide two options (x and y), which allow // the consumer to define the offset origin. // If we position a popper on top of a reference element, we can set // `x` to `top` to make the popper grow towards its top instead of // its bottom. var left = void 0, top = void 0; if (sideA === 'bottom') { top = -offsetParentRect.height + offsets.bottom; } else { top = offsets.top; } if (sideB === 'right') { left = -offsetParentRect.width + offsets.right; } else { left = offsets.left; } if (gpuAcceleration && prefixedProperty) { styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; styles[sideA] = 0; styles[sideB] = 0; styles.willChange = 'transform'; } else { // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties var invertTop = sideA === 'bottom' ? -1 : 1; var invertLeft = sideB === 'right' ? -1 : 1; styles[sideA] = top * invertTop; styles[sideB] = left * invertLeft; styles.willChange = sideA + ', ' + sideB; } // Attributes var attributes = { 'x-placement': data.placement }; // Update `data` attributes, styles and arrowStyles data.attributes = _extends$1({}, attributes, data.attributes); data.styles = _extends$1({}, styles, data.styles); data.arrowStyles = _extends$1({}, data.offsets.arrow, data.arrowStyles); return data; } /** * Helper used to know if the given modifier depends from another one.
            * It checks if the needed modifier is listed and enabled. * @method * @memberof Popper.Utils * @param {Array} modifiers - list of modifiers * @param {String} requestingName - name of requesting modifier * @param {String} requestedName - name of requested modifier * @returns {Boolean} */ function isModifierRequired(modifiers, requestingName, requestedName) { var requesting = find(modifiers, function (_ref) { var name = _ref.name; return name === requestingName; }); var isRequired = !!requesting && modifiers.some(function (modifier) { return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; }); if (!isRequired) { var _requesting = '`' + requestingName + '`'; var requested = '`' + requestedName + '`'; console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); } return isRequired; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function arrow(data, options) { // arrow depends on keepTogether in order to work if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { return data; } var arrowElement = options.element; // if arrowElement is a string, suppose it's a CSS selector if (typeof arrowElement === 'string') { arrowElement = data.instance.popper.querySelector(arrowElement); // if arrowElement is not found, don't run the modifier if (!arrowElement) { return data; } } else { // if the arrowElement isn't a query selector we must check that the // provided DOM node is child of its popper node if (!data.instance.popper.contains(arrowElement)) { console.warn('WARNING: `arrow.element` must be child of its popper element!'); return data; } } var placement = data.placement.split('-')[0]; var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var isVertical = ['left', 'right'].indexOf(placement) !== -1; var len = isVertical ? 'height' : 'width'; var sideCapitalized = isVertical ? 'Top' : 'Left'; var side = sideCapitalized.toLowerCase(); var altSide = isVertical ? 'left' : 'top'; var opSide = isVertical ? 'bottom' : 'right'; var arrowElementSize = getOuterSizes(arrowElement)[len]; // // extends keepTogether behavior making sure the popper and its // reference have enough pixels in conjuction // // top/left side if (reference[opSide] - arrowElementSize < popper[side]) { data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize); } // bottom/right side if (reference[side] + arrowElementSize > popper[opSide]) { data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide]; } // compute center of the popper var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; // Compute the sideValue using the updated popper offsets // take popper margin in account because we don't have this info available var popperMarginSide = getStyleComputedProperty(data.instance.popper, 'margin' + sideCapitalized).replace('px', ''); var sideValue = center - getClientRect(data.offsets.popper)[side] - popperMarginSide; // prevent arrowElement from being placed not contiguously to its popper sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); data.arrowElement = arrowElement; data.offsets.arrow = {}; data.offsets.arrow[side] = Math.round(sideValue); data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node return data; } /** * Get the opposite placement variation of the given one * @method * @memberof Popper.Utils * @argument {String} placement variation * @returns {String} flipped placement variation */ function getOppositeVariation(variation) { if (variation === 'end') { return 'start'; } else if (variation === 'start') { return 'end'; } return variation; } /** * List of accepted placements to use as values of the `placement` option.
            * Valid placements are: * - `auto` * - `top` * - `right` * - `bottom` * - `left` * * Each placement can have a variation from this list: * - `-start` * - `-end` * * Variations are interpreted easily if you think of them as the left to right * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` * is right.
            * Vertically (`left` and `right`), `start` is top and `end` is bottom. * * Some valid examples are: * - `top-end` (on top of reference, right aligned) * - `right-start` (on right of reference, top aligned) * - `bottom` (on bottom, centered) * - `auto-right` (on the side with more space available, alignment depends by placement) * * @static * @type {Array} * @enum {String} * @readonly * @method placements * @memberof Popper */ var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; // Get rid of `auto` `auto-start` and `auto-end` var validPlacements = placements.slice(3); /** * Given an initial placement, returns all the subsequent placements * clockwise (or counter-clockwise). * * @method * @memberof Popper.Utils * @argument {String} placement - A valid placement (it accepts variations) * @argument {Boolean} counter - Set to true to walk the placements counterclockwise * @returns {Array} placements including their variations */ function clockwise(placement) { var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var index = validPlacements.indexOf(placement); var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index)); return counter ? arr.reverse() : arr; } var BEHAVIORS = { FLIP: 'flip', CLOCKWISE: 'clockwise', COUNTERCLOCKWISE: 'counterclockwise' }; /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function flip(data, options) { // if `inner` modifier is enabled, we can't use the `flip` modifier if (isModifierEnabled(data.instance.modifiers, 'inner')) { return data; } if (data.flipped && data.placement === data.originalPlacement) { // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides return data; } var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement); var placement = data.placement.split('-')[0]; var placementOpposite = getOppositePlacement(placement); var variation = data.placement.split('-')[1] || ''; var flipOrder = []; switch (options.behavior) { case BEHAVIORS.FLIP: flipOrder = [placement, placementOpposite]; break; case BEHAVIORS.CLOCKWISE: flipOrder = clockwise(placement); break; case BEHAVIORS.COUNTERCLOCKWISE: flipOrder = clockwise(placement, true); break; default: flipOrder = options.behavior; } flipOrder.forEach(function (step, index) { if (placement !== step || flipOrder.length === index + 1) { return data; } placement = data.placement.split('-')[0]; placementOpposite = getOppositePlacement(placement); var popperOffsets = data.offsets.popper; var refOffsets = data.offsets.reference; // using floor because the reference offsets may contain decimals we are not going to consider here var floor = Math.floor; var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom); var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom); var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; // flip the variation if required var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); if (overlapsRef || overflowsBoundaries || flippedVariation) { // this boolean to detect any flip loop data.flipped = true; if (overlapsRef || overflowsBoundaries) { placement = flipOrder[index + 1]; } if (flippedVariation) { variation = getOppositeVariation(variation); } data.placement = placement + (variation ? '-' + variation : ''); // this object contains `position`, we want to preserve it along with // any additional property we may add in the future data.offsets.popper = _extends$1({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement)); data = runModifiers(data.instance.modifiers, data, 'flip'); } }); return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function keepTogether(data) { var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var placement = data.placement.split('-')[0]; var floor = Math.floor; var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; var side = isVertical ? 'right' : 'bottom'; var opSide = isVertical ? 'left' : 'top'; var measurement = isVertical ? 'width' : 'height'; if (popper[side] < floor(reference[opSide])) { data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement]; } if (popper[opSide] > floor(reference[side])) { data.offsets.popper[opSide] = floor(reference[side]); } return data; } /** * Converts a string containing value + unit into a px value number * @function * @memberof {modifiers~offset} * @private * @argument {String} str - Value + unit string * @argument {String} measurement - `height` or `width` * @argument {Object} popperOffsets * @argument {Object} referenceOffsets * @returns {Number|String} * Value in pixels, or original string if no values were extracted */ function toValue(str, measurement, popperOffsets, referenceOffsets) { // separate value from unit var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); var value = +split[1]; var unit = split[2]; // If it's not a number it's an operator, I guess if (!value) { return str; } if (unit.indexOf('%') === 0) { var element = void 0; switch (unit) { case '%p': element = popperOffsets; break; case '%': case '%r': default: element = referenceOffsets; } var rect = getClientRect(element); return rect[measurement] / 100 * value; } else if (unit === 'vh' || unit === 'vw') { // if is a vh or vw, we calculate the size based on the viewport var size = void 0; if (unit === 'vh') { size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); } else { size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); } return size / 100 * value; } else { // if is an explicit pixel unit, we get rid of the unit and keep the value // if is an implicit unit, it's px, and we return just the value return value; } } /** * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. * @function * @memberof {modifiers~offset} * @private * @argument {String} offset * @argument {Object} popperOffsets * @argument {Object} referenceOffsets * @argument {String} basePlacement * @returns {Array} a two cells array with x and y offsets in numbers */ function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) { var offsets = [0, 0]; // Use height if placement is left or right and index is 0 otherwise use width // in this way the first offset will use an axis and the second one // will use the other one var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; // Split the offset string to obtain a list of values and operands // The regex addresses values with the plus or minus sign in front (+10, -20, etc) var fragments = offset.split(/(\+|\-)/).map(function (frag) { return frag.trim(); }); // Detect if the offset string contains a pair of values or a single one // they could be separated by comma or space var divider = fragments.indexOf(find(fragments, function (frag) { return frag.search(/,|\s/) !== -1; })); if (fragments[divider] && fragments[divider].indexOf(',') === -1) { console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'); } // If divider is found, we divide the list of values and operands to divide // them by ofset X and Y. var splitRegex = /\s*,\s*|\s+/; var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; // Convert the values with units to absolute pixels to allow our computations ops = ops.map(function (op, index) { // Most of the units rely on the orientation of the popper var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width'; var mergeWithPrevious = false; return op // This aggregates any `+` or `-` sign that aren't considered operators // e.g.: 10 + +5 => [10, +, +5] .reduce(function (a, b) { if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { a[a.length - 1] = b; mergeWithPrevious = true; return a; } else if (mergeWithPrevious) { a[a.length - 1] += b; mergeWithPrevious = false; return a; } else { return a.concat(b); } }, []) // Here we convert the string values into number values (in px) .map(function (str) { return toValue(str, measurement, popperOffsets, referenceOffsets); }); }); // Loop trough the offsets arrays and execute the operations ops.forEach(function (op, index) { op.forEach(function (frag, index2) { if (isNumeric(frag)) { offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); } }); }); return offsets; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @argument {Number|String} options.offset=0 * The offset value as described in the modifier description * @returns {Object} The data object, properly modified */ function offset(data, _ref) { var offset = _ref.offset; var placement = data.placement, _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var basePlacement = placement.split('-')[0]; var offsets = void 0; if (isNumeric(+offset)) { offsets = [+offset, 0]; } else { offsets = parseOffset(offset, popper, reference, basePlacement); } if (basePlacement === 'left') { popper.top += offsets[0]; popper.left -= offsets[1]; } else if (basePlacement === 'right') { popper.top += offsets[0]; popper.left += offsets[1]; } else if (basePlacement === 'top') { popper.left += offsets[0]; popper.top -= offsets[1]; } else if (basePlacement === 'bottom') { popper.left += offsets[0]; popper.top += offsets[1]; } data.popper = popper; return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function preventOverflow(data, options) { var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); // If offsetParent is the reference element, we really want to // go one step up and use the next offsetParent as reference to // avoid to make this modifier completely useless and look like broken if (data.instance.reference === boundariesElement) { boundariesElement = getOffsetParent(boundariesElement); } var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement); options.boundaries = boundaries; var order = options.priority; var popper = data.offsets.popper; var check = { primary: function primary(placement) { var value = popper[placement]; if (popper[placement] < boundaries[placement] && !options.escapeWithReference) { value = Math.max(popper[placement], boundaries[placement]); } return defineProperty({}, placement, value); }, secondary: function secondary(placement) { var mainSide = placement === 'right' ? 'left' : 'top'; var value = popper[mainSide]; if (popper[placement] > boundaries[placement] && !options.escapeWithReference) { value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height)); } return defineProperty({}, mainSide, value); } }; order.forEach(function (placement) { var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; popper = _extends$1({}, popper, check[side](placement)); }); data.offsets.popper = popper; return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function shift(data) { var placement = data.placement; var basePlacement = placement.split('-')[0]; var shiftvariation = placement.split('-')[1]; // if shift shiftvariation is specified, run the modifier if (shiftvariation) { var _data$offsets = data.offsets, reference = _data$offsets.reference, popper = _data$offsets.popper; var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; var side = isVertical ? 'left' : 'top'; var measurement = isVertical ? 'width' : 'height'; var shiftOffsets = { start: defineProperty({}, side, reference[side]), end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement]) }; data.offsets.popper = _extends$1({}, popper, shiftOffsets[shiftvariation]); } return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function hide(data) { if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { return data; } var refRect = data.offsets.reference; var bound = find(data.instance.modifiers, function (modifier) { return modifier.name === 'preventOverflow'; }).boundaries; if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) { // Avoid unnecessary DOM access if visibility hasn't changed if (data.hide === true) { return data; } data.hide = true; data.attributes['x-out-of-boundaries'] = ''; } else { // Avoid unnecessary DOM access if visibility hasn't changed if (data.hide === false) { return data; } data.hide = false; data.attributes['x-out-of-boundaries'] = false; } return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function inner(data) { var placement = data.placement; var basePlacement = placement.split('-')[0]; var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); data.placement = getOppositePlacement(placement); data.offsets.popper = getClientRect(popper); return data; } /** * Modifier function, each modifier can have a function of this type assigned * to its `fn` property.
            * These functions will be called on each update, this means that you must * make sure they are performant enough to avoid performance bottlenecks. * * @function ModifierFn * @argument {dataObject} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {dataObject} The data object, properly modified */ /** * Modifiers are plugins used to alter the behavior of your poppers.
            * Popper.js uses a set of 9 modifiers to provide all the basic functionalities * needed by the library. * * Usually you don't want to override the `order`, `fn` and `onLoad` props. * All the other properties are configurations that could be tweaked. * @namespace modifiers */ var modifiers = { /** * Modifier used to shift the popper on the start or end of its reference * element.
            * It will read the variation of the `placement` property.
            * It can be one either `-end` or `-start`. * @memberof modifiers * @inner */ shift: { /** @prop {number} order=100 - Index used to define the order of execution */ order: 100, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: shift }, /** * The `offset` modifier can shift your popper on both its axis. * * It accepts the following units: * - `px` or unitless, interpreted as pixels * - `%` or `%r`, percentage relative to the length of the reference element * - `%p`, percentage relative to the length of the popper element * - `vw`, CSS viewport width unit * - `vh`, CSS viewport height unit * * For length is intended the main axis relative to the placement of the popper.
            * This means that if the placement is `top` or `bottom`, the length will be the * `width`. In case of `left` or `right`, it will be the height. * * You can provide a single value (as `Number` or `String`), or a pair of values * as `String` divided by a comma or one (or more) white spaces.
            * The latter is a deprecated method because it leads to confusion and will be * removed in v2.
            * Additionally, it accepts additions and subtractions between different units. * Note that multiplications and divisions aren't supported. * * Valid examples are: * ``` * 10 * '10%' * '10, 10' * '10%, 10' * '10 + 10%' * '10 - 5vh + 3%' * '-10px + 5vh, 5px - 6%' * ``` * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap * > with their reference element, unfortunately, you will have to disable the `flip` modifier. * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373) * * @memberof modifiers * @inner */ offset: { /** @prop {number} order=200 - Index used to define the order of execution */ order: 200, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: offset, /** @prop {Number|String} offset=0 * The offset value as described in the modifier description */ offset: 0 }, /** * Modifier used to prevent the popper from being positioned outside the boundary. * * An scenario exists where the reference itself is not within the boundaries.
            * We can say it has "escaped the boundaries" — or just "escaped".
            * In this case we need to decide whether the popper should either: * * - detach from the reference and remain "trapped" in the boundaries, or * - if it should ignore the boundary and "escape with its reference" * * When `escapeWithReference` is set to`true` and reference is completely * outside its boundaries, the popper will overflow (or completely leave) * the boundaries in order to remain attached to the edge of the reference. * * @memberof modifiers * @inner */ preventOverflow: { /** @prop {number} order=300 - Index used to define the order of execution */ order: 300, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: preventOverflow, /** * @prop {Array} [priority=['left','right','top','bottom']] * Popper will try to prevent overflow following these priorities by default, * then, it could overflow on the left and on top of the `boundariesElement` */ priority: ['left', 'right', 'top', 'bottom'], /** * @prop {number} padding=5 * Amount of pixel used to define a minimum distance between the boundaries * and the popper this makes sure the popper has always a little padding * between the edges of its container */ padding: 5, /** * @prop {String|HTMLElement} boundariesElement='scrollParent' * Boundaries used by the modifier, can be `scrollParent`, `window`, * `viewport` or any DOM element. */ boundariesElement: 'scrollParent' }, /** * Modifier used to make sure the reference and its popper stay near eachothers * without leaving any gap between the two. Expecially useful when the arrow is * enabled and you want to assure it to point to its reference element. * It cares only about the first axis, you can still have poppers with margin * between the popper and its reference element. * @memberof modifiers * @inner */ keepTogether: { /** @prop {number} order=400 - Index used to define the order of execution */ order: 400, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: keepTogether }, /** * This modifier is used to move the `arrowElement` of the popper to make * sure it is positioned between the reference element and its popper element. * It will read the outer size of the `arrowElement` node to detect how many * pixels of conjuction are needed. * * It has no effect if no `arrowElement` is provided. * @memberof modifiers * @inner */ arrow: { /** @prop {number} order=500 - Index used to define the order of execution */ order: 500, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: arrow, /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */ element: '[x-arrow]' }, /** * Modifier used to flip the popper's placement when it starts to overlap its * reference element. * * Requires the `preventOverflow` modifier before it in order to work. * * **NOTE:** this modifier will interrupt the current update cycle and will * restart it if it detects the need to flip the placement. * @memberof modifiers * @inner */ flip: { /** @prop {number} order=600 - Index used to define the order of execution */ order: 600, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: flip, /** * @prop {String|Array} behavior='flip' * The behavior used to change the popper's placement. It can be one of * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid * placements (with optional variations). */ behavior: 'flip', /** * @prop {number} padding=5 * The popper will flip if it hits the edges of the `boundariesElement` */ padding: 5, /** * @prop {String|HTMLElement} boundariesElement='viewport' * The element which will define the boundaries of the popper position, * the popper will never be placed outside of the defined boundaries * (except if keepTogether is enabled) */ boundariesElement: 'viewport' }, /** * Modifier used to make the popper flow toward the inner of the reference element. * By default, when this modifier is disabled, the popper will be placed outside * the reference element. * @memberof modifiers * @inner */ inner: { /** @prop {number} order=700 - Index used to define the order of execution */ order: 700, /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */ enabled: false, /** @prop {ModifierFn} */ fn: inner }, /** * Modifier used to hide the popper when its reference element is outside of the * popper boundaries. It will set a `x-out-of-boundaries` attribute which can * be used to hide with a CSS selector the popper when its reference is * out of boundaries. * * Requires the `preventOverflow` modifier before it in order to work. * @memberof modifiers * @inner */ hide: { /** @prop {number} order=800 - Index used to define the order of execution */ order: 800, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: hide }, /** * Computes the style that will be applied to the popper element to gets * properly positioned. * * Note that this modifier will not touch the DOM, it just prepares the styles * so that `applyStyle` modifier can apply it. This separation is useful * in case you need to replace `applyStyle` with a custom implementation. * * This modifier has `850` as `order` value to maintain backward compatibility * with previous versions of Popper.js. Expect the modifiers ordering method * to change in future major versions of the library. * * @memberof modifiers * @inner */ computeStyle: { /** @prop {number} order=850 - Index used to define the order of execution */ order: 850, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: computeStyle, /** * @prop {Boolean} gpuAcceleration=true * If true, it uses the CSS 3d transformation to position the popper. * Otherwise, it will use the `top` and `left` properties. */ gpuAcceleration: true, /** * @prop {string} [x='bottom'] * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin. * Change this if your popper should grow in a direction different from `bottom` */ x: 'bottom', /** * @prop {string} [x='left'] * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin. * Change this if your popper should grow in a direction different from `right` */ y: 'right' }, /** * Applies the computed styles to the popper element. * * All the DOM manipulations are limited to this modifier. This is useful in case * you want to integrate Popper.js inside a framework or view library and you * want to delegate all the DOM manipulations to it. * * Note that if you disable this modifier, you must make sure the popper element * has its position set to `absolute` before Popper.js can do its work! * * Just disable this modifier and define you own to achieve the desired effect. * * @memberof modifiers * @inner */ applyStyle: { /** @prop {number} order=900 - Index used to define the order of execution */ order: 900, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: applyStyle, /** @prop {Function} */ onLoad: applyStyleOnLoad, /** * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier * @prop {Boolean} gpuAcceleration=true * If true, it uses the CSS 3d transformation to position the popper. * Otherwise, it will use the `top` and `left` properties. */ gpuAcceleration: undefined } }; /** * The `dataObject` is an object containing all the informations used by Popper.js * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks. * @name dataObject * @property {Object} data.instance The Popper.js instance * @property {String} data.placement Placement applied to popper * @property {String} data.originalPlacement Placement originally defined on init * @property {Boolean} data.flipped True if popper has been flipped by flip modifier * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper. * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`) * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`) * @property {Object} data.boundaries Offsets of the popper boundaries * @property {Object} data.offsets The measurements of popper, reference and arrow elements. * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0 */ /** * Default options provided to Popper.js constructor.
            * These can be overriden using the `options` argument of Popper.js.
            * To override an option, simply pass as 3rd argument an object with the same * structure of this object, example: * ``` * new Popper(ref, pop, { * modifiers: { * preventOverflow: { enabled: false } * } * }) * ``` * @type {Object} * @static * @memberof Popper */ var Defaults = { /** * Popper's placement * @prop {Popper.placements} placement='bottom' */ placement: 'bottom', /** * Whether events (resize, scroll) are initially enabled * @prop {Boolean} eventsEnabled=true */ eventsEnabled: true, /** * Set to true if you want to automatically remove the popper when * you call the `destroy` method. * @prop {Boolean} removeOnDestroy=false */ removeOnDestroy: false, /** * Callback called when the popper is created.
            * By default, is set to no-op.
            * Access Popper.js instance with `data.instance`. * @prop {onCreate} */ onCreate: function onCreate() {}, /** * Callback called when the popper is updated, this callback is not called * on the initialization/creation of the popper, but only on subsequent * updates.
            * By default, is set to no-op.
            * Access Popper.js instance with `data.instance`. * @prop {onUpdate} */ onUpdate: function onUpdate() {}, /** * List of modifiers used to modify the offsets before they are applied to the popper. * They provide most of the functionalities of Popper.js * @prop {modifiers} */ modifiers: modifiers }; /** * @callback onCreate * @param {dataObject} data */ /** * @callback onUpdate * @param {dataObject} data */ // Utils // Methods var Popper = function () { /** * Create a new Popper.js instance * @class Popper * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper * @param {HTMLElement} popper - The HTML element used as popper. * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) * @return {Object} instance - The generated Popper.js instance */ function Popper(reference, popper) { var _this = this; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; classCallCheck(this, Popper); this.scheduleUpdate = function () { return requestAnimationFrame(_this.update); }; // make update() debounced, so that it only runs at most once-per-tick this.update = debounce(this.update.bind(this)); // with {} we create a new object with the options inside it this.options = _extends$1({}, Popper.Defaults, options); // init state this.state = { isDestroyed: false, isCreated: false, scrollParents: [] }; // get reference and popper elements (allow jQuery wrappers) this.reference = reference.jquery ? reference[0] : reference; this.popper = popper.jquery ? popper[0] : popper; // Deep merge modifiers options this.options.modifiers = {}; Object.keys(_extends$1({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) { _this.options.modifiers[name] = _extends$1({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {}); }); // Refactoring modifiers' list (Object => Array) this.modifiers = Object.keys(this.options.modifiers).map(function (name) { return _extends$1({ name: name }, _this.options.modifiers[name]); }) // sort the modifiers by order .sort(function (a, b) { return a.order - b.order; }); // modifiers have the ability to execute arbitrary code when Popper.js get inited // such code is executed in the same order of its modifier // they could add new properties to their options configuration // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! this.modifiers.forEach(function (modifierOptions) { if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state); } }); // fire the first update to position the popper in the right place this.update(); var eventsEnabled = this.options.eventsEnabled; if (eventsEnabled) { // setup event listeners, they will take care of update the position in specific situations this.enableEventListeners(); } this.state.eventsEnabled = eventsEnabled; } // We can't use class properties because they don't get listed in the // class prototype and break stuff like Sinon stubs createClass$1(Popper, [{ key: 'update', value: function update$$1() { return update.call(this); } }, { key: 'destroy', value: function destroy$$1() { return destroy.call(this); } }, { key: 'enableEventListeners', value: function enableEventListeners$$1() { return enableEventListeners.call(this); } }, { key: 'disableEventListeners', value: function disableEventListeners$$1() { return disableEventListeners.call(this); } /** * Schedule an update, it will run on the next UI update available * @method scheduleUpdate * @memberof Popper */ /** * Collection of utilities useful when writing custom modifiers. * Starting from version 1.7, this method is available only if you * include `popper-utils.js` before `popper.js`. * * **DEPRECATION**: This way to access PopperUtils is deprecated * and will be removed in v2! Use the PopperUtils module directly instead. * Due to the high instability of the methods contained in Utils, we can't * guarantee them to follow semver. Use them at your own risk! * @static * @private * @type {Object} * @deprecated since version 1.8 * @member Utils * @memberof Popper */ }]); return Popper; }(); /** * The `referenceObject` is an object that provides an interface compatible with Popper.js * and lets you use it as replacement of a real DOM node.
            * You can use this method to position a popper relatively to a set of coordinates * in case you don't have a DOM node to use as reference. * * ``` * new Popper(referenceObject, popperNode); * ``` * * NB: This feature isn't supported in Internet Explorer 10 * @name referenceObject * @property {Function} data.getBoundingClientRect * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. * @property {number} data.clientWidth * An ES6 getter that will return the width of the virtual reference element. * @property {number} data.clientHeight * An ES6 getter that will return the height of the virtual reference element. */ Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; Popper.placements = placements; Popper.Defaults = Defaults; /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Dropdown = function () { /** * Check for Popper dependency * Popper - https://popper.js.org */ if (typeof Popper === 'undefined') { throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)'); } /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'dropdown'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.dropdown'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, CLICK: "click" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY, KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY }; var ClassName = { DISABLED: 'disabled', SHOW: 'show', DROPUP: 'dropup', MENURIGHT: 'dropdown-menu-right', MENULEFT: 'dropdown-menu-left' }; var Selector = { DATA_TOGGLE: '[data-toggle="dropdown"]', FORM_CHILD: '.dropdown form', MENU: '.dropdown-menu', NAVBAR_NAV: '.navbar-nav', VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)' }; var AttachmentMap = { TOP: 'top-start', TOPEND: 'top-end', BOTTOM: 'bottom-start', BOTTOMEND: 'bottom-end' }; var Default = { offset: 0, flip: true }; var DefaultType = { offset: '(number|string|function)', flip: 'boolean' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Dropdown = /*#__PURE__*/ function () { function Dropdown(element, config) { this._element = element; this._popper = null; this._config = this._getConfig(config); this._menu = this._getMenuElement(); this._inNavbar = this._detectNavbar(); this._addEventListeners(); } // getters var _proto = Dropdown.prototype; // public _proto.toggle = function toggle() { if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) { return; } var parent = Dropdown._getParentFromElement(this._element); var isActive = $(this._menu).hasClass(ClassName.SHOW); Dropdown._clearMenus(); if (isActive) { return; } var relatedTarget = { relatedTarget: this._element }; var showEvent = $.Event(Event.SHOW, relatedTarget); $(parent).trigger(showEvent); if (showEvent.isDefaultPrevented()) { return; } var element = this._element; // for dropup with alignment we use the parent as popper container if ($(parent).hasClass(ClassName.DROPUP)) { if ($(this._menu).hasClass(ClassName.MENULEFT) || $(this._menu).hasClass(ClassName.MENURIGHT)) { element = parent; } } this._popper = new Popper(element, this._menu, this._getPopperConfig()); // if this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) { $('body').children().on('mouseover', null, $.noop); } this._element.focus(); this._element.setAttribute('aria-expanded', true); $(this._menu).toggleClass(ClassName.SHOW); $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget)); }; _proto.dispose = function dispose() { $.removeData(this._element, DATA_KEY); $(this._element).off(EVENT_KEY); this._element = null; this._menu = null; if (this._popper !== null) { this._popper.destroy(); } this._popper = null; }; _proto.update = function update() { this._inNavbar = this._detectNavbar(); if (this._popper !== null) { this._popper.scheduleUpdate(); } }; // private _proto._addEventListeners = function _addEventListeners() { var _this = this; $(this._element).on(Event.CLICK, function (event) { event.preventDefault(); event.stopPropagation(); _this.toggle(); }); }; _proto._getConfig = function _getConfig(config) { config = $.extend({}, this.constructor.Default, $(this._element).data(), config); Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); return config; }; _proto._getMenuElement = function _getMenuElement() { if (!this._menu) { var parent = Dropdown._getParentFromElement(this._element); this._menu = $(parent).find(Selector.MENU)[0]; } return this._menu; }; _proto._getPlacement = function _getPlacement() { var $parentDropdown = $(this._element).parent(); var placement = AttachmentMap.BOTTOM; // Handle dropup if ($parentDropdown.hasClass(ClassName.DROPUP)) { placement = AttachmentMap.TOP; if ($(this._menu).hasClass(ClassName.MENURIGHT)) { placement = AttachmentMap.TOPEND; } } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) { placement = AttachmentMap.BOTTOMEND; } return placement; }; _proto._detectNavbar = function _detectNavbar() { return $(this._element).closest('.navbar').length > 0; }; _proto._getPopperConfig = function _getPopperConfig() { var _this2 = this; var offsetConf = {}; if (typeof this._config.offset === 'function') { offsetConf.fn = function (data) { data.offsets = $.extend({}, data.offsets, _this2._config.offset(data.offsets) || {}); return data; }; } else { offsetConf.offset = this._config.offset; } var popperConfig = { placement: this._getPlacement(), modifiers: { offset: offsetConf, flip: { enabled: this._config.flip } } // Disable Popper.js for Dropdown in Navbar }; if (this._inNavbar) { popperConfig.modifiers.applyStyle = { enabled: !this._inNavbar }; } return popperConfig; }; // static Dropdown._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $(this).data(DATA_KEY); var _config = typeof config === 'object' ? config : null; if (!data) { data = new Dropdown(this, _config); $(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; Dropdown._clearMenus = function _clearMenus(event) { if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { return; } var toggles = $.makeArray($(Selector.DATA_TOGGLE)); for (var i = 0; i < toggles.length; i++) { var parent = Dropdown._getParentFromElement(toggles[i]); var context = $(toggles[i]).data(DATA_KEY); var relatedTarget = { relatedTarget: toggles[i] }; if (!context) { continue; } var dropdownMenu = context._menu; if (!$(parent).hasClass(ClassName.SHOW)) { continue; } if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) { continue; } var hideEvent = $.Event(Event.HIDE, relatedTarget); $(parent).trigger(hideEvent); if (hideEvent.isDefaultPrevented()) { continue; } // if this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { $('body').children().off('mouseover', null, $.noop); } toggles[i].setAttribute('aria-expanded', 'false'); $(dropdownMenu).removeClass(ClassName.SHOW); $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget)); } }; Dropdown._getParentFromElement = function _getParentFromElement(element) { var parent; var selector = Util.getSelectorFromElement(element); if (selector) { parent = $(selector)[0]; } return parent || element.parentNode; }; Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE || /input|textarea/i.test(event.target.tagName)) { return; } event.preventDefault(); event.stopPropagation(); if (this.disabled || $(this).hasClass(ClassName.DISABLED)) { return; } var parent = Dropdown._getParentFromElement(this); var isActive = $(parent).hasClass(ClassName.SHOW); if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { if (event.which === ESCAPE_KEYCODE) { var toggle = $(parent).find(Selector.DATA_TOGGLE)[0]; $(toggle).trigger('focus'); } $(this).trigger('click'); return; } var items = $(parent).find(Selector.VISIBLE_ITEMS).get(); if (!items.length) { return; } var index = items.indexOf(event.target); if (event.which === ARROW_UP_KEYCODE && index > 0) { // up index--; } if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // down index++; } if (index < 0) { index = 0; } items[index].focus(); }; createClass(Dropdown, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }, { key: "DefaultType", get: function get() { return DefaultType; } }]); return Dropdown; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { event.preventDefault(); event.stopPropagation(); Dropdown._jQueryInterface.call($(this), 'toggle'); }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { e.stopPropagation(); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Dropdown._jQueryInterface; $.fn[NAME].Constructor = Dropdown; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Dropdown._jQueryInterface; }; return Dropdown; }($, Popper); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Modal = function () { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'modal'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.modal'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var TRANSITION_DURATION = 300; var BACKDROP_TRANSITION_DURATION = 150; var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key var Default = { backdrop: true, keyboard: true, focus: true, show: true }; var DefaultType = { backdrop: '(boolean|string)', keyboard: 'boolean', focus: 'boolean', show: 'boolean' }; var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, FOCUSIN: "focusin" + EVENT_KEY, RESIZE: "resize" + EVENT_KEY, CLICK_DISMISS: "click.dismiss" + EVENT_KEY, KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY, MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY, MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { SCROLLBAR_MEASURER: 'modal-scrollbar-measure', BACKDROP: 'modal-backdrop', OPEN: 'modal-open', FADE: 'fade', SHOW: 'show' }; var Selector = { DIALOG: '.modal-dialog', DATA_TOGGLE: '[data-toggle="modal"]', DATA_DISMISS: '[data-dismiss="modal"]', FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', STICKY_CONTENT: '.sticky-top', NAVBAR_TOGGLER: '.navbar-toggler' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Modal = /*#__PURE__*/ function () { function Modal(element, config) { this._config = this._getConfig(config); this._element = element; this._dialog = $(element).find(Selector.DIALOG)[0]; this._backdrop = null; this._isShown = false; this._isBodyOverflowing = false; this._ignoreBackdropClick = false; this._originalBodyPadding = 0; this._scrollbarWidth = 0; } // getters var _proto = Modal.prototype; // public _proto.toggle = function toggle(relatedTarget) { return this._isShown ? this.hide() : this.show(relatedTarget); }; _proto.show = function show(relatedTarget) { var _this = this; if (this._isTransitioning || this._isShown) { return; } if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) { this._isTransitioning = true; } var showEvent = $.Event(Event.SHOW, { relatedTarget: relatedTarget }); $(this._element).trigger(showEvent); if (this._isShown || showEvent.isDefaultPrevented()) { return; } this._isShown = true; this._checkScrollbar(); this._setScrollbar(); this._adjustDialog(); $(document.body).addClass(ClassName.OPEN); this._setEscapeEvent(); this._setResizeEvent(); $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) { return _this.hide(event); }); $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { $(_this._element).one(Event.MOUSEUP_DISMISS, function (event) { if ($(event.target).is(_this._element)) { _this._ignoreBackdropClick = true; } }); }); this._showBackdrop(function () { return _this._showElement(relatedTarget); }); }; _proto.hide = function hide(event) { var _this2 = this; if (event) { event.preventDefault(); } if (this._isTransitioning || !this._isShown) { return; } var hideEvent = $.Event(Event.HIDE); $(this._element).trigger(hideEvent); if (!this._isShown || hideEvent.isDefaultPrevented()) { return; } this._isShown = false; var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE); if (transition) { this._isTransitioning = true; } this._setEscapeEvent(); this._setResizeEvent(); $(document).off(Event.FOCUSIN); $(this._element).removeClass(ClassName.SHOW); $(this._element).off(Event.CLICK_DISMISS); $(this._dialog).off(Event.MOUSEDOWN_DISMISS); if (transition) { $(this._element).one(Util.TRANSITION_END, function (event) { return _this2._hideModal(event); }).emulateTransitionEnd(TRANSITION_DURATION); } else { this._hideModal(); } }; _proto.dispose = function dispose() { $.removeData(this._element, DATA_KEY); $(window, document, this._element, this._backdrop).off(EVENT_KEY); this._config = null; this._element = null; this._dialog = null; this._backdrop = null; this._isShown = null; this._isBodyOverflowing = null; this._ignoreBackdropClick = null; this._scrollbarWidth = null; }; _proto.handleUpdate = function handleUpdate() { this._adjustDialog(); }; // private _proto._getConfig = function _getConfig(config) { config = $.extend({}, Default, config); Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._showElement = function _showElement(relatedTarget) { var _this3 = this; var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE); if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { // don't move modals dom position document.body.appendChild(this._element); } this._element.style.display = 'block'; this._element.removeAttribute('aria-hidden'); this._element.scrollTop = 0; if (transition) { Util.reflow(this._element); } $(this._element).addClass(ClassName.SHOW); if (this._config.focus) { this._enforceFocus(); } var shownEvent = $.Event(Event.SHOWN, { relatedTarget: relatedTarget }); var transitionComplete = function transitionComplete() { if (_this3._config.focus) { _this3._element.focus(); } _this3._isTransitioning = false; $(_this3._element).trigger(shownEvent); }; if (transition) { $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION); } else { transitionComplete(); } }; _proto._enforceFocus = function _enforceFocus() { var _this4 = this; $(document).off(Event.FOCUSIN) // guard against infinite focus loop .on(Event.FOCUSIN, function (event) { if (document !== event.target && _this4._element !== event.target && !$(_this4._element).has(event.target).length) { _this4._element.focus(); } }); }; _proto._setEscapeEvent = function _setEscapeEvent() { var _this5 = this; if (this._isShown && this._config.keyboard) { $(this._element).on(Event.KEYDOWN_DISMISS, function (event) { if (event.which === ESCAPE_KEYCODE) { event.preventDefault(); _this5.hide(); } }); } else if (!this._isShown) { $(this._element).off(Event.KEYDOWN_DISMISS); } }; _proto._setResizeEvent = function _setResizeEvent() { var _this6 = this; if (this._isShown) { $(window).on(Event.RESIZE, function (event) { return _this6.handleUpdate(event); }); } else { $(window).off(Event.RESIZE); } }; _proto._hideModal = function _hideModal() { var _this7 = this; this._element.style.display = 'none'; this._element.setAttribute('aria-hidden', true); this._isTransitioning = false; this._showBackdrop(function () { $(document.body).removeClass(ClassName.OPEN); _this7._resetAdjustments(); _this7._resetScrollbar(); $(_this7._element).trigger(Event.HIDDEN); }); }; _proto._removeBackdrop = function _removeBackdrop() { if (this._backdrop) { $(this._backdrop).remove(); this._backdrop = null; } }; _proto._showBackdrop = function _showBackdrop(callback) { var _this8 = this; var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; if (this._isShown && this._config.backdrop) { var doAnimate = Util.supportsTransitionEnd() && animate; this._backdrop = document.createElement('div'); this._backdrop.className = ClassName.BACKDROP; if (animate) { $(this._backdrop).addClass(animate); } $(this._backdrop).appendTo(document.body); $(this._element).on(Event.CLICK_DISMISS, function (event) { if (_this8._ignoreBackdropClick) { _this8._ignoreBackdropClick = false; return; } if (event.target !== event.currentTarget) { return; } if (_this8._config.backdrop === 'static') { _this8._element.focus(); } else { _this8.hide(); } }); if (doAnimate) { Util.reflow(this._backdrop); } $(this._backdrop).addClass(ClassName.SHOW); if (!callback) { return; } if (!doAnimate) { callback(); return; } $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION); } else if (!this._isShown && this._backdrop) { $(this._backdrop).removeClass(ClassName.SHOW); var callbackRemove = function callbackRemove() { _this8._removeBackdrop(); if (callback) { callback(); } }; if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) { $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION); } else { callbackRemove(); } } else if (callback) { callback(); } }; // ---------------------------------------------------------------------- // the following methods are used to handle overflowing modals // todo (fat): these should probably be refactored out of modal.js // ---------------------------------------------------------------------- _proto._adjustDialog = function _adjustDialog() { var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; if (!this._isBodyOverflowing && isModalOverflowing) { this._element.style.paddingLeft = this._scrollbarWidth + "px"; } if (this._isBodyOverflowing && !isModalOverflowing) { this._element.style.paddingRight = this._scrollbarWidth + "px"; } }; _proto._resetAdjustments = function _resetAdjustments() { this._element.style.paddingLeft = ''; this._element.style.paddingRight = ''; }; _proto._checkScrollbar = function _checkScrollbar() { var rect = document.body.getBoundingClientRect(); this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; this._scrollbarWidth = this._getScrollbarWidth(); }; _proto._setScrollbar = function _setScrollbar() { var _this9 = this; if (this._isBodyOverflowing) { // Note: DOMNode.style.paddingRight returns the actual value or '' if not set // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set // Adjust fixed content padding $(Selector.FIXED_CONTENT).each(function (index, element) { var actualPadding = $(element)[0].style.paddingRight; var calculatedPadding = $(element).css('padding-right'); $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px"); }); // Adjust sticky content margin $(Selector.STICKY_CONTENT).each(function (index, element) { var actualMargin = $(element)[0].style.marginRight; var calculatedMargin = $(element).css('margin-right'); $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px"); }); // Adjust navbar-toggler margin $(Selector.NAVBAR_TOGGLER).each(function (index, element) { var actualMargin = $(element)[0].style.marginRight; var calculatedMargin = $(element).css('margin-right'); $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this9._scrollbarWidth + "px"); }); // Adjust body padding var actualPadding = document.body.style.paddingRight; var calculatedPadding = $('body').css('padding-right'); $('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); } }; _proto._resetScrollbar = function _resetScrollbar() { // Restore fixed content padding $(Selector.FIXED_CONTENT).each(function (index, element) { var padding = $(element).data('padding-right'); if (typeof padding !== 'undefined') { $(element).css('padding-right', padding).removeData('padding-right'); } }); // Restore sticky content and navbar-toggler margin $(Selector.STICKY_CONTENT + ", " + Selector.NAVBAR_TOGGLER).each(function (index, element) { var margin = $(element).data('margin-right'); if (typeof margin !== 'undefined') { $(element).css('margin-right', margin).removeData('margin-right'); } }); // Restore body padding var padding = $('body').data('padding-right'); if (typeof padding !== 'undefined') { $('body').css('padding-right', padding).removeData('padding-right'); } }; _proto._getScrollbarWidth = function _getScrollbarWidth() { // thx d.walsh var scrollDiv = document.createElement('div'); scrollDiv.className = ClassName.SCROLLBAR_MEASURER; document.body.appendChild(scrollDiv); var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; document.body.removeChild(scrollDiv); return scrollbarWidth; }; // static Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { return this.each(function () { var data = $(this).data(DATA_KEY); var _config = $.extend({}, Modal.Default, $(this).data(), typeof config === 'object' && config); if (!data) { data = new Modal(this, _config); $(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](relatedTarget); } else if (_config.show) { data.show(relatedTarget); } }); }; createClass(Modal, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }]); return Modal; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { var _this10 = this; var target; var selector = Util.getSelectorFromElement(this); if (selector) { target = $(selector)[0]; } var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data()); if (this.tagName === 'A' || this.tagName === 'AREA') { event.preventDefault(); } var $target = $(target).one(Event.SHOW, function (showEvent) { if (showEvent.isDefaultPrevented()) { // only register focus restorer if modal will actually get shown return; } $target.one(Event.HIDDEN, function () { if ($(_this10).is(':visible')) { _this10.focus(); } }); }); Modal._jQueryInterface.call($(target), config, this); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Modal._jQueryInterface; $.fn[NAME].Constructor = Modal; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Modal._jQueryInterface; }; return Modal; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Tooltip = function () { /** * Check for Popper dependency * Popper - https://popper.js.org */ if (typeof Popper === 'undefined') { throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)'); } /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'tooltip'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.tooltip'; var EVENT_KEY = "." + DATA_KEY; var JQUERY_NO_CONFLICT = $.fn[NAME]; var TRANSITION_DURATION = 150; var CLASS_PREFIX = 'bs-tooltip'; var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); var DefaultType = { animation: 'boolean', template: 'string', title: '(string|element|function)', trigger: 'string', delay: '(number|object)', html: 'boolean', selector: '(string|boolean)', placement: '(string|function)', offset: '(number|string)', container: '(string|element|boolean)', fallbackPlacement: '(string|array)' }; var AttachmentMap = { AUTO: 'auto', TOP: 'top', RIGHT: 'right', BOTTOM: 'bottom', LEFT: 'left' }; var Default = { animation: true, template: '', trigger: 'hover focus', title: '', delay: 0, html: false, selector: false, placement: 'top', offset: 0, container: false, fallbackPlacement: 'flip' }; var HoverState = { SHOW: 'show', OUT: 'out' }; var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, INSERTED: "inserted" + EVENT_KEY, CLICK: "click" + EVENT_KEY, FOCUSIN: "focusin" + EVENT_KEY, FOCUSOUT: "focusout" + EVENT_KEY, MOUSEENTER: "mouseenter" + EVENT_KEY, MOUSELEAVE: "mouseleave" + EVENT_KEY }; var ClassName = { FADE: 'fade', SHOW: 'show' }; var Selector = { TOOLTIP: '.tooltip', TOOLTIP_INNER: '.tooltip-inner', ARROW: '.arrow' }; var Trigger = { HOVER: 'hover', FOCUS: 'focus', CLICK: 'click', MANUAL: 'manual' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Tooltip = /*#__PURE__*/ function () { function Tooltip(element, config) { // private this._isEnabled = true; this._timeout = 0; this._hoverState = ''; this._activeTrigger = {}; this._popper = null; // protected this.element = element; this.config = this._getConfig(config); this.tip = null; this._setListeners(); } // getters var _proto = Tooltip.prototype; // public _proto.enable = function enable() { this._isEnabled = true; }; _proto.disable = function disable() { this._isEnabled = false; }; _proto.toggleEnabled = function toggleEnabled() { this._isEnabled = !this._isEnabled; }; _proto.toggle = function toggle(event) { if (!this._isEnabled) { return; } if (event) { var dataKey = this.constructor.DATA_KEY; var context = $(event.currentTarget).data(dataKey); if (!context) { context = new this.constructor(event.currentTarget, this._getDelegateConfig()); $(event.currentTarget).data(dataKey, context); } context._activeTrigger.click = !context._activeTrigger.click; if (context._isWithActiveTrigger()) { context._enter(null, context); } else { context._leave(null, context); } } else { if ($(this.getTipElement()).hasClass(ClassName.SHOW)) { this._leave(null, this); return; } this._enter(null, this); } }; _proto.dispose = function dispose() { clearTimeout(this._timeout); $.removeData(this.element, this.constructor.DATA_KEY); $(this.element).off(this.constructor.EVENT_KEY); $(this.element).closest('.modal').off('hide.bs.modal'); if (this.tip) { $(this.tip).remove(); } this._isEnabled = null; this._timeout = null; this._hoverState = null; this._activeTrigger = null; if (this._popper !== null) { this._popper.destroy(); } this._popper = null; this.element = null; this.config = null; this.tip = null; }; _proto.show = function show() { var _this = this; if ($(this.element).css('display') === 'none') { throw new Error('Please use show on visible elements'); } var showEvent = $.Event(this.constructor.Event.SHOW); if (this.isWithContent() && this._isEnabled) { $(this.element).trigger(showEvent); var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element); if (showEvent.isDefaultPrevented() || !isInTheDom) { return; } var tip = this.getTipElement(); var tipId = Util.getUID(this.constructor.NAME); tip.setAttribute('id', tipId); this.element.setAttribute('aria-describedby', tipId); this.setContent(); if (this.config.animation) { $(tip).addClass(ClassName.FADE); } var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement; var attachment = this._getAttachment(placement); this.addAttachmentClass(attachment); var container = this.config.container === false ? document.body : $(this.config.container); $(tip).data(this.constructor.DATA_KEY, this); if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) { $(tip).appendTo(container); } $(this.element).trigger(this.constructor.Event.INSERTED); this._popper = new Popper(this.element, tip, { placement: attachment, modifiers: { offset: { offset: this.config.offset }, flip: { behavior: this.config.fallbackPlacement }, arrow: { element: Selector.ARROW } }, onCreate: function onCreate(data) { if (data.originalPlacement !== data.placement) { _this._handlePopperPlacementChange(data); } }, onUpdate: function onUpdate(data) { _this._handlePopperPlacementChange(data); } }); $(tip).addClass(ClassName.SHOW); // if this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement) { $('body').children().on('mouseover', null, $.noop); } var complete = function complete() { if (_this.config.animation) { _this._fixTransition(); } var prevHoverState = _this._hoverState; _this._hoverState = null; $(_this.element).trigger(_this.constructor.Event.SHOWN); if (prevHoverState === HoverState.OUT) { _this._leave(null, _this); } }; if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) { $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION); } else { complete(); } } }; _proto.hide = function hide(callback) { var _this2 = this; var tip = this.getTipElement(); var hideEvent = $.Event(this.constructor.Event.HIDE); var complete = function complete() { if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) { tip.parentNode.removeChild(tip); } _this2._cleanTipClass(); _this2.element.removeAttribute('aria-describedby'); $(_this2.element).trigger(_this2.constructor.Event.HIDDEN); if (_this2._popper !== null) { _this2._popper.destroy(); } if (callback) { callback(); } }; $(this.element).trigger(hideEvent); if (hideEvent.isDefaultPrevented()) { return; } $(tip).removeClass(ClassName.SHOW); // if this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { $('body').children().off('mouseover', null, $.noop); } this._activeTrigger[Trigger.CLICK] = false; this._activeTrigger[Trigger.FOCUS] = false; this._activeTrigger[Trigger.HOVER] = false; if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) { $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); } else { complete(); } this._hoverState = ''; }; _proto.update = function update() { if (this._popper !== null) { this._popper.scheduleUpdate(); } }; // protected _proto.isWithContent = function isWithContent() { return Boolean(this.getTitle()); }; _proto.addAttachmentClass = function addAttachmentClass(attachment) { $(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); }; _proto.getTipElement = function getTipElement() { this.tip = this.tip || $(this.config.template)[0]; return this.tip; }; _proto.setContent = function setContent() { var $tip = $(this.getTipElement()); this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle()); $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); }; _proto.setElementContent = function setElementContent($element, content) { var html = this.config.html; if (typeof content === 'object' && (content.nodeType || content.jquery)) { // content is a DOM node or a jQuery if (html) { if (!$(content).parent().is($element)) { $element.empty().append(content); } } else { $element.text($(content).text()); } } else { $element[html ? 'html' : 'text'](content); } }; _proto.getTitle = function getTitle() { var title = this.element.getAttribute('data-original-title'); if (!title) { title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title; } return title; }; // private _proto._getAttachment = function _getAttachment(placement) { return AttachmentMap[placement.toUpperCase()]; }; _proto._setListeners = function _setListeners() { var _this3 = this; var triggers = this.config.trigger.split(' '); triggers.forEach(function (trigger) { if (trigger === 'click') { $(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) { return _this3.toggle(event); }); } else if (trigger !== Trigger.MANUAL) { var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN; var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT; $(_this3.element).on(eventIn, _this3.config.selector, function (event) { return _this3._enter(event); }).on(eventOut, _this3.config.selector, function (event) { return _this3._leave(event); }); } $(_this3.element).closest('.modal').on('hide.bs.modal', function () { return _this3.hide(); }); }); if (this.config.selector) { this.config = $.extend({}, this.config, { trigger: 'manual', selector: '' }); } else { this._fixTitle(); } }; _proto._fixTitle = function _fixTitle() { var titleType = typeof this.element.getAttribute('data-original-title'); if (this.element.getAttribute('title') || titleType !== 'string') { this.element.setAttribute('data-original-title', this.element.getAttribute('title') || ''); this.element.setAttribute('title', ''); } }; _proto._enter = function _enter(event, context) { var dataKey = this.constructor.DATA_KEY; context = context || $(event.currentTarget).data(dataKey); if (!context) { context = new this.constructor(event.currentTarget, this._getDelegateConfig()); $(event.currentTarget).data(dataKey, context); } if (event) { context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true; } if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { context._hoverState = HoverState.SHOW; return; } clearTimeout(context._timeout); context._hoverState = HoverState.SHOW; if (!context.config.delay || !context.config.delay.show) { context.show(); return; } context._timeout = setTimeout(function () { if (context._hoverState === HoverState.SHOW) { context.show(); } }, context.config.delay.show); }; _proto._leave = function _leave(event, context) { var dataKey = this.constructor.DATA_KEY; context = context || $(event.currentTarget).data(dataKey); if (!context) { context = new this.constructor(event.currentTarget, this._getDelegateConfig()); $(event.currentTarget).data(dataKey, context); } if (event) { context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false; } if (context._isWithActiveTrigger()) { return; } clearTimeout(context._timeout); context._hoverState = HoverState.OUT; if (!context.config.delay || !context.config.delay.hide) { context.hide(); return; } context._timeout = setTimeout(function () { if (context._hoverState === HoverState.OUT) { context.hide(); } }, context.config.delay.hide); }; _proto._isWithActiveTrigger = function _isWithActiveTrigger() { for (var trigger in this._activeTrigger) { if (this._activeTrigger[trigger]) { return true; } } return false; }; _proto._getConfig = function _getConfig(config) { config = $.extend({}, this.constructor.Default, $(this.element).data(), config); if (typeof config.delay === 'number') { config.delay = { show: config.delay, hide: config.delay }; } if (typeof config.title === 'number') { config.title = config.title.toString(); } if (typeof config.content === 'number') { config.content = config.content.toString(); } Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); return config; }; _proto._getDelegateConfig = function _getDelegateConfig() { var config = {}; if (this.config) { for (var key in this.config) { if (this.constructor.Default[key] !== this.config[key]) { config[key] = this.config[key]; } } } return config; }; _proto._cleanTipClass = function _cleanTipClass() { var $tip = $(this.getTipElement()); var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); if (tabClass !== null && tabClass.length > 0) { $tip.removeClass(tabClass.join('')); } }; _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(data) { this._cleanTipClass(); this.addAttachmentClass(this._getAttachment(data.placement)); }; _proto._fixTransition = function _fixTransition() { var tip = this.getTipElement(); var initConfigAnimation = this.config.animation; if (tip.getAttribute('x-placement') !== null) { return; } $(tip).removeClass(ClassName.FADE); this.config.animation = false; this.hide(); this.show(); this.config.animation = initConfigAnimation; }; // static Tooltip._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $(this).data(DATA_KEY); var _config = typeof config === 'object' && config; if (!data && /dispose|hide/.test(config)) { return; } if (!data) { data = new Tooltip(this, _config); $(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; createClass(Tooltip, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }, { key: "NAME", get: function get() { return NAME; } }, { key: "DATA_KEY", get: function get() { return DATA_KEY; } }, { key: "Event", get: function get() { return Event; } }, { key: "EVENT_KEY", get: function get() { return EVENT_KEY; } }, { key: "DefaultType", get: function get() { return DefaultType; } }]); return Tooltip; }(); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Tooltip._jQueryInterface; $.fn[NAME].Constructor = Tooltip; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Tooltip._jQueryInterface; }; return Tooltip; }($, Popper); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Popover = function () { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'popover'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.popover'; var EVENT_KEY = "." + DATA_KEY; var JQUERY_NO_CONFLICT = $.fn[NAME]; var CLASS_PREFIX = 'bs-popover'; var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); var Default = $.extend({}, Tooltip.Default, { placement: 'right', trigger: 'click', content: '', template: '' }); var DefaultType = $.extend({}, Tooltip.DefaultType, { content: '(string|element|function)' }); var ClassName = { FADE: 'fade', SHOW: 'show' }; var Selector = { TITLE: '.popover-header', CONTENT: '.popover-body' }; var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, INSERTED: "inserted" + EVENT_KEY, CLICK: "click" + EVENT_KEY, FOCUSIN: "focusin" + EVENT_KEY, FOCUSOUT: "focusout" + EVENT_KEY, MOUSEENTER: "mouseenter" + EVENT_KEY, MOUSELEAVE: "mouseleave" + EVENT_KEY /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Popover = /*#__PURE__*/ function (_Tooltip) { inheritsLoose(Popover, _Tooltip); function Popover() { return _Tooltip.apply(this, arguments) || this; } var _proto = Popover.prototype; // overrides _proto.isWithContent = function isWithContent() { return this.getTitle() || this._getContent(); }; _proto.addAttachmentClass = function addAttachmentClass(attachment) { $(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); }; _proto.getTipElement = function getTipElement() { this.tip = this.tip || $(this.config.template)[0]; return this.tip; }; _proto.setContent = function setContent() { var $tip = $(this.getTipElement()); // we use append for html objects to maintain js events this.setElementContent($tip.find(Selector.TITLE), this.getTitle()); this.setElementContent($tip.find(Selector.CONTENT), this._getContent()); $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); }; // private _proto._getContent = function _getContent() { return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content); }; _proto._cleanTipClass = function _cleanTipClass() { var $tip = $(this.getTipElement()); var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); if (tabClass !== null && tabClass.length > 0) { $tip.removeClass(tabClass.join('')); } }; // static Popover._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $(this).data(DATA_KEY); var _config = typeof config === 'object' ? config : null; if (!data && /destroy|hide/.test(config)) { return; } if (!data) { data = new Popover(this, _config); $(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; createClass(Popover, null, [{ key: "VERSION", // getters get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }, { key: "NAME", get: function get() { return NAME; } }, { key: "DATA_KEY", get: function get() { return DATA_KEY; } }, { key: "Event", get: function get() { return Event; } }, { key: "EVENT_KEY", get: function get() { return EVENT_KEY; } }, { key: "DefaultType", get: function get() { return DefaultType; } }]); return Popover; }(Tooltip); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $.fn[NAME] = Popover._jQueryInterface; $.fn[NAME].Constructor = Popover; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return Popover._jQueryInterface; }; return Popover; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.2): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var ScrollSpy = function () { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'scrollspy'; var VERSION = '4.0.0-beta.2'; var DATA_KEY = 'bs.scrollspy'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var Default = { offset: 10, method: 'auto', target: '' }; var DefaultType = { offset: 'number', method: 'string', target: '(string|element)' }; var Event = { ACTIVATE: "activate" + EVENT_KEY, SCROLL: "scroll" + EVENT_KEY, LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY }; var ClassName = { DROPDOWN_ITEM: 'dropdown-item', DROPDOWN_MENU: 'dropdown-menu', ACTIVE: 'active' }; var Selector = { DATA_SPY: '[data-spy="scroll"]', ACTIVE: '.active', NAV_LIST_GROUP: '.nav, .list-group', NAV_LINKS: '.nav-link', NAV_ITEMS: '.nav-item', LIST_ITEMS: '.list-group-item', DROPDOWN: '.dropdown', DROPDOWN_ITEMS: '.dropdown-item', DROPDOWN_TOGGLE: '.dropdown-toggle' }; var OffsetMethod = { OFFSET: 'offset', POSITION: 'position' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var ScrollSpy = /*#__PURE__*/ function () { function ScrollSpy(element, config) { var _this = this; this._element = element; this._scrollElement = element.tagName === 'BODY' ? window : element; this._config = this._getConfig(config); this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS); this._offsets = []; this._targets = []; this._activeTarget = null; this._scrollHeight = 0; $(this._scrollElement).on(Event.SCROLL, function (event) { return _this._process(event); }); this.refresh(); this._process(); } // getters var _proto = ScrollSpy.prototype; // public _proto.refresh = function refresh() { var _this2 = this; var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET; var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0; this._offsets = []; this._targets = []; this._scrollHeight = this._getScrollHeight(); var targets = $.makeArray($(this._selector)); targets.map(function (element) { var target; var targetSelector = Util.getSelectorFromElement(element); if (targetSelector) { target = $(targetSelector)[0]; } if (target) { var targetBCR = target.getBoundingClientRect(); if (targetBCR.width || targetBCR.height) { // todo (fat): remove sketch reliance on jQuery position/offset return [$(target)[offsetMethod]().top + offsetBase, targetSelector]; } } return null; }).filter(function (item) { return item; }).sort(function (a, b) { return a[0] - b[0]; }).forEach(function (item) { _this2._offsets.push(item[0]); _this2._targets.push(item[1]); }); }; _proto.dispose = function dispose() { $.removeData(this._element, DATA_KEY); $(this._scrollElement).off(EVENT_KEY); this._element = null; this._scrollElement = null; this._config = null; this._selector = null; this._offsets = null; this._targets = null; this._activeTarget = null; this._scrollHeight = null; }; // private _proto._getConfig = function _getConfig(config) { config = $.extend({}, Default, config); if (typeof config.target !== 'string') { var id = $(config.target).attr('id'); if (!id) { id = Util.getUID(NAME); $(config.target).attr('id', id); } config.target = "#" + id; } Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._getScrollTop = function _getScrollTop() { return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; }; _proto._getScrollHeight = function _getScrollHeight() { return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); }; _proto._getOffsetHeight = function _getOffsetHeight() { return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; }; _proto._process = function _process() { var scrollTop = this._getScrollTop() + this._config.offset; var scrollHeight = this._getScrollHeight(); var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); if (this._scrollHeight !== scrollHeight) { this.refresh(); } if (scrollTop >= maxScroll) { var target = this._targets[this._targets.length - 1]; if (this._activeTarget !== target) { this._activate(target); } return; } if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { this._activeTarget = null; this._clear(); return; } for (var i = this._offsets.length; i--;) { var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); if (isActiveTarget) { this._activate(this._targets[i]); } } }; _proto._activate = function _activate(target) { this._activeTarget = target; this._clear(); var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style queries = queries.map(function (selector) { return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]"); }); var $link = $(queries.join(',')); if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); $link.addClass(ClassName.ACTIVE); } else { // Set triggered link as active $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active // With both
              and
            ================================================ FILE: open-layui-web/src/main/view/static/login.html.bak ================================================ OCP ================================================ FILE: open-layui-web/src/main/view/static/login.html.bak1 ================================================ OCP ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/actList.html ================================================ 流程部署
            ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/actModelList.html ================================================ 模型列表
            ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/deploy/act-node.html ================================================ 流程节点分配
            分配角色
            分配成员
            ------开发中------
            ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/index.html ================================================ 
            ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ActivitiRest.js ================================================ var ActivitiRest = { options: {}, getProcessDefinitionByKey: function(processDefinitionKey, callback) { var url = Lang.sub(this.options.processDefinitionByKeyUrl, {processDefinitionKey: processDefinitionKey}); $.ajax({ url: url, dataType: 'jsonp', cache: false, async: true, success: function(data, textStatus) { var processDefinition = data; if (!processDefinition) { console.error("Process definition '" + processDefinitionKey + "' not found"); } else { callback.apply({processDefinitionId: processDefinition.id}); } } }).done(function(data, textStatus) { console.log("ajax done"); }).fail(function(jqXHR, textStatus, error){ console.error('Get diagram layout['+processDefinitionKey+'] failure: ', textStatus, 'error: ', error, jqXHR); }); }, getProcessDefinition: function(processDefinitionId, callback) { var url = Lang.sub(this.options.processDefinitionUrl, {processDefinitionId: processDefinitionId}); $.ajax({ url: url, dataType: 'jsonp', cache: false, async: true, success: function(data, textStatus) { var processDefinitionDiagramLayout = data; if (!processDefinitionDiagramLayout) { console.error("Process definition diagram layout '" + processDefinitionId + "' not found"); return; } else { callback.apply({processDefinitionDiagramLayout: processDefinitionDiagramLayout}); } } }).done(function(data, textStatus) { console.log("ajax done"); }).fail(function(jqXHR, textStatus, error){ console.log('Get diagram layout['+processDefinitionId+'] failure: ', textStatus, jqXHR); }); }, getHighLights: function(processInstanceId, callback) { var url = Lang.sub(this.options.processInstanceHighLightsUrl, {processInstanceId: processInstanceId}); $.ajax({ url: url, dataType: 'jsonp', cache: false, async: true, success: function(data, textStatus) { console.log("ajax returned data"); var highLights = data; if (!highLights) { console.log("highLights not found"); return; } else { callback.apply({highLights: highLights}); } } }).done(function(data, textStatus) { console.log("ajax done"); }).fail(function(jqXHR, textStatus, error){ console.log('Get HighLights['+processInstanceId+'] failure: ', textStatus, jqXHR); }); } }; ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ActivityImpl.js ================================================ /** * * @author Tom Baeyens * @author (Javascript) Dmitry Farafonov */ var ActivityImpl = function(activityJson){ this.outgoingTransitions = []; this.outgoingTransitions = []; this.incomingTransitions = []; this.activityBehavior = null; this.parent = null; this.isScope = false; this.isAsync = false; this.isExclusive = false; this.x = -1; this.y = -1; this.width = -1; this.height = -1; this.properties = {}; //console.log("activityJson: ", activityJson); if (activityJson != undefined) { this.setId(activityJson.activityId); for (var propertyName in activityJson.properties) { this.setProperty(propertyName, activityJson.properties[propertyName]); } //this.setProperty("name", activityJson.activityName); //this.setProperty("type", activityJson.activityType); this.setX(activityJson.x); this.setY(activityJson.y); this.setWidth(activityJson.width); this.setHeight(activityJson.height); if (activityJson.multiInstance) this.setProperty("multiInstance", activityJson.multiInstance); if (activityJson.collapsed) { this.setProperty("collapsed", activityJson.collapsed); } if (activityJson.isInterrupting != undefined) this.setProperty("isInterrupting", activityJson.isInterrupting); } }; ActivityImpl.prototype = { outgoingTransitions: [], outgoingTransitions: [], incomingTransitions: [], activityBehavior: null, parent: null, isScope: false, isAsync: false, isExclusive: false, id: null, properties: {}, // Graphical information x: -1, y: -1, width: -1, height: -1, setId: function(id){ this.id = id; }, getId: function(){ return this.id; }, setProperty: function(name, value){ this.properties[name] = value; }, getProperty: function(name){ return this.properties[name]; }, createOutgoingTransition: function(transitionId){ }, toString: function(id) { return "Activity("+id+")"; }, getParentActivity: function(){ /* if (parent instanceof ActivityImpl) { 79 return (ActivityImpl) parent; 80 } 81 return null; */ return this.parent; }, // restricted setters /////////////////////////////////////////////////////// setOutgoingTransitions: function(outgoingTransitions){ this.outgoingTransitions = outgoingTransitions; }, setParent: function(parent){ this.parent = parent; }, setIncomingTransitions: function(incomingTransitions){ this.incomingTransitions = incomingTransitions; }, // getters and setters ////////////////////////////////////////////////////// getOutgoingTransitions: function(){ return this.outgoingTransitions; }, getActivityBehavior: function(){ return this.activityBehavior; }, setActivityBehavior: function(activityBehavior){ this.activityBehavior = activityBehavior; }, getParent: function(){ return this.parent; }, getIncomingTransitions: function(){ return this.incomingTransitions; }, isScope: function(){ return this.isScope; }, setScope: function(isScope){ this.isScope = isScope; }, getX: function(){ return this.x; }, setX: function(x){ this.x = x; }, getY: function(){ return this.y; }, setY: function(y){ this.y = y; }, getWidth: function(){ return this.width; }, setWidth: function(width){ this.width = width; }, getHeight: function(){ return this.height; }, setHeight: function(height){ this.height = height; }, isAsync: function() { return this.isAsync; }, setAsync: function(isAsync) { this.isAsync = isAsync; }, isExclusive: function() { return this.isExclusive; }, setExclusive: function(isExclusive) { this.isExclusive = isExclusive; }, vvoid: function(){} }; ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/Color.js ================================================ /** * Web color table * * @author Dmitry Farafonov */ var Color = { /** * The color white. In the default sRGB space. */ white : Raphael.getRGB("rgb(255,255,255)"), /** * The color white. In the default sRGB space. */ WHITE : this.white, /** * The color light gray. In the default sRGB space. */ lightGray : Raphael.getRGB("rgb(192, 192, 192)"), /** * The color light gray. In the default sRGB space. */ LIGHT_GRAY : this.lightGray, /** * The color gray. In the default sRGB space. */ gray : Raphael.getRGB("rgb(128, 128, 128)"), /** * The color gray. In the default sRGB space. */ GRAY : this.gray, /** * The color dark gray. In the default sRGB space. */ darkGray : Raphael.getRGB("rgb(64, 64, 64)"), /** * The color dark gray. In the default sRGB space. */ DARK_GRAY : this.darkGray, /** * The color black. In the default sRGB space. */ black : Raphael.getRGB("rgb(0, 0, 0)"), /** * The color black. In the default sRGB space. */ BLACK : this.black, /** * The color red. In the default sRGB space. */ red : Raphael.getRGB("rgb(255, 0, 0)"), /** * The color red. In the default sRGB space. */ RED : this.red, /** * The color pink. In the default sRGB space. */ pink : Raphael.getRGB("rgb(255, 175, 175)"), /** * The color pink. In the default sRGB space. */ PINK : this.pink, /** * The color orange. In the default sRGB space. */ orange : Raphael.getRGB("rgb(255, 200, 0)"), /** * The color orange. In the default sRGB space. */ ORANGE : this.orange, /** * The color yellow. In the default sRGB space. */ yellow : Raphael.getRGB("rgb(255, 255, 0)"), /** * The color yellow. In the default sRGB space. */ YELLOW : this.yellow, /** * The color green. In the default sRGB space. */ green : Raphael.getRGB("rgb(0, 255, 0)"), /** * The color green. In the default sRGB space. */ GREEN : this.green, /** * The color magenta. In the default sRGB space. */ magenta : Raphael.getRGB("rgb(255, 0, 255)"), /** * The color magenta. In the default sRGB space. */ MAGENTA : this.magenta, /** * The color cyan. In the default sRGB space. */ cyan : Raphael.getRGB("rgb(0, 255, 255)"), /** * The color cyan. In the default sRGB space. */ CYAN : this.cyan, /** * The color blue. In the default sRGB space. */ blue : Raphael.getRGB("rgb(0, 0, 255)"), /** * The color blue. In the default sRGB space. */ BLUE : this.blue, /************************************************************************/ // http://www.stm.dp.ua/web-design/color-html.php Snow : Raphael.getRGB("#FFFAFA "), // 255 250 250 GhostWhite : Raphael.getRGB("#F8F8FF "), // 248 248 255 WhiteSmoke : Raphael.getRGB("#F5F5F5 "), // 245 245 245 Gainsboro : Raphael.getRGB("#DCDCDC "), // 220 220 220 FloralWhite : Raphael.getRGB("#FFFAF0 "), // 255 250 240 OldLace : Raphael.getRGB("#FDF5E6 "), // 253 245 230 Linen : Raphael.getRGB("#FAF0E6 "), // 250 240 230 AntiqueWhite : Raphael.getRGB("#FAEBD7 "), // 250 235 215 PapayaWhip : Raphael.getRGB("#FFEFD5 "), // 255 239 213 BlanchedAlmond : Raphael.getRGB("#FFEBCD "), // 255 235 205 Bisque : Raphael.getRGB("#FFE4C4 "), // 255 228 196 PeachPuff : Raphael.getRGB("#FFDAB9 "), // 255 218 185 NavajoWhite : Raphael.getRGB("#FFDEAD "), // 255 222 173 Moccasin : Raphael.getRGB("#FFE4B5 "), // 255 228 181 Cornsilk : Raphael.getRGB("#FFF8DC "), // 255 248 220 Ivory : Raphael.getRGB("#FFFFF0 "), // 255 255 240 LemonChiffon : Raphael.getRGB("#FFFACD "), // 255 250 205 Seashell : Raphael.getRGB("#FFF5EE "), // 255 245 238 Honeydew : Raphael.getRGB("#F0FFF0 "), // 240 255 240 MintCream : Raphael.getRGB("#F5FFFA "), // 245 255 250 Azure : Raphael.getRGB("#F0FFFF "), // 240 255 255 AliceBlue : Raphael.getRGB("#F0F8FF "), // 240 248 255 lavender : Raphael.getRGB("#E6E6FA "), // 230 230 250 LavenderBlush : Raphael.getRGB("#FFF0F5 "), // 255 240 245 MistyRose : Raphael.getRGB("#FFE4E1 "), // 255 228 225 White : Raphael.getRGB("#FFFFFF "), // 255 255 255 Black : Raphael.getRGB("#000000 "), // 0 0 0 DarkSlateGray : Raphael.getRGB("#2F4F4F "), // 47 79 79 DimGrey : Raphael.getRGB("#696969 "), // 105 105 105 SlateGrey : Raphael.getRGB("#708090 "), // 112 128 144 LightSlateGray : Raphael.getRGB("#778899 "), // 119 136 153 Grey : Raphael.getRGB("#BEBEBE "), // 190 190 190 LightGray : Raphael.getRGB("#D3D3D3 "), // 211 211 211 MidnightBlue : Raphael.getRGB("#191970 "), // 25 25 112 NavyBlue : Raphael.getRGB("#000080 "), // 0 0 128 CornflowerBlue : Raphael.getRGB("#6495ED "), // 100 149 237 DarkSlateBlue : Raphael.getRGB("#483D8B "), // 72 61 139 SlateBlue : Raphael.getRGB("#6A5ACD "), // 106 90 205 MediumSlateBlue : Raphael.getRGB("#7B68EE "), // 123 104 238 LightSlateBlue : Raphael.getRGB("#8470FF "), // 132 112 255 MediumBlue : Raphael.getRGB("#0000CD "), // 0 0 205 RoyalBlue : Raphael.getRGB("#4169E1 "), // 65 105 225 Blue : Raphael.getRGB("#0000FF "), // 0 0 255 DodgerBlue : Raphael.getRGB("#1E90FF "), // 30 144 255 DeepSkyBlue : Raphael.getRGB("#00BFFF "), // 0 191 255 SkyBlue : Raphael.getRGB("#87CEEB "), // 135 206 235 LightSkyBlue : Raphael.getRGB("#87CEFA "), // 135 206 250 SteelBlue : Raphael.getRGB("#4682B4 "), // 70 130 180 LightSteelBlue : Raphael.getRGB("#B0C4DE "), // 176 196 222 LightBlue : Raphael.getRGB("#ADD8E6 "), // 173 216 230 PowderBlue : Raphael.getRGB("#B0E0E6 "), // 176 224 230 PaleTurquoise : Raphael.getRGB("#AFEEEE "), // 175 238 238 DarkTurquoise : Raphael.getRGB("#00CED1 "), // 0 206 209 MediumTurquoise : Raphael.getRGB("#48D1CC "), // 72 209 204 Turquoise : Raphael.getRGB("#40E0D0 "), // 64 224 208 Cyan : Raphael.getRGB("#00FFFF "), // 0 255 255 LightCyan : Raphael.getRGB("#E0FFFF "), // 224 255 255 CadetBlue : Raphael.getRGB("#5F9EA0 "), // 95 158 160 MediumAquamarine: Raphael.getRGB("#66CDAA "), // 102 205 170 Aquamarine : Raphael.getRGB("#7FFFD4 "), // 127 255 212 DarkGreen : Raphael.getRGB("#006400 "), // 0 100 0 DarkOliveGreen : Raphael.getRGB("#556B2F "), // 85 107 47 DarkSeaGreen : Raphael.getRGB("#8FBC8F "), // 143 188 143 SeaGreen : Raphael.getRGB("#2E8B57 "), // 46 139 87 MediumSeaGreen : Raphael.getRGB("#3CB371 "), // 60 179 113 LightSeaGreen : Raphael.getRGB("#20B2AA "), // 32 178 170 PaleGreen : Raphael.getRGB("#98FB98 "), // 152 251 152 SpringGreen : Raphael.getRGB("#00FF7F "), // 0 255 127 LawnGreen : Raphael.getRGB("#7CFC00 "), // 124 252 0 Green : Raphael.getRGB("#00FF00 "), // 0 255 0 Chartreuse : Raphael.getRGB("#7FFF00 "), // 127 255 0 MedSpringGreen : Raphael.getRGB("#00FA9A "), // 0 250 154 GreenYellow : Raphael.getRGB("#ADFF2F "), // 173 255 47 LimeGreen : Raphael.getRGB("#32CD32 "), // 50 205 50 YellowGreen : Raphael.getRGB("#9ACD32 "), // 154 205 50 ForestGreen : Raphael.getRGB("#228B22 "), // 34 139 34 OliveDrab : Raphael.getRGB("#6B8E23 "), // 107 142 35 DarkKhaki : Raphael.getRGB("#BDB76B "), // 189 183 107 PaleGoldenrod : Raphael.getRGB("#EEE8AA "), // 238 232 170 LtGoldenrodYello: Raphael.getRGB("#FAFAD2 "), // 250 250 210 LightYellow : Raphael.getRGB("#FFFFE0 "), // 255 255 224 Yellow : Raphael.getRGB("#FFFF00 "), // 255 255 0 Gold : Raphael.getRGB("#FFD700 "), // 255 215 0 LightGoldenrod : Raphael.getRGB("#EEDD82 "), // 238 221 130 goldenrod : Raphael.getRGB("#DAA520 "), // 218 165 32 DarkGoldenrod : Raphael.getRGB("#B8860B "), // 184 134 11 RosyBrown : Raphael.getRGB("#BC8F8F "), // 188 143 143 IndianRed : Raphael.getRGB("#CD5C5C "), // 205 92 92 SaddleBrown : Raphael.getRGB("#8B4513 "), // 139 69 19 Sienna : Raphael.getRGB("#A0522D "), // 160 82 45 Peru : Raphael.getRGB("#CD853F "), // 205 133 63 Burlywood : Raphael.getRGB("#DEB887 "), // 222 184 135 Beige : Raphael.getRGB("#F5F5DC "), // 245 245 220 Wheat : Raphael.getRGB("#F5DEB3 "), // 245 222 179 SandyBrown : Raphael.getRGB("#F4A460 "), // 244 164 96 Tan : Raphael.getRGB("#D2B48C "), // 210 180 140 Chocolate : Raphael.getRGB("#D2691E "), // 210 105 30 Firebrick : Raphael.getRGB("#B22222 "), // 178 34 34 Brown : Raphael.getRGB("#A52A2A "), // 165 42 42 DarkSalmon : Raphael.getRGB("#E9967A "), // 233 150 122 Salmon : Raphael.getRGB("#FA8072 "), // 250 128 114 LightSalmon : Raphael.getRGB("#FFA07A "), // 255 160 122 Orange : Raphael.getRGB("#FFA500 "), // 255 165 0 DarkOrange : Raphael.getRGB("#FF8C00 "), // 255 140 0 Coral : Raphael.getRGB("#FF7F50 "), // 255 127 80 LightCoral : Raphael.getRGB("#F08080 "), // 240 128 128 Tomato : Raphael.getRGB("#FF6347 "), // 255 99 71 OrangeRed : Raphael.getRGB("#FF4500 "), // 255 69 0 Red : Raphael.getRGB("#FF0000 "), // 255 0 0 HotPink : Raphael.getRGB("#FF69B4 "), // 255 105 180 DeepPink : Raphael.getRGB("#FF1493 "), // 255 20 147 Pink : Raphael.getRGB("#FFC0CB "), // 255 192 203 LightPink : Raphael.getRGB("#FFB6C1 "), // 255 182 193 PaleVioletRed : Raphael.getRGB("#DB7093 "), // 219 112 147 Maroon : Raphael.getRGB("#B03060 "), // 176 48 96 MediumVioletRed : Raphael.getRGB("#C71585 "), // 199 21 133 VioletRed : Raphael.getRGB("#D02090 "), // 208 32 144 Magenta : Raphael.getRGB("#FF00FF "), // 255 0 255 Violet : Raphael.getRGB("#EE82EE "), // 238 130 238 Plum : Raphael.getRGB("#DDA0DD "), // 221 160 221 Orchid : Raphael.getRGB("#DA70D6 "), // 218 112 214 MediumOrchid : Raphael.getRGB("#BA55D3 "), // 186 85 211 DarkOrchid : Raphael.getRGB("#9932CC "), // 153 50 204 DarkViolet : Raphael.getRGB("#9400D3 "), // 148 0 211 BlueViolet : Raphael.getRGB("#8A2BE2 "), // 138 43 226 Purple : Raphael.getRGB("#A020F0 "), // 160 32 240 MediumPurple : Raphael.getRGB("#9370DB "), // 147 112 219 Thistle : Raphael.getRGB("#D8BFD8 "), // 216 191 216 Snow1 : Raphael.getRGB("#FFFAFA "), // 255 250 250 Snow2 : Raphael.getRGB("#EEE9E9 "), // 238 233 233 Snow3 : Raphael.getRGB("#CDC9C9 "), // 205 201 201 Snow4 : Raphael.getRGB("#8B8989 "), // 139 137 137 Seashell1 : Raphael.getRGB("#FFF5EE "), // 255 245 238 Seashell2 : Raphael.getRGB("#EEE5DE "), // 238 229 222 Seashell3 : Raphael.getRGB("#CDC5BF "), // 205 197 191 Seashell4 : Raphael.getRGB("#8B8682 "), // 139 134 130 AntiqueWhite1 : Raphael.getRGB("#FFEFDB "), // 255 239 219 AntiqueWhite2 : Raphael.getRGB("#EEDFCC "), // 238 223 204 AntiqueWhite3 : Raphael.getRGB("#CDC0B0 "), // 205 192 176 AntiqueWhite4 : Raphael.getRGB("#8B8378 "), // 139 131 120 Bisque1 : Raphael.getRGB("#FFE4C4 "), // 255 228 196 Bisque2 : Raphael.getRGB("#EED5B7 "), // 238 213 183 Bisque3 : Raphael.getRGB("#CDB79E "), // 205 183 158 Bisque4 : Raphael.getRGB("#8B7D6B "), // 139 125 107 PeachPuff1 : Raphael.getRGB("#FFDAB9 "), // 255 218 185 PeachPuff2 : Raphael.getRGB("#EECBAD "), // 238 203 173 PeachPuff3 : Raphael.getRGB("#CDAF95 "), // 205 175 149 PeachPuff4 : Raphael.getRGB("#8B7765 "), // 139 119 101 NavajoWhite1 : Raphael.getRGB("#FFDEAD "), // 255 222 173 NavajoWhite2 : Raphael.getRGB("#EECFA1 "), // 238 207 161 NavajoWhite3 : Raphael.getRGB("#CDB38B "), // 205 179 139 NavajoWhite4 : Raphael.getRGB("#8B795E "), // 139 121 94 LemonChiffon1 : Raphael.getRGB("#FFFACD "), // 255 250 205 LemonChiffon2 : Raphael.getRGB("#EEE9BF "), // 238 233 191 LemonChiffon3 : Raphael.getRGB("#CDC9A5 "), // 205 201 165 LemonChiffon4 : Raphael.getRGB("#8B8970 "), // 139 137 112 Cornsilk1 : Raphael.getRGB("#FFF8DC "), // 255 248 220 Cornsilk2 : Raphael.getRGB("#EEE8CD "), // 238 232 205 Cornsilk3 : Raphael.getRGB("#CDC8B1 "), // 205 200 177 Cornsilk4 : Raphael.getRGB("#8B8878 "), // 139 136 120 Ivory1 : Raphael.getRGB("#FFFFF0 "), // 255 255 240 Ivory2 : Raphael.getRGB("#EEEEE0 "), // 238 238 224 Ivory3 : Raphael.getRGB("#CDCDC1 "), // 205 205 193 Ivory4 : Raphael.getRGB("#8B8B83 "), // 139 139 131 Honeydew1 : Raphael.getRGB("#F0FFF0 "), // 240 255 240 Honeydew2 : Raphael.getRGB("#E0EEE0 "), // 224 238 224 Honeydew3 : Raphael.getRGB("#C1CDC1 "), // 193 205 193 Honeydew4 : Raphael.getRGB("#838B83 "), // 131 139 131 LavenderBlush1 : Raphael.getRGB("#FFF0F5 "), // 255 240 245 LavenderBlush2 : Raphael.getRGB("#EEE0E5 "), // 238 224 229 LavenderBlush3 : Raphael.getRGB("#CDC1C5 "), // 205 193 197 LavenderBlush4 : Raphael.getRGB("#8B8386 "), // 139 131 134 MistyRose1 : Raphael.getRGB("#FFE4E1 "), // 255 228 225 MistyRose2 : Raphael.getRGB("#EED5D2 "), // 238 213 210 MistyRose3 : Raphael.getRGB("#CDB7B5 "), // 205 183 181 MistyRose4 : Raphael.getRGB("#8B7D7B "), // 139 125 123 Azure1 : Raphael.getRGB("#F0FFFF "), // 240 255 255 Azure2 : Raphael.getRGB("#E0EEEE "), // 224 238 238 Azure3 : Raphael.getRGB("#C1CDCD "), // 193 205 205 Azure4 : Raphael.getRGB("#838B8B "), // 131 139 139 SlateBlue1 : Raphael.getRGB("#836FFF "), // 131 111 255 SlateBlue2 : Raphael.getRGB("#7A67EE "), // 122 103 238 SlateBlue3 : Raphael.getRGB("#6959CD "), // 105 89 205 SlateBlue4 : Raphael.getRGB("#473C8B "), // 71 60 139 RoyalBlue1 : Raphael.getRGB("#4876FF "), // 72 118 255 RoyalBlue2 : Raphael.getRGB("#436EEE "), // 67 110 238 RoyalBlue3 : Raphael.getRGB("#3A5FCD "), // 58 95 205 RoyalBlue4 : Raphael.getRGB("#27408B "), // 39 64 139 Blue1 : Raphael.getRGB("#0000FF "), // 0 0 255 Blue2 : Raphael.getRGB("#0000EE "), // 0 0 238 Blue3 : Raphael.getRGB("#0000CD "), // 0 0 205 Blue4 : Raphael.getRGB("#00008B "), // 0 0 139 DodgerBlue1 : Raphael.getRGB("#1E90FF "), // 30 144 255 DodgerBlue2 : Raphael.getRGB("#1C86EE "), // 28 134 238 DodgerBlue3 : Raphael.getRGB("#1874CD "), // 24 116 205 DodgerBlue4 : Raphael.getRGB("#104E8B "), // 16 78 139 SteelBlue1 : Raphael.getRGB("#63B8FF "), // 99 184 255 SteelBlue2 : Raphael.getRGB("#5CACEE "), // 92 172 238 SteelBlue3 : Raphael.getRGB("#4F94CD "), // 79 148 205 SteelBlue4 : Raphael.getRGB("#36648B "), // 54 100 139 DeepSkyBlue1 : Raphael.getRGB("#00BFFF "), // 0 191 255 DeepSkyBlue2 : Raphael.getRGB("#00B2EE "), // 0 178 238 DeepSkyBlue3 : Raphael.getRGB("#009ACD "), // 0 154 205 DeepSkyBlue4 : Raphael.getRGB("#00688B "), // 0 104 139 SkyBlue1 : Raphael.getRGB("#87CEFF "), // 135 206 255 SkyBlue2 : Raphael.getRGB("#7EC0EE "), // 126 192 238 SkyBlue3 : Raphael.getRGB("#6CA6CD "), // 108 166 205 SkyBlue4 : Raphael.getRGB("#4A708B "), // 74 112 139 LightSkyBlue1 : Raphael.getRGB("#B0E2FF "), // 176 226 255 LightSkyBlue2 : Raphael.getRGB("#A4D3EE "), // 164 211 238 LightSkyBlue3 : Raphael.getRGB("#8DB6CD "), // 141 182 205 LightSkyBlue4 : Raphael.getRGB("#607B8B "), // 96 123 139 SlateGray1 : Raphael.getRGB("#C6E2FF "), // 198 226 255 SlateGray2 : Raphael.getRGB("#B9D3EE "), // 185 211 238 SlateGray3 : Raphael.getRGB("#9FB6CD "), // 159 182 205 SlateGray4 : Raphael.getRGB("#6C7B8B "), // 108 123 139 LightSteelBlue1 : Raphael.getRGB("#CAE1FF "), // 202 225 255 LightSteelBlue2 : Raphael.getRGB("#BCD2EE "), // 188 210 238 LightSteelBlue3 : Raphael.getRGB("#A2B5CD "), // 162 181 205 LightSteelBlue4 : Raphael.getRGB("#6E7B8B "), // 110 123 139 LightBlue1 : Raphael.getRGB("#BFEFFF "), // 191 239 255 LightBlue2 : Raphael.getRGB("#B2DFEE "), // 178 223 238 LightBlue3 : Raphael.getRGB("#9AC0CD "), // 154 192 205 LightBlue4 : Raphael.getRGB("#68838B "), // 104 131 139 LightCyan1 : Raphael.getRGB("#E0FFFF "), // 224 255 255 LightCyan2 : Raphael.getRGB("#D1EEEE "), // 209 238 238 LightCyan3 : Raphael.getRGB("#B4CDCD "), // 180 205 205 LightCyan4 : Raphael.getRGB("#7A8B8B "), // 122 139 139 PaleTurquoise1 : Raphael.getRGB("#BBFFFF "), // 187 255 255 PaleTurquoise2 : Raphael.getRGB("#AEEEEE "), // 174 238 238 PaleTurquoise3 : Raphael.getRGB("#96CDCD "), // 150 205 205 PaleTurquoise4 : Raphael.getRGB("#668B8B "), // 102 139 139 CadetBlue1 : Raphael.getRGB("#98F5FF "), // 152 245 255 CadetBlue2 : Raphael.getRGB("#8EE5EE "), // 142 229 238 CadetBlue3 : Raphael.getRGB("#7AC5CD "), // 122 197 205 CadetBlue4 : Raphael.getRGB("#53868B "), // 83 134 139 Turquoise1 : Raphael.getRGB("#00F5FF "), // 0 245 255 Turquoise2 : Raphael.getRGB("#00E5EE "), // 0 229 238 Turquoise3 : Raphael.getRGB("#00C5CD "), // 0 197 205 Turquoise4 : Raphael.getRGB("#00868B "), // 0 134 139 Cyan1 : Raphael.getRGB("#00FFFF "), // 0 255 255 Cyan2 : Raphael.getRGB("#00EEEE "), // 0 238 238 Cyan3 : Raphael.getRGB("#00CDCD "), // 0 205 205 Cyan4 : Raphael.getRGB("#008B8B "), // 0 139 139 DarkSlateGray1 : Raphael.getRGB("#97FFFF "), // 151 255 255 DarkSlateGray2 : Raphael.getRGB("#8DEEEE "), // 141 238 238 DarkSlateGray3 : Raphael.getRGB("#79CDCD "), // 121 205 205 DarkSlateGray4 : Raphael.getRGB("#528B8B "), // 82 139 139 Aquamarine1 : Raphael.getRGB("#7FFFD4 "), // 127 255 212 Aquamarine2 : Raphael.getRGB("#76EEC6 "), // 118 238 198 Aquamarine3 : Raphael.getRGB("#66CDAA "), // 102 205 170 Aquamarine4 : Raphael.getRGB("#458B74 "), // 69 139 116 DarkSeaGreen1 : Raphael.getRGB("#C1FFC1 "), // 193 255 193 DarkSeaGreen2 : Raphael.getRGB("#B4EEB4 "), // 180 238 180 DarkSeaGreen3 : Raphael.getRGB("#9BCD9B "), // 155 205 155 DarkSeaGreen4 : Raphael.getRGB("#698B69 "), // 105 139 105 SeaGreen1 : Raphael.getRGB("#54FF9F "), // 84 255 159 SeaGreen2 : Raphael.getRGB("#4EEE94 "), // 78 238 148 SeaGreen3 : Raphael.getRGB("#43CD80 "), // 67 205 128 SeaGreen4 : Raphael.getRGB("#2E8B57 "), // 46 139 87 PaleGreen1 : Raphael.getRGB("#9AFF9A "), // 154 255 154 PaleGreen2 : Raphael.getRGB("#90EE90 "), // 144 238 144 PaleGreen3 : Raphael.getRGB("#7CCD7C "), // 124 205 124 PaleGreen4 : Raphael.getRGB("#548B54 "), // 84 139 84 SpringGreen1 : Raphael.getRGB("#00FF7F "), // 0 255 127 SpringGreen2 : Raphael.getRGB("#00EE76 "), // 0 238 118 SpringGreen3 : Raphael.getRGB("#00CD66 "), // 0 205 102 SpringGreen4 : Raphael.getRGB("#008B45 "), // 0 139 69 Green1 : Raphael.getRGB("#00FF00 "), // 0 255 0 Green2 : Raphael.getRGB("#00EE00 "), // 0 238 0 Green3 : Raphael.getRGB("#00CD00 "), // 0 205 0 Green4 : Raphael.getRGB("#008B00 "), // 0 139 0 Chartreuse1 : Raphael.getRGB("#7FFF00 "), // 127 255 0 Chartreuse2 : Raphael.getRGB("#76EE00 "), // 118 238 0 Chartreuse3 : Raphael.getRGB("#66CD00 "), // 102 205 0 Chartreuse4 : Raphael.getRGB("#458B00 "), // 69 139 0 OliveDrab1 : Raphael.getRGB("#C0FF3E "), // 192 255 62 OliveDrab2 : Raphael.getRGB("#B3EE3A "), // 179 238 58 OliveDrab3 : Raphael.getRGB("#9ACD32 "), // 154 205 50 OliveDrab4 : Raphael.getRGB("#698B22 "), // 105 139 34 DarkOliveGreen1 : Raphael.getRGB("#CAFF70 "), // 202 255 112 DarkOliveGreen2 : Raphael.getRGB("#BCEE68 "), // 188 238 104 DarkOliveGreen3 : Raphael.getRGB("#A2CD5A "), // 162 205 90 DarkOliveGreen4 : Raphael.getRGB("#6E8B3D "), // 110 139 61 Khaki1 : Raphael.getRGB("#FFF68F "), // 255 246 143 Khaki2 : Raphael.getRGB("#EEE685 "), // 238 230 133 Khaki3 : Raphael.getRGB("#CDC673 "), // 205 198 115 Khaki4 : Raphael.getRGB("#8B864E "), // 139 134 78 LightGoldenrod1 : Raphael.getRGB("#FFEC8B "), // 255 236 139 LightGoldenrod2 : Raphael.getRGB("#EEDC82 "), // 238 220 130 LightGoldenrod3 : Raphael.getRGB("#CDBE70 "), // 205 190 112 LightGoldenrod4 : Raphael.getRGB("#8B814C "), // 139 129 76 LightYellow1 : Raphael.getRGB("#FFFFE0 "), // 255 255 224 LightYellow2 : Raphael.getRGB("#EEEED1 "), // 238 238 209 LightYellow3 : Raphael.getRGB("#CDCDB4 "), // 205 205 180 LightYellow4 : Raphael.getRGB("#8B8B7A "), // 139 139 122 Yellow1 : Raphael.getRGB("#FFFF00 "), // 255 255 0 Yellow2 : Raphael.getRGB("#EEEE00 "), // 238 238 0 Yellow3 : Raphael.getRGB("#CDCD00 "), // 205 205 0 Yellow4 : Raphael.getRGB("#8B8B00 "), // 139 139 0 Gold1 : Raphael.getRGB("#FFD700 "), // 255 215 0 Gold2 : Raphael.getRGB("#EEC900 "), // 238 201 0 Gold3 : Raphael.getRGB("#CDAD00 "), // 205 173 0 Gold4 : Raphael.getRGB("#8B7500 "), // 139 117 0 Goldenrod1 : Raphael.getRGB("#FFC125 "), // 255 193 37 Goldenrod2 : Raphael.getRGB("#EEB422 "), // 238 180 34 Goldenrod3 : Raphael.getRGB("#CD9B1D "), // 205 155 29 Goldenrod4 : Raphael.getRGB("#8B6914 "), // 139 105 20 DarkGoldenrod1 : Raphael.getRGB("#FFB90F "), // 255 185 15 DarkGoldenrod2 : Raphael.getRGB("#EEAD0E "), // 238 173 14 DarkGoldenrod3 : Raphael.getRGB("#CD950C "), // 205 149 12 DarkGoldenrod4 : Raphael.getRGB("#8B658B "), // 139 101 8 RosyBrown1 : Raphael.getRGB("#FFC1C1 "), // 255 193 193 RosyBrown2 : Raphael.getRGB("#EEB4B4 "), // 238 180 180 RosyBrown3 : Raphael.getRGB("#CD9B9B "), // 205 155 155 RosyBrown4 : Raphael.getRGB("#8B6969 "), // 139 105 105 IndianRed1 : Raphael.getRGB("#FF6A6A "), // 255 106 106 IndianRed2 : Raphael.getRGB("#EE6363 "), // 238 99 99 IndianRed3 : Raphael.getRGB("#CD5555 "), // 205 85 85 IndianRed4 : Raphael.getRGB("#8B3A3A "), // 139 58 58 Sienna1 : Raphael.getRGB("#FF8247 "), // 255 130 71 Sienna2 : Raphael.getRGB("#EE7942 "), // 238 121 66 Sienna3 : Raphael.getRGB("#CD6839 "), // 205 104 57 Sienna4 : Raphael.getRGB("#8B4726 "), // 139 71 38 Burlywood1 : Raphael.getRGB("#FFD39B "), // 255 211 155 Burlywood2 : Raphael.getRGB("#EEC591 "), // 238 197 145 Burlywood3 : Raphael.getRGB("#CDAA7D "), // 205 170 125 Burlywood4 : Raphael.getRGB("#8B7355 "), // 139 115 85 Wheat1 : Raphael.getRGB("#FFE7BA "), // 255 231 186 Wheat2 : Raphael.getRGB("#EED8AE "), // 238 216 174 Wheat3 : Raphael.getRGB("#CDBA96 "), // 205 186 150 Wheat4 : Raphael.getRGB("#8B7E66 "), // 139 126 102 Tan1 : Raphael.getRGB("#FFA54F "), // 255 165 79 Tan2 : Raphael.getRGB("#EE9A49 "), // 238 154 73 Tan3 : Raphael.getRGB("#CD853F "), // 205 133 63 Tan4 : Raphael.getRGB("#8B5A2B "), // 139 90 43 Chocolate1 : Raphael.getRGB("#FF7F24 "), // 255 127 36 Chocolate2 : Raphael.getRGB("#EE7621 "), // 238 118 33 Chocolate3 : Raphael.getRGB("#CD661D "), // 205 102 29 Chocolate4 : Raphael.getRGB("#8B4513 "), // 139 69 19 Firebrick1 : Raphael.getRGB("#FF3030 "), // 255 48 48 Firebrick2 : Raphael.getRGB("#EE2C2C "), // 238 44 44 Firebrick3 : Raphael.getRGB("#CD2626 "), // 205 38 38 Firebrick4 : Raphael.getRGB("#8B1A1A "), // 139 26 26 Brown1 : Raphael.getRGB("#FF4040 "), // 255 64 64 Brown2 : Raphael.getRGB("#EE3B3B "), // 238 59 59 Brown3 : Raphael.getRGB("#CD3333 "), // 205 51 51 Brown4 : Raphael.getRGB("#8B2323 "), // 139 35 35 Salmon1 : Raphael.getRGB("#FF8C69 "), // 255 140 105 Salmon2 : Raphael.getRGB("#EE8262 "), // 238 130 98 Salmon3 : Raphael.getRGB("#CD7054 "), // 205 112 84 Salmon4 : Raphael.getRGB("#8B4C39 "), // 139 76 57 LightSalmon1 : Raphael.getRGB("#FFA07A "), // 255 160 122 LightSalmon2 : Raphael.getRGB("#EE9572 "), // 238 149 114 LightSalmon3 : Raphael.getRGB("#CD8162 "), // 205 129 98 LightSalmon4 : Raphael.getRGB("#8B5742 "), // 139 87 66 Orange1 : Raphael.getRGB("#FFA500 "), // 255 165 0 Orange2 : Raphael.getRGB("#EE9A00 "), // 238 154 0 Orange3 : Raphael.getRGB("#CD8500 "), // 205 133 0 Orange4 : Raphael.getRGB("#8B5A00 "), // 139 90 0 DarkOrange1 : Raphael.getRGB("#FF7F00 "), // 255 127 0 DarkOrange2 : Raphael.getRGB("#EE7600 "), // 238 118 0 DarkOrange3 : Raphael.getRGB("#CD6600 "), // 205 102 0 DarkOrange4 : Raphael.getRGB("#8B4500 "), // 139 69 0 Coral1 : Raphael.getRGB("#FF7256 "), // 255 114 86 Coral2 : Raphael.getRGB("#EE6A50 "), // 238 106 80 Coral3 : Raphael.getRGB("#CD5B45 "), // 205 91 69 Coral4 : Raphael.getRGB("#8B3E2F "), // 139 62 47 Tomato1 : Raphael.getRGB("#FF6347 "), // 255 99 71 Tomato2 : Raphael.getRGB("#EE5C42 "), // 238 92 66 Tomato3 : Raphael.getRGB("#CD4F39 "), // 205 79 57 Tomato4 : Raphael.getRGB("#8B3626 "), // 139 54 38 OrangeRed1 : Raphael.getRGB("#FF4500 "), // 255 69 0 OrangeRed2 : Raphael.getRGB("#EE4000 "), // 238 64 0 OrangeRed3 : Raphael.getRGB("#CD3700 "), // 205 55 0 OrangeRed4 : Raphael.getRGB("#8B2500 "), // 139 37 0 Red1 : Raphael.getRGB("#FF0000 "), // 255 0 0 Red2 : Raphael.getRGB("#EE0000 "), // 238 0 0 Red3 : Raphael.getRGB("#CD0000 "), // 205 0 0 Red4 : Raphael.getRGB("#8B0000 "), // 139 0 0 DeepPink1 : Raphael.getRGB("#FF1493 "), // 255 20 147 DeepPink2 : Raphael.getRGB("#EE1289 "), // 238 18 137 DeepPink3 : Raphael.getRGB("#CD1076 "), // 205 16 118 DeepPink4 : Raphael.getRGB("#8B0A50 "), // 139 10 80 HotPink1 : Raphael.getRGB("#FF6EB4 "), // 255 110 180 HotPink2 : Raphael.getRGB("#EE6AA7 "), // 238 106 167 HotPink3 : Raphael.getRGB("#CD6090 "), // 205 96 144 HotPink4 : Raphael.getRGB("#8B3A62 "), // 139 58 98 Pink1 : Raphael.getRGB("#FFB5C5 "), // 255 181 197 Pink2 : Raphael.getRGB("#EEA9B8 "), // 238 169 184 Pink3 : Raphael.getRGB("#CD919E "), // 205 145 158 Pink4 : Raphael.getRGB("#8B636C "), // 139 99 108 LightPink1 : Raphael.getRGB("#FFAEB9 "), // 255 174 185 LightPink2 : Raphael.getRGB("#EEA2AD "), // 238 162 173 LightPink3 : Raphael.getRGB("#CD8C95 "), // 205 140 149 LightPink4 : Raphael.getRGB("#8B5F65 "), // 139 95 101 PaleVioletRed1 : Raphael.getRGB("#FF82AB "), // 255 130 171 PaleVioletRed2 : Raphael.getRGB("#EE799F "), // 238 121 159 PaleVioletRed3 : Raphael.getRGB("#CD6889 "), // 205 104 137 PaleVioletRed4 : Raphael.getRGB("#8B475D "), // 139 71 93 Maroon1 : Raphael.getRGB("#FF34B3 "), // 255 52 179 Maroon2 : Raphael.getRGB("#EE30A7 "), // 238 48 167 Maroon3 : Raphael.getRGB("#CD2990 "), // 205 41 144 Maroon4 : Raphael.getRGB("#8B1C62 "), // 139 28 98 VioletRed1 : Raphael.getRGB("#FF3E96 "), // 255 62 150 VioletRed2 : Raphael.getRGB("#EE3A8C "), // 238 58 140 VioletRed3 : Raphael.getRGB("#CD3278 "), // 205 50 120 VioletRed4 : Raphael.getRGB("#8B2252 "), // 139 34 82 Magenta1 : Raphael.getRGB("#FF00FF "), // 255 0 255 Magenta2 : Raphael.getRGB("#EE00EE "), // 238 0 238 Magenta3 : Raphael.getRGB("#CD00CD "), // 205 0 205 Magenta4 : Raphael.getRGB("#8B008B "), // 139 0 139 Orchid1 : Raphael.getRGB("#FF83FA "), // 255 131 250 Orchid2 : Raphael.getRGB("#EE7AE9 "), // 238 122 233 Orchid3 : Raphael.getRGB("#CD69C9 "), // 205 105 201 Orchid4 : Raphael.getRGB("#8B4789 "), // 139 71 137 Plum1 : Raphael.getRGB("#FFBBFF "), // 255 187 255 Plum2 : Raphael.getRGB("#EEAEEE "), // 238 174 238 Plum3 : Raphael.getRGB("#CD96CD "), // 205 150 205 Plum4 : Raphael.getRGB("#8B668B "), // 139 102 139 MediumOrchid1 : Raphael.getRGB("#E066FF "), // 224 102 255 MediumOrchid2 : Raphael.getRGB("#D15FEE "), // 209 95 238 MediumOrchid3 : Raphael.getRGB("#B452CD "), // 180 82 205 MediumOrchid4 : Raphael.getRGB("#7A378B "), // 122 55 139 DarkOrchid1 : Raphael.getRGB("#BF3EFF "), // 191 62 255 DarkOrchid2 : Raphael.getRGB("#B23AEE "), // 178 58 238 DarkOrchid3 : Raphael.getRGB("#9A32CD "), // 154 50 205 DarkOrchid4 : Raphael.getRGB("#68228B "), // 104 34 139 Purple1 : Raphael.getRGB("#9B30FF "), // 155 48 255 Purple2 : Raphael.getRGB("#912CEE "), // 145 44 238 Purple3 : Raphael.getRGB("#7D26CD "), // 125 38 205 Purple4 : Raphael.getRGB("#551A8B "), // 85 26 139 MediumPurple1 : Raphael.getRGB("#AB82FF "), // 171 130 255 MediumPurple2 : Raphael.getRGB("#9F79EE "), // 159 121 238 MediumPurple3 : Raphael.getRGB("#8968CD "), // 137 104 205 MediumPurple4 : Raphael.getRGB("#5D478B "), // 93 71 139 Thistle1 : Raphael.getRGB("#FFE1FF "), // 255 225 255 Thistle2 : Raphael.getRGB("#EED2EE "), // 238 210 238 Thistle3 : Raphael.getRGB("#CDB5CD "), // 205 181 205 Thistle4 : Raphael.getRGB("#8B7B8B "), // 139 123 139 grey11 : Raphael.getRGB("#1C1C1C "), // 28 28 28 grey21 : Raphael.getRGB("#363636 "), // 54 54 54 grey31 : Raphael.getRGB("#4F4F4F "), // 79 79 79 grey41 : Raphael.getRGB("#696969 "), // 105 105 105 grey51 : Raphael.getRGB("#828282 "), // 130 130 130 grey61 : Raphael.getRGB("#9C9C9C "), // 156 156 156 grey71 : Raphael.getRGB("#B5B5B5 "), // 181 181 181 gray81 : Raphael.getRGB("#CFCFCF "), // 207 207 207 gray91 : Raphael.getRGB("#E8E8E8 "), // 232 232 232 DarkGrey : Raphael.getRGB("#A9A9A9 "), // 169 169 169 DarkBlue : Raphael.getRGB("#00008B "), // 0 0 139 DarkCyan : Raphael.getRGB("#008B8B "), // 0 139 139 DarkMagenta : Raphael.getRGB("#8B008B "), // 139 0 139 DarkRed : Raphael.getRGB("#8B0000 "), // 139 0 0 LightGreen : Raphael.getRGB("#90EE90 "), // 144 238 144 get: function(R, G, B){ return Raphael.getRGB("rgb(" + R + ", " + G + ", " + B + ")"); } }; ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/LineBreakMeasurer.js ================================================ /** * Word wrapping * * @author (Javascript) Dmitry Farafonov */ var AttributedStringIterator = function(text){ //this.text = this.rtrim(this.ltrim(text)); text = text.replace(/(\s)+/, " "); this.text = this.rtrim(text); /* if (beginIndex < 0 || beginIndex > endIndex || endIndex > length()) { throw new IllegalArgumentException("Invalid substring range"); } */ this.beginIndex = 0; this.endIndex = this.text.length; this.currentIndex = this.beginIndex; //console.group("[AttributedStringIterator]"); var i = 0; var string = this.text; var fullPos = 0; //console.log("string: \"" + string + "\", length: " + string.length); this.startWordOffsets = []; this.startWordOffsets.push(fullPos); // TODO: remove i 1000 while (i<1000) { var pos = string.search(/[ \t\n\f-\.\,]/); if (pos == -1) break; // whitespace start fullPos += pos; string = string.substr(pos); ////console.log("fullPos: " + fullPos + ", pos: " + pos + ", string: ", string); // remove whitespaces var pos = string.search(/[^ \t\n\f-\.\,]/); if (pos == -1) break; // whitespace end fullPos += pos; string = string.substr(pos); ////console.log("fullPos: " + fullPos); this.startWordOffsets.push(fullPos); i++; } //console.log("startWordOffsets: ", this.startWordOffsets); //console.groupEnd(); }; AttributedStringIterator.prototype = { getEndIndex: function(pos){ if (typeof(pos) == "undefined") return this.endIndex; var string = this.text.substr(pos, this.endIndex - pos); var posEndOfLine = string.search(/[\n]/); if (posEndOfLine == -1) return this.endIndex; else return pos + posEndOfLine; }, getBeginIndex: function(){ return this.beginIndex; }, isWhitespace: function(pos){ var str = this.text[pos]; var whitespaceChars = " \t\n\f"; return (whitespaceChars.indexOf(str) != -1); }, isNewLine: function(pos){ var str = this.text[pos]; var whitespaceChars = "\n"; return (whitespaceChars.indexOf(str) != -1); }, preceding: function(pos){ //console.group("[AttributedStringIterator.preceding]"); for(var i in this.startWordOffsets) { var startWordOffset = this.startWordOffsets[i]; if (pos < startWordOffset && i>0) { //console.log("startWordOffset: " + this.startWordOffsets[i-1]); //console.groupEnd(); return this.startWordOffsets[i-1]; } } //console.log("pos: " + pos); //console.groupEnd(); return this.startWordOffsets[i]; }, following: function(pos){ //console.group("[AttributedStringIterator.following]"); for(var i in this.startWordOffsets) { var startWordOffset = this.startWordOffsets[i]; if (pos < startWordOffset && i>0) { //console.log("startWordOffset: " + this.startWordOffsets[i]); //console.groupEnd(); return this.startWordOffsets[i]; } } //console.log("pos: " + pos); //console.groupEnd(); return this.startWordOffsets[i]; }, ltrim: function(str){ var patt2=/^\s+/g; return str.replace(patt2, ""); }, rtrim: function(str){ var patt2=/\s+$/g; return str.replace(patt2, ""); }, getLayout: function(start, limit){ return this.text.substr(start, limit - start); }, getCharAtPos: function(pos) { return this.text[pos]; } }; var LineBreakMeasurer = function(paper, x, y, text, fontAttrs){ this.paper = paper; this.text = new AttributedStringIterator(text); this.fontAttrs = fontAttrs; if (this.text.getEndIndex() - this.text.getBeginIndex() < 1) { throw {message: "Text must contain at least one character.", code: "IllegalArgumentException"}; } //this.measurer = new TextMeasurer(paper, this.text, this.fontAttrs); this.limit = this.text.getEndIndex(); this.pos = this.start = this.text.getBeginIndex(); this.rafaelTextObject = this.paper.text(x, y, this.text.text).attr(fontAttrs).attr("text-anchor", "start"); this.svgTextObject = this.rafaelTextObject[0]; }; LineBreakMeasurer.prototype = { nextOffset: function(wrappingWidth, offsetLimit, requireNextWord) { //console.group("[nextOffset]"); var nextOffset = this.pos; if (this.pos < this.limit) { if (offsetLimit <= this.pos) { throw {message: "offsetLimit must be after current position", code: "IllegalArgumentException"}; } var charAtMaxAdvance = this.getLineBreakIndex(this.pos, wrappingWidth); //charAtMaxAdvance --; //console.log("charAtMaxAdvance:", charAtMaxAdvance, ", [" + this.text.getCharAtPos(charAtMaxAdvance) + "]"); if (charAtMaxAdvance == this.limit) { nextOffset = this.limit; //console.log("charAtMaxAdvance == this.limit"); } else if (this.text.isNewLine(charAtMaxAdvance)) { //console.log("isNewLine"); nextOffset = charAtMaxAdvance+1; } else if (this.text.isWhitespace(charAtMaxAdvance)) { // TODO: find next noSpaceChar //return nextOffset; nextOffset = this.text.following(charAtMaxAdvance); } else { // Break is in a word; back up to previous break. /* var testPos = charAtMaxAdvance + 1; if (testPos == this.limit) { console.error("hbz..."); } else { nextOffset = this.text.preceding(charAtMaxAdvance); } */ nextOffset = this.text.preceding(charAtMaxAdvance); if (nextOffset <= this.pos) { nextOffset = Math.max(this.pos+1, charAtMaxAdvance); } } } if (nextOffset > offsetLimit) { nextOffset = offsetLimit; } //console.log("nextOffset: " + nextOffset); //console.groupEnd(); return nextOffset; }, nextLayout: function(wrappingWidth) { //console.groupCollapsed("[nextLayout]"); if (this.pos < this.limit) { var requireNextWord = false; var layoutLimit = this.nextOffset(wrappingWidth, this.limit, requireNextWord); //console.log("layoutLimit:", layoutLimit); if (layoutLimit == this.pos) { //console.groupEnd(); return null; } var result = this.text.getLayout(this.pos, layoutLimit); //console.log("layout: \"" + result + "\""); // remove end of line //var posEndOfLine = this.text.getEndIndex(this.pos); //if (posEndOfLine < result.length) // result = result.substr(0, posEndOfLine); this.pos = layoutLimit; //console.groupEnd(); return result; } else { //console.groupEnd(); return null; } }, getLineBreakIndex: function(pos, wrappingWidth) { //console.group("[getLineBreakIndex]"); //console.log("pos:"+pos + ", text: \""+ this.text.text.replace(/\n/g, "_").substr(pos, 1) + "\""); var bb = this.rafaelTextObject.getBBox(); var charNum = -1; try { var svgPoint = this.svgTextObject.getStartPositionOfChar(pos); //var dot = this.paper.ellipse(svgPoint.x, svgPoint.y, 1, 1).attr({"stroke-width": 0, fill: Color.blue}); svgPoint.x = svgPoint.x + wrappingWidth; //svgPoint.y = bb.y; //console.log("svgPoint:", svgPoint); //var dot = this.paper.ellipse(svgPoint.x, svgPoint.y, 1, 1).attr({"stroke-width": 0, fill: Color.red}); charNum = this.svgTextObject.getCharNumAtPosition(svgPoint); } catch (e){ console.warn("getStartPositionOfChar error, pos:" + pos); /* var testPos = pos + 1; if (testPos < this.limit) { return testPos } */ } //console.log("charNum:", charNum); if (charNum == -1) { //console.groupEnd(); return this.text.getEndIndex(pos); } else { // When case there is new line between pos and charnum then use this new line var newLineIndex = this.text.getEndIndex(pos); if (newLineIndex < charNum ) { console.log("newLineIndex <= charNum, newLineIndex:"+newLineIndex+", charNum:"+charNum, "\"" + this.text.text.substr(newLineIndex+1).replace(/\n/g, "?") + "\""); //console.groupEnd(); return newLineIndex; } //var charAtMaxAdvance = this.text.text.substring(charNum, charNum + 1); var charAtMaxAdvance = this.text.getCharAtPos(charNum); //console.log("!!charAtMaxAdvance: " + charAtMaxAdvance); //console.groupEnd(); return charNum; } }, getPosition: function() { return this.pos; } }; ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/Polyline.js ================================================ /** * Class to generate polyline * * @author Dmitry Farafonov */ var ANCHOR_TYPE= { main: "main", middle: "middle", first: "first", last: "last" }; function Anchor(uuid, type, x, y) { this.uuid = uuid; this.x = x this.y = y this.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main; }; Anchor.prototype = { uuid: null, x: 0, y: 0, type: ANCHOR_TYPE.main, isFirst: false, isLast: false, ndex: 0, typeIndex: 0 }; function Polyline(uuid, points, strokeWidth) { /* Array on coordinates: * points: [{x: 410, y: 110}, 1 * {x: 570, y: 110}, 1 2 * {x: 620, y: 240}, 2 3 * {x: 750, y: 270}, 3 4 * {x: 650, y: 370}]; 4 */ this.points = points; /* * path for graph * [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]] */ this.path = []; this.anchors = []; if (strokeWidth) this.strokeWidth = strokeWidth; this.closePath = false; this.init(); }; Polyline.prototype = { id: null, points: [], path: [], anchors: [], strokeWidth: 1, radius: 15, showDetails: false, element: null, isDefaultConditionAvailable: false, closePath: false, init: function(points){ var linesCount = this.getLinesCount(); if (linesCount < 1) return; this.normalizeCoordinates(); // create anchors this.pushAnchor(ANCHOR_TYPE.first, this.getLine(0).x1, this.getLine(0).y1); for(var i = 1; i < linesCount; i++){ var line1 = this.getLine(i-1), line2 = this.getLine(i); //this.pushAnchor(ANCHOR_TYPE.middle, line1.x1 + line1.x2-line1.x1, line1.y1 + line1.y2-line1.y1); this.pushAnchor(ANCHOR_TYPE.main, line1.x2, line1.y2); //this.pushAnchor(ANCHOR_TYPE.middle, line2.x1 + line2.x2-line2.x1, line2.y1 + line2.y2-line2.y1); } this.pushAnchor(ANCHOR_TYPE.last, this.getLine(linesCount-1).x2, this.getLine(linesCount-1).y2); this.rebuildPath(); }, normalizeCoordinates: function(){ for(var i=0; i < this.points.length; i++){ this.points[i].x = parseFloat(this.points[i].x); this.points[i].y = parseFloat(this.points[i].y); } }, getLinesCount: function(){ return this.points.length-1; }, _getLine: function(i){ return {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y}; }, getLine: function(i){ var line = this._getLine(i); line.angle = this.getLineAngle(i) ; return line; }, getLineAngle: function(i){ var line = this._getLine(i); return Math.atan2(line.y2 - line.y1, line.x2 - line.x1); }, getLineLengthX: function(i){ var line = this.getLine(i); return (line.x2 - line.x1); }, getLineLengthY: function(i){ var line = this.getLine(i); return (line.y2 - line.y1); }, getLineLength: function(i){ var line = this.getLine(i); return Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2)); }, getAnchors: function(){ // // ???? return this.anchors; }, getAnchorsCount: function(type){ if (!type) return this.anchors.length; else { var count = 0; for(var i=0; i < this.getAnchorsCount(); i++){ var anchor = this.anchors[i]; if (anchor.getType() == type) { count++; } } return count; } }, pushAnchor: function(type, x, y, index){ if (type == ANCHOR_TYPE.first) { index = 0; typeIndex = 0; } else if (type == ANCHOR_TYPE.last) { index = this.getAnchorsCount(); typeIndex = 0; } else if (!index) { index = this.anchors.length; } else { // anchors, , index //var anchor = this.getAnchor() for(var i=0; i < this.getAnchorsCount(); i++){ var anchor = this.anchors[i]; if (anchor.index > index) { anchor.index++; anchor.typeIndex++; } } } var anchor = new Anchor(this.id, ANCHOR_TYPE.main, x, y, index, typeIndex); this.anchors.push(anchor); }, getAnchor: function(position){ return this.anchors[position]; }, getAnchorByType: function(type, position){ if (type == ANCHOR_TYPE.first) return this.anchors[0]; if (type == ANCHOR_TYPE.last) return this.anchors[this.getAnchorsCount()-1]; for(var i=0; i < this.getAnchorsCount(); i++){ var anchor = this.anchors[i]; if (anchor.type == type) { if( position == anchor.position) return anchor; } } return null; }, addNewPoint: function(position, x, y){ // for(var i = 0; i < this.getLinesCount(); i++){ var line = this.getLine(i); if (x > line.x1 && x < line.x2 && y > line.y1 && y < line.y2) { this.points.splice(i+1,0,{x: x, y: y}); break; } } this.rebuildPath(); }, rebuildPath: function(){ var path = []; for(var i = 0; i < this.getAnchorsCount(); i++){ var anchor = this.getAnchor(i); var pathType = "" if (i==0) pathType = "M"; else pathType = "L"; // TODO: save previous points and calculate new path just if points are updated, and then save currents values as previous var targetX = anchor.x, targetY = anchor.y; if (i>0 && i < this.getAnchorsCount()-1) { // get new x,y var cx = anchor.x, cy = anchor.y; // pivot point of prev line var AO = this.getLineLength(i-1); if (AO < this.radius) { AO = this.radius; } this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10)); //console.log("isDefaultConditionAvailable", this.isDefaultConditionAvailable); var ED = this.getLineLengthY(i-1) * this.radius / AO; var OD = this.getLineLengthX(i-1) * this.radius / AO; targetX = anchor.x - OD; targetY = anchor.y - ED; if (AO < 2*this.radius && i>1) { targetX = anchor.x - this.getLineLengthX(i-1)/2; targetY = anchor.y - this.getLineLengthY(i-1)/2;; } // pivot point of next line var AO = this.getLineLength(i); if (AO < this.radius) { AO = this.radius; } var ED = this.getLineLengthY(i) * this.radius / AO; var OD = this.getLineLengthX(i) * this.radius / AO; var nextSrcX = anchor.x + OD; var nextSrcY = anchor.y + ED; if (AO < 2*this.radius && i 10)); //console.log("-- isDefaultConditionAvailable", this.isDefaultConditionAvailable); } // anti smoothing if (this.strokeWidth%2 == 1) { targetX += 0.5; targetY += 0.5; } path.push([pathType, targetX, targetY]); if (i>0 && i < this.getAnchorsCount()-1) { path.push(["C", ax, ay, bx, by, zx, zy]); } } if (this.closePath) { console.log("closePath:", this.closePath); path.push(["Z"]); } this.path = path; }, transform: function(transformation){ this.element.transform(transformation); }, attr: function(attrs){ //console.log("attrs: " +attrs, "", this.element); // TODO: foreach and set each this.element.attr(attrs); } }; function Polygone(points, strokeWidth) { /* Array on coordinates: * points: [{x: 410, y: 110}, 1 * {x: 570, y: 110}, 1 2 * {x: 620, y: 240}, 2 3 * {x: 750, y: 270}, 3 4 * {x: 650, y: 370}]; 4 */ this.points = points; /* * path for graph * [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]] */ this.path = []; this.anchors = []; if (strokeWidth) this.strokeWidth = strokeWidth; this.closePath = true; this.init(); }; /* * Poligone is inherited from Poliline: draws closedPath of polyline */ var Foo = function () { }; Foo.prototype = Polyline.prototype; Polygone.prototype = new Foo(); Polygone.prototype.rebuildPath = function(){ var path = []; //console.log("Polygone rebuildPath"); for(var i = 0; i < this.getAnchorsCount(); i++){ var anchor = this.getAnchor(i); var pathType = "" if (i==0) pathType = "M"; else pathType = "L"; var targetX = anchor.x, targetY = anchor.y; // anti smoothing if (this.strokeWidth%2 == 1) { targetX += 0.5; targetY += 0.5; } path.push([pathType, targetX, targetY]); } if (this.closePath) path.push(["Z"]); this.path = path; }; /* Polygone.prototype.transform = function(transformation){ this.element.transform(transformation); }; */ ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ProcessDiagramCanvas.js ================================================ /** * Represents a canvas on which BPMN 2.0 constructs can be drawn. * * Some of the icons used are licenced under a Creative Commons Attribution 2.5 * License, see http://www.famfamfam.com/lab/icons/silk/ * * @see ProcessDiagramGenerator * @author (Java) Joram Barrez * @author (Javascript) Dmitry Farafonov */ //Color.Cornsilk var ARROW_HEAD_SIMPLE = "simple"; var ARROW_HEAD_EMPTY = "empty"; var ARROW_HEAD_FILL = "FILL"; var MULTILINE_VERTICAL_ALIGN_TOP = "top"; var MULTILINE_VERTICAL_ALIGN_MIDDLE = "middle"; var MULTILINE_VERTICAL_ALIGN_BOTTOM = "bottom"; var MULTILINE_HORIZONTAL_ALIGN_LEFT = "start"; var MULTILINE_HORIZONTAL_ALIGN_MIDDLE = "middle"; var MULTILINE_HORIZONTAL_ALIGN_RIGHT = "end"; // Predefined sized var TEXT_PADDING = 3; var ARROW_WIDTH = 4; var CONDITIONAL_INDICATOR_WIDTH = 16; var MARKER_WIDTH = 12; var ANNOTATION_TEXT_PADDING = 7; // Colors var TASK_COLOR = Color.OldLace; // original: Color.get(255, 255, 204); var TASK_STROKE_COLOR = Color.black; /*Color.SlateGrey; */ //var EXPANDED_SUBPROCESS_ATTRS = Color.black; /*Color.SlateGrey; */ var BOUNDARY_EVENT_COLOR = Color.white; var CONDITIONAL_INDICATOR_COLOR = Color.get(255, 255, 255); var HIGHLIGHT_COLOR = Color.Firebrick1; //var SEQUENCEFLOW_COLOR = Color.DimGrey; var SEQUENCEFLOW_COLOR = Color.black; var CATCHING_EVENT_COLOR = Color.black; /* Color.SlateGrey; */ var START_EVENT_COLOR = Color.get(251,251,251); var START_EVENT_STROKE_COLOR = Color.black; /* Color.SlateGrey; */ var END_EVENT_COLOR = Color.get(251,251,251); //var END_EVENT_STROKE_COLOR = Color.black; var NONE_END_EVENT_COLOR = Color.Firebrick4; var NONE_END_EVENT_STROKE_COLOR = Color.Firebrick4; var ERROR_END_EVENT_COLOR = Color.Firebrick; var ERROR_END_EVENT_STROKE_COLOR = Color.Firebrick; //var LABEL_COLOR = Color.get(112, 146, 190); var LABEL_COLOR = Color.get(72, 106, 150); // Fonts var NORMAL_FONT = {font: "10px Arial", opacity: 1, fill: Color.black}; var LABEL_FONT = {font: "11px Arial", "font-style":"italic", opacity: 1, "fill": LABEL_COLOR}; var LABEL_FONT_SMOOTH = {font: "10px Arial", "font-style":"italic", opacity: 1, "fill": LABEL_COLOR, stroke: LABEL_COLOR, "stroke-width":.4}; var TASK_FONT = {font: "11px Arial", opacity: 1, fill: Color.black}; var TASK_FONT_SMOOTH = {font: "11px Arial", opacity: 1, fill: Color.black, stroke: LABEL_COLOR, "stroke-width":.4}; var POOL_LANE_FONT = {font: "11px Arial", opacity: 1, fill: Color.black}; var EXPANDED_SUBPROCESS_FONT = {font: "11px Arial", opacity: 1, fill: Color.black}; // Strokes var NORMAL_STROKE = 1; var SEQUENCEFLOW_STROKE = 1.5; var SEQUENCEFLOW_HIGHLIGHT_STROKE = 2; var THICK_TASK_BORDER_STROKE = 2.5; var GATEWAY_TYPE_STROKE = 3.2; var END_EVENT_STROKE = NORMAL_STROKE+2; var MULTI_INSTANCE_STROKE = 1.3; var EVENT_SUBPROCESS_ATTRS = {"stroke": Color.black, "stroke-width": NORMAL_STROKE, "stroke-dasharray": ". "}; //var EXPANDED_SUBPROCESS_ATTRS = {"stroke": Color.black, "stroke-width": NORMAL_STROKE, "fill": Color.FloralWhite}; var EXPANDED_SUBPROCESS_ATTRS = {"stroke": Color.black, "stroke-width": NORMAL_STROKE, "fill": Color.WhiteSmoke}; var NON_INTERRUPTING_EVENT_STROKE = "- "; var TASK_CORNER_ROUND = 10; var EXPANDED_SUBPROCESS_CORNER_ROUND = 10; // icons var ICON_SIZE = 16; var ICON_PADDING = 4; var USERTASK_IMAGE = "images/deployer/user.png"; var SCRIPTTASK_IMAGE = "images/deployer/script.png"; var SERVICETASK_IMAGE = "images/deployer/service.png"; var RECEIVETASK_IMAGE = "images/deployer/receive.png"; var SENDTASK_IMAGE = "images/deployer/send.png"; var MANUALTASK_IMAGE = "images/deployer/manual.png"; var BUSINESS_RULE_TASK_IMAGE = "images/deployer/business_rule.png"; var TIMER_IMAGE = "images/deployer/timer.png"; var MESSAGE_CATCH_IMAGE = "images/deployer/message_catch.png"; var MESSAGE_THROW_IMAGE = "images/deployer/message_throw.png"; var ERROR_THROW_IMAGE = "images/deployer/error_throw.png"; var ERROR_CATCH_IMAGE = "images/deployer/error_catch.png"; var SIGNAL_CATCH_IMAGE = "images/deployer/signal_catch.png"; var SIGNAL_THROW_IMAGE = "images/deployer/signal_throw.png"; var MULTIPLE_CATCH_IMAGE = "images/deployer/multiple_catch.png"; var ObjectType = { ELLIPSE: "ellipse", FLOW: "flow", RECT: "rect", RHOMBUS: "rhombus" }; function OBJ(type){ this.c = null; this.type = type; this.nestedElements = []; }; OBJ.prototype = { }; var CONNECTION_TYPE = { SEQUENCE_FLOW: "sequence_flow", MESSAGE_FLOW: "message_flow", ASSOCIATION: "association" }; var ProcessDiagramCanvas = function(){ }; ProcessDiagramCanvas.prototype = { // var DefaultProcessDiagramCanvas = { canvasHolder: "holder", canvasWidth: 0, canvasHeight: 0, paint: Color.black, strokeWidth: 0, font: null, fontSmoothing: null, g: null, ninjaPaper: null, objects: [], processDefinitionId: null, activity: null, frame: null, debug: false, /** * Creates an empty canvas with given width and height. */ init: function(width, height, processDefinitionId){ this.canvasWidth = width; this.canvasHeight = height; // TODO: name it as 'canvasName' if (!processDefinitionId) processDefinitionId = "holder"; this.processDefinitionId = processDefinitionId; this.canvasHolder = this.processDefinitionId; var h = document.getElementById(this.canvasHolder); if (!h) return; h.style.width = this.canvasWidth; h.style.height = this.canvasHeight; this.g = Raphael(this.canvasHolder); this.g.clear(); //this.setPaint(Color.DimGrey); this.setPaint(Color.black); //this.setPaint(Color.white); this.setStroke(NORMAL_STROKE); //this.setFont("Arial", 11); this.setFont(NORMAL_FONT); //this.font = this.g.getFont("Arial"); this.fontSmoothing = true; // ninja! var RaphaelOriginal = Raphael; this.ninjaPaper =(function (local_raphael) { var paper = local_raphael(1, 1, 1, 1, processDefinitionId); return paper; })(Raphael.ninja()); Raphael = RaphaelOriginal; }, setPaint: function(color){ this.paint = color; }, getPaint: function(){ return this.paint; }, setStroke: function(strokeWidth){ this.strokeWidth = strokeWidth; }, getStroke: function(){ return this.strokeWidth; }, /* setFont: function(family, weight, style, stretch){ this.font = this.g.getFont(family, weight); }, */ setFont: function(font){ this.font = font; }, getFont: function(){ return this.font; }, drawShaddow: function(object){ var border = object.clone(); border.attr({"stroke-width": this.strokeWidth + 6, "stroke": Color.white, "fill": Color.white, "opacity": 1, "stroke-dasharray":null}); //border.toBack(); object.toFront(); return border; }, setConextObject: function(obj){ this.contextObject = obj; }, getConextObject: function(){ return this.contextObject; }, setContextToElement: function(object){ var contextObject = this.getConextObject(); object.id = contextObject.id; object.data("contextObject", contextObject); }, onClick: function(event, instance, element){ var overlay = element; var set = overlay.data("set"); var contextObject = overlay.data("contextObject"); //console.log("["+contextObject.getProperty("type")+"], activityId: " + contextObject.getId()); if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.click) { var args = [instance, element, contextObject]; ProcessDiagramGenerator.options.on.click.apply(event, args); } }, onRightClick: function(event, instance, element){ var overlay = element; var set = overlay.data("set"); var contextObject = overlay.data("contextObject"); //console.log("[%s], activityId: %s (RIGHTCLICK)", contextObject.getProperty("type"), contextObject.getId()); if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.rightClick) { var args = [instance, element, contextObject]; ProcessDiagramGenerator.options.on.rightClick.apply(event, args); } }, onHoverIn: function(event, instance, element){ var overlay = element; var set = overlay.data("set"); var contextObject = overlay.data("contextObject"); var border = instance.g.getById(contextObject.id + "_border"); border.attr("opacity", 0.3); // provide callback if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.over) { var args = [instance, element, contextObject]; ProcessDiagramGenerator.options.on.over.apply(event, args); } }, onHoverOut: function(event, instance, element){ var overlay = element; var set = overlay.data("set"); var contextObject = overlay.data("contextObject"); var border = instance.g.getById(contextObject.id + "_border"); border.attr("opacity", 0.0); // provide callback if (ProcessDiagramGenerator.options && ProcessDiagramGenerator.options.on && ProcessDiagramGenerator.options.on.out) { var args = [instance, element, contextObject]; ProcessDiagramGenerator.options.on.out.apply(event, args); } }, addHandlers: function(set, x, y, width, height, type){ var contextObject = this.getConextObject(); var cx = x+width/2, cy = y+height/2; if (type == "event") { var border = this.g.ellipse(cx, cy, width/2+4, height/2+4); var overlay = this.g.ellipse(cx, cy, width/2, height/2); } else if (type == "gateway") { // rhombus var border = this.g.path( "M" + (x - 4) + " " + (y + (height / 2)) + "L" + (x + (width / 2)) + " " + (y + height + 4) + "L" + (x + width + 4) + " " + (y + (height / 2)) + "L" + (x + (width / 2)) + " " + (y - 4) + "z" ); var overlay = this.g.path( "M" + x + " " + (y + (height / 2)) + "L" + (x + (width / 2)) + " " + (y + height) + "L" + (x + width) + " " + (y + (height / 2)) + "L" + (x + (width / 2)) + " " + y + "z" ); } else if (type == "task") { var border = this.g.rect(x - 4, y - 4, width+9, height+9, TASK_CORNER_ROUND+4); var overlay = this.g.rect(x, y, width, height, TASK_CORNER_ROUND); } border.attr({stroke: Color.get(132,112,255)/*Color.Tan1*/,"stroke-width": 4, opacity: 0.0}); border.id = contextObject.id + "_border"; set.push(border); overlay.attr({stroke: Color.Orange,"stroke-width": 3, fill: Color.get(0,0,0), opacity: 0.0, cursor: "hand"}); overlay.data("set",set); overlay.id = contextObject.id; overlay.data("contextObject",contextObject); var instance = this; overlay.mousedown(function(event){if (event.button == 2) instance.onRightClick(event, instance, this);}); overlay.click(function(event){instance.onClick(event, instance, this);}); overlay.hover(function(event){instance.onHoverIn(event, instance, this);}, function(event){instance.onHoverOut(event, instance, this);}); }, /* * Start Events: * * drawNoneStartEvent * drawTimerStartEvent * drawMessageStartEvent * drawErrorStartEvent * drawSignalStartEvent * _drawStartEventImage * _drawStartEvent */ drawNoneStartEvent: function(x, y, width, height) { this.g.setStart(); var isInterrupting = undefined; this._drawStartEvent(x, y, width, height, isInterrupting, null); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawTimerStartEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawStartEvent(x, y, width, height, isInterrupting, null); var cx = x + width/2 - this.getStroke()/4; var cy = y + height/2 - this.getStroke()/4; var w = width*.9;// - this.getStroke()*2; var h = height*.9;// - this.getStroke()*2; this._drawClock(cx, cy, w, h); if (this.gebug) var center = this.g.ellipse(cx, cy, 3, 3).attr({stroke:"none", fill: Color.green}); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawMessageStartEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawStartEvent(x, y, width, height, isInterrupting, null); this._drawStartEventImage(x, y, width, height, MESSAGE_CATCH_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawErrorStartEvent: function(x, y, width, height, name) { this.g.setStart(); var isInterrupting = undefined; this._drawStartEvent(x, y, width, height, isInterrupting); this._drawStartEventImage(x, y, width, height, ERROR_CATCH_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawSignalStartEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawStartEvent(x, y, width, height, isInterrupting, null); this._drawStartEventImage(x, y, width, height, SIGNAL_CATCH_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawMultipleStartEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawStartEvent(x, y, width, height, isInterrupting, null); var cx = x + width/2 - this.getStroke()/4; var cy = y + height/2 - this.getStroke()/4; var w = width*1; var h = height*1; this._drawPentagon(cx, cy, w, h); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, _drawStartEventImage: function(x, y, width, height, image){ var cx = x + width/2 - this.getStroke()/2; var cy = y + height/2 - this.getStroke()/2; var w = width*.65;// - this.getStroke()*2; var h = height*.65;// - this.getStroke()*2; var img = this.g.image(image, cx-w/2, cy-h/2, w, h); }, _drawStartEvent: function(x, y, width, height, isInterrupting){ var originalPaint = this.getPaint(); if (typeof(START_EVENT_STROKE_COLOR) != "undefined") this.setPaint(START_EVENT_STROKE_COLOR); width -= this.strokeWidth / 2; height -= this.strokeWidth / 2; x = x + width/2; y = y + height/2; var circle = this.g.ellipse(x, y, width/2, height/2); circle.attr({"stroke-width": this.strokeWidth, "stroke": this.paint, //"stroke": START_EVENT_STROKE_COLOR, "fill": START_EVENT_COLOR}); // white shaddow this.drawShaddow(circle); if (isInterrupting!=null && isInterrupting!=undefined && !isInterrupting) circle.attr({"stroke-dasharray": NON_INTERRUPTING_EVENT_STROKE}); this.setContextToElement(circle); this.setPaint(originalPaint); }, /* * End Events: * * drawNoneEndEvent * drawErrorEndEvent * drawMessageEndEvent * drawSignalEndEvent * drawMultipleEndEvent * _drawEndEventImage * _drawNoneEndEvent */ drawNoneEndEvent: function(x, y, width, height) { this.g.setStart(); this._drawNoneEndEvent(x, y, width, height, null, "noneEndEvent"); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawErrorEndEvent: function(x, y, width, height) { this.g.setStart(); var type = "errorEndEvent"; this._drawNoneEndEvent(x, y, width, height, null, type); this._drawEndEventImage(x, y, width, height, ERROR_THROW_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawMessageEndEvent: function(x, y, width, height, name) { this.g.setStart(); var type = "errorEndEvent"; this._drawNoneEndEvent(x, y, width, height, null, type); this._drawEndEventImage(x, y, width, height, MESSAGE_THROW_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawSignalEndEvent: function(x, y, width, height, name) { this.g.setStart(); var type = "errorEndEvent"; this._drawNoneEndEvent(x, y, width, height, null, type); this._drawEndEventImage(x, y, width, height, SIGNAL_THROW_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawMultipleEndEvent: function(x, y, width, height, name) { this.g.setStart(); var type = "errorEndEvent"; this._drawNoneEndEvent(x, y, width, height, null, type); var cx = x + width/2;// - this.getStroke(); var cy = y + height/2;// - this.getStroke(); var w = width*1; var h = height*1; var filled = true; this._drawPentagon(cx, cy, w, h, filled); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawTerminateEndEvent: function(x, y, width, height) { this.g.setStart(); var type = "errorEndEvent"; this._drawNoneEndEvent(x, y, width, height, null, type); var cx = x + width/2;// - this.getStroke()/2; var cy = y + height/2;// - this.getStroke()/2; var w = width/2*.6; var h = height/2*.6; var circle = this.g.ellipse(cx, cy, w, h).attr({fill: Color.black}); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, _drawEndEventImage: function(x, y, width, height, image){ var cx = x + width/2 - this.getStroke()/2; var cy = y + height/2 - this.getStroke()/2; var w = width*.65; var h = height*.65; var img = this.g.image(image, cx-w/2, cy-h/2, w, h); }, _drawNoneEndEvent: function(x, y, width, height, image, type) { var originalPaint = this.getPaint(); if (typeof(CATCHING_EVENT_COLOR) != "undefined") this.setPaint(CATCHING_EVENT_COLOR); var strokeColor = this.getPaint(); var fillColor = this.getPaint(); if (type == "errorEndEvent") { strokeColor = ERROR_END_EVENT_STROKE_COLOR; fillColor = ERROR_END_EVENT_COLOR; } else if (type == "noneEndEvent") { strokeColor = NONE_END_EVENT_STROKE_COLOR; fillColor = NONE_END_EVENT_COLOR; } else // event circles width -= this.strokeWidth / 2; height -= this.strokeWidth / 2; x = x + width/2;// + this.strokeWidth/2; y = y + width/2;// + this.strokeWidth/2; // outerCircle var outerCircle = this.g.ellipse(x, y, width/2, height/2); // white shaddow var shaddow = this.drawShaddow(outerCircle); outerCircle.attr({"stroke-width": this.strokeWidth, "stroke": strokeColor, "fill": fillColor}); var innerCircleX = x; var innerCircleY = y; var innerCircleWidth = width/2 - 2; var innerCircleHeight = height/2 - 2; var innerCircle = this.g.ellipse(innerCircleX, innerCircleY, innerCircleWidth, innerCircleHeight); innerCircle.attr({"stroke-width": this.strokeWidth, "stroke": strokeColor, "fill": Color.white}); // TODO: implement it //var originalPaint = this.getPaint(); //this.g.setPaint(BOUNDARY_EVENT_COLOR); this.setPaint(originalPaint); }, /* * Catching Events: * * drawCatchingTimerEvent * drawCatchingErrorEvent * drawCatchingSignalEvent * drawCatchingMessageEvent * drawCatchingMultipleEvent * _drawCatchingEventImage * _drawCatchingEvent */ drawCatchingTimerEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, isInterrupting, null); var innerCircleWidth = width - 4; var innerCircleHeight = height - 4; var cx = x + width/2 - this.getStroke()/4; var cy = y + height/2 - this.getStroke()/4; var w = innerCircleWidth*.9;// - this.getStroke()*2; var h = innerCircleHeight*.9;// - this.getStroke()*2; this._drawClock(cx, cy, w, h); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawCatchingErrorEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, isInterrupting, null); this._drawCatchingEventImage(x, y, width, height, ERROR_CATCH_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawCatchingSignalEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, isInterrupting, null); this._drawCatchingEventImage(x, y, width, height, SIGNAL_CATCH_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawCatchingMessageEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, isInterrupting, null); this._drawCatchingEventImage(x, y, width, height, MESSAGE_CATCH_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawCatchingMultipleEvent: function(x, y, width, height, isInterrupting, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, isInterrupting, null); var cx = x + width/2 - this.getStroke(); var cy = y + height/2 - this.getStroke(); var w = width*.9; var h = height*.9; this._drawPentagon(cx, cy, w, h); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, _drawCatchingEventImage: function(x, y, width, height, image){ var innerCircleWidth = width - 4; var innerCircleHeight = height - 4; var cx = x + width/2 - this.getStroke()/2; var cy = y + height/2 - this.getStroke()/2; var w = innerCircleWidth*.6;// - this.getStroke()*2; var h = innerCircleHeight*.6;// - this.getStroke()*2; var img = this.g.image(image, cx-w/2, cy-h/2, w, h); }, _drawCatchingEvent: function(x, y, width, height, isInterrupting, image) { var originalPaint = this.getPaint(); if (typeof(CATCHING_EVENT_COLOR) != "undefined") this.setPaint(CATCHING_EVENT_COLOR); // event circles width -= this.strokeWidth / 2; height -= this.strokeWidth / 2; x = x + width/2;// + this.strokeWidth/2; y = y + width/2;// + this.strokeWidth/2; // outerCircle var outerCircle = this.g.ellipse(x, y, width/2, height/2); // white shaddow var shaddow = this.drawShaddow(outerCircle); //console.log("isInterrupting: " + isInterrupting, "x:" , x, "y:",y); if (isInterrupting!=null && isInterrupting!=undefined && !isInterrupting) outerCircle.attr({"stroke-dasharray": NON_INTERRUPTING_EVENT_STROKE}); outerCircle.attr({"stroke-width": this.strokeWidth, "stroke": this.getPaint(), "fill": BOUNDARY_EVENT_COLOR}); var innerCircleX = x; var innerCircleY = y; var innerCircleRadiusX = width/2 - 4; var innerCircleRadiusY = height/2 - 4; var innerCircle = this.g.ellipse(innerCircleX, innerCircleY, innerCircleRadiusX, innerCircleRadiusY); innerCircle.attr({"stroke-width": this.strokeWidth, "stroke": this.getPaint()}); if (image) { var imageWidth = imageHeight = innerCircleRadiusX*1.2 + this.getStroke()*2; var imageX = innerCircleX-imageWidth/2 - this.strokeWidth/2; var imageY = innerCircleY-imageWidth/2 - this.strokeWidth/2; var img = this.g.image(image, imageX, imageY, imageWidth, imageHeight); } this.setPaint(originalPaint); var set = this.g.set(); set.push(outerCircle, innerCircle, shaddow); this.setContextToElement(outerCircle); // TODO: add shapes to set /* var st = this.g.set(); st.push( this.g.ellipse(innerCircleX, innerCircleY, 2, 2), this.g.ellipse(imageX, imageY, 2, 2) ); st.attr({fill: "red", "stroke-width":0}); */ }, /* * Catching Events: * * drawThrowingNoneEvent * drawThrowingSignalEvent * drawThrowingMessageEvent * drawThrowingMultipleEvent */ drawThrowingNoneEvent: function(x, y, width, height, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, null, null); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawThrowingSignalEvent: function(x, y, width, height, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, null, null); this._drawCatchingEventImage(x, y, width, height, SIGNAL_THROW_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawThrowingMessageEvent: function(x, y, width, height, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, null, null); this._drawCatchingEventImage(x, y, width, height, MESSAGE_THROW_IMAGE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, drawThrowingMultipleEvent: function(x, y, width, height, name) { this.g.setStart(); this._drawCatchingEvent(x, y, width, height, null, null); var cx = x + width/2 - this.getStroke(); var cy = y + height/2 - this.getStroke(); var w = width*.9; var h = height*.9; var filled = true; this._drawPentagon(cx, cy, w, h, filled); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "event"); }, /* * Draw flows: * * _connectFlowToActivity * _drawFlow * _drawDefaultSequenceFlowIndicator * drawSequenceflow * drawMessageflow * drawAssociation * _drawCircleTail * _drawArrowHead * _drawConditionalSequenceFlowIndicator * drawSequenceflowWithoutArrow */ _connectFlowToActivity: function(sourceActivityId, destinationActivityId, waypoints){ var sourceActivity = this.g.getById(sourceActivityId); var destinationActivity = this.g.getById(destinationActivityId); if (sourceActivity == null || destinationActivity == null) { if (sourceActivity == null) console.error("source activity["+sourceActivityId+"] not found"); else console.error("destination activity["+destinationActivityId+"] not found"); return null; } var bbSourceActivity = sourceActivity.getBBox() var bbDestinationActivity = destinationActivity.getBBox() var path = []; var newWaypoints = []; for(var i = 0; i < waypoints.length; i++){ var pathType = "" if (i==0) pathType = "M"; else pathType = "L"; path.push([pathType, waypoints[i].x, waypoints[i].y]); newWaypoints.push({x:waypoints[i].x, y:waypoints[i].y}); } var ninjaPathSourceActivity = this.ninjaPaper.path(sourceActivity.realPath); var ninjaPathDestinationActivity = this.ninjaPaper.path(destinationActivity.realPath); var ninjaBBSourceActivity = ninjaPathSourceActivity.getBBox(); var ninjaBBDestinationActivity = ninjaPathDestinationActivity.getBBox(); // set target of the flow to the center of the taskObject var newPath = path; var originalSource = {x: newPath[0][1], y: newPath[0][2]}; var originalTarget = {x: newPath[newPath.length-1][1], y: newPath[newPath.length-1][2]}; newPath[0][1] = ninjaBBSourceActivity.x + (ninjaBBSourceActivity.x2 - ninjaBBSourceActivity.x ) / 2; newPath[0][2] = ninjaBBSourceActivity.y + (ninjaBBSourceActivity.y2 - ninjaBBSourceActivity.y ) / 2; newPath[newPath.length-1][1] = ninjaBBDestinationActivity.x + (ninjaBBDestinationActivity.x2 - ninjaBBDestinationActivity.x ) / 2; newPath[newPath.length-1][2] = ninjaBBDestinationActivity.y + (ninjaBBDestinationActivity.y2 - ninjaBBDestinationActivity.y ) / 2; var ninjaPathFlowObject = this.ninjaPaper.path(newPath); var ninjaBBFlowObject = ninjaPathFlowObject.getBBox(); var intersectionsSource = Raphael.pathIntersection(ninjaPathSourceActivity.realPath, ninjaPathFlowObject.realPath); var intersectionsDestination = Raphael.pathIntersection(ninjaPathDestinationActivity.realPath, ninjaPathFlowObject.realPath); var intersectionSource = intersectionsSource.pop(); var intersectionDestination = intersectionsDestination.pop(); if (intersectionSource != undefined) { if (this.gebug) { var diameter = 5; var dotOriginal = this.g.ellipse(originalSource.x, originalSource.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Pink}); var dot = this.g.ellipse(intersectionSource.x, intersectionSource.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Green}); } newWaypoints[0].x = intersectionSource.x; newWaypoints[0].y = intersectionSource.y; } if (intersectionDestination != undefined) { if (this.gebug) { var diameter = 5; var dotOriginal = this.g.ellipse(originalTarget.x, originalTarget.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Red}); var dot = this.g.ellipse(intersectionDestination.x, intersectionDestination.y, diameter, diameter).attr({"fill": Color.white, "stroke": Color.Blue}); } newWaypoints[newWaypoints.length-1].x = intersectionDestination.x; newWaypoints[newWaypoints.length-1].y = intersectionDestination.y; } this.ninjaPaper.clear(); return newWaypoints; }, _drawFlow: function(waypoints, conditional, isDefault, highLighted, withArrowHead, connectionType){ var originalPaint = this.getPaint(); var originalStroke = this.getStroke(); this.setPaint(SEQUENCEFLOW_COLOR); this.setStroke(SEQUENCEFLOW_STROKE); if (highLighted) { this.setPaint(HIGHLIGHT_COLOR); this.setStroke(SEQUENCEFLOW_HIGHLIGHT_STROKE); } // TODO: generate polylineId or do something!! var uuid = Raphael.createUUID(); var contextObject = this.getConextObject(); var newWaypoints = waypoints; if (contextObject) { var newWaypoints = this._connectFlowToActivity(contextObject.sourceActivityId, contextObject.destinationActivityId, waypoints); if (!newWaypoints) { console.error("Error draw flow from '"+contextObject.sourceActivityId+"' to '"+contextObject.destinationActivityId+"' "); return; } } var polyline = new Polyline(uuid, newWaypoints, this.getStroke()); //var polyline = new Polyline(waypoints, 3); polyline.element = this.g.path(polyline.path); polyline.element.attr("stroke-width", this.getStroke()); polyline.element.attr("stroke", this.getPaint()); if (contextObject) { polyline.element.id = contextObject.id; polyline.element.data("contextObject", contextObject); } else { polyline.element.id = uuid; } /* polyline.element.mouseover(function(){ this.attr({"stroke-width": NORMAL_STROKE + 2}); }).mouseout(function(){ this.attr({"stroke-width": NORMAL_STROKE}); }); */ var last = polyline.getAnchorsCount()-1; var x = polyline.getAnchor(last).x; var y = polyline.getAnchor(last).y; //var c = this.g.ellipse(x, y, 5, 5); var lastLineIndex = polyline.getLinesCount()-1; var line = polyline.getLine(lastLineIndex); var firstLine = polyline.getLine(0); var arrowHead = null, circleTail = null, defaultSequenceFlowIndicator = null, conditionalSequenceFlowIndicator = null; if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW) { circleTail = this._drawCircleTail(firstLine, connectionType); } if(withArrowHead) arrowHead = this._drawArrowHead(line, connectionType); //console.log("isDefault: ", isDefault, ", isDefaultConditionAvailable: ", polyline.isDefaultConditionAvailable); if (isDefault && polyline.isDefaultConditionAvailable) { //var angle = polyline.getLineAngle(0); //console.log("firstLine", firstLine); defaultSequenceFlowIndicator = this._drawDefaultSequenceFlowIndicator(firstLine); } if (conditional) { conditionalSequenceFlowIndicator = this._drawConditionalSequenceFlowIndicator(firstLine); } // draw flow name var flowName = contextObject.name; if (flowName) { var xPointArray = contextObject.xPointArray; var yPointArray = contextObject.yPointArray; var textX = xPointArray[0] < xPointArray[1] ? xPointArray[0] : xPointArray[1]; var textY = yPointArray[0] < yPointArray[1] ? yPointArray[1] : yPointArray[0]; // fix xy textX += 20; textY -= 10; this.g.text(textX, textY, flowName).attr(LABEL_FONT); } var st = this.g.set(); st.push(polyline.element, arrowHead, circleTail, conditionalSequenceFlowIndicator); polyline.element.data("set", st); polyline.element.data("withArrowHead", withArrowHead); var polyCloneAttrNormal = {"stroke-width": this.getStroke() + 5, stroke: Color.get(132,112,255), opacity: 0.0, cursor: "hand"}; var polyClone = st.clone().attr(polyCloneAttrNormal).hover(function () { //if (polyLine.data("isSelected")) return; polyClone.attr({opacity: 0.2}); }, function () { //if (polyLine.data("isSelected")) return; polyClone.attr({opacity: 0.0}); }); polyClone.data("objectId", polyline.element.id); polyClone.click(function(){ var instance = this; var objectId = instance.data("objectId"); var object = this.paper.getById(objectId); var contextObject = object.data("contextObject"); if (contextObject) { console.log("[flow], objectId: " + object.id +", flow: " + contextObject.flow); ProcessDiagramGenerator.showFlowInfo(contextObject); } }).dblclick(function(){ console.log("!!! DOUBLE CLICK !!!"); }).hover(function (mouseEvent) { var instance = this; var objectId = instance.data("objectId"); var object = this.paper.getById(objectId); var contextObject = object.data("contextObject"); if (contextObject) ProcessDiagramGenerator.showFlowInfo(contextObject); }); polyClone.data("parentId", uuid); if (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW) polyline.element.attr("stroke-width", this.getStroke()); else if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW) polyline.element.attr({"stroke-dasharray": "--"}); else if (connectionType == CONNECTION_TYPE.ASSOCIATION) polyline.element.attr({"stroke-dasharray": ". "}); this.setPaint(originalPaint); this.setStroke(originalStroke); }, _drawDefaultSequenceFlowIndicator: function(line) { //console.log("line: ", line); var len = 10; c = len/2, f = 8; var defaultIndicator = this.g.path("M" + (-c) + " " + 0 + "L" + (c) + " " + 0); defaultIndicator.attr("stroke-width", this.getStroke()+0); defaultIndicator.attr("stroke", this.getPaint()); var cosAngle = Math.cos((line.angle)); var sinAngle = Math.sin((line.angle)); var dx = f * cosAngle; var dy = f * sinAngle; var x1 = line.x1 + dx + 0*c*cosAngle; var y1 = line.y1 + dy + 0*c*sinAngle; defaultIndicator.transform("t" + (x1) + "," + (y1) + ""); defaultIndicator.transform("...r" + Raphael.deg(line.angle - 3*Math.PI / 4) + " " + 0 + " " + 0); /* var c0 = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Blue}); c0.transform("t" + (line.x1) + "," + (line.y1) + ""); var center = this.g.ellipse(0, 0, 1, 1).attr({stroke: Color.Red}); center.transform("t" + (line.x1+dx) + "," + (line.y1+dy) + ""); */ return defaultIndicator; }, drawSequenceflow: function(waypoints, conditional, isDefault, highLighted) { var withArrowHead = true; this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW); }, drawMessageflow: function(waypoints, highLighted) { var withArrowHead = true; var conditional=isDefault=false; this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.MESSAGE_FLOW); }, drawAssociation: function(waypoints, withArrowHead, highLighted) { var withArrowHead = withArrowHead; var conditional=isDefault=false; this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.ASSOCIATION); }, _drawCircleTail: function(line, connectionType){ var diameter = ARROW_WIDTH/2*1.5; // anti smoothing if (this.strokeWidth%2 == 1) line.x1 += .5, line.y1 += .5; var circleTail = this.g.ellipse(line.x1, line.y1, diameter, diameter); circleTail.attr("fill", Color.white); circleTail.attr("stroke", this.getPaint()); return circleTail; }, _drawArrowHead: function(line, connectionType){ var doubleArrowWidth = 2 * ARROW_WIDTH; if (connectionType == CONNECTION_TYPE.ASSOCIATION) var arrowHead = this.g.path("M-" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "L 0 0 L" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth); else var arrowHead = this.g.path("M0 0L-" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "L" + (ARROW_WIDTH/2+.5) + " -" + doubleArrowWidth + "z"); //arrowHead.transform("t" + 0 + ",-" + this.getStroke() + ""); // anti smoothing if (this.strokeWidth%2 == 1) line.x2 += .5, line.y2 += .5; arrowHead.transform("t" + line.x2 + "," + line.y2 + ""); arrowHead.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0); if (!connectionType || connectionType == CONNECTION_TYPE.SEQUENCE_FLOW) arrowHead.attr("fill", this.getPaint()); else if (connectionType == CONNECTION_TYPE.MESSAGE_FLOW) arrowHead.attr("fill", Color.white); arrowHead.attr("stroke-width", this.getStroke()); arrowHead.attr("stroke", this.getPaint()); return arrowHead; }, /* drawArrowHead2: function(srcX, srcY, targetX, targetY) { var doubleArrowWidth = 2 * ARROW_WIDTH; //var arrowHead = this.g.path("M-" + ARROW_WIDTH/2 + " -" + doubleArrowWidth + "L0 0" + "L" + ARROW_WIDTH/2 + " -" + doubleArrowWidth + "z"); var arrowHead = this.g.path("M0 0L-" + ARROW_WIDTH/1.5 + " -" + doubleArrowWidth + "L" + ARROW_WIDTH/1.5 + " -" + doubleArrowWidth + "z"); //var c = DefaultProcessDiagramCanvas.g.ellipse(0, 0, 3, 3); //c.transform("t"+targetX+","+targetY+""); var angle = Math.atan2(targetY - srcY, targetX - srcX); arrowHead.transform("t"+targetX+","+targetY+""); arrowHead.transform("...r" + Raphael.deg(angle - Math.PI / 2) + " "+0+" "+0); //console.log(arrowHead.transform()); //console.log("--> " + Raphael.deg(angle - Math.PI / 2)); arrowHead.attr("fill", this.getPaint()); arrowHead.attr("stroke", this.getPaint()); / * // shaddow var c0 = arrowHead.clone(); c0.transform("...t-1 1"); c0.attr("stroke-width", this.strokeWidth); c0.attr("stroke", Color.black); c0.attr("opacity", 0.15); c0.toBack(); * / }, */ _drawConditionalSequenceFlowIndicator: function(line){ var horizontal = (CONDITIONAL_INDICATOR_WIDTH * 0.7); var halfOfHorizontal = horizontal / 2; var halfOfVertical = CONDITIONAL_INDICATOR_WIDTH / 2; var uuid = null; var waypoints = [{x: 0, y: 0}, {x: -halfOfHorizontal, y: halfOfVertical}, {x: 0, y: CONDITIONAL_INDICATOR_WIDTH}, {x: halfOfHorizontal, y: halfOfVertical}]; /* var polyline = new Polyline(uuid, waypoints, this.getStroke()); polyline.element = this.g.path(polyline.path); polyline.element.attr("stroke-width", this.getStroke()); polyline.element.attr("stroke", this.getPaint()); polyline.element.id = uuid; */ var polygone = new Polygone(waypoints, this.getStroke()); polygone.element = this.g.path(polygone.path); polygone.element.attr("fill", Color.white); polygone.transform("t" + line.x1 + "," + line.y1 + ""); polygone.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0); var cosAngle = Math.cos((line.angle)); var sinAngle = Math.sin((line.angle)); //polygone.element.attr("stroke-width", this.getStroke()); //polygone.element.attr("stroke", this.getPaint()); polygone.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()}); return polygone.element; }, drawSequenceflowWithoutArrow: function(waypoints, conditional, isDefault, highLighted) { var withArrowHead = false; this._drawFlow(waypoints, conditional, isDefault, highLighted, withArrowHead, CONNECTION_TYPE.SEQUENCE_FLOW); }, /* * Draw artifacts */ drawPoolOrLane: function(x, y, width, height, name){ // anti smoothing if (this.strokeWidth%2 == 1) x = Math.round(x) + .5, y = Math.round(y) + .5; // shape var rect = this.g.rect(x, y, width, height); var attr = {"stroke-width": NORMAL_STROKE, stroke: TASK_STROKE_COLOR}; rect.attr(attr); // Add the name as text, vertical if(name != null && name.length > 0) { var attr = POOL_LANE_FONT; // Include some padding var availableTextSpace = height - 6; // Create rotation for derived font var truncated = this.fitTextToWidth(name, availableTextSpace); var realWidth = this.getStringWidth(truncated, attr); var realHeight = this.getStringHeight(truncated, attr); //console.log("truncated:", truncated, ", height:", height, ", realHeight:", realHeight, ", availableTextSpace:", availableTextSpace, ", realWidth:", realWidth); var newX = x + 2 + realHeight*1 - realHeight/2; var newY = 3 + y + availableTextSpace - (availableTextSpace - realWidth) / 2 - realWidth/2; var textElement = this.g.text(newX, newY, truncated).attr(attr); //console.log(".getBBox(): ", t.getBBox()); textElement.transform("r" + Raphael.deg(270 * Math.PI/180) + " " + newX + " " + newY); } // TODO: add to set }, _drawTask: function(name, x, y, width, height, thickBorder) { var originalPaint = this.getPaint(); this.setPaint(TASK_COLOR); // anti smoothing if (this.strokeWidth%2 == 1) x = Math.round(x) + .5, y = Math.round(y) + .5; // shape var shape = this.g.rect(x, y, width, height, TASK_CORNER_ROUND); var attr = {"stroke-width": this.strokeWidth, stroke: TASK_STROKE_COLOR, fill: this.getPaint()}; shape.attr(attr); //shape.attr({fill: "90-"+this.getPaint()+"-" + Color.get(250, 250, 244)}); var contextObject = this.getConextObject(); if (contextObject) { shape.id = contextObject.id; shape.data("contextObject", contextObject); } //var activity = this.getConextObject(); //console.log("activity: " + activity.getId(), activity); //Object.clone(activity); /* c.mouseover(function(){ this.attr({"stroke-width": NORMAL_STROKE + 2}); }).mouseout(function(){ this.attr({"stroke-width": NORMAL_STROKE}); }); */ this.setPaint(originalPaint); // white shaddow this.drawShaddow(shape); if (thickBorder) { shape.attr({"stroke-width": THICK_TASK_BORDER_STROKE}); } else { //g.draw(rect); } // text if (name) { var fontAttr = TASK_FONT; // Include some padding var paddingX = 5; var paddingY = 5; var availableTextSpace = width - paddingX*2; // TODO: this.setFont // var originalFont = this.getFont(); // this.setFont(TASK_FONT) /* var truncated = this.fitTextToWidth(name, availableTextSpace); var realWidth = this.getStringWidth(truncated, fontAttr); var realHeight = this.getStringHeight(truncated, fontAttr); //var t = this.g.text(x + width/2 + realWidth*0/2 + paddingX*0, y + height/2, truncated).attr(fontAttr); */ //console.log("draw task name: " + name); var boxWidth = width - (2 * TEXT_PADDING); var boxHeight = height - ICON_SIZE - ICON_PADDING - ICON_PADDING - MARKER_WIDTH - 2 - 2; var boxX = x + width/2 - boxWidth/2; var boxY = y + height/2 - boxHeight/2 + ICON_PADDING + ICON_PADDING - 2 - 2; /* var boxWidth = width - (2 * ANNOTATION_TEXT_PADDING); var boxHeight = height - (2 * ANNOTATION_TEXT_PADDING); var boxX = x + width/2 - boxWidth/2; var boxY = y + height/2 - boxHeight/2; */ this.drawTaskLabel(name, boxX, boxY, boxWidth, boxHeight); } }, drawTaskLabel: function(text, x, y, boxWidth, boxHeight){ var originalFont = this.getFont(); this.setFont(TASK_FONT); this._drawMultilineText(text, x, y, boxWidth, boxHeight, MULTILINE_VERTICAL_ALIGN_MIDDLE, MULTILINE_HORIZONTAL_ALIGN_MIDDLE); this.setFont(originalFont); }, drawAnnotationText: function(text, x, y, width, height){ //this._drawMultilineText(text, x, y, width, height, "start"); var originalPaint = this.getPaint(); var originalFont = this.getFont(); this.setPaint(Color.black); this.setFont(TASK_FONT); this._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_LEFT); this.setPaint(originalPaint); this.setFont(originalFont); }, drawLabel: function(text, x, y, width, height){ //this._drawMultilineText(text, x, y, width, height, "start"); var originalPaint = this.getPaint(); var originalFont = this.getFont(); this.setPaint(LABEL_COLOR); //this.setFont(LABEL_FONT); this.setFont(LABEL_FONT_SMOOTH); // predefined box width for labels // TODO: use label width as is, but not height (for stretching) if (!width || !height) { width = 100; height = 0; } // TODO: remove it. It is debug x = x - width/2; this._drawMultilineText(text, x, y, width, height, MULTILINE_VERTICAL_ALIGN_TOP, MULTILINE_HORIZONTAL_ALIGN_MIDDLE); this.setPaint(originalPaint); this.setFont(originalFont); }, /* drawMultilineLabel: function(text, x, y){ var originalFont = this.getFont(); this.setFont(LABEL_FONT_SMOOTH); var boxWidth = 80; x = x - boxWidth/2 this._drawMultilineText(text, x, y, boxWidth, null, "middle"); this.setFont(originalFont); }, */ getStringWidth: function(text, fontAttrs){ var textElement = this.g.text(0, 0, text).attr(fontAttrs).hide(); var bb = textElement.getBBox(); //console.log("string width: ", t.getBBox().width); return textElement.getBBox().width; }, getStringHeight: function(text, fontAttrs){ var textElement = this.g.text(0, 0, text).attr(fontAttrs).hide(); var bb = textElement.getBBox(); //console.log("string height: ", t.getBBox().height); return textElement.getBBox().height; }, fitTextToWidth: function(original, width) { var text = original; // TODO: move attr on parameters var attr = {font: "11px Arial", opacity: 0}; // remove length for "..." var dots = this.g.text(0, 0, "...").attr(attr).hide(); var dotsBB = dots.getBBox(); var maxWidth = width - dotsBB.width; var textElement = this.g.text(0, 0, text).attr(attr).hide(); var bb = textElement.getBBox(); // it's a little bit incorrect with "..." while (bb.width > maxWidth && text.length > 0) { text = text.substring(0, text.length - 1); textElement.attr({"text": text}); bb = textElement.getBBox(); } // remove element from paper textElement.remove(); if (text != original) { text = text + "..."; } return text; }, wrapTextToWidth: function(original, width){ //return original; var text = original; var wrappedText = "\n"; // TODO: move attr on parameters var attr = {font: "11px Arial", opacity: 0}; var textElement = this.g.text(0, 0, wrappedText).attr(attr).hide(); var bb = textElement.getBBox(); var resultText = ""; var i = 0, j = 0; while (text.length > 0) { while (bb.width < width && text.length>0) { // remove "\n" wrappedText = wrappedText.substring(0,wrappedText.length-1); // add new char, add "\n" wrappedText = wrappedText + text.substring(0,1) + "\n"; text = text.substring(1); textElement.attr({"text": wrappedText}); bb = textElement.getBBox(); i++; if (i>200) break; } // remove "\n" wrappedText = wrappedText.substring(0, wrappedText.length - 1); if (text.length == 0) { resultText += wrappedText; break; } // return last char to text text = wrappedText.substring(wrappedText.length-1) + text; // remove last char from wrappedText wrappedText = wrappedText.substring(0, wrappedText.length-1) + "\n"; textElement.attr({"text": wrappedText}); bb = textElement.getBBox(); //console.log(">> ", wrappedText, ", ", text); resultText += wrappedText; wrappedText = "\n"; j++; if (j>20) break; } // remove element from paper textElement.remove(); return resultText; }, wrapTextToWidth2: function(original, width){ var text = original; var wrappedText = "\n"; // TODO: move attr on parameters var attr = {font: "11px Arial", opacity: 0}; var textElement = this.g.text(0, 0, wrappedText).attr(attr).hide(); var bb = textElement.getBBox(); var resultText = ""; var i = 0, j = 0; while (text.length > 0) { while (bb.width < width && text.length>0) { // remove "\n" wrappedText = wrappedText.substring(0,wrappedText.length-1); // add new char, add "\n" wrappedText = wrappedText + text.substring(0,1) + "\n"; text = text.substring(1); textElement.attr({"text": wrappedText}); bb = textElement.getBBox(); i++; if (i>200) break; } // remove "\n" wrappedText = wrappedText.substring(0, wrappedText.length - 1); if (text.length == 0) { resultText += wrappedText; break; } // return last char to text text = wrappedText.substring(wrappedText.length-1) + text; // remove last char from wrappedText wrappedText = wrappedText.substring(0, wrappedText.length-1) + "\n"; textElement.attr({"text": wrappedText}); bb = textElement.getBBox(); //console.log(">> ", wrappedText, ", ", text); resultText += wrappedText; wrappedText = "\n"; j++; if (j>20) break; } // remove element from paper textElement.remove(); return resultText; }, drawUserTask: function(name, x, y, width, height) { this.g.setStart(); this._drawTask(name, x, y, width, height); var img = this.g.image(USERTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawScriptTask: function(name, x, y, width, height) { this.g.setStart(); this._drawTask(name, x, y, width, height); var img = this.g.image(SCRIPTTASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawServiceTask: function(name, x, y, width, height) { this.g.setStart(); this._drawTask(name, x, y, width, height); var img = this.g.image(SERVICETASK_IMAGE, x + ICON_PADDING, y + ICON_PADDING, ICON_SIZE, ICON_SIZE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawReceiveTask: function(name, x, y, width, height) { this.g.setStart(); this._drawTask(name, x, y, width, height); var img = this.g.image(RECEIVETASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawSendTask: function(name, x, y, width, height) { this.g.setStart(); this._drawTask(name, x, y, width, height); var img = this.g.image(SENDTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawManualTask: function(name, x, y, width, height) { this.g.setStart(); this._drawTask(name, x, y, width, height); var img = this.g.image(MANUALTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawBusinessRuleTask: function(name, x, y, width, height) { this.g.setStart(); this._drawTask(name, x, y, width, height); var img = this.g.image(BUSINESS_RULE_TASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawExpandedSubProcess: function(name, x, y, width, height, isTriggeredByEvent){ this.g.setStart(); // anti smoothing if (this.strokeWidth%2 == 1) x = Math.round(x) + .5, y = Math.round(y) + .5; // shape var rect = this.g.rect(x, y, width, height, EXPANDED_SUBPROCESS_CORNER_ROUND); // Use different stroke (dashed) if(isTriggeredByEvent) { rect.attr(EVENT_SUBPROCESS_ATTRS); } else { rect.attr(EXPANDED_SUBPROCESS_ATTRS); } this.setContextToElement(rect); var fontAttr = EXPANDED_SUBPROCESS_FONT; // Include some padding var paddingX = 10; var paddingY = 5; var availableTextSpace = width - paddingX*2; var truncated = this.fitTextToWidth(name, availableTextSpace); var realWidth = this.getStringWidth(truncated, fontAttr); var realHeight = this.getStringHeight(truncated, fontAttr); var textElement = this.g.text(x + width/2 - realWidth*0/2 + 0*paddingX, y + realHeight/2 + paddingY, truncated).attr(fontAttr); var set = this.g.setFinish(); // TODO: Expanded Sub Process may has specific handlers //this.addHandlers(set, x, y, width, height, "task"); }, drawCollapsedSubProcess: function(name, x, y, width, height, isTriggeredByEvent) { this.g.setStart(); this._drawCollapsedTask(name, x, y, width, height, false); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, drawCollapsedCallActivity: function(name, x, y, width, height) { this.g.setStart(); this._drawCollapsedTask(name, x, y, width, height, true); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "task"); }, _drawCollapsedTask: function(name, x, y, width, height, thickBorder) { // The collapsed marker is now visualized separately this._drawTask(name, x, y, width, height, thickBorder); }, drawCollapsedMarker: function(x, y, width, height){ // rectangle var rectangleWidth = MARKER_WIDTH; var rectangleHeight = MARKER_WIDTH; // anti smoothing if (this.strokeWidth%2 == 1) y += .5; var rect = this.g.rect(x + (width - rectangleWidth) / 2, y + height - rectangleHeight - 3, rectangleWidth, rectangleHeight); // plus inside rectangle var cx = rect.attr("x") + rect.attr("width")/2; var cy = rect.attr("y") + rect.attr("height")/2; var line = this.g.path( "M" + cx + " " + (cy+2) + "L" + cx + " " + (cy-2) + "M" + (cx-2) + " " + cy + "L" + (cx+2) + " " + cy ).attr({"stroke-width": this.strokeWidth}); }, drawActivityMarkers: function(x, y, width, height, multiInstanceSequential, multiInstanceParallel, collapsed){ if (collapsed) { if (!multiInstanceSequential && !multiInstanceParallel) { this.drawCollapsedMarker(x, y, width, height); } else { this.drawCollapsedMarker(x - MARKER_WIDTH / 2 - 2, y, width, height); if (multiInstanceSequential) { console.log("is collapsed and multiInstanceSequential"); this.drawMultiInstanceMarker(true, x + MARKER_WIDTH / 2 + 2, y, width, height); } else if (multiInstanceParallel) { console.log("is collapsed and multiInstanceParallel"); this.drawMultiInstanceMarker(false, x + MARKER_WIDTH / 2 + 2, y, width, height); } } } else { if (multiInstanceSequential) { console.log("is multiInstanceSequential"); this.drawMultiInstanceMarker(true, x, y, width, height); } else if (multiInstanceParallel) { console.log("is multiInstanceParallel"); this.drawMultiInstanceMarker(false, x, y, width, height); } } }, drawGateway: function(x, y, width, height) { var rhombus = this.g.path( "M" + x + " " + (y + (height / 2)) + "L" + (x + (width / 2)) + " " + (y + height) + "L" + (x + width) + " " + (y + (height / 2)) + "L" + (x + (width / 2)) + " " + y + "z" ); // white shaddow this.drawShaddow(rhombus); rhombus.attr("stroke-width", this.strokeWidth); rhombus.attr("stroke", Color.SlateGrey); rhombus.attr({fill: Color.white}); this.setContextToElement(rhombus); return rhombus; }, drawParallelGateway: function(x, y, width, height) { this.g.setStart(); // rhombus this.drawGateway(x, y, width, height); // plus inside rhombus var originalStroke = this.getStroke(); this.setStroke(GATEWAY_TYPE_STROKE); var plus = this.g.path( "M" + (x + 10) + " " + (y + height / 2) + "L" + (x + width - 10) + " " + (y + height / 2) + // horizontal "M" + (x + width / 2) + " " + (y + height - 10) + "L" + (x + width / 2) + " " + (y + 10) // vertical ); plus.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()}); this.setStroke(originalStroke); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "gateway"); }, drawExclusiveGateway: function(x, y, width, height) { this.g.setStart(); // rhombus var rhombus = this.drawGateway(x, y, width, height); var quarterWidth = width / 4; var quarterHeight = height / 4; // X inside rhombus var originalStroke = this.getStroke(); this.setStroke(GATEWAY_TYPE_STROKE); var iks = this.g.path( "M" + (x + quarterWidth + 3) + " " + (y + quarterHeight + 3) + "L" + (x + 3 * quarterWidth - 3) + " " + (y + 3 * quarterHeight - 3) + "M" + (x + quarterWidth + 3) + " " + (y + 3 * quarterHeight - 3) + "L" + (x + 3 * quarterWidth - 3) + " " + (y + quarterHeight + 3) ); iks.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()}); this.setStroke(originalStroke); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "gateway"); }, drawInclusiveGateway: function(x, y, width, height){ this.g.setStart(); // rhombus this.drawGateway(x, y, width, height); var diameter = width / 4; // circle inside rhombus var originalStroke = this.getStroke(); this.setStroke(GATEWAY_TYPE_STROKE); var circle = this.g.ellipse(width/2 + x, height/2 + y, diameter, diameter); circle.attr({"stroke-width": this.getStroke(), "stroke": this.getPaint()}); this.setStroke(originalStroke); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "gateway"); }, drawEventBasedGateway: function(x, y, width, height){ this.g.setStart(); // rhombus this.drawGateway(x, y, width, height); var diameter = width / 2; // rombus inside rhombus var originalStroke = this.getStroke(); this.setStroke(GATEWAY_TYPE_STROKE); // draw GeneralPath (polygon) var n=5; var angle = 2*Math.PI/n; var x1Points = []; var y1Points = []; for ( var index = 0; index < n; index++ ) { var v = index*angle - Math.PI/2; x1Points[index] = x + parseInt(Math.round(width/2)) + parseInt(Math.round((width/4)*Math.cos(v))); y1Points[index] = y + parseInt(Math.round(height/2)) + parseInt(Math.round((height/4)*Math.sin(v))); } //g.drawPolygon(x1Points, y1Points, n); var path = ""; for ( var index = 0; index < n; index++ ) { if (index == 0) path += "M"; else path += "L"; path += x1Points[index] + "," + y1Points[index]; } path += "z"; var polygone = this.g.path(path); polygone.attr("stroke-width", this.strokeWidth); polygone.attr("stroke", this.getPaint()); this.setStroke(originalStroke); var set = this.g.setFinish(); this.addHandlers(set, x, y, width, height, "gateway"); }, /* * drawMultiInstanceMarker * drawHighLight * highLightFlow */ drawMultiInstanceMarker: function(sequential, x, y, width, height) { var rectangleWidth = MARKER_WIDTH; var rectangleHeight = MARKER_WIDTH; // anti smoothing if (this.strokeWidth%2 == 1) x += .5;//, y += .5; var lineX = x + (width - rectangleWidth) / 2; var lineY = y + height - rectangleHeight - 3; var originalStroke = this.getStroke(); this.setStroke(MULTI_INSTANCE_STROKE); if (sequential) { var line = this.g.path( "M" + lineX + " " + lineY + "L" + (lineX + rectangleWidth) + " " + lineY + "M" + lineX + " " + (lineY + rectangleHeight / 2) + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight / 2) + "M" + lineX + " " + (lineY + rectangleHeight) + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight) ).attr({"stroke-width": this.strokeWidth}); } else { var line = this.g.path( "M" + lineX + " " + lineY + "L" + lineX + " " + (lineY + rectangleHeight) + "M" + (lineX + rectangleWidth / 2) + " " + lineY + "L" + (lineX + rectangleWidth / 2) + " " + (lineY + rectangleHeight) + "M" + (lineX + rectangleWidth) + " " + lineY + "L" + (lineX + rectangleWidth) + " " + (lineY + rectangleHeight) ).attr({"stroke-width": this.strokeWidth}); } this.setStroke(originalStroke); }, drawHighLight: function(x, y, width, height){ var originalPaint = this.getPaint(); var originalStroke = this.getStroke(); this.setPaint(HIGHLIGHT_COLOR); this.setStroke(THICK_TASK_BORDER_STROKE); //var c = this.g.rect(x - width/2 - THICK_TASK_BORDER_STROKE, y - height/2 - THICK_TASK_BORDER_STROKE, width + THICK_TASK_BORDER_STROKE*2, height + THICK_TASK_BORDER_STROKE*2, 5); var rect = this.g.rect(x - THICK_TASK_BORDER_STROKE, y - THICK_TASK_BORDER_STROKE, width + THICK_TASK_BORDER_STROKE*2, height + THICK_TASK_BORDER_STROKE*2, TASK_CORNER_ROUND); rect.attr("stroke-width", this.strokeWidth); rect.attr("stroke", this.getPaint()); this.setPaint(originalPaint); this.setStroke(originalStroke); }, highLightActivity: function(activityId){ var shape = this.g.getById(activityId); if (!shape) { console.error("Activity " + activityId + " not found"); return; } var contextObject = shape.data("contextObject"); if (contextObject) console.log("--> highLightActivity: ["+contextObject.getProperty("type")+"], activityId: " + contextObject.getId()); else console.log("--> highLightActivity: ", shape, shape.data("contextObject")); shape.attr("stroke-width", THICK_TASK_BORDER_STROKE); shape.attr("stroke", HIGHLIGHT_COLOR); }, highLightFlow: function(flowId){ var shapeFlow = this.g.getById(flowId); if (!shapeFlow) { console.error("Flow " + flowId + " not found"); return; } var contextObject = shapeFlow.data("contextObject"); if (contextObject) console.log("--> highLightFlow: ["+contextObject.id+"] " + contextObject.flow); //console.log("--> highLightFlow: ", flow.flow, flow.data("set")); var st = shapeFlow.data("set"); st.attr("stroke-width", SEQUENCEFLOW_HIGHLIGHT_STROKE); st.attr("stroke", HIGHLIGHT_COLOR); var withArrowHead = shapeFlow.data("withArrowHead"); if (withArrowHead) st[1].attr("fill", HIGHLIGHT_COLOR); st.forEach(function(el){ //console.log("---->", el); //el.attr("") }); }, _drawClock: function(cx, cy, width, height){ var circle = this.g.ellipse(cx, cy, 1, 1).attr({stroke:"none", fill: Color.get(232, 239, 241)}); //var c = this.g.ellipse(cx, cy, width, height).attr({stroke:"none", fill: Color.red}); //x = cx - width/2; //y = cy - height/2; var clock = this.g.path( /* outer circle */ "M15.5,2.374 C8.251,2.375,2.376,8.251,2.374,15.5 C2.376,22.748,8.251,28.623,15.5,28.627c7.249-0.004,13.124-5.879,13.125-13.127C28.624,8.251,22.749,2.375,15.5,2.374z" + /* inner circle */ "M15.5,26.623 C8.909,26.615,4.385,22.09,4.375,15.5 C4.385,8.909,8.909,4.384,15.5,4.374c4.59,0.01,11.115,3.535,11.124,11.125C26.615,22.09,22.091,26.615,15.5,26.623z" + /* 9 */ "M8.625,15.5c-0.001-0.552-0.448-0.999-1.001-1c-0.553,0-1,0.448-1,1c0,0.553,0.449,1,1,1C8.176,16.5,8.624,16.053,8.625,15.5z" + /* 8 */ "M8.179,18.572c-0.478,0.277-0.642,0.889-0.365,1.367c0.275,0.479,0.889,0.641,1.365,0.365c0.479-0.275,0.643-0.887,0.367-1.367C9.27,18.461,8.658,18.297,8.179,18.572z" + /* 10 */ "M9.18,10.696c-0.479-0.276-1.09-0.112-1.366,0.366s-0.111,1.09,0.365,1.366c0.479,0.276,1.09,0.113,1.367-0.366C9.821,11.584,9.657,10.973,9.18,10.696z" + /* 2 */ "M22.822,12.428c0.478-0.275,0.643-0.888,0.366-1.366c-0.275-0.478-0.89-0.642-1.366-0.366c-0.479,0.278-0.642,0.89-0.366,1.367C21.732,12.54,22.344,12.705,22.822,12.428z" + /* 7 */ "M12.062,21.455c-0.478-0.275-1.089-0.111-1.366,0.367c-0.275,0.479-0.111,1.09,0.366,1.365c0.478,0.277,1.091,0.111,1.365-0.365C12.704,22.344,12.54,21.732,12.062,21.455z" + /* 11 */ "M12.062,9.545c0.479-0.276,0.642-0.888,0.366-1.366c-0.276-0.478-0.888-0.642-1.366-0.366s-0.642,0.888-0.366,1.366C10.973,9.658,11.584,9.822,12.062,9.545z" + /* 4 */ "M22.823,18.572c-0.48-0.275-1.092-0.111-1.367,0.365c-0.275,0.479-0.112,1.092,0.367,1.367c0.477,0.275,1.089,0.113,1.365-0.365C23.464,19.461,23.3,18.848,22.823,18.572z" + /* 2 */ "M19.938,7.813c-0.477-0.276-1.091-0.111-1.365,0.366c-0.275,0.48-0.111,1.091,0.366,1.367s1.089,0.112,1.366-0.366C20.581,8.702,20.418,8.089,19.938,7.813z" + /* 3 */ "M23.378,14.5c-0.554,0.002-1.001,0.45-1.001,1c0.001,0.552,0.448,1,1.001,1c0.551,0,1-0.447,1-1C24.378,14.949,23.929,14.5,23.378,14.5z" + /* arrows */ "M15.501,6.624c-0.552,0-1,0.448-1,1l-0.466,7.343l-3.004,1.96c-0.478,0.277-0.642,0.889-0.365,1.365c0.275,0.479,0.889,0.643,1.365,0.367l3.305-1.676C15.39,16.99,15.444,17,15.501,17c0.828,0,1.5-0.671,1.5-1.5l-0.5-7.876C16.501,7.072,16.053,6.624,15.501,6.624z" + /* 9 */ "M15.501,22.377c-0.552,0-1,0.447-1,1s0.448,1,1,1s1-0.447,1-1S16.053,22.377,15.501,22.377z" + /* 8 */ "M18.939,21.455c-0.479,0.277-0.643,0.889-0.366,1.367c0.275,0.477,0.888,0.643,1.366,0.365c0.478-0.275,0.642-0.889,0.366-1.365C20.028,21.344,19.417,21.18,18.939,21.455z" + ""); clock.attr({fill: Color.black, stroke: "none"}); //clock.transform("t " + (cx-29.75/2) + " " + (cy-29.75/2)); //clock.transform("...s 0.85"); //clock.transform("...s " + .85 + " " + .85); clock.transform("t " + (-2.374) + " " + (-2.374) ); clock.transform("...t -" + (15.5-2.374) + " -" + (15.5-2.374) ); clock.transform("...s " + 1*(width/35) + " " + 1*(height/35)); clock.transform("...T " + cx + " " + cy); //clock.transform("t " + (cx-width/2) + " " + (cy-height/2)); //console.log(".getBBox(): ", clock.getBBox()); //console.log(".attr(): ", c.attrs); circle.attr("rx", clock.getBBox().width/2); circle.attr("ry", clock.getBBox().height/2); //return circle }, _drawPentagon: function(cx, cy, width, height, filled){ // draw GeneralPath (polygon) var n=5; var angle = 2*Math.PI/n; var waypoints = []; for ( var index = 0; index < n; index++ ) { var v = index*angle - Math.PI/2; var point = {}; point.x = -width*1.2/2 + parseInt(Math.round(width*1.2/2)) + parseInt(Math.round((width*1.2/4)*Math.cos(v))); point.y = -height*1.2/2 + parseInt(Math.round(height*1.2/2)) + parseInt(Math.round((height*1.2/4)*Math.sin(v))); waypoints[index] = point; } var polygone = new Polygone(waypoints, this.getStroke()); polygone.element = this.g.path(polygone.path); if (filled) polygone.element.attr("fill", Color.black); else polygone.element.attr("fill", Color.white); polygone.element.transform("s " + 1*(width/35) + " " + 1*(height/35)); polygone.element.transform("...T " + cx + " " + cy); }, //_drawMultilineText: function(text, x, y, boxWidth, boxHeight, textAnchor) { _drawMultilineText: function(text, x, y, boxWidth, boxHeight, verticalAlign, horizontalAlign) { if (!text || text == "") return; // Autostretch boxHeight if boxHeight is 0 if (boxHeight == 0) verticalAlign = MULTILINE_VERTICAL_ALIGN_TOP; //var TEXT_PADDING = 3; var width = boxWidth; if (boxHeight) var height = boxHeight; var layouts = []; //var font = {font: "11px Arial", opacity: 1, "fill": LABEL_COLOR}; var font = this.getFont(); var measurer = new LineBreakMeasurer(this.g, x, y, text, font); var lineHeight = measurer.rafaelTextObject.getBBox().height; //console.log("text: ", text.replace(/\n/g, "?")); if (height) { var availableLinesCount = parseInt(height/lineHeight); //console.log("availableLinesCount: " + availableLinesCount); } var i = 1; while (measurer.getPosition() < measurer.text.getEndIndex()) { var layout = measurer.nextLayout(width); //console.log("LAYOUT: " + layout + ", getPosition: " + measurer.getPosition()); if (layout != null) { // TODO: and check if measurer has next layout. If no then don't draw dots if (!availableLinesCount || i < availableLinesCount) { layouts.push(layout); } else { layouts.push(this.fitTextToWidth(layout + "...", boxWidth)); break; } } i++; }; //console.log(layouts); measurer.rafaelTextObject.attr({"text": layouts.join("\n")}); if (horizontalAlign) measurer.rafaelTextObject.attr({"text-anchor": horizontalAlign}); // end, middle, start var bb = measurer.rafaelTextObject.getBBox(); // TODO: there is somethin wrong with wertical align. May be: measurer.rafaelTextObject.attr({"y": y + height/2 - bb.height/2}) measurer.rafaelTextObject.attr({"y": y + bb.height/2}); //var bb = measurer.rafaelTextObject.getBBox(); if (measurer.rafaelTextObject.attr("text-anchor") == MULTILINE_HORIZONTAL_ALIGN_MIDDLE ) measurer.rafaelTextObject.attr("x", x + boxWidth/2); else if (measurer.rafaelTextObject.attr("text-anchor") == MULTILINE_HORIZONTAL_ALIGN_RIGHT ) measurer.rafaelTextObject.attr("x", x + boxWidth); var boxStyle = {stroke: Color.LightSteelBlue2, "stroke-width": 1.0, "stroke-dasharray": "- "}; //var box = this.g.rect(x+.5, y + .5, width, height).attr(boxStyle); var textAreaCX = x + boxWidth/2; var height = boxHeight; if (!height) height = bb.height; var textAreaCY = y + height/2; var dotLeftTop = this.g.ellipse(x, y, 3, 3).attr({"stroke-width": 0, fill: Color.LightSteelBlue, stroke: "none"}).hide(); var dotCenter = this.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: "none"}).hide(); /* // real bbox var bb = measurer.rafaelTextObject.getBBox(); var rect = paper.rect(bb.x+.5, bb.y + .5, bb.width, bb.height).attr({"stroke-width": 1}); */ var rect = this.g.rect(x, y, boxWidth, height).attr({"stroke-width": 1}).attr(boxStyle).hide(); var debugSet = this.g.set(); debugSet.push(dotLeftTop, dotCenter, rect); //debugSet.show(); }, drawTextAnnotation: function(text, x, y, width, height){ var lineLength = 18; var path = []; path.push(["M", x + lineLength, y]); path.push(["L", x, y]); path.push(["L", x, y + height]); path.push(["L", x + lineLength, y + height]); path.push(["L", x + lineLength, y + height -1]); path.push(["L", x + 1, y + height -1]); path.push(["L", x + 1, y + 1]); path.push(["L", x + lineLength, y + 1]); path.push(["z"]); var textAreaLines = this.g.path(path); var boxWidth = width - (2 * ANNOTATION_TEXT_PADDING); var boxHeight = height - (2 * ANNOTATION_TEXT_PADDING); var boxX = x + width/2 - boxWidth/2; var boxY = y + height/2 - boxHeight/2; // for debug var rectStyle = {stroke: Color(112, 146, 190), "stroke-width": 1.0, "stroke-dasharray": "- "}; var r = this.g.rect(boxX, boxY, boxWidth, boxHeight).attr(rectStyle); // this.drawAnnotationText(text, boxX, boxY, boxWidth, boxHeight); }, drawLabel111111111: function(text, x, y, width, height, labelAttrs){ var debug = false; // text if (text != null && text != undefined && text != "") { var attr = LABEL_FONT; //console.log("x", x, "y", y, "width", width, "height", height ); wrappedText = text; if (labelAttrs && labelAttrs.wrapWidth) { wrappedText = this.wrapTextToWidth(wrappedText, labelAttrs.wrapWidth); } var realWidth = this.getStringWidth(wrappedText, attr); var realHeight = this.getStringHeight(wrappedText, attr); var textAreaCX = x + width/2; var textAreaCY = y + 3 + height + this.getStringHeight(wrappedText, attr)/2; var textX = textAreaCX; var textY = textAreaCY; var textAttrs = {}; if (labelAttrs && labelAttrs.align) { switch (labelAttrs.align) { case "left": textAttrs["text-anchor"] = "start"; textX = textX - realWidth/2; break; case "center": textAttrs["text-anchor"] = "middle"; break; case "right": textAttrs["text-anchor"] = "end"; textX = textX + realWidth/2; break; } } if (labelAttrs && labelAttrs.wrapWidth) { if (true) { // Draw frameborder var textAreaStyle = {stroke: Color.LightSteelBlue2, "stroke-width": 1.0, "stroke-dasharray": "- "}; var textAreaX = textAreaCX - realWidth/2; var textAreaY = textAreaCY+.5 - realHeight/2; var textArea = this.g.rect(textAreaX, textAreaY, realWidth, realHeight).attr(textAreaStyle); var textAreaLines = this.g.path("M" + textAreaX + " " + textAreaY + "L" + (textAreaX+realWidth) + " " + (textAreaY+realHeight) + "M" + + (textAreaX+realWidth) + " " + textAreaY + "L" + textAreaX + " " + (textAreaY+realHeight)); textAreaLines.attr(textAreaStyle); this.g.ellipse(textAreaCX, textAreaCY, 3, 3).attr({fill: Color.LightSteelBlue2, stroke: "none"}); } } var label = this.g.text(textX, textY, wrappedText).attr(attr).attr(textAttrs); //label.id = Raphael.createUUID(); //console.log("label ", label.id, ", ", wrappedText); if (this.fontSmoothing) { label.attr({stroke: LABEL_COLOR, "stroke-width":.4}); } // debug if (debug) { var imageAreaStyle = {stroke: Color.grey61, "stroke-width": 1.0, "stroke-dasharray": "- "}; var imageArea = this.g.rect(x+.5, y+.5, width, height).attr(imageAreaStyle); var imageAreaLines = this.g.path("M" + x + " " + y + "L" + (x+width) + " " + (y+height) + "M" + + (x+width) + " " + y + "L" + x + " " + (y+height)); imageAreaLines.attr(imageAreaStyle); var dotStyle = {fill: Color.Coral, stroke: "none"}; this.g.ellipse(x, y, 3, 3).attr(dotStyle); this.g.ellipse(x+width, y, 2, 2).attr(dotStyle); this.g.ellipse(x+width, y+height, 2, 2).attr(dotStyle); this.g.ellipse(x, y+height, 2, 2).attr(dotStyle); } return label; } }, vvoid: function(){} }; ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/ProcessDiagramGenerator.js ================================================ /** * Class to generate an image based the diagram interchange information in a * BPMN 2.0 process. * * @author (Javascript) Dmitry Farafonov */ var ProcessDiagramGenerator = { options: {}, processDiagramCanvas: [], activityDrawInstructions:{}, processDiagrams: {}, diagramBreadCrumbs: null, init: function(){ // start event this.activityDrawInstructions["startEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawNoneStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // start timer event this.activityDrawInstructions["startTimerEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawTimerStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty("name")); }; // start event this.activityDrawInstructions["messageStartEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawMessageStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty("name")); }; // start signal event this.activityDrawInstructions["startSignalEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawSignalStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty("name")); }; // start multiple event this.activityDrawInstructions["startMultipleEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawMultipleStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty("name")); }; // signal catch this.activityDrawInstructions["intermediateSignalCatch"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawCatchingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // message catch this.activityDrawInstructions["intermediateMessageCatch"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawCatchingMessageEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // multiple catch this.activityDrawInstructions["intermediateMultipleCatch"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawCatchingMultipleEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // signal throw this.activityDrawInstructions["intermediateSignalThrow"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawThrowingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty("name")); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // message throw this.activityDrawInstructions["intermediateMessageThrow"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawThrowingMessageEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty("name")); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // multiple throw this.activityDrawInstructions["intermediateMultipleThrow"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawThrowingMultipleEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty("name")); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // none throw this.activityDrawInstructions["intermediateThrowEvent"] = function() { var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawThrowingNoneEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty("name")); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // end event this.activityDrawInstructions["endEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawNoneEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // error end event this.activityDrawInstructions["errorEndEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawErrorEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // message end event this.activityDrawInstructions["messageEndEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawMessageEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // signal end event this.activityDrawInstructions["signalEndEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawSignalEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // multiple end event this.activityDrawInstructions["multipleEndEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawMultipleEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // terminate end event this.activityDrawInstructions["terminateEndEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawTerminateEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // error start event this.activityDrawInstructions["errorStartEvent"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawErrorStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), activityImpl.getProperty("name")); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // task this.activityDrawInstructions["task"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); // TODO: //console.error("task is not implemented yet"); /* var activityImpl = this; processDiagramCanvas.drawTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), thickBorder); */ }; // user task this.activityDrawInstructions["userTask"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawUserTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // script task this.activityDrawInstructions["scriptTask"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawScriptTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // service task this.activityDrawInstructions["serviceTask"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawServiceTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // receive task this.activityDrawInstructions["receiveTask"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawReceiveTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // send task this.activityDrawInstructions["sendTask"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawSendTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // manual task this.activityDrawInstructions["manualTask"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawManualTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // businessRuleTask task this.activityDrawInstructions["businessRuleTask"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawBusinessRuleTask(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // exclusive gateway this.activityDrawInstructions["exclusiveGateway"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawExclusiveGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // inclusive gateway this.activityDrawInstructions["inclusiveGateway"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawInclusiveGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // parallel gateway this.activityDrawInstructions["parallelGateway"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawParallelGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // eventBasedGateway this.activityDrawInstructions["eventBasedGateway"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawEventBasedGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; // Boundary timer this.activityDrawInstructions["boundaryTimer"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawCatchingTimerEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // Boundary catch error this.activityDrawInstructions["boundaryError"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawCatchingErrorEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // Boundary signal event this.activityDrawInstructions["boundarySignal"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawCatchingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // Boundary message event this.activityDrawInstructions["boundaryMessage"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = activityImpl.getProperty("isInterrupting"); processDiagramCanvas.drawCatchingMessageEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, null); var label = ProcessDiagramGenerator.getActivitiLabel(activityImpl); if (label) processDiagramCanvas.drawLabel(label.text, label.x, label.y, label.width, label.height); }; // timer catch event this.activityDrawInstructions["intermediateTimer"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); var isInterrupting = null; processDiagramCanvas.drawCatchingTimerEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isInterrupting, activityImpl.getProperty("name")); }; // subprocess this.activityDrawInstructions["subProcess"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; // TODO: processDiagramCanvas.setConextObject(activityImpl); var isExpanded = activityImpl.getProperty("isExpanded"); var isTriggeredByEvent = activityImpl.getProperty("triggeredByEvent"); if(isTriggeredByEvent == undefined) { isTriggeredByEvent = true; } // TODO: check why isTriggeredByEvent = true when undefined isTriggeredByEvent = false; if (isExpanded != undefined && isExpanded == false) { processDiagramCanvas.drawCollapsedSubProcess(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isTriggeredByEvent); } else { processDiagramCanvas.drawExpandedSubProcess(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isTriggeredByEvent); } //console.error("subProcess is not implemented yet"); }; // call activity this.activityDrawInstructions["callActivity"] = function(){ var activityImpl = this.activity; var processDiagramCanvas = this.processDiagramCanvas; processDiagramCanvas.setConextObject(activityImpl); processDiagramCanvas.drawCollapsedCallActivity(activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight()); }; $(document).ready(function(){ // Protect right click on SVG elements (and on canvas too) document.body.oncontextmenu = function(event) { if (window.event.srcElement.tagName == "shape" || window.event.srcElement.tagName == "DIV" && window.event.srcElement.parentElement.className == "diagram") { // IE DIAGRAM CANVAS OR SHAPE DETECTED! return false; } return (!Object.isSVGElement(window.event.srcElement)); }; }); }, getActivitiLabel:function(activityImpl){ /* TODO: Label object should be in activityImpl and looks like: { x: 250, y: 250, width: 80, height: 30 } And then: if (!activityImpl.label) return null; var label = activityImpl.label; label.text = activityImpl.name; return label; */ // But now default label for all events is: return { text: activityImpl.getProperty("name"), x: activityImpl.getX() + .5 + activityImpl.getWidth()/2, y: activityImpl.getY() + .5 + activityImpl.getHeight() + ICON_PADDING, width: 100, height: 0 }; }, generateDiagram: function(processDefinitionDiagramLayout){ // Init canvas var processDefinitionId = processDefinitionDiagramLayout.processDefinition.id; //console.log("Init canvas ", processDefinitionId); if (this.getProcessDiagram(processDefinitionId) != undefined) { // TODO: may be reset canvas if exists.. Or just show //console.log("ProcessDiagram '" + processDefinitionId + "' is already generated. Just show it."); return; } var processDiagram = this.initProcessDiagramCanvas(processDefinitionDiagramLayout); var processDiagramCanvas = processDiagram.diagramCanvas; // Draw pool shape, if process is participant in collaboration if(processDefinitionDiagramLayout.participantProcess != undefined) { //console.log("Draw pool shape"); var pProc = processDefinitionDiagramLayout.participantProcess; processDiagramCanvas.drawPoolOrLane(pProc.x, pProc.y, pProc.width, pProc.height, pProc.name); } var laneSets = processDefinitionDiagramLayout.laneSets; var activities = processDefinitionDiagramLayout.activities; var sequenceFlows = processDefinitionDiagramLayout.sequenceFlows; pb1.set('value', 0); var cnt = 0; if (laneSets) for(var i in laneSets) { cnt += laneSets[i].lanes.length; } if (activities) cnt += activities.length; if (sequenceFlows) cnt += sequenceFlows.length; var step = (cnt>0)? 100/cnt : 0; var progress = 0; //console.log("progress bar step: ", step); var task1 = new $.AsyncQueue(); // Draw lanes task1.add(function (task1) { if (!laneSets) laneSets = []; //console.log("> draw lane sets, count:", laneSets.length) }); for(var i in laneSets) { var laneSet = laneSets[i]; //laneSet.id, laneSet.name task1.add(laneSet.lanes,function (task1, lane) { progress += step; pb1.set('value', parseInt(progress)); //console.log("--> laneId: " + lane.name + ", name: " + lane.name); processDiagramCanvas.drawPoolOrLane(lane.x, lane.y, lane.width, lane.height, lane.name); }); } // Draw activities task1.add(function (task1) { if (!activities) activities = []; //console.log("> draw activities, count:", activities.length) }); var activitiesLength = activities.length; task1.add(activities,function (task1, activityJson) { var activity = new ActivityImpl(activityJson); activitiesLength --; progress += step; pb1.set('value', parseInt(progress)); //console.log(activitiesLength, "--> activityId: " + activity.getId() + ", name: " + activity.getProperty("name")); ProcessDiagramGenerator.drawActivity(processDiagramCanvas, activity); }); // Draw sequence-flows task1.add(function (task1) { if (!sequenceFlows) sequenceFlows = []; //console.log("> draw sequence flows, count:", sequenceFlows.length) }); var flowsLength = sequenceFlows.length; task1.add(sequenceFlows,function (task1, flow) { var waypoints = []; for(var j in flow.xPointArray) { waypoints[j] = {x: flow.xPointArray[j], y: flow.yPointArray[j]}; } var isDefault = flow.isDefault; var isConditional = flow.isConditional; var isHighLighted = flow.isHighLighted; // TODO: add source and destination for sequence flows in REST // parse for test var f = flow.flow; var matches = f.match(/\((.*)\)--.*-->\((.*)\)/); var sourceActivityId, destinationActivityId; if (matches != null) { sourceActivityId = matches[1]; destinationActivityId = matches[2]; } flow.sourceActivityId = sourceActivityId; flow.destinationActivityId = destinationActivityId; // flowsLength--; progress += step; pb1.set('value', parseInt(progress)); //console.log(flowsLength, "--> flow: " + flow.flow); processDiagramCanvas.setConextObject(flow); processDiagramCanvas.drawSequenceflow(waypoints, isConditional, isDefault, isHighLighted); }); task1.onComplete(function(){ if (progress<100) pb1.set('value', 100); //console.log("COMPLETE!!!"); //console.timeEnd('generateDiagram'); }); task1.run(); }, getProcessDiagram: function (processDefinitionId) { return this.processDiagrams[processDefinitionId]; }, initProcessDiagramCanvas: function (processDefinitionDiagramLayout) { var minX = 0; var maxX = 0; var minY = 0; var maxY = 0; if(processDefinitionDiagramLayout.participantProcess != undefined) { var pProc = processDefinitionDiagramLayout.participantProcess; minX = pProc.x; maxX = pProc.x + pProc.width; minY = pProc.y; maxY = pProc.y + pProc.height; } var activities = processDefinitionDiagramLayout.activities; for(var i in activities) { var activityJson = activities[i]; var activity = new ActivityImpl(activityJson); // width if (activity.getX() + activity.getWidth() > maxX) { maxX = activity.getX() + activity.getWidth(); } if (activity.getX() < minX) { minX = activity.getX(); } // height if (activity.getY() + activity.getHeight() > maxY) { maxY = activity.getY() + activity.getHeight(); } if (activity.getY() < minY) { minY = activity.getY(); } } var sequenceFlows = processDefinitionDiagramLayout.sequenceFlows; for(var i in sequenceFlows) { var flow = sequenceFlows[i]; var waypoints = []; for(var j in flow.xPointArray) { waypoints[j] = {x: flow.xPointArray[j], y: flow.yPointArray[j]}; // width if (waypoints[j].x > maxX) { maxX = waypoints[j].x; } if (waypoints[j].x < minX) { minX = waypoints[j].x; } // height if (waypoints[j].y > maxY) { maxY = waypoints[j].y; } if (waypoints[j].y < minY) { minY = waypoints[j].y; } } } var laneSets = processDefinitionDiagramLayout.laneSets; for(var i in laneSets) { var laneSet = laneSets[i]; //laneSet.id, laneSet.name for(var j in laneSet.lanes) { var lane = laneSet.lanes[j]; // width if (lane.x + lane.width > maxX) { maxX = lane.x + lane.width; } if (lane.x < minX) { minX = lane.x; } // height if (lane.y + lane.height > maxY) { maxY = lane.y + lane.height; } if (lane.y < minY) { minY = lane.y; } } } var diagramCanvas = new ProcessDiagramCanvas(); if (diagramCanvas) { // create div in diagramHolder var diagramHolder = document.getElementById(this.options.diagramHolderId); if (!diagramHolder) throw {msg: "Diagram holder not found", error: "diagramHolderNotFound"}; var div = document.createElement("DIV"); div.id = processDefinitionDiagramLayout.processDefinition.id; div.className = "diagram"; diagramHolder.appendChild(div); diagramCanvas.init(maxX + 20, maxY + 20, processDefinitionDiagramLayout.processDefinition.id); this.processDiagrams[processDefinitionDiagramLayout.processDefinition.id] = { processDefinitionDiagramLayout: processDefinitionDiagramLayout, diagramCanvas: diagramCanvas }; } return this.getProcessDiagram(processDefinitionDiagramLayout.processDefinition.id); //return new DefaultProcessDiagramCanvas(maxX + 10, maxY + 10, minX, minY); }, drawActivity: function(processDiagramCanvas, activity, highLightedActivities) { var type = activity.getProperty("type"); var drawInstruction = this.activityDrawInstructions[type]; if (drawInstruction != null) { drawInstruction.apply({processDiagramCanvas:processDiagramCanvas, activity:activity}); } else { //console.error("no drawInstruction for " + type + ": ", activity); } // Actually draw the markers if (activity.getProperty("multiInstance") != undefined || activity.getProperty("collapsed") != undefined) { //console.log(activity.getProperty("name"), activity.properties); var multiInstanceSequential = (activity.getProperty("multiInstance") == "sequential"); var multiInstanceParallel = (activity.getProperty("multiInstance") == "parrallel"); var collapsed = activity.getProperty("collapsed"); processDiagramCanvas.drawActivityMarkers(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight(), multiInstanceSequential, multiInstanceParallel, collapsed); } /* processDiagramCanvas.drawActivityMarkers(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight(), multiInstanceSequential, multiInstanceParallel, collapsed); */ // TODO: Draw highlighted activities if they are present }, setHighLights: function(highLights){ if (highLights.processDefinitionId == undefined) { //console.error("Process instance " + highLights.processInstanceId + " doesn't exist"); return; } var processDiagram = this.getProcessDiagram(highLights.processDefinitionId); if (processDiagram == undefined) { //console.error("Process diagram " + highLights.processDefinitionId + " not found"); return; } var processDiagramCanvas = processDiagram.diagramCanvas; // TODO: remove highLightes from all activities before set new highLight for (var i in highLights.activities) { var activityId = highLights.activities[i]; processDiagramCanvas.highLightActivity(activityId); } // TODO: remove highLightes from all flows before set new highLight for (var i in highLights.flows) { var flowId = highLights.flows[i]; var object = processDiagramCanvas.g.getById(flowId); var flow = object.data("contextObject"); flow.isHighLighted = true; processDiagramCanvas.highLightFlow(flowId); } }, drawHighLights: function(processInstanceId) { // Load highLights for the processInstanceId /* var url = Lang.sub(this.options.processInstanceHighLightsUrl, {processInstanceId: processInstanceId}); $.ajax({ url: url, type: 'GET', dataType: 'json', cache: false, async: true, }).done(function(data) { var highLights = data; if (!highLights) { console.log("highLights not found"); return; } console.log("highLights[" + highLights.processDefinitionId + "][" + processInstanceId + "]: ", highLights); ProcessDiagramGenerator.setHighLights(highLights); }).fail(function(jqXHR, textStatus){ console.log('Get HighLights['+processDefinitionId+'] failure: ', textStatus, jqXHR); }); */ ActivitiRest.getHighLights(processInstanceId, this._drawHighLights); }, _drawHighLights: function() { var highLights = this.highLights; ProcessDiagramGenerator.setHighLights(highLights); }, // Load processDefinition drawDiagram: function(processDefinitionId) { // Hide all diagrams var diagrams = $("#" + this.options.diagramHolderId + " div.diagram"); diagrams.addClass("hidden"); // If processDefinitionId doesn't contain ":" then it's a "processDefinitionKey", not an id. // Get process definition by key if (processDefinitionId.indexOf(":") < 0) { ActivitiRest.getProcessDefinitionByKey(processDefinitionId, this._drawDiagram); } else { this._drawDiagram.apply({processDefinitionId: processDefinitionId}); } }, _drawDiagram: function() { var processDefinitionId = this.processDefinitionId; ProcessDiagramGenerator.addBreadCrumbsItem(processDefinitionId); // Check if processDefinition is already loaded and rendered var processDiagram = ProcessDiagramGenerator.getProcessDiagram(processDefinitionId); if (processDiagram != undefined && processDiagram != null) { //console.log("Process diagram " + processDefinitionId + " is already loaded"); //return; var diagram = document.getElementById(processDefinitionId); $(diagram).removeClass("hidden"); // Regenerate image var processDefinitionDiagramLayout = processDiagram.processDefinitionDiagramLayout; ProcessDiagramGenerator.generateDiagram(processDefinitionDiagramLayout); return; } //console.time('loadDiagram'); // Load processDefinition ActivitiRest.getProcessDefinition(processDefinitionId, ProcessDiagramGenerator._generateDiagram); }, _generateDiagram: function() { var processDefinitionDiagramLayout = this.processDefinitionDiagramLayout; //console.log("process-definition-diagram-layout["+processDefinitionDiagramLayout.processDefinition.id+"]: ", processDefinitionDiagramLayout); //console.timeEnd('loadDiagram'); //console.time('generateDiagram'); pb1.set('value', 0); ProcessDiagramGenerator.generateDiagram(processDefinitionDiagramLayout); }, getProcessDefinitionByKey: function(processDefinitionKey) { var url = Lang.sub(this.options.processDefinitionByKeyUrl, {processDefinitionKey: processDefinitionKey}); var processDefinition; $.ajax({ url: url, type: 'POST', dataType: 'json', cache: false, async: false }).done(function(data) { //console.log("ajax returned data"); //console.log("ajax returned data:", data); processDefinition = data; if (!processDefinition) { //console.error("Process definition '" + processDefinitionKey + "' not found"); } }).fail(function(jqXHR, textStatus){ //console.error('Get diagram layout['+processDefinitionKey+'] failure: ', textStatus, jqXHR); }); if (processDefinition) { //console.log("Get process definition by key '" + processDefinitionKey + "': ", processDefinition.id); return processDefinition; } else { return null; } }, addBreadCrumbsItem: function(processDefinitionId){ var TPL_UL_CONTAINER = '
              ', TPL_LI_CONTAINER = '
            • {name}
            • '; if (!this.diagramBreadCrumbs) this.diagramBreadCrumbs = $("#" + this.options.diagramBreadCrumbsId); if (!this.diagramBreadCrumbs) return; var ul = this.diagramBreadCrumbs.find("ul"); //console.log("ul: ", ul); if (ul.size() == 0) { ul = $(TPL_UL_CONTAINER); this.diagramBreadCrumbs.append(ul); } var liListOld = ul.find("li"); //console.warn("liListOld", liListOld); // TODO: if there is any items after current then remove that before adding new item (m.b. it is a duplicate) var currentBreadCrumbsItemId = this.currentBreadCrumbsItemId; found = false; liListOld.each( function(index, item) { //console.warn("item:", $(this)); if (!found && currentBreadCrumbsItemId == $(this).attr("id")) { found = true; return; } if (found) { //console.warn("remove ", $(this).attr("id")); $(this).remove(); } } ); var liListNew = ul.find("li"); //console.log("liListNew size: ", liListNew.size()); var values = { id: 'breadCrumbsItem_' + liListNew.size(), processDefinitionId: processDefinitionId, name: processDefinitionId }; var tpl = Lang.sub(TPL_LI_CONTAINER, values); //console.log("tpl: ", tpl); ul.append(tpl); var li = ul.find("#" + values.id); //console.warn("li:", li); $('#' + values.id).on('click', this._breadCrumbsItemClick); ul.find("li").removeClass("selected"); li.attr("num", liListNew.size()); li.addClass("selected"); this.currentBreadCrumbsItemId = li.attr("id"); }, _breadCrumbsItemClick: function(){ var li = $(this), id = li.attr("id"), processDefinitionId = li.attr("processDefinitionId"); //console.warn("_breadCrumbsItemClick: ", id, ", processDefinitionId: ", processDefinitionId); var ul = ProcessDiagramGenerator.diagramBreadCrumbs.one("ul"); ul.find("li").removeClass("selected"); li.addClass("selected"); ProcessDiagramGenerator.currentBreadCrumbsItemId = li.attr("id"); // Hide all diagrams var diagrams = $("#"+ProcessDiagramGenerator.options.diagramHolderId+" div.diagram"); diagrams.addClass("hidden"); var processDiagram = ProcessDiagramGenerator.getProcessDiagram(processDefinitionId); var diagram = document.getElementById(processDefinitionId); if (!diagram) return; $(diagram).removeClass("hidden"); // Regenerate image var processDefinitionDiagramLayout = processDiagram.processDefinitionDiagramLayout; ProcessDiagramGenerator.generateDiagram(processDefinitionDiagramLayout); }, showFlowInfo: function(flow){ var diagramInfo = $("#" + this.options.diagramInfoId); if (!diagramInfo) return; var values = { flow: flow.flow, isDefault: (flow.isDefault)? "true":"", isConditional: (flow.isConditional)? "true":"", isHighLighted: (flow.isHighLighted)? "true":"", sourceActivityId: flow.sourceActivityId, destinationActivityId: flow.destinationActivityId }; var TPL_FLOW_INFO = '
              {flow}
              ' + '
              sourceActivityId: {sourceActivityId}
              ' + '
              destinationActivityId: {destinationActivityId}
              ' + '
              isDefault: {isDefault}
              ' + '
              isConditional: {isConditional}
              ' + '
              isHighLighted: {isHighLighted}
              '; var tpl = Lang.sub(TPL_FLOW_INFO, values); //console.log("info: ", tpl); diagramInfo.html(tpl); }, showActivityInfo: function(activity){ var diagramInfo = $("#" + this.options.diagramInfoId); if (!diagramInfo) return; var values = { activityId: activity.getId(), name: activity.getProperty("name"), type: activity.getProperty("type") }; var TPL_ACTIVITY_INFO = '' + '
              activityId: {activityId}
              ' + '
              name: {name}
              ' + '
              type: {type}
              '; var TPL_CALLACTIVITY_INFO = '' + '
              collapsed: {collapsed}
              ' + '
              processDefinitonKey: {processDefinitonKey}
              '; var template = TPL_ACTIVITY_INFO; if (activity.getProperty("type") == "callActivity") { values.collapsed = activity.getProperty("collapsed"); values.processDefinitonKey = activity.getProperty("processDefinitonKey"); template += TPL_CALLACTIVITY_INFO; } else if (activity.getProperty("type") == "callActivity") { } var tpl = Lang.sub(template, values); //console.log("info: ", tpl); diagramInfo.html(tpl); }, hideInfo: function(){ var diagramInfo = $("#" + this.options.diagramInfoId); if (!diagramInfo) return; diagramInfo.html(""); }, vvoid: function(){} }; var Lang = { SUBREGEX: /\{\s*([^\|\}]+?)\s*(?:\|([^\}]*))?\s*\}/g, UNDEFINED: 'undefined', isUndefined: function(o) { return typeof o === Lang.UNDEFINED; }, sub: function(s, o) { return ((s.replace) ? s.replace(Lang.SUBREGEX, function(match, key) { return (!Lang.isUndefined(o[key])) ? o[key] : match; }) : s); } }; if (Lang.isUndefined(console)) { console = { log: function() {}, warn: function() {}, error: function() {}}; } ProcessDiagramGenerator.init(); ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/jquery/jquery.asyncqueue.js ================================================ /* * This file is part of the jquery plugin "asyncQueue". * * (c) Sebastien Roch * @author (parallel) Dmitry Farafonov * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ (function($){ $.AsyncQueue = function() { var that = this, queue = [], completeFunc, failureFunc, paused = false, lastCallbackData, _run, _complete, inQueue = 0, defaultTimeOut = 10; _run = function() { var f = queue.shift(); if (f) { inQueue++; setTimeout(function(){ f.fn.apply(that, [that]); if (!f.isParallel) if (paused === false) { _run(); } inQueue --; if (inQueue == 0 && queue.length == 0) _complete(); }, f.timeOut); if (f.isParallel) if (paused === false) { _run(); } } }; _complete = function(){ if (completeFunc) completeFunc.apply(that, [that]); }; this.onComplete = function(func) { completeFunc = func; }; this.onFailure = function(func) { failureFunc = func; }; this.add = function(func) { // TODO: add callback for queue[i] complete var obj = arguments[0]; if (obj && Object.prototype.toString.call(obj) === "[object Array]") { var fn = arguments[1]; var timeOut = (typeof(arguments[2]) != "undefined")? arguments[2] : defaultTimeOut; if (typeof(fn) == "function") { for(var i = 0; i < obj.length; i++) { var f = function(objx){ queue.push({isParallel: true, fn: function(){fn.apply(that, [that, objx]);}, timeOut: timeOut}); }(obj[i]) } } } else { var fn = arguments[0]; var timeOut = (typeof(arguments[1]) != "undefined")? arguments[2] : defaultTimeOut; queue.push({isParallel: false, fn: func, timeOut: timeOut}); } return this; }; this.addParallel = function(func, timeOut) { // TODO: add callback for queue[i] complete queue.push({isParallel: true, fn: func, timeOut: timeOut}); return this; }; this.storeData = function(dataObject) { lastCallbackData = dataObject; return this; }; this.lastCallbackData = function () { return lastCallbackData; }; this.run = function() { paused = false; _run(); }; this.pause = function () { paused = true; return this; }; this.failure = function() { paused = true; if (failureFunc) { var args = [that]; for(i = 0; i < arguments.length; i++) { args.push(arguments[i]); } failureFunc.apply(that, args); } }; this.size = function(){ return queue.length; }; return this; } })(jQuery); ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/diagram-viewer/js/jquery/jquery.js ================================================ /*! * jQuery JavaScript Library v1.7.1 * http://jquery.com/ * * Copyright 2011, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Mon Nov 21 21:11:03 2011 -0500 */ (function( window, undefined ) { // Use the correct document accordingly with window argument (sandbox) var document = window.document, navigator = window.navigator, location = window.location; var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // A central reference to the root jQuery(document) rootjQuery, // A simple way to check for HTML strings or ID strings // Prioritize #id over to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, // Used for trimming whitespace trimLeft = /^\s+/, trimRight = /\s+$/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, // JSON RegExp rvalidchars = /^[\],:{}\s]*$/, rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, // Useragent RegExp rwebkit = /(webkit)[ \/]([\w.]+)/, ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, // Matches dashed string for camelizing rdashAlpha = /-([a-z]|[0-9])/ig, rmsPrefix = /^-ms-/, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return ( letter + "" ).toUpperCase(); }, // Keep a UserAgent string for use with jQuery.browser userAgent = navigator.userAgent, // For matching the engine and version of the browser browserMatch, // The deferred used on DOM ready readyList, // The ready event handler DOMContentLoaded, // Save a reference to some core methods toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, trim = String.prototype.trim, indexOf = Array.prototype.indexOf, // [[Class]] -> type pairs class2type = {}; jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context && document.body ) { this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; doc = ( context ? context.ownerDocument || context : document ); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; } return jQuery.merge( this, selector ); // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used jquery: "1.7.1", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set size: function() { return this.length; }, toArray: function() { return slice.call( this, 0 ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set var ret = this.constructor(); if ( jQuery.isArray( elems ) ) { push.apply( ret, elems ); } else { jQuery.merge( ret, elems ); } // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; if ( name === "find" ) { ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; } else if ( name ) { ret.selector = this.selector + "." + name + "(" + selector + ")"; } // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // Add the callback readyList.add( fn ); return this; }, eq: function( i ) { i = +i; return i === -1 ? this.slice( i ) : this.slice( i, i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Either a released hold or an DOMready/load event and not yet ready if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.fireWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).off( "ready" ); } } }, bindReady: function() { if ( readyList ) { return; } readyList = jQuery.Callbacks( "once memory" ); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, // A crude way of determining if an object is a window isWindow: function( obj ) { return obj && typeof obj === "object" && "setInterval" in obj; }, isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); }, type: function( obj ) { return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; }, isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } try { // Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, error: function( msg ) { throw new Error( msg ); }, parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data ); // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js if ( rvalidchars.test( data.replace( rvalidescape, "@" ) .replace( rvalidtokens, "]" ) .replace( rvalidbraces, "")) ) { return ( new Function( "return " + data ) )(); } jQuery.error( "Invalid JSON: " + data ); }, // Cross-browser xml parsing parseXML: function( data ) { var xml, tmp; try { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } } catch( e ) { xml = undefined; } if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop: function() {}, // Evaluates a script in a global context // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { if ( data && rnotwhite.test( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, // Convert dashed to camelCase; used by the css and data modules // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction( object ); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most util use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object; }, // Use native String.trim function wherever possible trim: trim ? function( text ) { return text == null ? "" : trim.call( text ); } : // Otherwise use our own trimming functionality function( text ) { return text == null ? "" : text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); }, // results is for internal usage only makeArray: function( array, results ) { var ret = results || []; if ( array != null ) { // The window, strings (and functions) also have 'length' // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 var type = jQuery.type( array ); if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { jQuery.merge( ret, array ); } } return ret; }, inArray: function( elem, array, i ) { var len; if ( array ) { if ( indexOf ) { return indexOf.call( array, elem, i ); } len = array.length; i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; for ( ; i < len; i++ ) { // Skip accessing in sparse arrays if ( i in array && array[ i ] === elem ) { return i; } } } return -1; }, merge: function( first, second ) { var i = first.length, j = 0; if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, inv ) { var ret = [], retVal; inv = !!inv; // Go through the array, only saving the items // that pass the validator function for ( var i = 0, length = elems.length; i < length; i++ ) { retVal = !!callback( elems[ i ], i ); if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, // jquery objects are treated as arrays isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, } else { for ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays return ret.concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { if ( typeof context === "string" ) { var tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind var args = slice.call( arguments, 2 ), proxy = function() { return fn.apply( context, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; return proxy; }, // Mutifunctional method to get and set values to a collection // The value/s can optionally be executed if it's a function access: function( elems, key, value, exec, fn, pass ) { var length = elems.length; // Setting many attributes if ( typeof key === "object" ) { for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value ); } return elems; } // Setting one attribute if ( value !== undefined ) { // Optionally, function values get executed if exec is true exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; } // Getting an attribute return length ? fn( elems[0], key ) : undefined; }, now: function() { return ( new Date() ).getTime(); }, // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { ua = ua.toLowerCase(); var match = rwebkit.exec( ua ) || ropera.exec( ua ) || rmsie.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || []; return { browser: match[1] || "", version: match[2] || "0" }; }, sub: function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; }, browser: {} }); // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); browserMatch = jQuery.uaMatch( userAgent ); if ( browserMatch.browser ) { jQuery.browser[ browserMatch.browser ] = true; jQuery.browser.version = browserMatch.version; } // Deprecated, use jQuery.browser.webkit instead if ( jQuery.browser.webkit ) { jQuery.browser.safari = true; } // IE doesn't match non-breaking spaces with \s if ( rnotwhite.test( "\xA0" ) ) { trimLeft = /^[\s\xA0]+/; trimRight = /[\s\xA0]+$/; } // All jQuery objects should point back to these rootjQuery = jQuery(document); // Cleanup functions for the document ready method if ( document.addEventListener ) { DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); }; } else if ( document.attachEvent ) { DOMContentLoaded = function() { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", DOMContentLoaded ); jQuery.ready(); } }; } // The DOM ready check for Internet Explorer function doScrollCheck() { if ( jQuery.isReady ) { return; } try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch(e) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions jQuery.ready(); } return jQuery; })(); // String to Object flags format cache var flagsCache = {}; // Convert String-formatted flags into Object-formatted ones and store in cache function createFlags( flags ) { var object = flagsCache[ flags ] = {}, i, length; flags = flags.split( /\s+/ ); for ( i = 0, length = flags.length; i < length; i++ ) { object[ flags[i] ] = true; } return object; } /* * Create a callback list using the following parameters: * * flags: an optional list of space-separated flags that will change how * the callback list behaves * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible flags: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( flags ) { // Convert flags from String-formatted to Object-formatted // (we check in cache first) flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; var // Actual callback list list = [], // Stack of fire calls for repeatable lists stack = [], // Last fire value (for non-forgettable lists) memory, // Flag to know if list is currently firing firing, // First callback to fire (used internally by add and fireWith) firingStart, // End of the loop when firing firingLength, // Index of currently firing callback (modified by remove if needed) firingIndex, // Add one or several callbacks to the list add = function( args ) { var i, length, elem, type, actual; for ( i = 0, length = args.length; i < length; i++ ) { elem = args[ i ]; type = jQuery.type( elem ); if ( type === "array" ) { // Inspect recursively add( elem ); } else if ( type === "function" ) { // Add if not in unique mode and callback is not in if ( !flags.unique || !self.has( elem ) ) { list.push( elem ); } } } }, // Fire callbacks fire = function( context, args ) { args = args || []; memory = !flags.memory || [ context, args ]; firing = true; firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; for ( ; list && firingIndex < firingLength; firingIndex++ ) { if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { memory = true; // Mark as halted break; } } firing = false; if ( list ) { if ( !flags.once ) { if ( stack && stack.length ) { memory = stack.shift(); self.fireWith( memory[ 0 ], memory[ 1 ] ); } } else if ( memory === true ) { self.disable(); } else { list = []; } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { var length = list.length; add( arguments ); // Do we need to add the callbacks to the // current firing batch? if ( firing ) { firingLength = list.length; // With memory, if we're not firing then // we should call right away, unless previous // firing was halted (stopOnFalse) } else if ( memory && memory !== true ) { firingStart = length; fire( memory[ 0 ], memory[ 1 ] ); } } return this; }, // Remove a callback from the list remove: function() { if ( list ) { var args = arguments, argIndex = 0, argLength = args.length; for ( ; argIndex < argLength ; argIndex++ ) { for ( var i = 0; i < list.length; i++ ) { if ( args[ argIndex ] === list[ i ] ) { // Handle firingIndex and firingLength if ( firing ) { if ( i <= firingLength ) { firingLength--; if ( i <= firingIndex ) { firingIndex--; } } } // Remove the element list.splice( i--, 1 ); // If we have some unicity property then // we only need to do this once if ( flags.unique ) { break; } } } } } return this; }, // Control if a given callback is in the list has: function( fn ) { if ( list ) { var i = 0, length = list.length; for ( ; i < length; i++ ) { if ( fn === list[ i ] ) { return true; } } } return false; }, // Remove all callbacks from the list empty: function() { list = []; return this; }, // Have the list do nothing anymore disable: function() { list = stack = memory = undefined; return this; }, // Is it disabled? disabled: function() { return !list; }, // Lock the list in its current state lock: function() { stack = undefined; if ( !memory || memory === true ) { self.disable(); } return this; }, // Is it locked? locked: function() { return !stack; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( stack ) { if ( firing ) { if ( !flags.once ) { stack.push( [ context, args ] ); } } else if ( !( flags.once && memory ) ) { fire( context, args ); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!memory; } }; return self; }; var // Static reference to slice sliceDeferred = [].slice; jQuery.extend({ Deferred: function( func ) { var doneList = jQuery.Callbacks( "once memory" ), failList = jQuery.Callbacks( "once memory" ), progressList = jQuery.Callbacks( "memory" ), state = "pending", lists = { resolve: doneList, reject: failList, notify: progressList }, promise = { done: doneList.add, fail: failList.add, progress: progressList.add, state: function() { return state; }, // Deprecated isResolved: doneList.fired, isRejected: failList.fired, then: function( doneCallbacks, failCallbacks, progressCallbacks ) { deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); return this; }, always: function() { deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); return this; }, pipe: function( fnDone, fnFail, fnProgress ) { return jQuery.Deferred(function( newDefer ) { jQuery.each( { done: [ fnDone, "resolve" ], fail: [ fnFail, "reject" ], progress: [ fnProgress, "notify" ] }, function( handler, data ) { var fn = data[ 0 ], action = data[ 1 ], returned; if ( jQuery.isFunction( fn ) ) { deferred[ handler ](function() { returned = fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); } else { newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); } }); } else { deferred[ handler ]( newDefer[ action ] ); } }); }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { if ( obj == null ) { obj = promise; } else { for ( var key in promise ) { obj[ key ] = promise[ key ]; } } return obj; } }, deferred = promise.promise({}), key; for ( key in lists ) { deferred[ key ] = lists[ key ].fire; deferred[ key + "With" ] = lists[ key ].fireWith; } // Handle state deferred.done( function() { state = "resolved"; }, failList.disable, progressList.lock ).fail( function() { state = "rejected"; }, doneList.disable, progressList.lock ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper when: function( firstParam ) { var args = sliceDeferred.call( arguments, 0 ), i = 0, length = args.length, pValues = new Array( length ), count = length, pCount = length, deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? firstParam : jQuery.Deferred(), promise = deferred.promise(); function resolveFunc( i ) { return function( value ) { args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; if ( !( --count ) ) { deferred.resolveWith( deferred, args ); } }; } function progressFunc( i ) { return function( value ) { pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; deferred.notifyWith( promise, pValues ); }; } if ( length > 1 ) { for ( ; i < length; i++ ) { if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); } else { --count; } } if ( !count ) { deferred.resolveWith( deferred, args ); } } else if ( deferred !== firstParam ) { deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); } return promise; } }); jQuery.support = (function() { var support, all, a, select, opt, input, marginDiv, fragment, tds, events, eventName, i, isSupported, div = document.createElement( "div" ), documentElement = document.documentElement; // Preliminary tests div.setAttribute("className", "t"); div.innerHTML = "
              a"; all = div.getElementsByTagName( "*" ); a = div.getElementsByTagName( "a" )[ 0 ]; // Can't get basic test support if ( !all || !all.length || !a ) { return {}; } // First batch of supports tests select = document.createElement( "select" ); opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName( "input" )[ 0 ]; support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: ( div.firstChild.nodeType === 3 ), // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables tbody: !div.getElementsByTagName("tbody").length, // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName("link").length, // Get the style information from getAttribute // (IE uses .cssText instead) style: /top/.test( a.getAttribute("style") ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) hrefNormalized: ( a.getAttribute("href") === "/a" ), // Make sure that element opacity exists // (IE uses filter instead) // Use a regex to work around a WebKit issue. See #5145 opacity: /^0.55/.test( a.style.opacity ), // Verify style float existence // (IE uses styleFloat instead of cssFloat) cssFloat: !!a.style.cssFloat, // Make sure that if no value is specified for a checkbox // that it defaults to "on". // (WebKit defaults to "" instead) checkOn: ( input.value === "on" ), // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: opt.selected, // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) getSetAttribute: div.className !== "t", // Tests for enctype support on a form(#6743) enctype: !!document.createElement("form").enctype, // Makes sure cloning an html5 element does not cause problems // Where outerHTML is undefined, this still works html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", // Will be defined later submitBubbles: true, changeBubbles: true, focusinBubbles: false, deleteExpando: true, noCloneEvent: true, inlineBlockNeedsLayout: false, shrinkWrapBlocks: false, reliableMarginRight: true }; // Make sure checked status is properly cloned input.checked = true; support.noCloneChecked = input.cloneNode( true ).checked; // Make sure that the options inside disabled selects aren't marked as disabled // (WebKit marks them as disabled) select.disabled = true; support.optDisabled = !opt.disabled; // Test to see if it's possible to delete an expando from an element // Fails in Internet Explorer try { delete div.test; } catch( e ) { support.deleteExpando = false; } if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { div.attachEvent( "onclick", function() { // Cloning a node shouldn't copy over any // bound event handlers (IE does this) support.noCloneEvent = false; }); div.cloneNode( true ).fireEvent( "onclick" ); } // Check if a radio maintains its value // after being appended to the DOM input = document.createElement("input"); input.value = "t"; input.setAttribute("type", "radio"); support.radioValue = input.value === "t"; input.setAttribute("checked", "checked"); div.appendChild( input ); fragment = document.createDocumentFragment(); fragment.appendChild( div.lastChild ); // WebKit doesn't clone checked state correctly in fragments support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; // Check if a disconnected checkbox will retain its checked // value of true after appended to the DOM (IE6/7) support.appendChecked = input.checked; fragment.removeChild( input ); fragment.appendChild( div ); div.innerHTML = ""; // Check if div with explicit width and no margin-right incorrectly // gets computed margin-right based on width of container. For more // info see bug #3333 // Fails in WebKit before Feb 2011 nightlies // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right if ( window.getComputedStyle ) { marginDiv = document.createElement( "div" ); marginDiv.style.width = "0"; marginDiv.style.marginRight = "0"; div.style.width = "2px"; div.appendChild( marginDiv ); support.reliableMarginRight = ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; } // Technique from Juriy Zaytsev // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ // We only care about the case where non-standard event systems // are used, namely in IE. Short-circuiting here helps us to // avoid an eval call (in setAttribute) which can cause CSP // to go haywire. See: https://developer.mozilla.org/en/Security/CSP if ( div.attachEvent ) { for( i in { submit: 1, change: 1, focusin: 1 }) { eventName = "on" + i; isSupported = ( eventName in div ); if ( !isSupported ) { div.setAttribute( eventName, "return;" ); isSupported = ( typeof div[ eventName ] === "function" ); } support[ i + "Bubbles" ] = isSupported; } } fragment.removeChild( div ); // Null elements to avoid leaks in IE fragment = select = opt = marginDiv = div = input = null; // Run tests that need a body at doc ready jQuery(function() { var container, outer, inner, table, td, offsetSupport, conMarginTop, ptlm, vb, style, html, body = document.getElementsByTagName("body")[0]; if ( !body ) { // Return for frameset docs that don't have a body return; } conMarginTop = 1; ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; vb = "visibility:hidden;border:0;"; style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; html = "
              " + "" + "
              "; container = document.createElement("div"); container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; body.insertBefore( container, body.firstChild ); // Construct the test element div = document.createElement("div"); container.appendChild( div ); // Check if table cells still have offsetWidth/Height when they are set // to display:none and there are still other visible table cells in a // table row; if so, offsetWidth/Height are not reliable for use when // determining if an element has been hidden directly using // display:none (it is still safe to use offsets if a parent element is // hidden; don safety goggles and see bug #4512 for more information). // (only IE 8 fails this test) div.innerHTML = "
              t
              "; tds = div.getElementsByTagName( "td" ); isSupported = ( tds[ 0 ].offsetHeight === 0 ); tds[ 0 ].style.display = ""; tds[ 1 ].style.display = "none"; // Check if empty table cells still have offsetWidth/Height // (IE <= 8 fail this test) support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); // Figure out if the W3C box model works as expected div.innerHTML = ""; div.style.width = div.style.paddingLeft = "1px"; jQuery.boxModel = support.boxModel = div.offsetWidth === 2; if ( typeof div.style.zoom !== "undefined" ) { // Check if natively block-level elements act like inline-block // elements when setting their display to 'inline' and giving // them layout // (IE < 8 does this) div.style.display = "inline"; div.style.zoom = 1; support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); // Check if elements with layout shrink-wrap their children // (IE 6 does this) div.style.display = ""; div.innerHTML = "
              "; support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); } div.style.cssText = ptlm + vb; div.innerHTML = html; outer = div.firstChild; inner = outer.firstChild; td = outer.nextSibling.firstChild.firstChild; offsetSupport = { doesNotAddBorder: ( inner.offsetTop !== 5 ), doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) }; inner.style.position = "fixed"; inner.style.top = "20px"; // safari subtracts parent border width here which is 5px offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); inner.style.position = inner.style.top = ""; outer.style.overflow = "hidden"; outer.style.position = "relative"; offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); body.removeChild( container ); div = container = null; jQuery.extend( support, offsetSupport ); }); return support; })(); var rbrace = /^(?:\{.*\}|\[.*\])$/, rmultiDash = /([A-Z])/g; jQuery.extend({ cache: {}, // Please use with caution uuid: 0, // Unique for each copy of jQuery on the page // Non-digits removed to match rinlinejQuery expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), // The following elements throw uncatchable exceptions if you // attempt to add expando properties to them. noData: { "embed": true, // Ban all objects except for Flash (which handle expandos) "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", "applet": true }, hasData: function( elem ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; return !!elem && !isEmptyDataObject( elem ); }, data: function( elem, name, data, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var privateCache, thisCache, ret, internalKey = jQuery.expando, getByName = typeof name === "string", // We have to handle DOM nodes and JS objects differently because IE6-7 // can't GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // Only DOM nodes need the global jQuery cache; JS object data is // attached directly to the object so GC can occur automatically cache = isNode ? jQuery.cache : elem, // Only defining an ID for JS objects if its cache already exists allows // the code to shortcut on the same path as a DOM node with no cache id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, isEvents = name === "events"; // Avoid doing any more work than we need to when trying to get data on an // object that has no data at all if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { return; } if ( !id ) { // Only DOM nodes need a new unique ID for each element since their data // ends up in the global cache if ( isNode ) { elem[ internalKey ] = id = ++jQuery.uuid; } else { id = internalKey; } } if ( !cache[ id ] ) { cache[ id ] = {}; // Avoids exposing jQuery metadata on plain JS objects when the object // is serialized using JSON.stringify if ( !isNode ) { cache[ id ].toJSON = jQuery.noop; } } // An object can be passed to jQuery.data instead of a key/value pair; this gets // shallow copied over onto the existing cache if ( typeof name === "object" || typeof name === "function" ) { if ( pvt ) { cache[ id ] = jQuery.extend( cache[ id ], name ); } else { cache[ id ].data = jQuery.extend( cache[ id ].data, name ); } } privateCache = thisCache = cache[ id ]; // jQuery data() is stored in a separate object inside the object's internal data // cache in order to avoid key collisions between internal data and user-defined // data. if ( !pvt ) { if ( !thisCache.data ) { thisCache.data = {}; } thisCache = thisCache.data; } if ( data !== undefined ) { thisCache[ jQuery.camelCase( name ) ] = data; } // Users should not attempt to inspect the internal events object using jQuery.data, // it is undocumented and subject to change. But does anyone listen? No. if ( isEvents && !thisCache[ name ] ) { return privateCache.events; } // Check for both converted-to-camel and non-converted data property names // If a data property was specified if ( getByName ) { // First Try to find as-is property data ret = thisCache[ name ]; // Test for null|undefined property data if ( ret == null ) { // Try to find the camelCased property ret = thisCache[ jQuery.camelCase( name ) ]; } } else { ret = thisCache; } return ret; }, removeData: function( elem, name, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var thisCache, i, l, // Reference to internal data cache key internalKey = jQuery.expando, isNode = elem.nodeType, // See jQuery.data for more information cache = isNode ? jQuery.cache : elem, // See jQuery.data for more information id = isNode ? elem[ internalKey ] : internalKey; // If there is already no cache entry for this object, there is no // purpose in continuing if ( !cache[ id ] ) { return; } if ( name ) { thisCache = pvt ? cache[ id ] : cache[ id ].data; if ( thisCache ) { // Support array or space separated string names for data keys if ( !jQuery.isArray( name ) ) { // try the string as a key before any manipulation if ( name in thisCache ) { name = [ name ]; } else { // split the camel cased version by spaces unless a key with the spaces exists name = jQuery.camelCase( name ); if ( name in thisCache ) { name = [ name ]; } else { name = name.split( " " ); } } } for ( i = 0, l = name.length; i < l; i++ ) { delete thisCache[ name[i] ]; } // If there is no data left in the cache, we want to continue // and let the cache object itself get destroyed if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { return; } } } // See jQuery.data for more information if ( !pvt ) { delete cache[ id ].data; // Don't destroy the parent cache unless the internal data object // had been the only thing left in it if ( !isEmptyDataObject(cache[ id ]) ) { return; } } // Browsers that fail expando deletion also refuse to delete expandos on // the window, but it will allow it on all other JS objects; other browsers // don't care // Ensure that `cache` is not a window object #10080 if ( jQuery.support.deleteExpando || !cache.setInterval ) { delete cache[ id ]; } else { cache[ id ] = null; } // We destroyed the cache and need to eliminate the expando on the node to avoid // false lookups in the cache for entries that no longer exist if ( isNode ) { // IE does not allow us to delete expando properties from nodes, // nor does it have a removeAttribute function on Document nodes; // we must handle all of these cases if ( jQuery.support.deleteExpando ) { delete elem[ internalKey ]; } else if ( elem.removeAttribute ) { elem.removeAttribute( internalKey ); } else { elem[ internalKey ] = null; } } }, // For internal use only. _data: function( elem, name, data ) { return jQuery.data( elem, name, data, true ); }, // A method for determining if a DOM node can handle the data expando acceptData: function( elem ) { if ( elem.nodeName ) { var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; if ( match ) { return !(match === true || elem.getAttribute("classid") !== match); } } return true; } }); jQuery.fn.extend({ data: function( key, value ) { var parts, attr, name, data = null; if ( typeof key === "undefined" ) { if ( this.length ) { data = jQuery.data( this[0] ); if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { attr = this[0].attributes; for ( var i = 0, l = attr.length; i < l; i++ ) { name = attr[i].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.substring(5) ); dataAttr( this[0], name, data[ name ] ); } } jQuery._data( this[0], "parsedAttrs", true ); } } return data; } else if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } parts = key.split("."); parts[1] = parts[1] ? "." + parts[1] : ""; if ( value === undefined ) { data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); // Try to fetch any internally stored data first if ( data === undefined && this.length ) { data = jQuery.data( this[0], key ); data = dataAttr( this[0], key, data ); } return data === undefined && parts[1] ? this.data( parts[0] ) : data; } else { return this.each(function() { var self = jQuery( this ), args = [ parts[0], value ]; self.triggerHandler( "setData" + parts[1] + "!", args ); jQuery.data( this, key, value ); self.triggerHandler( "changeData" + parts[1] + "!", args ); }); } }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); function dataAttr( elem, key, data ) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : jQuery.isNumeric( data ) ? parseFloat( data ) : rbrace.test( data ) ? jQuery.parseJSON( data ) : data; } catch( e ) {} // Make sure we set the data so it isn't changed later jQuery.data( elem, key, data ); } else { data = undefined; } } return data; } // checks a cache object for emptiness function isEmptyDataObject( obj ) { for ( var name in obj ) { // if the public data object is empty, the private is still empty if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { continue; } if ( name !== "toJSON" ) { return false; } } return true; } function handleQueueMarkDefer( elem, type, src ) { var deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", defer = jQuery._data( elem, deferDataKey ); if ( defer && ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { // Give room for hard-coded callbacks to fire first // and eventually mark/queue something else on the element setTimeout( function() { if ( !jQuery._data( elem, queueDataKey ) && !jQuery._data( elem, markDataKey ) ) { jQuery.removeData( elem, deferDataKey, true ); defer.fire(); } }, 0 ); } } jQuery.extend({ _mark: function( elem, type ) { if ( elem ) { type = ( type || "fx" ) + "mark"; jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); } }, _unmark: function( force, elem, type ) { if ( force !== true ) { type = elem; elem = force; force = false; } if ( elem ) { type = type || "fx"; var key = type + "mark", count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); if ( count ) { jQuery._data( elem, key, count ); } else { jQuery.removeData( elem, key, true ); handleQueueMarkDefer( elem, type, "mark" ); } } }, queue: function( elem, type, data ) { var q; if ( elem ) { type = ( type || "fx" ) + "queue"; q = jQuery._data( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !q || jQuery.isArray(data) ) { q = jQuery._data( elem, type, jQuery.makeArray(data) ); } else { q.push( data ); } } return q || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), fn = queue.shift(), hooks = {}; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift( "inprogress" ); } jQuery._data( elem, type + ".run", hooks ); fn.call( elem, function() { jQuery.dequeue( elem, type ); }, hooks ); } if ( !queue.length ) { jQuery.removeData( elem, type + "queue " + type + ".run", true ); handleQueueMarkDefer( elem, type, "queue" ); } } }); jQuery.fn.extend({ queue: function( type, data ) { if ( typeof type !== "string" ) { data = type; type = "fx"; } if ( data === undefined ) { return jQuery.queue( this[0], type ); } return this.each(function() { var queue = jQuery.queue( this, type, data ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; return this.queue( type, function( next, hooks ) { var timeout = setTimeout( next, time ); hooks.stop = function() { clearTimeout( timeout ); }; }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, object ) { if ( typeof type !== "string" ) { object = type; type = undefined; } type = type || "fx"; var defer = jQuery.Deferred(), elements = this, i = elements.length, count = 1, deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", tmp; function resolve() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } } while( i-- ) { if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { count++; tmp.add( resolve ); } } resolve(); return defer.promise(); } }); var rclass = /[\n\t\r]/g, rspace = /\s+/, rreturn = /\r/g, rtype = /^(?:button|input)$/i, rfocusable = /^(?:button|input|object|select|textarea)$/i, rclickable = /^a(?:rea)?$/i, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, getSetAttribute = jQuery.support.getSetAttribute, nodeHook, boolHook, fixSpecified; jQuery.fn.extend({ attr: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.attr ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); }, prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { // try/catch handles cases where IE balks (such as removing a property on window) try { this[ name ] = undefined; delete this[ name ]; } catch( e ) {} }); }, addClass: function( value ) { var classNames, i, l, elem, setClass, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.call(this, j, this.className) ); }); } if ( value && typeof value === "string" ) { classNames = value.split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 ) { if ( !elem.className && classNames.length === 1 ) { elem.className = value; } else { setClass = " " + elem.className + " "; for ( c = 0, cl = classNames.length; c < cl; c++ ) { if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { setClass += classNames[ c ] + " "; } } elem.className = jQuery.trim( setClass ); } } } } return this; }, removeClass: function( value ) { var classNames, i, l, elem, className, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).removeClass( value.call(this, j, this.className) ); }); } if ( (value && typeof value === "string") || value === undefined ) { classNames = ( value || "" ).split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 && elem.className ) { if ( value ) { className = (" " + elem.className + " ").replace( rclass, " " ); for ( c = 0, cl = classNames.length; c < cl; c++ ) { className = className.replace(" " + classNames[ c ] + " ", " "); } elem.className = jQuery.trim( className ); } else { elem.className = ""; } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isBool = typeof stateVal === "boolean"; if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), state = stateVal, classNames = value.split( rspace ); while ( (className = classNames[ i++ ]) ) { // check each className given, space seperated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } // toggle whole className this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " ", i = 0, l = this.length; for ( ; i < l; i++ ) { if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { return true; } } return false; }, val: function( value ) { var hooks, ret, isFunction, elem = this[0]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } ret = elem.value; return typeof ret === "string" ? // handle most util string cases ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } return; } isFunction = jQuery.isFunction( value ); return this.each(function( i ) { var self = jQuery(this), val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, self.val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { val = jQuery.map(val, function ( value ) { return value == null ? "" : value + ""; }); } hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; // If set returns undefined, fall back to normal setting if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); } }); jQuery.extend({ valHooks: { option: { get: function( elem ) { // attributes.value is undefined in Blackberry 4.7 but // uses .value. See #6932 var val = elem.attributes.value; return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { var value, i, max, option, index = elem.selectedIndex, values = [], options = elem.options, one = elem.type === "select-one"; // Nothing was selected if ( index < 0 ) { return null; } // Loop through all the selected options i = one ? index : 0; max = one ? index + 1 : options.length; for ( ; i < max; i++ ) { option = options[ i ]; // Don't return options that are disabled or in a disabled optgroup if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } // Fixes Bug #2551 -- select.val() broken in IE after form.reset() if ( one && !values.length && options.length ) { return jQuery( options[ index ] ).val(); } return values; }, set: function( elem, value ) { var values = jQuery.makeArray( value ); jQuery(elem).find("option").each(function() { this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); if ( !values.length ) { elem.selectedIndex = -1; } return values; } } }, attrFn: { val: true, css: true, html: true, text: true, data: true, width: true, height: true, offset: true }, attr: function( elem, name, value, pass ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === "undefined" ) { return jQuery.prop( elem, name, value ); } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); // All attributes are lowercase // Grab necessary hook if one is defined if ( notxml ) { name = name.toLowerCase(); hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); return; } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, "" + value ); return value; } } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { ret = elem.getAttribute( name ); // Non-existent attributes return null, we normalize to undefined return ret === null ? undefined : ret; } }, removeAttr: function( elem, value ) { var propName, attrNames, name, l, i = 0; if ( value && elem.nodeType === 1 ) { attrNames = value.toLowerCase().split( rspace ); l = attrNames.length; for ( ; i < l; i++ ) { name = attrNames[ i ]; if ( name ) { propName = jQuery.propFix[ name ] || name; // See #9699 for explanation of this approach (setting first, then removal) jQuery.attr( elem, name, "" ); elem.removeAttribute( getSetAttribute ? name : propName ); // Set corresponding property to false for boolean attributes if ( rboolean.test( name ) && propName in elem ) { elem[ propName ] = false; } } } } }, attrHooks: { type: { set: function( elem, value ) { // We can't allow the type property to be changed (since it causes problems in IE) if ( rtype.test( elem.nodeName ) && elem.parentNode ) { jQuery.error( "type property can't be changed" ); } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to it's default in case type is set after value // This is for element creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } }, // Use the value property for back compat // Use the nodeHook for button elements in IE6/7 (#1954) value: { get: function( elem, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.get( elem, name ); } return name in elem ? elem.value : null; }, set: function( elem, value, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.set( elem, value, name ); } // Does not return so that setAttribute is also used elem.value = value; } } }, propFix: { tabindex: "tabIndex", readonly: "readOnly", "for": "htmlFor", "class": "className", maxlength: "maxLength", cellspacing: "cellSpacing", cellpadding: "cellPadding", rowspan: "rowSpan", colspan: "colSpan", usemap: "useMap", frameborder: "frameBorder", contenteditable: "contentEditable" }, prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { return ( elem[ name ] = value ); } } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { return elem[ name ]; } } }, propHooks: { tabIndex: { get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ var attributeNode = elem.getAttributeNode("tabindex"); return attributeNode && attributeNode.specified ? parseInt( attributeNode.value, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; } } } }); // Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; // Hook for boolean attributes boolHook = { get: function( elem, name ) { // Align boolean attributes with corresponding properties // Fall back to attribute presence where some booleans are not supported var attrNode, property = jQuery.prop( elem, name ); return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? name.toLowerCase() : undefined; }, set: function( elem, value, name ) { var propName; if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { // value is true since we know at this point it's type boolean and not false // Set boolean attributes to the same name and set the DOM property propName = jQuery.propFix[ name ] || name; if ( propName in elem ) { // Only set the IDL specifically if it already exists on the element elem[ propName ] = true; } elem.setAttribute( name, name.toLowerCase() ); } return name; } }; // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !getSetAttribute ) { fixSpecified = { name: true, id: true }; // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue nodeHook = jQuery.valHooks.button = { get: function( elem, name ) { var ret; ret = elem.getAttributeNode( name ); return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? ret.nodeValue : undefined; }, set: function( elem, value, name ) { // Set the existing or create a new attribute node var ret = elem.getAttributeNode( name ); if ( !ret ) { ret = document.createAttribute( name ); elem.setAttributeNode( ret ); } return ( ret.nodeValue = value + "" ); } }; // Apply the nodeHook to tabindex jQuery.attrHooks.tabindex.set = nodeHook.set; // Set width and height to auto instead of 0 on empty string( Bug #8150 ) // This is for removals jQuery.each([ "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { set: function( elem, value ) { if ( value === "" ) { elem.setAttribute( name, "auto" ); return value; } } }); }); // Set contenteditable to false on removals(#10429) // Setting to empty string throws an error as an invalid value jQuery.attrHooks.contenteditable = { get: nodeHook.get, set: function( elem, value, name ) { if ( value === "" ) { value = "false"; } nodeHook.set( elem, value, name ); } }; } // Some attributes require a special call on IE if ( !jQuery.support.hrefNormalized ) { jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { get: function( elem ) { var ret = elem.getAttribute( name, 2 ); return ret === null ? undefined : ret; } }); }); } if ( !jQuery.support.style ) { jQuery.attrHooks.style = { get: function( elem ) { // Return undefined in the case of empty string // Normalize to lowercase since IE uppercases css property names return elem.style.cssText.toLowerCase() || undefined; }, set: function( elem, value ) { return ( elem.style.cssText = "" + value ); } }; } // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !jQuery.support.optSelected ) { jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { get: function( elem ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } return null; } }); } // IE6/7 call enctype encoding if ( !jQuery.support.enctype ) { jQuery.propFix.enctype = "encoding"; } // Radios and checkboxes getter/setter if ( !jQuery.support.checkOn ) { jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { get: function( elem ) { // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified return elem.getAttribute("value") === null ? "on" : elem.value; } }; }); } jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); } } }); }); var rformElems = /^(?:textarea|input|select)$/i, rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, rhoverHack = /\bhover(\.\S+)?\b/, rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|contextmenu)|click/, rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, quickParse = function( selector ) { var quick = rquickIs.exec( selector ); if ( quick ) { // 0 1 2 3 // [ _, tag, id, class ] quick[1] = ( quick[1] || "" ).toLowerCase(); quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); } return quick; }, quickIs = function( elem, m ) { var attrs = elem.attributes || {}; return ( (!m[1] || elem.nodeName.toLowerCase() === m[1]) && (!m[2] || (attrs.id || {}).value === m[2]) && (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) ); }, hoverHack = function( events ) { return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); }; /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { add: function( elem, types, handler, data, selector ) { var elemData, eventHandle, events, t, tns, type, namespaces, handleObj, handleObjIn, quick, handlers, special; // Don't attach events to noData or text/comment nodes (allow plain objects tho) if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { return; } // Caller can pass in an object of custom data in lieu of the handler if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; } // Make sure that the handler has a unique ID, used to find/remove it later if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure and main handler, if this is the first events = elemData.events; if ( !events ) { elemData.events = events = {}; } eventHandle = elemData.handle; if ( !eventHandle ) { elemData.handle = eventHandle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events eventHandle.elem = elem; } // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); types = jQuery.trim( hoverHack(types) ).split( " " ); for ( t = 0; t < types.length; t++ ) { tns = rtypenamespace.exec( types[t] ) || []; type = tns[1]; namespaces = ( tns[2] || "" ).split( "." ).sort(); // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; // If selector defined, determine special event api type, otherwise given type type = ( selector ? special.delegateType : special.bindType ) || type; // Update special based on newly reset type special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers handleObj = jQuery.extend({ type: type, origType: tns[1], data: data, handler: handler, guid: handler.guid, selector: selector, quick: quickParse( selector ), namespace: namespaces.join(".") }, handleObjIn ); // Init the event handler queue if we're the first handlers = events[ type ]; if ( !handlers ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener/attachEvent if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add to the element's handler list, delegates in front if ( selector ) { handlers.splice( handlers.delegateCount++, 0, handleObj ); } else { handlers.push( handleObj ); } // Keep track of which events have ever been used, for event optimization jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, global: {}, // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), t, tns, type, origType, namespaces, origCount, j, events, special, handle, eventType, handleObj; if ( !elemData || !(events = elemData.events) ) { return; } // Once for each type.namespace in types; type may be omitted types = jQuery.trim( hoverHack( types || "" ) ).split(" "); for ( t = 0; t < types.length; t++ ) { tns = rtypenamespace.exec( types[t] ) || []; type = origType = tns[1]; namespaces = tns[2]; // Unbind all events (on this namespace, if provided) for the element if ( !type ) { for ( type in events ) { jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); } continue; } special = jQuery.event.special[ type ] || {}; type = ( selector? special.delegateType : special.bindType ) || type; eventType = events[ type ] || []; origCount = eventType.length; namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; // Remove matching events for ( j = 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !namespaces || namespaces.test( handleObj.namespace ) ) && ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { eventType.splice( j--, 1 ); if ( handleObj.selector ) { eventType.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( eventType.length === 0 && origCount !== eventType.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; } } // Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { handle = elemData.handle; if ( handle ) { handle.elem = null; } // removeData also checks for emptiness and clears the expando if empty // so use it instead of delete jQuery.removeData( elem, [ "events", "handle" ], true ); } }, // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { "getData": true, "setData": true, "changeData": true }, trigger: function( event, data, elem, onlyHandlers ) { // Don't do events on text and comment nodes if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { return; } // Event object or event type var type = event.type || event, namespaces = [], cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } if ( type.indexOf( "!" ) >= 0 ) { // Exclusive events trigger only for the exact event (no namespaces) type = type.slice(0, -1); exclusive = true; } if ( type.indexOf( "." ) >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { // No jQuery handlers for this event type, and it can't have inline handlers return; } // Caller can pass in an Event, Object, or just an event type string event = typeof event === "object" ? // jQuery.Event object event[ jQuery.expando ] ? event : // Object literal new jQuery.Event( type, event ) : // Just the event type (string) new jQuery.Event( type ); event.type = type; event.isTrigger = true; event.exclusive = exclusive; event.namespace = namespaces.join( "." ); event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; // Handle a global trigger if ( !elem ) { // TODO: Stop taunting the data cache; remove global events and always attach to document cache = jQuery.cache; for ( i in cache ) { if ( cache[ i ].events && cache[ i ].events[ type ] ) { jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); } } return; } // Clean up the event in case it is being reused event.result = undefined; if ( !event.target ) { event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data != null ? jQuery.makeArray( data ) : []; data.unshift( event ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) eventPath = [[ elem, special.bindType || type ]]; if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { bubbleType = special.delegateType || type; cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; old = null; for ( ; cur; cur = cur.parentNode ) { eventPath.push([ cur, bubbleType ]); old = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( old && old === elem.ownerDocument ) { eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); } } // Fire handlers on the event path for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { cur = eventPath[i][0]; event.type = eventPath[i][1]; handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } // Note that this is a bare JS function and not a jQuery handler handle = ontype && cur[ ontype ]; if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { event.preventDefault(); } } event.type = type; // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction() check here because IE6/7 fails that test. // Don't do default actions on window, that's where global variables be (#6170) // IE<9 dies on focus/blur to hidden element (#1486) if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method old = elem[ ontype ]; if ( old ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; elem[ type ](); jQuery.event.triggered = undefined; if ( old ) { elem[ ontype ] = old; } } } } return event.result; }, dispatch: function( event ) { // Make a writable jQuery.Event from the native event object event = jQuery.event.fix( event || window.event ); var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), delegateCount = handlers.delegateCount, args = [].slice.call( arguments, 0 ), run_all = !event.exclusive && !event.namespace, handlerQueue = [], i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event; event.delegateTarget = this; // Determine handlers that should run if there are delegated events // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { // Pregenerate a single jQuery object for reuse with .is() jqcur = jQuery(this); jqcur.context = this.ownerDocument || this; for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { selMatch = {}; matches = []; jqcur[0] = cur; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; sel = handleObj.selector; if ( selMatch[ sel ] === undefined ) { selMatch[ sel ] = ( handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) ); } if ( selMatch[ sel ] ) { matches.push( handleObj ); } } if ( matches.length ) { handlerQueue.push({ elem: cur, matches: matches }); } } } // Add the remaining (directly-bound) handlers if ( handlers.length > delegateCount ) { handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); } // Run delegates first; they may want to stop propagation beneath us for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { matched = handlerQueue[ i ]; event.currentTarget = matched.elem; for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { handleObj = matched.matches[ j ]; // Triggered event must either 1) be non-exclusive and have no namespace, or // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { event.data = handleObj.data; event.handleObj = handleObj; ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) .apply( matched.elem, args ); if ( ret !== undefined ) { event.result = ret; if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } } } } } return event.result; }, // Includes some event props shared by KeyEvent and MouseEvent // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, keyHooks: { props: "char charCode key keyCode".split(" "), filter: function( event, original ) { // Add which for key events if ( event.which == null ) { event.which = original.charCode != null ? original.charCode : original.keyCode; } return event; } }, mouseHooks: { props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function( event, original ) { var eventDoc, doc, body, button = original.button, fromElement = original.fromElement; // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && original.clientX != null ) { eventDoc = event.target.ownerDocument || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); } // Add relatedTarget, if necessary if ( !event.relatedTarget && fromElement ) { event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && button !== undefined ) { event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); } return event; } }, fix: function( event ) { if ( event[ jQuery.expando ] ) { return event; } // Create a writable copy of the event object and normalize some properties var i, prop, originalEvent = event, fixHook = jQuery.event.fixHooks[ event.type ] || {}, copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; event = jQuery.Event( originalEvent ); for ( i = copy.length; i; ) { prop = copy[ --i ]; event[ prop ] = originalEvent[ prop ]; } // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) if ( !event.target ) { event.target = originalEvent.srcElement || document; } // Target should not be a text node (#504, Safari) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) if ( event.metaKey === undefined ) { event.metaKey = event.ctrlKey; } return fixHook.filter? fixHook.filter( event, originalEvent ) : event; }, special: { ready: { // Make sure the ready event is setup setup: jQuery.bindReady }, load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { delegateType: "focusin" }, blur: { delegateType: "focusout" }, beforeunload: { setup: function( data, namespaces, eventHandle ) { // We only want to do this special case on windows if ( jQuery.isWindow( this ) ) { this.onbeforeunload = eventHandle; } }, teardown: function( namespaces, eventHandle ) { if ( this.onbeforeunload === eventHandle ) { this.onbeforeunload = null; } } } }, simulate: function( type, elem, event, bubble ) { // Piggyback on a donor event to simulate a different one. // Fake originalEvent to avoid donor's stopPropagation, but if the // simulated event prevents default then we do the same on the donor. var e = jQuery.extend( new jQuery.Event(), event, { type: type, isSimulated: true, originalEvent: {} } ); if ( bubble ) { jQuery.event.trigger( e, null, elem ); } else { jQuery.event.dispatch.call( elem, e ); } if ( e.isDefaultPrevented() ) { event.preventDefault(); } } }; // Some plugins are using, but it's undocumented/deprecated and will be removed. // The 1.7 special event interface should provide all the hooks needed now. jQuery.event.handle = jQuery.event.dispatch; jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, handle, false ); } } : function( elem, type, handle ) { if ( elem.detachEvent ) { elem.detachEvent( "on" + type, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; function returnFalse() { return false; } function returnTrue() { return true; } // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { preventDefault: function() { this.isDefaultPrevented = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if preventDefault exists run it on the original event if ( e.preventDefault ) { e.preventDefault(); // otherwise set the returnValue property of the original event to false (IE) } else { e.returnValue = false; } }, stopPropagation: function() { this.isPropagationStopped = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if stopPropagation exists run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // otherwise set the cancelBubble property of the original event to true (IE) e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); }, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse }; // Create mouseenter/leave events using mouseover/out and event-time checks jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { delegateType: fix, bindType: fix, handle: function( event ) { var target = this, related = event.relatedTarget, handleObj = event.handleObj, selector = handleObj.selector, ret; // For mousenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if ( !related || (related !== target && !jQuery.contains( target, related )) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; } return ret; } }; }); // IE submit delegation if ( !jQuery.support.submitBubbles ) { jQuery.event.special.submit = { setup: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Lazy-add a submit handler when a descendant form may potentially be submitted jQuery.event.add( this, "click._submit keypress._submit", function( e ) { // Node name check avoids a VML-related crash in IE (#9807) var elem = e.target, form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; if ( form && !form._submit_attached ) { jQuery.event.add( form, "submit._submit", function( event ) { // If form was submitted by the user, bubble the event up the tree if ( this.parentNode && !event.isTrigger ) { jQuery.event.simulate( "submit", this.parentNode, event, true ); } }); form._submit_attached = true; } }); // return undefined since we don't need an event listener }, teardown: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Remove delegated handlers; cleanData eventually reaps submit handlers attached above jQuery.event.remove( this, "._submit" ); } }; } // IE change delegation and checkbox/radio fix if ( !jQuery.support.changeBubbles ) { jQuery.event.special.change = { setup: function() { if ( rformElems.test( this.nodeName ) ) { // IE doesn't fire change on a check/radio until blur; trigger it on click // after a propertychange. Eat the blur-change in special.change.handle. // This still fires onchange a second time for check/radio after blur. if ( this.type === "checkbox" || this.type === "radio" ) { jQuery.event.add( this, "propertychange._change", function( event ) { if ( event.originalEvent.propertyName === "checked" ) { this._just_changed = true; } }); jQuery.event.add( this, "click._change", function( event ) { if ( this._just_changed && !event.isTrigger ) { this._just_changed = false; jQuery.event.simulate( "change", this, event, true ); } }); } return false; } // Delegated event; lazy-add a change handler on descendant inputs jQuery.event.add( this, "beforeactivate._change", function( e ) { var elem = e.target; if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { jQuery.event.add( elem, "change._change", function( event ) { if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { jQuery.event.simulate( "change", this.parentNode, event, true ); } }); elem._change_attached = true; } }); }, handle: function( event ) { var elem = event.target; // Swallow native change events from checkbox/radio, we already triggered them above if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { return event.handleObj.handler.apply( this, arguments ); } }, teardown: function() { jQuery.event.remove( this, "._change" ); return rformElems.test( this.nodeName ); } }; } // Create "bubbling" focus and blur events if ( !jQuery.support.focusinBubbles ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler while someone wants focusin/focusout var attaches = 0, handler = function( event ) { jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); }; jQuery.event.special[ fix ] = { setup: function() { if ( attaches++ === 0 ) { document.addEventListener( orig, handler, true ); } }, teardown: function() { if ( --attaches === 0 ) { document.removeEventListener( orig, handler, true ); } } }; }); } jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { var origFn, type; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data = selector; selector = undefined; } for ( type in types ) { this.on( type, selector, data, types[ type ], one ); } return this; } if ( data == null && fn == null ) { // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { // ( types, selector, fn ) fn = data; data = undefined; } else { // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { return this; } if ( one === 1 ) { origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return this.each( function() { jQuery.event.add( this, types, fn, data, selector ); }); }, one: function( types, selector, data, fn ) { return this.on.call( this, types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event var handleObj = types.handleObj; jQuery( types.delegateTarget ).off( handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { // ( types-object [, selector] ) for ( var type in types ) { this.off( type, selector, types[ type ] ); } return this; } if ( selector === false || typeof selector === "function" ) { // ( types [, fn] ) fn = selector; selector = undefined; } if ( fn === false ) { fn = returnFalse; } return this.each(function() { jQuery.event.remove( this, types, fn, selector ); }); }, bind: function( types, data, fn ) { return this.on( types, null, data, fn ); }, unbind: function( types, fn ) { return this.off( types, null, fn ); }, live: function( types, data, fn ) { jQuery( this.context ).on( types, this.selector, data, fn ); return this; }, die: function( types, fn ) { jQuery( this.context ).off( types, this.selector || "**", fn ); return this; }, delegate: function( selector, types, data, fn ) { return this.on( types, selector, data, fn ); }, undelegate: function( selector, types, fn ) { // ( namespace ) or ( selector, types [, fn] ) return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { if ( this[0] ) { return jQuery.event.trigger( type, data, this[0], true ); } }, toggle: function( fn ) { // Save reference to arguments for access in closure var args = arguments, guid = fn.guid || jQuery.guid++, i = 0, toggler = function( event ) { // Figure out which function to execute var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); // Make sure that clicks stop event.preventDefault(); // and execute the function return args[ lastToggle ].apply( this, arguments ) || false; }; // link all the functions, so any of them can unbind this click handler toggler.guid = guid; while ( i < args.length ) { args[ i++ ].guid = guid; } return this.click( toggler ); }, hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } }); jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( data, fn ) { if ( fn == null ) { fn = data; data = null; } return arguments.length > 0 ? this.on( name, null, data, fn ) : this.trigger( name ); }; if ( jQuery.attrFn ) { jQuery.attrFn[ name ] = true; } if ( rkeyEvent.test( name ) ) { jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; } if ( rmouseEvent.test( name ) ) { jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); /*! * Sizzle CSS Selector Engine * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, expando = "sizcache" + (Math.random() + '').replace('.', ''), done = 0, toString = Object.prototype.toString, hasDuplicate = false, baseHasDuplicate = true, rBackslash = /\\/g, rReturn = /\r\n/g, rNonWord = /\W/; // Here we check if the JavaScript engine is using some sort of // optimization where it does not always call our comparision // function. If that is the case, discard the hasDuplicate value. // Thus far that includes Google Chrome. [0, 0].sort(function() { baseHasDuplicate = false; return 0; }); var Sizzle = function( selector, context, results, seed ) { results = results || []; context = context || document; var origContext = context; if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } if ( !selector || typeof selector !== "string" ) { return results; } var m, set, checkSet, extra, ret, cur, pop, i, prune = true, contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); m = chunker.exec( soFar ); if ( m ) { soFar = m[3]; parts.push( m[1] ); if ( m[2] ) { extra = m[3]; break; } } } while ( m ); if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context, seed ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { selector = parts.shift(); if ( Expr.relative[ selector ] ) { selector += parts.shift(); } set = posProcess( selector, set, seed ); } } } else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { ret = Sizzle.find( parts.shift(), context, contextXML ); context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; } if ( context ) { ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; if ( parts.length > 0 ) { checkSet = makeArray( set ); } else { prune = false; } while ( parts.length ) { cur = parts.pop(); pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop, contextXML ); } } else { checkSet = parts = []; } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { Sizzle.error( cur || selector ); } if ( toString.call(checkSet) === "[object Array]" ) { if ( !prune ) { results.push.apply( results, checkSet ); } else if ( context && context.nodeType === 1 ) { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, origContext, results, seed ); Sizzle.uniqueSort( results ); } return results; }; Sizzle.uniqueSort = function( results ) { if ( sortOrder ) { hasDuplicate = baseHasDuplicate; results.sort( sortOrder ); if ( hasDuplicate ) { for ( var i = 1; i < results.length; i++ ) { if ( results[i] === results[ i - 1 ] ) { results.splice( i--, 1 ); } } } } return results; }; Sizzle.matches = function( expr, set ) { return Sizzle( expr, null, null, set ); }; Sizzle.matchesSelector = function( node, expr ) { return Sizzle( expr, null, null, [node] ).length > 0; }; Sizzle.find = function( expr, context, isXML ) { var set, i, len, match, type, left; if ( !expr ) { return []; } for ( i = 0, len = Expr.order.length; i < len; i++ ) { type = Expr.order[i]; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { left = match[1]; match.splice( 1, 1 ); if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace( rBackslash, "" ); set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( "*" ) : []; } return { set: set, expr: expr }; }; Sizzle.filter = function( expr, set, inplace, not ) { var match, anyFound, type, found, item, filter, left, i, pass, old = expr, result = [], curLoop = set, isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); while ( expr && set.length ) { for ( type in Expr.filter ) { if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { filter = Expr.filter[ type ]; left = match[1]; anyFound = false; match.splice(1,1); if ( left.substr( left.length - 1 ) === "\\" ) { continue; } if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } if ( match ) { for ( i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { found = filter( item, match, i, curLoop ); pass = not ^ found; if ( inplace && found != null ) { if ( pass ) { anyFound = true; } else { curLoop[i] = false; } } else if ( pass ) { result.push( item ); anyFound = true; } } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } // Improper expression if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } old = expr; } return curLoop; }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** * Utility function for retreiving the text value of an array of DOM nodes * @param {Array|Element} elem */ var getText = Sizzle.getText = function( elem ) { var i, node, nodeType = elem.nodeType, ret = ""; if ( nodeType ) { if ( nodeType === 1 || nodeType === 9 ) { // Use textContent || innerText for elements if ( typeof elem.textContent === 'string' ) { return elem.textContent; } else if ( typeof elem.innerText === 'string' ) { // Replace IE's carriage returns return elem.innerText.replace( rReturn, '' ); } else { // Traverse it's children for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } } else { // If no nodeType, this is expected to be an array for ( i = 0; (node = elem[i]); i++ ) { // Do not traverse comment nodes if ( node.nodeType !== 8 ) { ret += getText( node ); } } } return ret; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, leftMatch: {}, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function( elem ) { return elem.getAttribute( "href" ); }, type: function( elem ) { return elem.getAttribute( "type" ); } }, relative: { "+": function(checkSet, part){ var isPartStr = typeof part === "string", isTag = isPartStr && !rNonWord.test( part ), isPartStrNotTag = isPartStr && !isTag; if ( isTag ) { part = part.toLowerCase(); } for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { if ( (elem = checkSet[i]) ) { while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; } } if ( isPartStrNotTag ) { Sizzle.filter( part, checkSet, true ); } }, ">": function( checkSet, part ) { var elem, isPartStr = typeof part === "string", i = 0, l = checkSet.length; if ( isPartStr && !rNonWord.test( part ) ) { part = part.toLowerCase(); for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; } } } else { for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; } } if ( isPartStr ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part, isXML){ var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); }, "~": function( checkSet, part, isXML ) { var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); } }, find: { ID: function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [m] : []; } }, NAME: function( match, context ) { if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName( match[1] ); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function( match, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( match[1] ); } } }, preFilter: { CLASS: function( match, curLoop, inplace, result, not, isXML ) { match = " " + match[1].replace( rBackslash, "" ) + " "; if ( isXML ) { return match; } for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { if ( elem ) { if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { if ( !inplace ) { result.push( elem ); } } else if ( inplace ) { curLoop[i] = false; } } } return false; }, ID: function( match ) { return match[1].replace( rBackslash, "" ); }, TAG: function( match, curLoop ) { return match[1].replace( rBackslash, "" ).toLowerCase(); }, CHILD: function( match ) { if ( match[1] === "nth" ) { if ( !match[2] ) { Sizzle.error( match[0] ); } match[2] = match[2].replace(/^\+|\s*/g, ''); // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } else if ( match[2] ) { Sizzle.error( match[0] ); } // TODO: Move to normal caching system match[0] = done++; return match; }, ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } // Handle if an un-quoted value was used match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function( match, curLoop, inplace, result, not ) { if ( match[1] === "not" ) { // If we're dealing with a complex expression, or a simple one if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { match[3] = Sizzle(match[3], null, null, curLoop); } else { var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); if ( !inplace ) { result.push.apply( result, ret ); } return false; } } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } return match; }, POS: function( match ) { match.unshift( true ); return match; } }, filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; }, disabled: function( elem ) { return elem.disabled === true; }, checked: function( elem ) { return elem.checked === true; }, selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, parent: function( elem ) { return !!elem.firstChild; }, empty: function( elem ) { return !elem.firstChild; }, has: function( elem, i, match ) { return !!Sizzle( match[3], elem ).length; }, header: function( elem ) { return (/h\d/i).test( elem.nodeName ); }, text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, radio: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; }, checkbox: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; }, file: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; }, password: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; }, submit: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "submit" === elem.type; }, image: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; }, reset: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "reset" === elem.type; }, button: function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && "button" === elem.type || name === "button"; }, input: function( elem ) { return (/input|select|textarea|button/i).test( elem.nodeName ); }, focus: function( elem ) { return elem === elem.ownerDocument.activeElement; } }, setFilters: { first: function( elem, i ) { return i === 0; }, last: function( elem, i, match, array ) { return i === array.length - 1; }, even: function( elem, i ) { return i % 2 === 0; }, odd: function( elem, i ) { return i % 2 === 1; }, lt: function( elem, i, match ) { return i < match[3] - 0; }, gt: function( elem, i, match ) { return i > match[3] - 0; }, nth: function( elem, i, match ) { return match[3] - 0 === i; }, eq: function( elem, i, match ) { return match[3] - 0 === i; } }, filter: { PSEUDO: function( elem, match, i, array ) { var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var j = 0, l = not.length; j < l; j++ ) { if ( not[j] === elem ) { return false; } } return true; } else { Sizzle.error( name ); } }, CHILD: function( elem, match ) { var first, last, doneName, parent, cache, count, diff, type = match[1], node = elem; switch ( type ) { case "only": case "first": while ( (node = node.previousSibling) ) { if ( node.nodeType === 1 ) { return false; } } if ( type === "first" ) { return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { if ( node.nodeType === 1 ) { return false; } } return true; case "nth": first = match[2]; last = match[3]; if ( first === 1 && last === 0 ) { return true; } doneName = match[0]; parent = elem.parentNode; if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } } parent[ expando ] = doneName; } diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; } else { return ( diff % first === 0 && diff / first >= 0 ); } } }, ID: function( elem, match ) { return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; }, CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; }, ATTR: function( elem, match ) { var name = match[1], result = Sizzle.attr ? Sizzle.attr( elem, name ) : Expr.attrHandle[ name ] ? Expr.attrHandle[ name ]( elem ) : elem[ name ] != null ? elem[ name ] : elem.getAttribute( name ), value = result + "", type = match[2], check = match[4]; return result == null ? type === "!=" : !type && Sizzle.attr ? result != null : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function( elem, match, i, array ) { var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var origPOS = Expr.match.POS, fescape = function(all, num){ return "\\" + (num - 0 + 1); }; for ( var type in Expr.match ) { Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); } var makeArray = function( array, results ) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. // Also verifies that the returned array holds DOM nodes // (which is not the case in the Blackberry browser) try { Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; // Provide a fallback method if it does not work } catch( e ) { makeArray = function( array, results ) { var i = 0, ret = results || []; if ( toString.call(array) === "[object Array]" ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( ; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } var sortOrder, siblingCheck; if ( document.documentElement.compareDocumentPosition ) { sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; return 0; } if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { return a.compareDocumentPosition ? -1 : 1; } return a.compareDocumentPosition(b) & 4 ? -1 : 1; }; } else { sortOrder = function( a, b ) { // The nodes are identical, we can exit early if ( a === b ) { hasDuplicate = true; return 0; // Fallback to using sourceIndex (in IE) if it's available on both nodes } else if ( a.sourceIndex && b.sourceIndex ) { return a.sourceIndex - b.sourceIndex; } var al, bl, ap = [], bp = [], aup = a.parentNode, bup = b.parentNode, cur = aup; // If the nodes are siblings (or identical) we can do a quick check if ( aup === bup ) { return siblingCheck( a, b ); // If no parents were found then the nodes are disconnected } else if ( !aup ) { return -1; } else if ( !bup ) { return 1; } // Otherwise they're somewhere else in the tree so we need // to build up a full list of the parentNodes for comparison while ( cur ) { ap.unshift( cur ); cur = cur.parentNode; } cur = bup; while ( cur ) { bp.unshift( cur ); cur = cur.parentNode; } al = ap.length; bl = bp.length; // Start walking down the tree looking for a discrepancy for ( var i = 0; i < al && i < bl; i++ ) { if ( ap[i] !== bp[i] ) { return siblingCheck( ap[i], bp[i] ); } } // We ended someplace up the tree so do a sibling check return i === al ? siblingCheck( a, bp[i], -1 ) : siblingCheck( ap[i], b, 1 ); }; siblingCheck = function( a, b, ret ) { if ( a === b ) { return ret; } var cur = a.nextSibling; while ( cur ) { if ( cur === b ) { return -1; } cur = cur.nextSibling; } return 1; }; } // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("div"), id = "script" + (new Date()).getTime(), root = document.documentElement; form.innerHTML = ""; // Inject it into the root element, check its status, and remove it quickly root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( document.getElementById( id ) ) { Expr.find.ID = function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function( elem, match ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); // release memory in IE root = form = null; })(); (function(){ // Check to see if the browser returns only elements // when doing getElementsByTagName("*") // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function( match, context ) { var results = context.getElementsByTagName( match[1] ); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } // Check to see if an attribute returns normalized href attributes div.innerHTML = ""; if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#" ) { Expr.attrHandle.href = function( elem ) { return elem.getAttribute( "href", 2 ); }; } // release memory in IE div = null; })(); if ( document.querySelectorAll ) { (function(){ var oldSizzle = Sizzle, div = document.createElement("div"), id = "__sizzle__"; div.innerHTML = "

              "; // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } Sizzle = function( query, context, extra, seed ) { context = context || document; // Only use querySelectorAll on non-XML documents // (ID selectors don't work in non-HTML documents) if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } } else { return makeArray( [], extra ); } } try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { var oldContext = context, old = context.getAttribute( "id" ), nid = old || id, hasParent = context.parentNode, relativeHierarchySelector = /^\s*[+~]/.test( query ); if ( !old ) { context.setAttribute( "id", nid ); } else { nid = nid.replace( /'/g, "\\$&" ); } if ( relativeHierarchySelector && hasParent ) { context = context.parentNode; } try { if ( !relativeHierarchySelector || hasParent ) { return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); } } catch(pseudoError) { } finally { if ( !old ) { oldContext.removeAttribute( "id" ); } } } } return oldSizzle(query, context, extra, seed); }; for ( var prop in oldSizzle ) { Sizzle[ prop ] = oldSizzle[ prop ]; } // release memory in IE div = null; })(); } (function(){ var html = document.documentElement, matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; if ( matches ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9 fails this) var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), pseudoWorks = false; try { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); } catch( pseudoError ) { pseudoWorks = true; } Sizzle.matchesSelector = function( node, expr ) { // Make sure that attribute selectors are quoted expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || !disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9, so check for that node.document && node.document.nodeType !== 11 ) { return ret; } } } catch(e) {} } return Sizzle(expr, null, null, [node]).length > 0; }; } })(); (function(){ var div = document.createElement("div"); div.innerHTML = "
              "; // Opera can't find a second classname (in 9.6) // Also, make sure that getElementsByClassName actually exists if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { return; } // Safari caches class attributes, doesn't catch changes (in 3.2) div.lastChild.className = "e"; if ( div.getElementsByClassName("e").length === 1 ) { return; } Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { return context.getElementsByClassName(match[1]); } }; // release memory in IE div = null; })(); function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem[ expando ] === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 && !isXML ){ elem[ expando ] = doneName; elem.sizset = i; } if ( elem.nodeName.toLowerCase() === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem[ expando ] === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 ) { if ( !isXML ) { elem[ expando ] = doneName; elem.sizset = i; } if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } if ( document.documentElement.contains ) { Sizzle.contains = function( a, b ) { return a !== b && (a.contains ? a.contains(b) : true); }; } else if ( document.documentElement.compareDocumentPosition ) { Sizzle.contains = function( a, b ) { return !!(a.compareDocumentPosition(b) & 16); }; } else { Sizzle.contains = function() { return false; }; } Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; var posProcess = function( selector, context, seed ) { var match, tmpSet = [], later = "", root = context.nodeType ? [context] : context; // Position selectors must be done after the filter // And so must :not(positional) so we move all PSEUDOs to the end while ( (match = Expr.match.PSEUDO.exec( selector )) ) { later += match[0]; selector = selector.replace( Expr.match.PSEUDO, "" ); } selector = Expr.relative[selector] ? selector + "*" : selector; for ( var i = 0, l = root.length; i < l; i++ ) { Sizzle( selector, root[i], tmpSet, seed ); } return Sizzle.filter( later, tmpSet ); }; // EXPOSE // Override sizzle attribute retrieval Sizzle.attr = jQuery.attr; Sizzle.selectors.attrMap = {}; jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; })(); var runtil = /Until$/, rparentsprev = /^(?:parents|prevUntil|prevAll)/, // Note: This RegExp should be improved, or likely pulled from Sizzle rmultiselector = /,/, isSimple = /^.[^:#\[\.,]*$/, slice = Array.prototype.slice, POS = jQuery.expr.match.POS, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend({ find: function( selector ) { var self = this, i, l; if ( typeof selector !== "string" ) { return jQuery( selector ).filter(function() { for ( i = 0, l = self.length; i < l; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }); } var ret = this.pushStack( "", "find", selector ), length, n, r; for ( i = 0, l = this.length; i < l; i++ ) { length = ret.length; jQuery.find( selector, this[i], ret ); if ( i > 0 ) { // Make sure that the results are unique for ( n = length; n < ret.length; n++ ) { for ( r = 0; r < length; r++ ) { if ( ret[r] === ret[n] ) { ret.splice(n--, 1); break; } } } } } return ret; }, has: function( target ) { var targets = jQuery( target ); return this.filter(function() { for ( var i = 0, l = targets.length; i < l; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, not: function( selector ) { return this.pushStack( winnow(this, selector, false), "not", selector); }, filter: function( selector ) { return this.pushStack( winnow(this, selector, true), "filter", selector ); }, is: function( selector ) { return !!selector && ( typeof selector === "string" ? // If this is a positional selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". POS.test( selector ) ? jQuery( selector, this.context ).index( this[0] ) >= 0 : jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); }, closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; // Array (deprecated as of jQuery 1.7) if ( jQuery.isArray( selectors ) ) { var level = 1; while ( cur && cur.ownerDocument && cur !== context ) { for ( i = 0; i < selectors.length; i++ ) { if ( jQuery( cur ).is( selectors[ i ] ) ) { ret.push({ selector: selectors[ i ], elem: cur, level: level }); } } cur = cur.parentNode; level++; } return ret; } // String var pos = POS.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors, context || this.context ) : 0; for ( i = 0, l = this.length; i < l; i++ ) { cur = this[i]; while ( cur ) { if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { ret.push( cur ); break; } else { cur = cur.parentNode; if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { break; } } } } ret = ret.length > 1 ? jQuery.unique( ret ) : ret; return this.pushStack( ret, "closest", selectors ); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; } // index in selector if ( typeof elem === "string" ) { return jQuery.inArray( this[0], jQuery( elem ) ); } // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem, this ); }, add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? all : jQuery.unique( all ) ); }, andSelf: function() { return this.add( this.prevObject ); } }); // A painfully simple check to see if an element is disconnected // from a document (should be improved, where feasible). function isDisconnected( node ) { return !node || !node.parentNode || node.parentNode.nodeType === 11; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return jQuery.nth( elem, 2, "nextSibling" ); }, prev: function( elem ) { return jQuery.nth( elem, 2, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( elem.parentNode.firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.makeArray( elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ); if ( !runtil.test( name ) ) { selector = until; } if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); } ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { ret = ret.reverse(); } return this.pushStack( ret, name, slice.call( arguments ).join(",") ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { if ( not ) { expr = ":not(" + expr + ")"; } return elems.length === 1 ? jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : jQuery.find.matches(expr, elems); }, dir: function( elem, dir, until ) { var matched = [], cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, nth: function( cur, result, dir, elem ) { result = result || 1; var num = 0; for ( ; cur; cur = cur[dir] ) { if ( cur.nodeType === 1 && ++num === result ) { break; } } return cur; }, sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } }); // Implement the identical functionality for filter and not function winnow( elements, qualifier, keep ) { // Can't pass null or undefined to indexOf in Firefox 4 // Set to 0 to skip string check qualifier = qualifier || 0; if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep(elements, function( elem, i ) { var retVal = !!qualifier.call( elem, i, elem ); return retVal === keep; }); } else if ( qualifier.nodeType ) { return jQuery.grep(elements, function( elem, i ) { return ( elem === qualifier ) === keep; }); } else if ( typeof qualifier === "string" ) { var filtered = jQuery.grep(elements, function( elem ) { return elem.nodeType === 1; }); if ( isSimple.test( qualifier ) ) { return jQuery.filter(qualifier, filtered, !keep); } else { qualifier = jQuery.filter( qualifier, filtered ); } } return jQuery.grep(elements, function( elem, i ) { return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; }); } function createSafeFragment( document ) { var list = nodeNames.split( "|" ), safeFrag = document.createDocumentFragment(); if ( safeFrag.createElement ) { while ( list.length ) { safeFrag.createElement( list.pop() ); } } return safeFrag; } var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, rtagName = /<([\w:]+)/, rtbody = /", "" ], legend: [ 1, "
              ", "
              " ], thead: [ 1, "", "
              " ], tr: [ 2, "", "
              " ], td: [ 3, "", "
              " ], col: [ 2, "", "
              " ], area: [ 1, "", "" ], _default: [ 0, "", "" ] }, safeFragment = createSafeFragment( document ); wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; // IE can't serialize and
              Snippet:
              Directive How Source Rendered
              ng-bind-html Automatically uses $sanitize
              <div ng-bind-html="snippet">
              </div>
              ng-bind-html Bypass $sanitize by explicitly trusting the dangerous value
              <div ng-bind-html="deliberatelyTrustDangerousSnippet()">
              </div>
              ng-bind Automatically escapes
              <div ng-bind="snippet">
              </div>
              it('should sanitize the html snippet by default', function() { expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). toBe('

              an html\nclick here\nsnippet

              '); }); it('should inline raw snippet if bound to a trusted value', function() { expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). toBe("

              an html\n" + "click here\n" + "snippet

              "); }); it('should escape snippet without any filter', function() { expect(element(by.css('#bind-default div')).getInnerHtml()). toBe("<p style=\"color:blue\">an html\n" + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + "snippet</p>"); }); it('should update', function() { element(by.model('snippet')).clear(); element(by.model('snippet')).sendKeys('new text'); expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). toBe('new text'); expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( 'new text'); expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( "new <b onclick=\"alert(1)\">text</b>"); });
              */ function $SanitizeProvider() { this.$get = ['$$sanitizeUri', function($$sanitizeUri) { return function(html) { var buf = []; htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { return !/^unsafe/.test($$sanitizeUri(uri, isImage)); })); return buf.join(''); }; }]; } function sanitizeText(chars) { var buf = []; var writer = htmlSanitizeWriter(buf, angular.noop); writer.chars(chars); return buf.join(''); } // Regular Expressions for parsing tags and attributes var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, BEGIN_TAG_REGEXP = /^/g, DOCTYPE_REGEXP = /]*?)>/i, CDATA_REGEXP = //g, // Match everything outside of normal chars and " (quote character) NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Good source of info about elements and attributes // http://dev.w3.org/html5/spec/Overview.html#semantics // http://simon.html5.org/html-elements // Safe Void Elements - HTML5 // http://dev.w3.org/html5/spec/Overview.html#void-elements var voidElements = makeMap("area,br,col,hr,img,wbr"); // Elements that you can, intentionally, leave open (and which close themselves) // http://dev.w3.org/html5/spec/Overview.html#optional-tags var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), optionalEndTagInlineElements = makeMap("rp,rt"), optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements); // Safe Block Elements - HTML5 var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); // Inline Elements - HTML5 var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); // Special Elements (can contain anything) var specialElements = makeMap("script,style"); var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements); //Attributes that have href and hence need to be sanitized var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); var validAttrs = angular.extend({}, uriAttrs, makeMap( 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+ 'valign,value,vspace,width')); function makeMap(str) { var obj = {}, items = str.split(','), i; for (i = 0; i < items.length; i++) obj[items[i]] = true; return obj; } /** * @example * htmlParser(htmlString, { * start: function(tag, attrs, unary) {}, * end: function(tag) {}, * chars: function(text) {}, * comment: function(text) {} * }); * * @param {string} html string * @param {object} handler */ function htmlParser( html, handler ) { var index, chars, match, stack = [], last = html; stack.last = function() { return stack[ stack.length - 1 ]; }; while ( html ) { chars = true; // Make sure we're not in a script or style element if ( !stack.last() || !specialElements[ stack.last() ] ) { // Comment if ( html.indexOf("", index) === index) { if (handler.comment) handler.comment( html.substring( 4, index ) ); html = html.substring( index + 3 ); chars = false; } // DOCTYPE } else if ( DOCTYPE_REGEXP.test(html) ) { match = html.match( DOCTYPE_REGEXP ); if ( match ) { html = html.replace( match[0] , ''); chars = false; } // end tag } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { match = html.match( END_TAG_REGEXP ); if ( match ) { html = html.substring( match[0].length ); match[0].replace( END_TAG_REGEXP, parseEndTag ); chars = false; } // start tag } else if ( BEGIN_TAG_REGEXP.test(html) ) { match = html.match( START_TAG_REGEXP ); if ( match ) { html = html.substring( match[0].length ); match[0].replace( START_TAG_REGEXP, parseStartTag ); chars = false; } } if ( chars ) { index = html.indexOf("<"); var text = index < 0 ? html : html.substring( 0, index ); html = index < 0 ? "" : html.substring( index ); if (handler.chars) handler.chars( decodeEntities(text) ); } } else { html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){ text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); if (handler.chars) handler.chars( decodeEntities(text) ); return ""; }); parseEndTag( "", stack.last() ); } if ( html == last ) { throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + "of html: {0}", html); } last = html; } // Clean up any remaining tags parseEndTag(); function parseStartTag( tag, tagName, rest, unary ) { tagName = angular.lowercase(tagName); if ( blockElements[ tagName ] ) { while ( stack.last() && inlineElements[ stack.last() ] ) { parseEndTag( "", stack.last() ); } } if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { parseEndTag( "", tagName ); } unary = voidElements[ tagName ] || !!unary; if ( !unary ) stack.push( tagName ); var attrs = {}; rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { var value = doubleQuotedValue || singleQuotedValue || unquotedValue || ''; attrs[name] = decodeEntities(value); }); if (handler.start) handler.start( tagName, attrs, unary ); } function parseEndTag( tag, tagName ) { var pos = 0, i; tagName = angular.lowercase(tagName); if ( tagName ) // Find the closest opened tag of the same type for ( pos = stack.length - 1; pos >= 0; pos-- ) if ( stack[ pos ] == tagName ) break; if ( pos >= 0 ) { // Close all the open elements, up the stack for ( i = stack.length - 1; i >= pos; i-- ) if (handler.end) handler.end( stack[ i ] ); // Remove the open elements from the stack stack.length = pos; } } } var hiddenPre=document.createElement("pre"); var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; /** * decodes all entities into regular string * @param value * @returns {string} A string with decoded entities. */ function decodeEntities(value) { if (!value) { return ''; } // Note: IE8 does not preserve spaces at the start/end of innerHTML // so we must capture them and reattach them afterward var parts = spaceRe.exec(value); var spaceBefore = parts[1]; var spaceAfter = parts[3]; var content = parts[2]; if (content) { hiddenPre.innerHTML=content.replace(//g, '>'); } /** * create an HTML/XML writer which writes to buffer * @param {Array} buf use buf.jain('') to get out sanitized html string * @returns {object} in the form of { * start: function(tag, attrs, unary) {}, * end: function(tag) {}, * chars: function(text) {}, * comment: function(text) {} * } */ function htmlSanitizeWriter(buf, uriValidator){ var ignore = false; var out = angular.bind(buf, buf.push); return { start: function(tag, attrs, unary){ tag = angular.lowercase(tag); if (!ignore && specialElements[tag]) { ignore = tag; } if (!ignore && validElements[tag] === true) { out('<'); out(tag); angular.forEach(attrs, function(value, key){ var lkey=angular.lowercase(key); var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); if (validAttrs[lkey] === true && (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { out(' '); out(key); out('="'); out(encodeEntities(value)); out('"'); } }); out(unary ? '/>' : '>'); } }, end: function(tag){ tag = angular.lowercase(tag); if (!ignore && validElements[tag] === true) { out(''); } if (tag == ignore) { ignore = false; } }, chars: function(chars){ if (!ignore) { out(encodeEntities(chars)); } } }; } // define ngSanitize module and register $sanitize service angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); /* global sanitizeText: false */ /** * @ngdoc filter * @name ngSanitize.filter:linky * @function * * @description * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and * plain email address links. * * Requires the {@link ngSanitize `ngSanitize`} module to be installed. * * @param {string} text Input text. * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. * @returns {string} Html-linkified text. * * @usage * * @example
              Snippet:
              Filter Source Rendered
              linky filter
              <div ng-bind-html="snippet | linky">
              </div>
              linky target
              <div ng-bind-html="snippetWithTarget | linky:'_blank'">
              </div>
              no filter
              <div ng-bind="snippet">
              </div>
              it('should linkify the snippet with urls', function() { expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); }); it('should not linkify snippet without the linky filter', function() { expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); }); it('should update', function() { element(by.model('snippet')).clear(); element(by.model('snippet')).sendKeys('new http://link.'); expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). toBe('new http://link.'); expect(element.all(by.css('#linky-filter a')).count()).toEqual(1); expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()) .toBe('new http://link.'); }); it('should work with the target property', function() { expect(element(by.id('linky-target')). element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). toBe('http://angularjs.org/'); expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); }); */ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, MAILTO_REGEXP = /^mailto:/; return function(text, target) { if (!text) return text; var match; var raw = text; var html = []; var url; var i; while ((match = raw.match(LINKY_URL_REGEXP))) { // We can not end in these as they are sometimes found at the end of the sentence url = match[0]; // if we did not match ftp/http/mailto then assume mailto if (match[2] == match[3]) url = 'mailto:' + url; i = match.index; addText(raw.substr(0, i)); addLink(url, match[0].replace(MAILTO_REGEXP, '')); raw = raw.substring(i + match[0].length); } addText(raw); return $sanitize(html.join('')); function addText(text) { if (!text) { return; } html.push(sanitizeText(text)); } function addLink(url, text) { html.push(''); addText(text); html.push(''); } }; }]); })(window, window.angular); ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-loader-static-files/.bower.json ================================================ { "name": "angular-translate-loader-static-files", "version": "0.1.6", "main": "./angular-translate-loader-static-files.js", "dependencies": { "angular": "1.0.8", "angular-translate": "~1.1.1" }, "homepage": "https://github.com/PascalPrecht/bower-angular-translate-loader-static-files", "_release": "0.1.6", "_resolution": { "type": "version", "tag": "0.1.6", "commit": "eaac546d29d6cde45873e6bad9d18cdff071d983" }, "_source": "git://github.com/PascalPrecht/bower-angular-translate-loader-static-files.git", "_target": "0.1.6", "_originalSource": "angular-translate-loader-static-files" } ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js ================================================ /*! * angular-translate - v2.4.2 - 2014-10-21 * http://github.com/angular-translate/angular-translate * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate').factory('$translateStaticFilesLoader', [ '$q', '$http', function ($q, $http) { return function (options) { if (!options || (!angular.isString(options.prefix) || !angular.isString(options.suffix))) { throw new Error('Couldn\'t load static files, no prefix or suffix specified!'); } var deferred = $q.defer(); $http(angular.extend({ url: [ options.prefix, options.key, options.suffix ].join(''), method: 'GET', params: '' }, options.$http)).success(function (data) { deferred.resolve(data); }).error(function (data) { deferred.reject(options.key); }); return deferred.promise; }; } ]); ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-storage-cookie/.bower.json ================================================ { "name": "angular-translate-storage-cookie", "version": "0.1.6", "main": "./angular-translate-storage-cookie.js", "dependencies": { "angular": "1.0.8", "angular-cookies": "1.0.8", "angular-translate": "~1.1.1" }, "homepage": "https://github.com/PascalPrecht/bower-angular-translate-storage-cookie", "_release": "0.1.6", "_resolution": { "type": "version", "tag": "0.1.6", "commit": "fc9ea3275f0f9bf0a60ca073b58488d934a348ac" }, "_source": "git://github.com/PascalPrecht/bower-angular-translate-storage-cookie.git", "_target": "0.1.6", "_originalSource": "angular-translate-storage-cookie" } ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js ================================================ /*! * angular-translate - v2.4.2 - 2014-10-21 * http://github.com/angular-translate/angular-translate * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate').factory('$translateCookieStorage', [ '$cookieStore', function ($cookieStore) { var $translateCookieStorage = { get: function (name) { return $cookieStore.get(name); }, set: function (name, value) { $cookieStore.put(name, value); } }; return $translateCookieStorage; } ]); ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/angular-translate_2.4.2/angular-translate.js ================================================ /*! * angular-translate - v2.4.2 - 2014-10-21 * http://github.com/angular-translate/angular-translate * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate', ['ng']).run([ '$translate', function ($translate) { var key = $translate.storageKey(), storage = $translate.storage(); if (storage) { if (!storage.get(key)) { if (angular.isString($translate.preferredLanguage())) { $translate.use($translate.preferredLanguage()); } else { storage.set(key, $translate.use()); } } else { $translate.use(storage.get(key)); } } else if (angular.isString($translate.preferredLanguage())) { $translate.use($translate.preferredLanguage()); } } ]); angular.module('pascalprecht.translate').provider('$translate', [ '$STORAGE_KEY', function ($STORAGE_KEY) { var $translationTable = {}, $preferredLanguage, $availableLanguageKeys = [], $languageKeyAliases, $fallbackLanguage, $fallbackWasString, $uses, $nextLang, $storageFactory, $storageKey = $STORAGE_KEY, $storagePrefix, $missingTranslationHandlerFactory, $interpolationFactory, $interpolatorFactories = [], $interpolationSanitizationStrategy = false, $loaderFactory, $cloakClassName = 'translate-cloak', $loaderOptions, $notFoundIndicatorLeft, $notFoundIndicatorRight, $postCompilingEnabled = false, NESTED_OBJECT_DELIMITER = '.', loaderCache; var version = '2.4.2'; var getLocale = function () { var nav = window.navigator; return ((angular.isArray(nav.languages) ? nav.languages[0] : nav.language || nav.browserLanguage || nav.systemLanguage || nav.userLanguage) || '').split('-').join('_'); }; var indexOf = function (array, searchElement) { for (var i = 0, len = array.length; i < len; i++) { if (array[i] === searchElement) { return i; } } return -1; }; var trim = function () { return this.replace(/^\s+|\s+$/g, ''); }; var negotiateLocale = function (preferred) { var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length; for (; i < n; i++) { avail.push(angular.lowercase($availableLanguageKeys[i])); } if (indexOf(avail, locale) > -1) { return preferred; } if ($languageKeyAliases) { var alias; for (var langKeyAlias in $languageKeyAliases) { var hasWildcardKey = false; var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred); if (langKeyAlias.slice(-1) === '*') { hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1); } if (hasExactKey || hasWildcardKey) { alias = $languageKeyAliases[langKeyAlias]; if (indexOf(avail, angular.lowercase(alias)) > -1) { return alias; } } } } var parts = preferred.split('_'); if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) { return parts[0]; } return preferred; }; var translations = function (langKey, translationTable) { if (!langKey && !translationTable) { return $translationTable; } if (langKey && !translationTable) { if (angular.isString(langKey)) { return $translationTable[langKey]; } } else { if (!angular.isObject($translationTable[langKey])) { $translationTable[langKey] = {}; } angular.extend($translationTable[langKey], flatObject(translationTable)); } return this; }; this.translations = translations; this.cloakClassName = function (name) { if (!name) { return $cloakClassName; } $cloakClassName = name; return this; }; var flatObject = function (data, path, result, prevKey) { var key, keyWithPath, keyWithShortPath, val; if (!path) { path = []; } if (!result) { result = {}; } for (key in data) { if (!Object.prototype.hasOwnProperty.call(data, key)) { continue; } val = data[key]; if (angular.isObject(val)) { flatObject(val, path.concat(key), result, key); } else { keyWithPath = path.length ? '' + path.join(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key : key; if (path.length && key === prevKey) { keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER); result[keyWithShortPath] = '@:' + keyWithPath; } result[keyWithPath] = val; } } return result; }; this.addInterpolation = function (factory) { $interpolatorFactories.push(factory); return this; }; this.useMessageFormatInterpolation = function () { return this.useInterpolation('$translateMessageFormatInterpolation'); }; this.useInterpolation = function (factory) { $interpolationFactory = factory; return this; }; this.useSanitizeValueStrategy = function (value) { $interpolationSanitizationStrategy = value; return this; }; this.preferredLanguage = function (langKey) { setupPreferredLanguage(langKey); return this; }; var setupPreferredLanguage = function (langKey) { if (langKey) { $preferredLanguage = langKey; } return $preferredLanguage; }; this.translationNotFoundIndicator = function (indicator) { this.translationNotFoundIndicatorLeft(indicator); this.translationNotFoundIndicatorRight(indicator); return this; }; this.translationNotFoundIndicatorLeft = function (indicator) { if (!indicator) { return $notFoundIndicatorLeft; } $notFoundIndicatorLeft = indicator; return this; }; this.translationNotFoundIndicatorRight = function (indicator) { if (!indicator) { return $notFoundIndicatorRight; } $notFoundIndicatorRight = indicator; return this; }; this.fallbackLanguage = function (langKey) { fallbackStack(langKey); return this; }; var fallbackStack = function (langKey) { if (langKey) { if (angular.isString(langKey)) { $fallbackWasString = true; $fallbackLanguage = [langKey]; } else if (angular.isArray(langKey)) { $fallbackWasString = false; $fallbackLanguage = langKey; } if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) { $fallbackLanguage.push($preferredLanguage); } return this; } else { if ($fallbackWasString) { return $fallbackLanguage[0]; } else { return $fallbackLanguage; } } }; this.use = function (langKey) { if (langKey) { if (!$translationTable[langKey] && !$loaderFactory) { throw new Error('$translateProvider couldn\'t find translationTable for langKey: \'' + langKey + '\''); } $uses = langKey; return this; } return $uses; }; var storageKey = function (key) { if (!key) { if ($storagePrefix) { return $storagePrefix + $storageKey; } return $storageKey; } $storageKey = key; }; this.storageKey = storageKey; this.useUrlLoader = function (url, options) { return this.useLoader('$translateUrlLoader', angular.extend({ url: url }, options)); }; this.useStaticFilesLoader = function (options) { return this.useLoader('$translateStaticFilesLoader', options); }; this.useLoader = function (loaderFactory, options) { $loaderFactory = loaderFactory; $loaderOptions = options || {}; return this; }; this.useLocalStorage = function () { return this.useStorage('$translateLocalStorage'); }; this.useCookieStorage = function () { return this.useStorage('$translateCookieStorage'); }; this.useStorage = function (storageFactory) { $storageFactory = storageFactory; return this; }; this.storagePrefix = function (prefix) { if (!prefix) { return prefix; } $storagePrefix = prefix; return this; }; this.useMissingTranslationHandlerLog = function () { return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog'); }; this.useMissingTranslationHandler = function (factory) { $missingTranslationHandlerFactory = factory; return this; }; this.usePostCompiling = function (value) { $postCompilingEnabled = !!value; return this; }; this.determinePreferredLanguage = function (fn) { var locale = fn && angular.isFunction(fn) ? fn() : getLocale(); if (!$availableLanguageKeys.length) { $preferredLanguage = locale; } else { $preferredLanguage = negotiateLocale(locale); } return this; }; this.registerAvailableLanguageKeys = function (languageKeys, aliases) { if (languageKeys) { $availableLanguageKeys = languageKeys; if (aliases) { $languageKeyAliases = aliases; } return this; } return $availableLanguageKeys; }; this.useLoaderCache = function (cache) { if (cache === false) { loaderCache = undefined; } else if (cache === true) { loaderCache = true; } else if (typeof cache === 'undefined') { loaderCache = '$translationCache'; } else if (cache) { loaderCache = cache; } return this; }; this.$get = [ '$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) { var Storage, defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, startFallbackIteration; var $translate = function (translationId, interpolateParams, interpolationId) { if (angular.isArray(translationId)) { var translateAll = function (translationIds) { var results = {}; var promises = []; var translate = function (translationId) { var deferred = $q.defer(); var regardless = function (value) { results[translationId] = value; deferred.resolve([ translationId, value ]); }; $translate(translationId, interpolateParams, interpolationId).then(regardless, regardless); return deferred.promise; }; for (var i = 0, c = translationIds.length; i < c; i++) { promises.push(translate(translationIds[i])); } return $q.all(promises).then(function () { return results; }); }; return translateAll(translationId); } var deferred = $q.defer(); if (translationId) { translationId = trim.apply(translationId); } var promiseToWaitFor = function () { var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[$uses]; fallbackIndex = 0; if ($storageFactory && !promise) { var langKey = Storage.get($storageKey); promise = langPromises[langKey]; if ($fallbackLanguage && $fallbackLanguage.length) { var index = indexOf($fallbackLanguage, langKey); fallbackIndex = index === 0 ? 1 : 0; if (indexOf($fallbackLanguage, $preferredLanguage) < 0) { $fallbackLanguage.push($preferredLanguage); } } } return promise; }(); if (!promiseToWaitFor) { determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); } else { promiseToWaitFor.then(function () { determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); }, deferred.reject); } return deferred.promise; }; var applyNotFoundIndicators = function (translationId) { if ($notFoundIndicatorLeft) { translationId = [ $notFoundIndicatorLeft, translationId ].join(' '); } if ($notFoundIndicatorRight) { translationId = [ translationId, $notFoundIndicatorRight ].join(' '); } return translationId; }; var useLanguage = function (key) { $uses = key; $rootScope.$emit('$translateChangeSuccess', { language: key }); if ($storageFactory) { Storage.set($translate.storageKey(), $uses); } defaultInterpolator.setLocale($uses); angular.forEach(interpolatorHashMap, function (interpolator, id) { interpolatorHashMap[id].setLocale($uses); }); $rootScope.$emit('$translateChangeEnd', { language: key }); }; var loadAsync = function (key) { if (!key) { throw 'No language key specified for loading.'; } var deferred = $q.defer(); $rootScope.$emit('$translateLoadingStart', { language: key }); pendingLoader = true; var cache = loaderCache; if (typeof cache === 'string') { cache = $injector.get(cache); } var loaderOptions = angular.extend({}, $loaderOptions, { key: key, $http: angular.extend({}, { cache: cache }, $loaderOptions.$http) }); $injector.get($loaderFactory)(loaderOptions).then(function (data) { var translationTable = {}; $rootScope.$emit('$translateLoadingSuccess', { language: key }); if (angular.isArray(data)) { angular.forEach(data, function (table) { angular.extend(translationTable, flatObject(table)); }); } else { angular.extend(translationTable, flatObject(data)); } pendingLoader = false; deferred.resolve({ key: key, table: translationTable }); $rootScope.$emit('$translateLoadingEnd', { language: key }); }, function (key) { $rootScope.$emit('$translateLoadingError', { language: key }); deferred.reject(key); $rootScope.$emit('$translateLoadingEnd', { language: key }); }); return deferred.promise; }; if ($storageFactory) { Storage = $injector.get($storageFactory); if (!Storage.get || !Storage.set) { throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or set() method!'); } } if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) { defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); } if ($interpolatorFactories.length) { angular.forEach($interpolatorFactories, function (interpolatorFactory) { var interpolator = $injector.get(interpolatorFactory); interpolator.setLocale($preferredLanguage || $uses); if (angular.isFunction(interpolator.useSanitizeValueStrategy)) { interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); } interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator; }); } var getTranslationTable = function (langKey) { var deferred = $q.defer(); if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) { deferred.resolve($translationTable[langKey]); } else if (langPromises[langKey]) { langPromises[langKey].then(function (data) { translations(data.key, data.table); deferred.resolve(data.table); }, deferred.reject); } else { deferred.reject(); } return deferred.promise; }; var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) { var deferred = $q.defer(); getTranslationTable(langKey).then(function (translationTable) { if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { Interpolator.setLocale(langKey); deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams)); Interpolator.setLocale($uses); } else { deferred.reject(); } }, deferred.reject); return deferred.promise; }; var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) { var result, translationTable = $translationTable[langKey]; if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { Interpolator.setLocale(langKey); result = Interpolator.interpolate(translationTable[translationId], interpolateParams); Interpolator.setLocale($uses); } return result; }; var translateByHandler = function (translationId) { if ($missingTranslationHandlerFactory) { var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses); if (resultString !== undefined) { return resultString; } else { return translationId; } } else { return translationId; } }; var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { var deferred = $q.defer(); if (fallbackLanguageIndex < $fallbackLanguage.length) { var langKey = $fallbackLanguage[fallbackLanguageIndex]; getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(deferred.resolve, function () { resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator).then(deferred.resolve); }); } else { deferred.resolve(translateByHandler(translationId)); } return deferred.promise; }; var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { var result; if (fallbackLanguageIndex < $fallbackLanguage.length) { var langKey = $fallbackLanguage[fallbackLanguageIndex]; result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator); if (!result) { result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator); } } return result; }; var fallbackTranslation = function (translationId, interpolateParams, Interpolator) { return resolveForFallbackLanguage(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); }; var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) { return resolveForFallbackLanguageInstant(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); }; var determineTranslation = function (translationId, interpolateParams, interpolationId) { var deferred = $q.defer(); var table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { var translation = table[translationId]; if (translation.substr(0, 2) === '@:') { $translate(translation.substr(2), interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); } else { deferred.resolve(Interpolator.interpolate(translation, interpolateParams)); } } else { var missingTranslationHandlerTranslation; if ($missingTranslationHandlerFactory && !pendingLoader) { missingTranslationHandlerTranslation = translateByHandler(translationId); } if ($uses && $fallbackLanguage && $fallbackLanguage.length) { fallbackTranslation(translationId, interpolateParams, Interpolator).then(function (translation) { deferred.resolve(translation); }, function (_translationId) { deferred.reject(applyNotFoundIndicators(_translationId)); }); } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { deferred.resolve(missingTranslationHandlerTranslation); } else { deferred.reject(applyNotFoundIndicators(translationId)); } } return deferred.promise; }; var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) { var result, table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { var translation = table[translationId]; if (translation.substr(0, 2) === '@:') { result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId); } else { result = Interpolator.interpolate(translation, interpolateParams); } } else { var missingTranslationHandlerTranslation; if ($missingTranslationHandlerFactory && !pendingLoader) { missingTranslationHandlerTranslation = translateByHandler(translationId); } if ($uses && $fallbackLanguage && $fallbackLanguage.length) { fallbackIndex = 0; result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator); } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { result = missingTranslationHandlerTranslation; } else { result = applyNotFoundIndicators(translationId); } } return result; }; $translate.preferredLanguage = function (langKey) { if (langKey) { setupPreferredLanguage(langKey); } return $preferredLanguage; }; $translate.cloakClassName = function () { return $cloakClassName; }; $translate.fallbackLanguage = function (langKey) { if (langKey !== undefined && langKey !== null) { fallbackStack(langKey); if ($loaderFactory) { if ($fallbackLanguage && $fallbackLanguage.length) { for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { if (!langPromises[$fallbackLanguage[i]]) { langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]); } } } } $translate.use($translate.use()); } if ($fallbackWasString) { return $fallbackLanguage[0]; } else { return $fallbackLanguage; } }; $translate.useFallbackLanguage = function (langKey) { if (langKey !== undefined && langKey !== null) { if (!langKey) { startFallbackIteration = 0; } else { var langKeyPosition = indexOf($fallbackLanguage, langKey); if (langKeyPosition > -1) { startFallbackIteration = langKeyPosition; } } } }; $translate.proposedLanguage = function () { return $nextLang; }; $translate.storage = function () { return Storage; }; $translate.use = function (key) { if (!key) { return $uses; } var deferred = $q.defer(); $rootScope.$emit('$translateChangeStart', { language: key }); var aliasedKey = negotiateLocale(key); if (aliasedKey) { key = aliasedKey; } if (!$translationTable[key] && $loaderFactory && !langPromises[key]) { $nextLang = key; langPromises[key] = loadAsync(key).then(function (translation) { translations(translation.key, translation.table); deferred.resolve(translation.key); useLanguage(translation.key); if ($nextLang === key) { $nextLang = undefined; } }, function (key) { if ($nextLang === key) { $nextLang = undefined; } $rootScope.$emit('$translateChangeError', { language: key }); deferred.reject(key); $rootScope.$emit('$translateChangeEnd', { language: key }); }); } else { deferred.resolve(key); useLanguage(key); } return deferred.promise; }; $translate.storageKey = function () { return storageKey(); }; $translate.isPostCompilingEnabled = function () { return $postCompilingEnabled; }; $translate.refresh = function (langKey) { if (!$loaderFactory) { throw new Error('Couldn\'t refresh translation table, no loader registered!'); } var deferred = $q.defer(); function resolve() { deferred.resolve(); $rootScope.$emit('$translateRefreshEnd', { language: langKey }); } function reject() { deferred.reject(); $rootScope.$emit('$translateRefreshEnd', { language: langKey }); } $rootScope.$emit('$translateRefreshStart', { language: langKey }); if (!langKey) { var tables = [], loadingKeys = {}; if ($fallbackLanguage && $fallbackLanguage.length) { for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { tables.push(loadAsync($fallbackLanguage[i])); loadingKeys[$fallbackLanguage[i]] = true; } } if ($uses && !loadingKeys[$uses]) { tables.push(loadAsync($uses)); } $q.all(tables).then(function (tableData) { angular.forEach(tableData, function (data) { if ($translationTable[data.key]) { delete $translationTable[data.key]; } translations(data.key, data.table); }); if ($uses) { useLanguage($uses); } resolve(); }); } else if ($translationTable[langKey]) { loadAsync(langKey).then(function (data) { translations(data.key, data.table); if (langKey === $uses) { useLanguage($uses); } resolve(); }, reject); } else { reject(); } return deferred.promise; }; $translate.instant = function (translationId, interpolateParams, interpolationId) { if (translationId === null || angular.isUndefined(translationId)) { return translationId; } if (angular.isArray(translationId)) { var results = {}; for (var i = 0, c = translationId.length; i < c; i++) { results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId); } return results; } if (angular.isString(translationId) && translationId.length < 1) { return translationId; } if (translationId) { translationId = trim.apply(translationId); } var result, possibleLangKeys = []; if ($preferredLanguage) { possibleLangKeys.push($preferredLanguage); } if ($uses) { possibleLangKeys.push($uses); } if ($fallbackLanguage && $fallbackLanguage.length) { possibleLangKeys = possibleLangKeys.concat($fallbackLanguage); } for (var j = 0, d = possibleLangKeys.length; j < d; j++) { var possibleLangKey = possibleLangKeys[j]; if ($translationTable[possibleLangKey]) { if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') { result = determineTranslationInstant(translationId, interpolateParams, interpolationId); } } if (typeof result !== 'undefined') { break; } } if (!result && result !== '') { result = defaultInterpolator.interpolate(translationId, interpolateParams); if ($missingTranslationHandlerFactory && !pendingLoader) { result = translateByHandler(translationId); } } return result; }; $translate.versionInfo = function () { return version; }; $translate.loaderCache = function () { return loaderCache; }; if ($loaderFactory) { if (angular.equals($translationTable, {})) { $translate.use($translate.use()); } if ($fallbackLanguage && $fallbackLanguage.length) { var processAsyncResult = function (translation) { translations(translation.key, translation.table); $rootScope.$emit('$translateChangeEnd', { language: translation.key }); }; for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult); } } } return $translate; } ]; } ]); angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', [ '$interpolate', function ($interpolate) { var $translateInterpolator = {}, $locale, $identifier = 'default', $sanitizeValueStrategy = null, sanitizeValueStrategies = { escaped: function (params) { var result = {}; for (var key in params) { if (Object.prototype.hasOwnProperty.call(params, key)) { result[key] = angular.element('
              ').text(params[key]).html(); } } return result; } }; var sanitizeParams = function (params) { var result; if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) { result = sanitizeValueStrategies[$sanitizeValueStrategy](params); } else { result = params; } return result; }; $translateInterpolator.setLocale = function (locale) { $locale = locale; }; $translateInterpolator.getInterpolationIdentifier = function () { return $identifier; }; $translateInterpolator.useSanitizeValueStrategy = function (value) { $sanitizeValueStrategy = value; return this; }; $translateInterpolator.interpolate = function (string, interpolateParams) { if ($sanitizeValueStrategy) { interpolateParams = sanitizeParams(interpolateParams); } return $interpolate(string)(interpolateParams || {}); }; return $translateInterpolator; } ]); angular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY'); angular.module('pascalprecht.translate').directive('translate', [ '$translate', '$q', '$interpolate', '$compile', '$parse', '$rootScope', function ($translate, $q, $interpolate, $compile, $parse, $rootScope) { return { restrict: 'AE', scope: true, compile: function (tElement, tAttr) { var translateValuesExist = tAttr.translateValues ? tAttr.translateValues : undefined; var translateInterpolation = tAttr.translateInterpolation ? tAttr.translateInterpolation : undefined; var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i); var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)'; return function linkFn(scope, iElement, iAttr) { scope.interpolateParams = {}; scope.preText = ''; scope.postText = ''; iAttr.$observe('translate', function (translationId) { if (angular.equals(translationId, '') || !angular.isDefined(translationId)) { var interpolateMatches = iElement.text().match(interpolateRegExp); if (angular.isArray(interpolateMatches)) { scope.preText = interpolateMatches[1]; scope.postText = interpolateMatches[3]; scope.translationId = $interpolate(interpolateMatches[2])(scope.$parent); } else { scope.translationId = iElement.text().replace(/^\s+|\s+$/g, ''); } } else { scope.translationId = translationId; } }); iAttr.$observe('translateDefault', function (value) { scope.defaultText = value; }); if (translateValuesExist) { iAttr.$observe('translateValues', function (interpolateParams) { if (interpolateParams) { scope.$parent.$watch(function () { angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent)); }); } }); } if (translateValueExist) { var fn = function (attrName) { iAttr.$observe(attrName, function (value) { scope.interpolateParams[angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15)] = value; }); }; for (var attr in iAttr) { if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') { fn(attr); } } } var applyElementContent = function (value, scope, successful) { if (!successful && typeof scope.defaultText !== 'undefined') { value = scope.defaultText; } iElement.html(scope.preText + value + scope.postText); var globallyEnabled = $translate.isPostCompilingEnabled(); var locallyDefined = typeof tAttr.translateCompile !== 'undefined'; var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false'; if (globallyEnabled && !locallyDefined || locallyEnabled) { $compile(iElement.contents())(scope); } }; var updateTranslationFn = function () { if (!translateValuesExist && !translateValueExist) { return function () { var unwatch = scope.$watch('translationId', function (value) { if (scope.translationId && value) { $translate(value, {}, translateInterpolation).then(function (translation) { applyElementContent(translation, scope, true); unwatch(); }, function (translationId) { applyElementContent(translationId, scope, false); unwatch(); }); } }, true); }; } else { return function () { var updateTranslations = function () { if (scope.translationId && scope.interpolateParams) { $translate(scope.translationId, scope.interpolateParams, translateInterpolation).then(function (translation) { applyElementContent(translation, scope, true); }, function (translationId) { applyElementContent(translationId, scope, false); }); } }; scope.$watch('interpolateParams', updateTranslations, true); scope.$watch('translationId', updateTranslations); }; } }(); var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslationFn); updateTranslationFn(); scope.$on('$destroy', unbind); }; } }; } ]); angular.module('pascalprecht.translate').directive('translateCloak', [ '$rootScope', '$translate', function ($rootScope, $translate) { return { compile: function (tElement) { var applyCloak = function () { tElement.addClass($translate.cloakClassName()); }, removeCloak = function () { tElement.removeClass($translate.cloakClassName()); }, removeListener = $rootScope.$on('$translateChangeEnd', function () { removeCloak(); removeListener(); removeListener = null; }); applyCloak(); return function linkFn(scope, iElement, iAttr) { if (iAttr.translateCloak && iAttr.translateCloak.length) { iAttr.$observe('translateCloak', function (translationId) { $translate(translationId).then(removeCloak, applyCloak); }); } }; } }; } ]); angular.module('pascalprecht.translate').filter('translate', [ '$parse', '$translate', function ($parse, $translate) { var translateFilter = function (translationId, interpolateParams, interpolation) { if (!angular.isObject(interpolateParams)) { interpolateParams = $parse(interpolateParams)(this); } return $translate.instant(translationId, interpolateParams, interpolation); }; translateFilter.$stateful = true; return translateFilter; } ]); ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css ================================================ /*! * Stylesheet for the Date Range Picker, for use with Bootstrap 3.x * * Copyright 2013 Dan Grossman ( http://www.dangrossman.info ) * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Built for http://www.improvely.com */ .daterangepicker.dropdown-menu { max-width: none; z-index: 3000; } .daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar { float: left; margin: 4px; } .daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar { float: right; margin: 4px; } .daterangepicker .ranges { width: 160px; text-align: left; } .daterangepicker .ranges .range_inputs>div { float: left; } .daterangepicker .ranges .range_inputs>div:nth-child(2) { padding-left: 11px; } .daterangepicker .calendar { display: none; max-width: 270px; } .daterangepicker.show-calendar .calendar { display: block; } .daterangepicker .calendar.single .calendar-date { border: none; } .daterangepicker .calendar th, .daterangepicker .calendar td { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; white-space: nowrap; text-align: center; min-width: 32px; } .daterangepicker .daterangepicker_start_input label, .daterangepicker .daterangepicker_end_input label { color: #333; display: block; font-size: 11px; font-weight: normal; height: 20px; line-height: 20px; margin-bottom: 2px; text-shadow: #fff 1px 1px 0px; text-transform: uppercase; width: 74px; } .daterangepicker .ranges input { font-size: 11px; } .daterangepicker .ranges .input-mini { background-color: #eee; border: 1px solid #ccc; border-radius: 4px; color: #555; display: block; font-size: 11px; height: 30px; line-height: 30px; vertical-align: middle; margin: 0 0 10px 0; padding: 0 6px; width: 74px; } .daterangepicker .ranges ul { list-style: none; margin: 0; padding: 0; } .daterangepicker .ranges li { font-size: 13px; background: #f5f5f5; border: 1px solid #f5f5f5; color: #08c; padding: 3px 12px; margin-bottom: 8px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; cursor: pointer; } .daterangepicker .ranges li.active, .daterangepicker .ranges li:hover { background: #08c; border: 1px solid #08c; color: #fff; } .daterangepicker .calendar-date { border: 1px solid #ddd; padding: 4px; border-radius: 4px; background: #fff; } .daterangepicker .calendar-time { text-align: center; margin: 8px auto 0 auto; line-height: 30px; } .daterangepicker { position: absolute; background: #fff; top: 100px; left: 20px; padding: 4px; margin-top: 1px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .daterangepicker.opensleft:before { position: absolute; top: -7px; right: 9px; display: inline-block; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-left: 7px solid transparent; border-bottom-color: rgba(0, 0, 0, 0.2); content: ''; } .daterangepicker.opensleft:after { position: absolute; top: -6px; right: 10px; display: inline-block; border-right: 6px solid transparent; border-bottom: 6px solid #fff; border-left: 6px solid transparent; content: ''; } .daterangepicker.opensright:before { position: absolute; top: -7px; left: 9px; display: inline-block; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-left: 7px solid transparent; border-bottom-color: rgba(0, 0, 0, 0.2); content: ''; } .daterangepicker.opensright:after { position: absolute; top: -6px; left: 10px; display: inline-block; border-right: 6px solid transparent; border-bottom: 6px solid #fff; border-left: 6px solid transparent; content: ''; } .daterangepicker table { width: 100%; margin: 0; } .daterangepicker td, .daterangepicker th { text-align: center; width: 20px; height: 20px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; cursor: pointer; white-space: nowrap; } .daterangepicker td.off { color: #999; } .daterangepicker td.disabled { color: #999; } .daterangepicker td.available:hover, .daterangepicker th.available:hover { background: #eee; } .daterangepicker td.in-range { background: #ebf4f8; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .daterangepicker td.active, .daterangepicker td.active:hover { background-color: #357ebd; border-color: #3071a9; color: #fff; } .daterangepicker td.week, .daterangepicker th.week { font-size: 80%; color: #ccc; } .daterangepicker select.monthselect, .daterangepicker select.yearselect { font-size: 12px; padding: 1px; height: auto; margin: 0; cursor: default; } .daterangepicker select.monthselect { margin-right: 2%; width: 56%; } .daterangepicker select.yearselect { width: 40%; } .daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.ampmselect { width: 50px; margin-bottom: 0; } .daterangepicker_start_input { float: left; } .daterangepicker_end_input { float: left; padding-left: 11px } .daterangepicker th.month { width: auto; } ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js ================================================ /** * @version: 1.3.7 * @author: Dan Grossman http://www.dangrossman.info/ * @date: 2014-04-29 * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved. * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0 * @website: http://www.improvely.com/ */ !function ($, moment) { var DateRangePicker = function (element, options, cb) { // by default, the daterangepicker element is placed at the bottom of HTML body this.parentEl = 'body'; //element that triggered the date range picker this.element = $(element); //create the picker HTML object var DRPTemplate = ''; //custom options if (typeof options !== 'object' || options === null) options = {}; this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl); this.container = $(DRPTemplate).appendTo(this.parentEl); this.setOptions(options, cb); //apply CSS classes and labels to buttons var c = this.container; $.each(this.buttonClasses, function (idx, val) { c.find('button').addClass(val); }); this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel); this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel); if (this.applyClass.length) this.container.find('.applyBtn').addClass(this.applyClass); if (this.cancelClass.length) this.container.find('.cancelBtn').addClass(this.cancelClass); this.container.find('.applyBtn').html(this.locale.applyLabel); this.container.find('.cancelBtn').html(this.locale.cancelLabel); //event listeners this.container.find('.calendar') .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this)) .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this)) .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this)) .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this)) .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this)) .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this)) .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this)) .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this)); this.container.find('.ranges') .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this)) .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this)) .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this)) .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this)) .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this)) .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this)); if (this.element.is('input')) { this.element.on({ 'click.daterangepicker': $.proxy(this.show, this), 'focus.daterangepicker': $.proxy(this.show, this), 'keyup.daterangepicker': $.proxy(this.updateFromControl, this) }); } else { this.element.on('click.daterangepicker', $.proxy(this.toggle, this)); } }; DateRangePicker.prototype = { constructor: DateRangePicker, setOptions: function(options, callback) { this.startDate = moment().startOf('day'); this.endDate = moment().endOf('day'); this.minDate = false; this.maxDate = false; this.dateLimit = false; this.showDropdowns = false; this.showWeekNumbers = false; this.timePicker = false; this.timePickerIncrement = 30; this.timePicker12Hour = true; this.singleDatePicker = false; this.ranges = {}; this.opens = 'right'; if (this.element.hasClass('pull-right')) this.opens = 'left'; this.buttonClasses = ['btn', 'btn-small']; this.applyClass = 'btn-success'; this.cancelClass = 'btn-default'; this.format = 'MM/DD/YYYY'; this.separator = ' - '; this.locale = { applyLabel: 'Apply', cancelLabel: 'Cancel', fromLabel: 'From', toLabel: 'To', weekLabel: 'W', customRangeLabel: 'Custom Range', daysOfWeek: moment()._lang._weekdaysMin.slice(), monthNames: moment()._lang._monthsShort.slice(), firstDay: 0 }; this.cb = function () { }; if (typeof options.format === 'string') this.format = options.format; if (typeof options.separator === 'string') this.separator = options.separator; if (typeof options.startDate === 'string') this.startDate = moment(options.startDate, this.format); if (typeof options.endDate === 'string') this.endDate = moment(options.endDate, this.format); if (typeof options.minDate === 'string') this.minDate = moment(options.minDate, this.format); if (typeof options.maxDate === 'string') this.maxDate = moment(options.maxDate, this.format); if (typeof options.startDate === 'object') this.startDate = moment(options.startDate); if (typeof options.endDate === 'object') this.endDate = moment(options.endDate); if (typeof options.minDate === 'object') this.minDate = moment(options.minDate); if (typeof options.maxDate === 'object') this.maxDate = moment(options.maxDate); if (typeof options.applyClass === 'string') this.applyClass = options.applyClass; if (typeof options.cancelClass === 'string') this.cancelClass = options.cancelClass; if (typeof options.dateLimit === 'object') this.dateLimit = options.dateLimit; // update day names order to firstDay if (typeof options.locale === 'object') { if (typeof options.locale.daysOfWeek === 'object') { // Create a copy of daysOfWeek to avoid modification of original // options object for reusability in multiple daterangepicker instances this.locale.daysOfWeek = options.locale.daysOfWeek.slice(); } if (typeof options.locale.monthNames === 'object') { this.locale.monthNames = options.locale.monthNames.slice(); } if (typeof options.locale.firstDay === 'number') { this.locale.firstDay = options.locale.firstDay; var iterator = options.locale.firstDay; while (iterator > 0) { this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift()); iterator--; } } if (typeof options.locale.applyLabel === 'string') { this.locale.applyLabel = options.locale.applyLabel; } if (typeof options.locale.cancelLabel === 'string') { this.locale.cancelLabel = options.locale.cancelLabel; } if (typeof options.locale.fromLabel === 'string') { this.locale.fromLabel = options.locale.fromLabel; } if (typeof options.locale.toLabel === 'string') { this.locale.toLabel = options.locale.toLabel; } if (typeof options.locale.weekLabel === 'string') { this.locale.weekLabel = options.locale.weekLabel; } if (typeof options.locale.customRangeLabel === 'string') { this.locale.customRangeLabel = options.locale.customRangeLabel; } } if (typeof options.opens === 'string') this.opens = options.opens; if (typeof options.showWeekNumbers === 'boolean') { this.showWeekNumbers = options.showWeekNumbers; } if (typeof options.buttonClasses === 'string') { this.buttonClasses = [options.buttonClasses]; } if (typeof options.buttonClasses === 'object') { this.buttonClasses = options.buttonClasses; } if (typeof options.showDropdowns === 'boolean') { this.showDropdowns = options.showDropdowns; } if (typeof options.singleDatePicker === 'boolean') { this.singleDatePicker = options.singleDatePicker; } if (typeof options.timePicker === 'boolean') { this.timePicker = options.timePicker; } if (typeof options.timePickerIncrement === 'number') { this.timePickerIncrement = options.timePickerIncrement; } if (typeof options.timePicker12Hour === 'boolean') { this.timePicker12Hour = options.timePicker12Hour; } var start, end, range; //if no start/end dates set, check if an input element contains initial values if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') { if ($(this.element).is('input[type=text]')) { var val = $(this.element).val(); var split = val.split(this.separator); start = end = null; if (split.length == 2) { start = moment(split[0], this.format); end = moment(split[1], this.format); } else if (this.singleDatePicker) { start = moment(val, this.format); end = moment(val, this.format); } if (start !== null && end !== null) { this.startDate = start; this.endDate = end; } } } if (typeof options.ranges === 'object') { for (range in options.ranges) { start = moment(options.ranges[range][0]); end = moment(options.ranges[range][1]); // If we have a min/max date set, bound this range // to it, but only if it would otherwise fall // outside of the min/max. if (this.minDate && start.isBefore(this.minDate)) start = moment(this.minDate); if (this.maxDate && end.isAfter(this.maxDate)) end = moment(this.maxDate); // If the end of the range is before the minimum (if min is set) OR // the start of the range is after the max (also if set) don't display this // range option. if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) { continue; } this.ranges[range] = [start, end]; } var list = '
                '; for (range in this.ranges) { list += '
              • ' + range + '
              • '; } list += '
              • ' + this.locale.customRangeLabel + '
              • '; list += '
              '; this.container.find('.ranges ul').remove(); this.container.find('.ranges').prepend(list); } if (typeof callback === 'function') { this.cb = callback; } if (!this.timePicker) { this.startDate = this.startDate.startOf('day'); this.endDate = this.endDate.endOf('day'); } if (this.singleDatePicker) { this.opens = 'right'; this.container.find('.calendar.right').show(); this.container.find('.calendar.left').hide(); this.container.find('.ranges').hide(); if (!this.container.find('.calendar.right').hasClass('single')) this.container.find('.calendar.right').addClass('single'); } else { this.container.find('.calendar.right').removeClass('single'); this.container.find('.ranges').show(); } this.oldStartDate = this.startDate.clone(); this.oldEndDate = this.endDate.clone(); this.oldChosenLabel = this.chosenLabel; this.leftCalendar = { month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]), calendar: [] }; this.rightCalendar = { month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]), calendar: [] }; if (this.opens == 'right') { //swap calendar positions var left = this.container.find('.calendar.left'); var right = this.container.find('.calendar.right'); left.removeClass('left').addClass('right'); right.removeClass('right').addClass('left'); } if (typeof options.ranges === 'undefined' && !this.singleDatePicker) { this.container.addClass('show-calendar'); } this.container.addClass('opens' + this.opens); this.updateView(); this.updateCalendars(); }, setStartDate: function(startDate) { if (typeof startDate === 'string') this.startDate = moment(startDate, this.format); if (typeof startDate === 'object') this.startDate = moment(startDate); if (!this.timePicker) this.startDate = this.startDate.startOf('day'); this.oldStartDate = this.startDate.clone(); this.updateView(); this.updateCalendars(); }, setEndDate: function(endDate) { if (typeof endDate === 'string') this.endDate = moment(endDate, this.format); if (typeof endDate === 'object') this.endDate = moment(endDate); if (!this.timePicker) this.endDate = this.endDate.endOf('day'); this.oldEndDate = this.endDate.clone(); this.updateView(); this.updateCalendars(); }, updateView: function () { this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()); this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()); this.updateFormInputs(); }, updateFormInputs: function () { this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format)); this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format)); if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) { this.container.find('button.applyBtn').removeAttr('disabled'); } else { this.container.find('button.applyBtn').attr('disabled', 'disabled'); } }, updateFromControl: function () { if (!this.element.is('input')) return; if (!this.element.val().length) return; var dateString = this.element.val().split(this.separator), start = null, end = null; if(dateString.length === 2) { start = moment(dateString[0], this.format); end = moment(dateString[1], this.format); } if (this.singleDatePicker || start === null || end === null) { start = moment(this.element.val(), this.format); end = start; } if (end.isBefore(start)) return; this.oldStartDate = this.startDate.clone(); this.oldEndDate = this.endDate.clone(); this.startDate = start; this.endDate = end; if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) this.notify(); this.updateCalendars(); }, notify: function () { this.updateView(); this.cb(this.startDate, this.endDate, this.chosenLabel); }, move: function () { var parentOffset = { top: 0, left: 0 }; if (!this.parentEl.is('body')) { parentOffset = { top: this.parentEl.offset().top - this.parentEl.scrollTop(), left: this.parentEl.offset().left - this.parentEl.scrollLeft() }; } if (this.opens == 'left') { this.container.css({ top: this.element.offset().top + this.element.outerHeight() - parentOffset.top, right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left, left: 'auto' }); if (this.container.offset().left < 0) { this.container.css({ right: 'auto', left: 9 }); } } else { this.container.css({ top: this.element.offset().top + this.element.outerHeight() - parentOffset.top, left: this.element.offset().left - parentOffset.left, right: 'auto' }); if (this.container.offset().left + this.container.outerWidth() > $(window).width()) { this.container.css({ left: 'auto', right: 0 }); } } }, toggle: function (e) { if (this.element.hasClass('active')) { this.hide(); } else { this.show(); } }, show: function (e) { this.element.addClass('active'); this.container.show(); this.move(); // Create a click proxy that is private to this instance of datepicker, for unbinding this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this); // Bind global datepicker mousedown for hiding and $(document) .on('mousedown.daterangepicker', this._outsideClickProxy) // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy) // and also close when focus changes to outside the picker (eg. tabbing between controls) .on('focusin.daterangepicker', this._outsideClickProxy); this.element.trigger('show.daterangepicker', this); }, outsideClick: function (e) { var target = $(e.target); // if the page is clicked anywhere except within the daterangerpicker/button // itself then call this.hide() if ( target.closest(this.element).length || target.closest(this.container).length || target.closest('.calendar-date').length ) return; this.hide(); }, hide: function (e) { $(document) .off('mousedown.daterangepicker', this._outsideClickProxy) .off('click.daterangepicker', this._outsideClickProxy) .off('focusin.daterangepicker', this._outsideClickProxy); this.element.removeClass('active'); this.container.hide(); if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) this.notify(); this.oldStartDate = this.startDate.clone(); this.oldEndDate = this.endDate.clone(); this.element.trigger('hide.daterangepicker', this); }, enterRange: function (e) { // mouse pointer has entered a range label var label = e.target.innerHTML; if (label == this.locale.customRangeLabel) { this.updateView(); } else { var dates = this.ranges[label]; this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format)); this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format)); } }, showCalendars: function() { this.container.addClass('show-calendar'); this.move(); }, hideCalendars: function() { this.container.removeClass('show-calendar'); }, updateInputText: function() { if (this.element.is('input') && !this.singleDatePicker) { this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format)); } else if (this.element.is('input')) { this.element.val(this.startDate.format(this.format)); } }, clickRange: function (e) { var label = e.target.innerHTML; this.chosenLabel = label; if (label == this.locale.customRangeLabel) { this.showCalendars(); } else { var dates = this.ranges[label]; this.startDate = dates[0]; this.endDate = dates[1]; if (!this.timePicker) { this.startDate.startOf('day'); this.endDate.endOf('day'); } this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute()); this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute()); this.updateCalendars(); this.updateInputText(); this.hideCalendars(); this.hide(); this.element.trigger('apply.daterangepicker', this); } }, clickPrev: function (e) { var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.leftCalendar.month.subtract('month', 1); } else { this.rightCalendar.month.subtract('month', 1); } this.updateCalendars(); }, clickNext: function (e) { var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.leftCalendar.month.add('month', 1); } else { this.rightCalendar.month.add('month', 1); } this.updateCalendars(); }, enterDate: function (e) { var title = $(e.target).attr('data-title'); var row = title.substr(1, 1); var col = title.substr(3, 1); var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format)); } else { this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format)); } }, clickDate: function (e) { var title = $(e.target).attr('data-title'); var row = title.substr(1, 1); var col = title.substr(3, 1); var cal = $(e.target).parents('.calendar'); var startDate, endDate; if (cal.hasClass('left')) { startDate = this.leftCalendar.calendar[row][col]; endDate = this.endDate; if (typeof this.dateLimit === 'object') { var maxDate = moment(startDate).add(this.dateLimit).startOf('day'); if (endDate.isAfter(maxDate)) { endDate = maxDate; } } } else { startDate = this.startDate; endDate = this.rightCalendar.calendar[row][col]; if (typeof this.dateLimit === 'object') { var minDate = moment(endDate).subtract(this.dateLimit).startOf('day'); if (startDate.isBefore(minDate)) { startDate = minDate; } } } if (this.singleDatePicker && cal.hasClass('left')) { endDate = startDate.clone(); } else if (this.singleDatePicker && cal.hasClass('right')) { startDate = endDate.clone(); } cal.find('td').removeClass('active'); if (startDate.isSame(endDate) || startDate.isBefore(endDate)) { $(e.target).addClass('active'); this.startDate = startDate; this.endDate = endDate; this.chosenLabel = this.locale.customRangeLabel; } else if (startDate.isAfter(endDate)) { $(e.target).addClass('active'); var difference = this.endDate.diff(this.startDate); this.startDate = startDate; this.endDate = moment(startDate).add('ms', difference); this.chosenLabel = this.locale.customRangeLabel; } this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()); this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()); this.updateCalendars(); if (!this.timePicker) endDate.endOf('day'); if (this.singleDatePicker) this.clickApply(); }, clickApply: function (e) { this.updateInputText(); this.hide(); this.element.trigger('apply.daterangepicker', this); }, clickCancel: function (e) { this.startDate = this.oldStartDate; this.endDate = this.oldEndDate; this.chosenLabel = this.oldChosenLabel; this.updateView(); this.updateCalendars(); this.hide(); this.element.trigger('cancel.daterangepicker', this); }, updateMonthYear: function (e) { var isLeft = $(e.target).closest('.calendar').hasClass('left'), leftOrRight = isLeft ? 'left' : 'right', cal = this.container.find('.calendar.'+leftOrRight); // Month must be Number for new moment versions var month = parseInt(cal.find('.monthselect').val(), 10); var year = cal.find('.yearselect').val(); this[leftOrRight+'Calendar'].month.month(month).year(year); this.updateCalendars(); }, updateTime: function(e) { var cal = $(e.target).closest('.calendar'), isLeft = cal.hasClass('left'); var hour = parseInt(cal.find('.hourselect').val(), 10); var minute = parseInt(cal.find('.minuteselect').val(), 10); if (this.timePicker12Hour) { var ampm = cal.find('.ampmselect').val(); if (ampm === 'PM' && hour < 12) hour += 12; if (ampm === 'AM' && hour === 12) hour = 0; } if (isLeft) { var start = this.startDate.clone(); start.hour(hour); start.minute(minute); this.startDate = start; this.leftCalendar.month.hour(hour).minute(minute); } else { var end = this.endDate.clone(); end.hour(hour); end.minute(minute); this.endDate = end; this.rightCalendar.month.hour(hour).minute(minute); } this.updateCalendars(); }, updateCalendars: function () { this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left'); this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right'); this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate)); this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate)); this.container.find('.ranges li').removeClass('active'); var customRange = true; var i = 0; for (var range in this.ranges) { if (this.timePicker) { if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) { customRange = false; this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')') .addClass('active').html(); } } else { //ignore times when comparing dates if time picker is not enabled if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) { customRange = false; this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')') .addClass('active').html(); } } i++; } if (customRange) { this.chosenLabel = this.container.find('.ranges li:last') .addClass('active').html(); } }, buildCalendar: function (month, year, hour, minute, side) { var firstDay = moment([year, month, 1]); var lastMonth = moment(firstDay).subtract('month', 1).month(); var lastYear = moment(firstDay).subtract('month', 1).year(); var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth(); var dayOfWeek = firstDay.day(); var i; //initialize a 6 rows x 7 columns array for the calendar var calendar = []; for (i = 0; i < 6; i++) { calendar[i] = []; } //populate the calendar with date objects var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1; if (startDay > daysInLastMonth) startDay -= 7; if (dayOfWeek == this.locale.firstDay) startDay = daysInLastMonth - 6; var curDate = moment([lastYear, lastMonth, startDay, 12, minute]); var col, row; for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) { if (i > 0 && col % 7 === 0) { col = 0; row++; } calendar[row][col] = curDate.clone().hour(hour); curDate.hour(12); } return calendar; }, renderDropdowns: function (selected, minDate, maxDate) { var currentMonth = selected.month(); var monthHtml = '"; var currentYear = selected.year(); var maxYear = (maxDate && maxDate.year()) || (currentYear + 5); var minYear = (minDate && minDate.year()) || (currentYear - 50); var yearHtml = ''; return monthHtml + yearHtml; }, renderCalendar: function (calendar, selected, minDate, maxDate) { var html = '
              '; html += ''; html += ''; html += ''; // add empty cell for week number if (this.showWeekNumbers) html += ''; if (!minDate || minDate.isBefore(calendar[1][1])) { html += ''; } else { html += ''; } var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY"); if (this.showDropdowns) { dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate); } html += ''; if (!maxDate || maxDate.isAfter(calendar[1][1])) { html += ''; } else { html += ''; } html += ''; html += ''; // add week number label if (this.showWeekNumbers) html += ''; $.each(this.locale.daysOfWeek, function (index, dayOfWeek) { html += ''; }); html += ''; html += ''; html += ''; for (var row = 0; row < 6; row++) { html += ''; // add week number if (this.showWeekNumbers) html += ''; for (var col = 0; col < 7; col++) { var cname = 'available '; cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off'; if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) { cname = ' off disabled '; } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) { cname += ' active '; if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) { cname += ' start-date '; } if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) { cname += ' end-date '; } } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) { cname += ' in-range '; if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; } if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; } } var title = 'r' + row + 'c' + col; html += ''; } html += ''; } html += ''; html += '
              ' + dateHtml + '
              ' + this.locale.weekLabel + '' + dayOfWeek + '
              ' + calendar[row][0].week() + '' + calendar[row][col].date() + '
              '; html += '
              '; var i; if (this.timePicker) { html += '
              '; html += ' : '; html += ' '; if (this.timePicker12Hour) { html += ''; } html += '
              '; } return html; }, remove: function() { this.container.remove(); this.element.off('.daterangepicker'); this.element.removeData('daterangepicker'); } }; $.fn.daterangepicker = function (options, cb) { this.each(function () { var el = $(this); if (el.data('daterangepicker')) el.data('daterangepicker').remove(); el.data('daterangepicker', new DateRangePicker(el, options, cb)); }); return this; }; }(window.jQuery, window.moment); ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css ================================================ /*! * Bootstrap v3.1.1 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ .btn-default, .btn-primary, .btn-success, .btn-info, .btn-warning, .btn-danger { text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); } .btn-default:active, .btn-primary:active, .btn-success:active, .btn-info:active, .btn-warning:active, .btn-danger:active, .btn-default.active, .btn-primary.active, .btn-success.active, .btn-info.active, .btn-warning.active, .btn-danger.active { -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } .btn:active, .btn.active { background-image: none; } .btn-default { text-shadow: 0 1px 0 #fff; background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-color: #dbdbdb; border-color: #ccc; } .btn-default:hover, .btn-default:focus { background-color: #e0e0e0; background-position: 0 -15px; } .btn-default:active, .btn-default.active { background-color: #e0e0e0; border-color: #dbdbdb; } .btn-primary { background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-color: #2b669a; } .btn-primary:hover, .btn-primary:focus { background-color: #2d6ca2; background-position: 0 -15px; } .btn-primary:active, .btn-primary.active { background-color: #2d6ca2; border-color: #2b669a; } .btn-success { background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-color: #3e8f3e; } .btn-success:hover, .btn-success:focus { background-color: #419641; background-position: 0 -15px; } .btn-success:active, .btn-success.active { background-color: #419641; border-color: #3e8f3e; } .btn-info { background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-color: #28a4c9; } .btn-info:hover, .btn-info:focus { background-color: #2aabd2; background-position: 0 -15px; } .btn-info:active, .btn-info.active { background-color: #2aabd2; border-color: #28a4c9; } .btn-warning { background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-color: #e38d13; } .btn-warning:hover, .btn-warning:focus { background-color: #eb9316; background-position: 0 -15px; } .btn-warning:active, .btn-warning.active { background-color: #eb9316; border-color: #e38d13; } .btn-danger { background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-color: #b92c28; } .btn-danger:hover, .btn-danger:focus { background-color: #c12e2a; background-position: 0 -15px; } .btn-danger:active, .btn-danger.active { background-color: #c12e2a; border-color: #b92c28; } .thumbnail, .img-thumbnail { -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); box-shadow: 0 1px 2px rgba(0, 0, 0, .075); } .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { background-color: #e8e8e8; background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); background-repeat: repeat-x; } .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { background-color: #357ebd; background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); background-repeat: repeat-x; } .navbar-default { background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); } .navbar-default .navbar-nav > .active > a { background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); background-repeat: repeat-x; -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); } .navbar-brand, .navbar-nav > li > a { text-shadow: 0 1px 0 rgba(255, 255, 255, .25); } .navbar-inverse { background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; } .navbar-inverse .navbar-nav > .active > a { background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); background-image: linear-gradient(to bottom, #222 0%, #282828 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); background-repeat: repeat-x; -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); } .navbar-inverse .navbar-brand, .navbar-inverse .navbar-nav > li > a { text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); } .navbar-static-top, .navbar-fixed-top, .navbar-fixed-bottom { border-radius: 0; } .alert { text-shadow: 0 1px 0 rgba(255, 255, 255, .2); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); } .alert-success { background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); background-repeat: repeat-x; border-color: #b2dba1; } .alert-info { background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); background-repeat: repeat-x; border-color: #9acfea; } .alert-warning { background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); background-repeat: repeat-x; border-color: #f5e79e; } .alert-danger { background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); background-repeat: repeat-x; border-color: #dca7a7; } .progress { background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); background-repeat: repeat-x; } .progress-bar { background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); background-repeat: repeat-x; } .progress-bar-success { background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); background-repeat: repeat-x; } .progress-bar-info { background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); background-repeat: repeat-x; } .progress-bar-warning { background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); background-repeat: repeat-x; } .progress-bar-danger { background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); background-repeat: repeat-x; } .list-group { border-radius: 4px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); box-shadow: 0 1px 2px rgba(0, 0, 0, .075); } .list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus { text-shadow: 0 -1px 0 #3071a9; background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); background-repeat: repeat-x; border-color: #3278b3; } .panel { -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); box-shadow: 0 1px 2px rgba(0, 0, 0, .05); } .panel-default > .panel-heading { background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); background-repeat: repeat-x; } .panel-primary > .panel-heading { background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); background-repeat: repeat-x; } .panel-success > .panel-heading { background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); background-repeat: repeat-x; } .panel-info > .panel-heading { background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); background-repeat: repeat-x; } .panel-warning > .panel-heading { background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); background-repeat: repeat-x; } .panel-danger > .panel-heading { background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); background-repeat: repeat-x; } .well { background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); background-repeat: repeat-x; border-color: #dcdcdc; -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); } /*# sourceMappingURL=bootstrap-theme.css.map */ ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css ================================================ /*! * Bootstrap v3.1.1 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ html { font-family: sans-serif; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } body { margin: 0; } article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; } audio, canvas, progress, video { display: inline-block; vertical-align: baseline; } audio:not([controls]) { display: none; height: 0; } [hidden], template { display: none; } a { background: transparent; } a:active, a:hover { outline: 0; } abbr[title] { border-bottom: 1px dotted; } b, strong { font-weight: bold; } dfn { font-style: italic; } h1 { margin: .67em 0; font-size: 2em; } mark { color: #000; background: #ff0; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sup { top: -.5em; } sub { bottom: -.25em; } img { border: 0; } svg:not(:root) { overflow: hidden; } figure { margin: 1em 40px; } hr { height: 0; -moz-box-sizing: content-box; box-sizing: content-box; } pre { overflow: auto; } code, kbd, pre, samp { font-family: monospace, monospace; font-size: 1em; } button, input, optgroup, select, textarea { margin: 0; font: inherit; color: inherit; } button { overflow: visible; } button, select { text-transform: none; } button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; cursor: pointer; } button[disabled], html input[disabled] { cursor: default; } button::-moz-focus-inner, input::-moz-focus-inner { padding: 0; border: 0; } input { line-height: normal; } input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; } input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } input[type="search"] { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; -webkit-appearance: textfield; } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } fieldset { padding: .35em .625em .75em; margin: 0 2px; border: 1px solid #c0c0c0; } legend { padding: 0; border: 0; } textarea { overflow: auto; } optgroup { font-weight: bold; } table { border-spacing: 0; border-collapse: collapse; } td, th { padding: 0; } @media print { * { color: #000 !important; text-shadow: none !important; background: transparent !important; box-shadow: none !important; } a, a:visited { text-decoration: underline; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } select { background: #fff !important; } .navbar { display: none; } .table td, .table th { background-color: #fff !important; } .btn > .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table-bordered th, .table-bordered td { border: 1px solid #ddd !important; } } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } *:before, *:after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html { font-size: 62.5%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.42857143; color: #333; background-color: #fff; } input, button, select, textarea { font-family: inherit; font-size: inherit; line-height: inherit; } a { color: #428bca; text-decoration: none; } a:hover, a:focus { color: #2a6496; text-decoration: underline; } a:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } figure { margin: 0; } img { vertical-align: middle; } .img-responsive, .thumbnail > img, .thumbnail a > img, .carousel-inner > .item > img, .carousel-inner > .item > a > img { display: block; max-width: 100%; height: auto; } .img-rounded { border-radius: 6px; } .img-thumbnail { display: inline-block; max-width: 100%; height: auto; padding: 4px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; -webkit-transition: all .2s ease-in-out; transition: all .2s ease-in-out; } .img-circle { border-radius: 50%; } hr { margin-top: 20px; margin-bottom: 20px; border: 0; border-top: 1px solid #eee; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { font-family: inherit; font-weight: 500; line-height: 1.1; color: inherit; } h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small, h1 .small, h2 .small, h3 .small, h4 .small, h5 .small, h6 .small, .h1 .small, .h2 .small, .h3 .small, .h4 .small, .h5 .small, .h6 .small { font-weight: normal; line-height: 1; color: #999; } h1, .h1, h2, .h2, h3, .h3 { margin-top: 20px; margin-bottom: 10px; } h1 small, .h1 small, h2 small, .h2 small, h3 small, .h3 small, h1 .small, .h1 .small, h2 .small, .h2 .small, h3 .small, .h3 .small { font-size: 65%; } h4, .h4, h5, .h5, h6, .h6 { margin-top: 10px; margin-bottom: 10px; } h4 small, .h4 small, h5 small, .h5 small, h6 small, .h6 small, h4 .small, .h4 .small, h5 .small, .h5 .small, h6 .small, .h6 .small { font-size: 75%; } h1, .h1 { font-size: 36px; } h2, .h2 { font-size: 30px; } h3, .h3 { font-size: 24px; } h4, .h4 { font-size: 18px; } h5, .h5 { font-size: 14px; } h6, .h6 { font-size: 12px; } p { margin: 0 0 10px; } .lead { margin-bottom: 20px; font-size: 16px; font-weight: 200; line-height: 1.4; } @media (min-width: 768px) { .lead { font-size: 21px; } } small, .small { font-size: 85%; } cite { font-style: normal; } .text-left { text-align: left; } .text-right { text-align: right; } .text-center { text-align: center; } .text-justify { text-align: justify; } .text-muted { color: #999; } .text-primary { color: #428bca; } a.text-primary:hover { color: #3071a9; } .text-success { color: #3c763d; } a.text-success:hover { color: #2b542c; } .text-info { color: #31708f; } a.text-info:hover { color: #245269; } .text-warning { color: #8a6d3b; } a.text-warning:hover { color: #66512c; } .text-danger { color: #a94442; } a.text-danger:hover { color: #843534; } .bg-primary { color: #fff; background-color: #428bca; } a.bg-primary:hover { background-color: #3071a9; } .bg-success { background-color: #dff0d8; } a.bg-success:hover { background-color: #c1e2b3; } .bg-info { background-color: #d9edf7; } a.bg-info:hover { background-color: #afd9ee; } .bg-warning { background-color: #fcf8e3; } a.bg-warning:hover { background-color: #f7ecb5; } .bg-danger { background-color: #f2dede; } a.bg-danger:hover { background-color: #e4b9b9; } .page-header { padding-bottom: 9px; margin: 40px 0 20px; border-bottom: 1px solid #eee; } ul, ol { margin-top: 0; margin-bottom: 10px; } ul ul, ol ul, ul ol, ol ol { margin-bottom: 0; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; margin-left: -5px; list-style: none; } .list-inline > li { display: inline-block; padding-right: 5px; padding-left: 5px; } dl { margin-top: 0; margin-bottom: 20px; } dt, dd { line-height: 1.42857143; } dt { font-weight: bold; } dd { margin-left: 0; } @media (min-width: 768px) { .dl-horizontal dt { float: left; width: 160px; overflow: hidden; clear: left; text-align: right; text-overflow: ellipsis; white-space: nowrap; } .dl-horizontal dd { margin-left: 180px; } } abbr[title], abbr[data-original-title] { cursor: help; border-bottom: 1px dotted #999; } .initialism { font-size: 90%; text-transform: uppercase; } blockquote { padding: 10px 20px; margin: 0 0 20px; font-size: 17.5px; border-left: 5px solid #eee; } blockquote p:last-child, blockquote ul:last-child, blockquote ol:last-child { margin-bottom: 0; } blockquote footer, blockquote small, blockquote .small { display: block; font-size: 80%; line-height: 1.42857143; color: #999; } blockquote footer:before, blockquote small:before, blockquote .small:before { content: '\2014 \00A0'; } .blockquote-reverse, blockquote.pull-right { padding-right: 15px; padding-left: 0; text-align: right; border-right: 5px solid #eee; border-left: 0; } .blockquote-reverse footer:before, blockquote.pull-right footer:before, .blockquote-reverse small:before, blockquote.pull-right small:before, .blockquote-reverse .small:before, blockquote.pull-right .small:before { content: ''; } .blockquote-reverse footer:after, blockquote.pull-right footer:after, .blockquote-reverse small:after, blockquote.pull-right small:after, .blockquote-reverse .small:after, blockquote.pull-right .small:after { content: '\00A0 \2014'; } blockquote:before, blockquote:after { content: ""; } address { margin-bottom: 20px; font-style: normal; line-height: 1.42857143; } code, kbd, pre, samp { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; } code { padding: 2px 4px; font-size: 90%; color: #c7254e; white-space: nowrap; background-color: #f9f2f4; border-radius: 4px; } kbd { padding: 2px 4px; font-size: 90%; color: #fff; background-color: #333; border-radius: 3px; box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); } pre { display: block; padding: 9.5px; margin: 0 0 10px; font-size: 13px; line-height: 1.42857143; color: #333; word-break: break-all; word-wrap: break-word; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; } pre code { padding: 0; font-size: inherit; color: inherit; white-space: pre-wrap; background-color: transparent; border-radius: 0; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 768px) { .container { width: 750px; } } @media (min-width: 992px) { .container { width: 970px; } } @media (min-width: 1200px) { .container { width: 1170px; } } .container-fluid { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .row { margin-right: -15px; margin-left: -15px; } .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { float: left; } .col-xs-12 { width: 100%; } .col-xs-11 { width: 91.66666667%; } .col-xs-10 { width: 83.33333333%; } .col-xs-9 { width: 75%; } .col-xs-8 { width: 66.66666667%; } .col-xs-7 { width: 58.33333333%; } .col-xs-6 { width: 50%; } .col-xs-5 { width: 41.66666667%; } .col-xs-4 { width: 33.33333333%; } .col-xs-3 { width: 25%; } .col-xs-2 { width: 16.66666667%; } .col-xs-1 { width: 8.33333333%; } .col-xs-pull-12 { right: 100%; } .col-xs-pull-11 { right: 91.66666667%; } .col-xs-pull-10 { right: 83.33333333%; } .col-xs-pull-9 { right: 75%; } .col-xs-pull-8 { right: 66.66666667%; } .col-xs-pull-7 { right: 58.33333333%; } .col-xs-pull-6 { right: 50%; } .col-xs-pull-5 { right: 41.66666667%; } .col-xs-pull-4 { right: 33.33333333%; } .col-xs-pull-3 { right: 25%; } .col-xs-pull-2 { right: 16.66666667%; } .col-xs-pull-1 { right: 8.33333333%; } .col-xs-pull-0 { right: 0; } .col-xs-push-12 { left: 100%; } .col-xs-push-11 { left: 91.66666667%; } .col-xs-push-10 { left: 83.33333333%; } .col-xs-push-9 { left: 75%; } .col-xs-push-8 { left: 66.66666667%; } .col-xs-push-7 { left: 58.33333333%; } .col-xs-push-6 { left: 50%; } .col-xs-push-5 { left: 41.66666667%; } .col-xs-push-4 { left: 33.33333333%; } .col-xs-push-3 { left: 25%; } .col-xs-push-2 { left: 16.66666667%; } .col-xs-push-1 { left: 8.33333333%; } .col-xs-push-0 { left: 0; } .col-xs-offset-12 { margin-left: 100%; } .col-xs-offset-11 { margin-left: 91.66666667%; } .col-xs-offset-10 { margin-left: 83.33333333%; } .col-xs-offset-9 { margin-left: 75%; } .col-xs-offset-8 { margin-left: 66.66666667%; } .col-xs-offset-7 { margin-left: 58.33333333%; } .col-xs-offset-6 { margin-left: 50%; } .col-xs-offset-5 { margin-left: 41.66666667%; } .col-xs-offset-4 { margin-left: 33.33333333%; } .col-xs-offset-3 { margin-left: 25%; } .col-xs-offset-2 { margin-left: 16.66666667%; } .col-xs-offset-1 { margin-left: 8.33333333%; } .col-xs-offset-0 { margin-left: 0; } @media (min-width: 768px) { .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { float: left; } .col-sm-12 { width: 100%; } .col-sm-11 { width: 91.66666667%; } .col-sm-10 { width: 83.33333333%; } .col-sm-9 { width: 75%; } .col-sm-8 { width: 66.66666667%; } .col-sm-7 { width: 58.33333333%; } .col-sm-6 { width: 50%; } .col-sm-5 { width: 41.66666667%; } .col-sm-4 { width: 33.33333333%; } .col-sm-3 { width: 25%; } .col-sm-2 { width: 16.66666667%; } .col-sm-1 { width: 8.33333333%; } .col-sm-pull-12 { right: 100%; } .col-sm-pull-11 { right: 91.66666667%; } .col-sm-pull-10 { right: 83.33333333%; } .col-sm-pull-9 { right: 75%; } .col-sm-pull-8 { right: 66.66666667%; } .col-sm-pull-7 { right: 58.33333333%; } .col-sm-pull-6 { right: 50%; } .col-sm-pull-5 { right: 41.66666667%; } .col-sm-pull-4 { right: 33.33333333%; } .col-sm-pull-3 { right: 25%; } .col-sm-pull-2 { right: 16.66666667%; } .col-sm-pull-1 { right: 8.33333333%; } .col-sm-pull-0 { right: 0; } .col-sm-push-12 { left: 100%; } .col-sm-push-11 { left: 91.66666667%; } .col-sm-push-10 { left: 83.33333333%; } .col-sm-push-9 { left: 75%; } .col-sm-push-8 { left: 66.66666667%; } .col-sm-push-7 { left: 58.33333333%; } .col-sm-push-6 { left: 50%; } .col-sm-push-5 { left: 41.66666667%; } .col-sm-push-4 { left: 33.33333333%; } .col-sm-push-3 { left: 25%; } .col-sm-push-2 { left: 16.66666667%; } .col-sm-push-1 { left: 8.33333333%; } .col-sm-push-0 { left: 0; } .col-sm-offset-12 { margin-left: 100%; } .col-sm-offset-11 { margin-left: 91.66666667%; } .col-sm-offset-10 { margin-left: 83.33333333%; } .col-sm-offset-9 { margin-left: 75%; } .col-sm-offset-8 { margin-left: 66.66666667%; } .col-sm-offset-7 { margin-left: 58.33333333%; } .col-sm-offset-6 { margin-left: 50%; } .col-sm-offset-5 { margin-left: 41.66666667%; } .col-sm-offset-4 { margin-left: 33.33333333%; } .col-sm-offset-3 { margin-left: 25%; } .col-sm-offset-2 { margin-left: 16.66666667%; } .col-sm-offset-1 { margin-left: 8.33333333%; } .col-sm-offset-0 { margin-left: 0; } } @media (min-width: 992px) { .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { float: left; } .col-md-12 { width: 100%; } .col-md-11 { width: 91.66666667%; } .col-md-10 { width: 83.33333333%; } .col-md-9 { width: 75%; } .col-md-8 { width: 66.66666667%; } .col-md-7 { width: 58.33333333%; } .col-md-6 { width: 50%; } .col-md-5 { width: 41.66666667%; } .col-md-4 { width: 33.33333333%; } .col-md-3 { width: 25%; } .col-md-2 { width: 16.66666667%; } .col-md-1 { width: 8.33333333%; } .col-md-pull-12 { right: 100%; } .col-md-pull-11 { right: 91.66666667%; } .col-md-pull-10 { right: 83.33333333%; } .col-md-pull-9 { right: 75%; } .col-md-pull-8 { right: 66.66666667%; } .col-md-pull-7 { right: 58.33333333%; } .col-md-pull-6 { right: 50%; } .col-md-pull-5 { right: 41.66666667%; } .col-md-pull-4 { right: 33.33333333%; } .col-md-pull-3 { right: 25%; } .col-md-pull-2 { right: 16.66666667%; } .col-md-pull-1 { right: 8.33333333%; } .col-md-pull-0 { right: 0; } .col-md-push-12 { left: 100%; } .col-md-push-11 { left: 91.66666667%; } .col-md-push-10 { left: 83.33333333%; } .col-md-push-9 { left: 75%; } .col-md-push-8 { left: 66.66666667%; } .col-md-push-7 { left: 58.33333333%; } .col-md-push-6 { left: 50%; } .col-md-push-5 { left: 41.66666667%; } .col-md-push-4 { left: 33.33333333%; } .col-md-push-3 { left: 25%; } .col-md-push-2 { left: 16.66666667%; } .col-md-push-1 { left: 8.33333333%; } .col-md-push-0 { left: 0; } .col-md-offset-12 { margin-left: 100%; } .col-md-offset-11 { margin-left: 91.66666667%; } .col-md-offset-10 { margin-left: 83.33333333%; } .col-md-offset-9 { margin-left: 75%; } .col-md-offset-8 { margin-left: 66.66666667%; } .col-md-offset-7 { margin-left: 58.33333333%; } .col-md-offset-6 { margin-left: 50%; } .col-md-offset-5 { margin-left: 41.66666667%; } .col-md-offset-4 { margin-left: 33.33333333%; } .col-md-offset-3 { margin-left: 25%; } .col-md-offset-2 { margin-left: 16.66666667%; } .col-md-offset-1 { margin-left: 8.33333333%; } .col-md-offset-0 { margin-left: 0; } } @media (min-width: 1200px) { .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { float: left; } .col-lg-12 { width: 100%; } .col-lg-11 { width: 91.66666667%; } .col-lg-10 { width: 83.33333333%; } .col-lg-9 { width: 75%; } .col-lg-8 { width: 66.66666667%; } .col-lg-7 { width: 58.33333333%; } .col-lg-6 { width: 50%; } .col-lg-5 { width: 41.66666667%; } .col-lg-4 { width: 33.33333333%; } .col-lg-3 { width: 25%; } .col-lg-2 { width: 16.66666667%; } .col-lg-1 { width: 8.33333333%; } .col-lg-pull-12 { right: 100%; } .col-lg-pull-11 { right: 91.66666667%; } .col-lg-pull-10 { right: 83.33333333%; } .col-lg-pull-9 { right: 75%; } .col-lg-pull-8 { right: 66.66666667%; } .col-lg-pull-7 { right: 58.33333333%; } .col-lg-pull-6 { right: 50%; } .col-lg-pull-5 { right: 41.66666667%; } .col-lg-pull-4 { right: 33.33333333%; } .col-lg-pull-3 { right: 25%; } .col-lg-pull-2 { right: 16.66666667%; } .col-lg-pull-1 { right: 8.33333333%; } .col-lg-pull-0 { right: 0; } .col-lg-push-12 { left: 100%; } .col-lg-push-11 { left: 91.66666667%; } .col-lg-push-10 { left: 83.33333333%; } .col-lg-push-9 { left: 75%; } .col-lg-push-8 { left: 66.66666667%; } .col-lg-push-7 { left: 58.33333333%; } .col-lg-push-6 { left: 50%; } .col-lg-push-5 { left: 41.66666667%; } .col-lg-push-4 { left: 33.33333333%; } .col-lg-push-3 { left: 25%; } .col-lg-push-2 { left: 16.66666667%; } .col-lg-push-1 { left: 8.33333333%; } .col-lg-push-0 { left: 0; } .col-lg-offset-12 { margin-left: 100%; } .col-lg-offset-11 { margin-left: 91.66666667%; } .col-lg-offset-10 { margin-left: 83.33333333%; } .col-lg-offset-9 { margin-left: 75%; } .col-lg-offset-8 { margin-left: 66.66666667%; } .col-lg-offset-7 { margin-left: 58.33333333%; } .col-lg-offset-6 { margin-left: 50%; } .col-lg-offset-5 { margin-left: 41.66666667%; } .col-lg-offset-4 { margin-left: 33.33333333%; } .col-lg-offset-3 { margin-left: 25%; } .col-lg-offset-2 { margin-left: 16.66666667%; } .col-lg-offset-1 { margin-left: 8.33333333%; } .col-lg-offset-0 { margin-left: 0; } } table { max-width: 100%; background-color: transparent; } th { text-align: left; } .table { width: 100%; margin-bottom: 20px; } .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { padding: 8px; line-height: 1.42857143; vertical-align: top; border-top: 1px solid #ddd; } .table > thead > tr > th { vertical-align: bottom; border-bottom: 2px solid #ddd; } .table > caption + thead > tr:first-child > th, .table > colgroup + thead > tr:first-child > th, .table > thead:first-child > tr:first-child > th, .table > caption + thead > tr:first-child > td, .table > colgroup + thead > tr:first-child > td, .table > thead:first-child > tr:first-child > td { border-top: 0; } .table > tbody + tbody { border-top: 2px solid #ddd; } .table .table { background-color: #fff; } .table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td { padding: 5px; } .table-bordered { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { border-bottom-width: 2px; } .table-striped > tbody > tr:nth-child(odd) > td, .table-striped > tbody > tr:nth-child(odd) > th { background-color: #f9f9f9; } .table-hover > tbody > tr:hover > td, .table-hover > tbody > tr:hover > th { background-color: #f5f5f5; } table col[class*="col-"] { position: static; display: table-column; float: none; } table td[class*="col-"], table th[class*="col-"] { position: static; display: table-cell; float: none; } .table > thead > tr > td.active, .table > tbody > tr > td.active, .table > tfoot > tr > td.active, .table > thead > tr > th.active, .table > tbody > tr > th.active, .table > tfoot > tr > th.active, .table > thead > tr.active > td, .table > tbody > tr.active > td, .table > tfoot > tr.active > td, .table > thead > tr.active > th, .table > tbody > tr.active > th, .table > tfoot > tr.active > th { background-color: #f5f5f5; } .table-hover > tbody > tr > td.active:hover, .table-hover > tbody > tr > th.active:hover, .table-hover > tbody > tr.active:hover > td, .table-hover > tbody > tr.active:hover > th { background-color: #e8e8e8; } .table > thead > tr > td.success, .table > tbody > tr > td.success, .table > tfoot > tr > td.success, .table > thead > tr > th.success, .table > tbody > tr > th.success, .table > tfoot > tr > th.success, .table > thead > tr.success > td, .table > tbody > tr.success > td, .table > tfoot > tr.success > td, .table > thead > tr.success > th, .table > tbody > tr.success > th, .table > tfoot > tr.success > th { background-color: #dff0d8; } .table-hover > tbody > tr > td.success:hover, .table-hover > tbody > tr > th.success:hover, .table-hover > tbody > tr.success:hover > td, .table-hover > tbody > tr.success:hover > th { background-color: #d0e9c6; } .table > thead > tr > td.info, .table > tbody > tr > td.info, .table > tfoot > tr > td.info, .table > thead > tr > th.info, .table > tbody > tr > th.info, .table > tfoot > tr > th.info, .table > thead > tr.info > td, .table > tbody > tr.info > td, .table > tfoot > tr.info > td, .table > thead > tr.info > th, .table > tbody > tr.info > th, .table > tfoot > tr.info > th { background-color: #d9edf7; } .table-hover > tbody > tr > td.info:hover, .table-hover > tbody > tr > th.info:hover, .table-hover > tbody > tr.info:hover > td, .table-hover > tbody > tr.info:hover > th { background-color: #c4e3f3; } .table > thead > tr > td.warning, .table > tbody > tr > td.warning, .table > tfoot > tr > td.warning, .table > thead > tr > th.warning, .table > tbody > tr > th.warning, .table > tfoot > tr > th.warning, .table > thead > tr.warning > td, .table > tbody > tr.warning > td, .table > tfoot > tr.warning > td, .table > thead > tr.warning > th, .table > tbody > tr.warning > th, .table > tfoot > tr.warning > th { background-color: #fcf8e3; } .table-hover > tbody > tr > td.warning:hover, .table-hover > tbody > tr > th.warning:hover, .table-hover > tbody > tr.warning:hover > td, .table-hover > tbody > tr.warning:hover > th { background-color: #faf2cc; } .table > thead > tr > td.danger, .table > tbody > tr > td.danger, .table > tfoot > tr > td.danger, .table > thead > tr > th.danger, .table > tbody > tr > th.danger, .table > tfoot > tr > th.danger, .table > thead > tr.danger > td, .table > tbody > tr.danger > td, .table > tfoot > tr.danger > td, .table > thead > tr.danger > th, .table > tbody > tr.danger > th, .table > tfoot > tr.danger > th { background-color: #f2dede; } .table-hover > tbody > tr > td.danger:hover, .table-hover > tbody > tr > th.danger:hover, .table-hover > tbody > tr.danger:hover > td, .table-hover > tbody > tr.danger:hover > th { background-color: #ebcccc; } @media (max-width: 767px) { .table-responsive { width: 100%; margin-bottom: 15px; overflow-x: scroll; overflow-y: hidden; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid #ddd; } .table-responsive > .table { margin-bottom: 0; } .table-responsive > .table > thead > tr > th, .table-responsive > .table > tbody > tr > th, .table-responsive > .table > tfoot > tr > th, .table-responsive > .table > thead > tr > td, .table-responsive > .table > tbody > tr > td, .table-responsive > .table > tfoot > tr > td { white-space: nowrap; } .table-responsive > .table-bordered { border: 0; } .table-responsive > .table-bordered > thead > tr > th:first-child, .table-responsive > .table-bordered > tbody > tr > th:first-child, .table-responsive > .table-bordered > tfoot > tr > th:first-child, .table-responsive > .table-bordered > thead > tr > td:first-child, .table-responsive > .table-bordered > tbody > tr > td:first-child, .table-responsive > .table-bordered > tfoot > tr > td:first-child { border-left: 0; } .table-responsive > .table-bordered > thead > tr > th:last-child, .table-responsive > .table-bordered > tbody > tr > th:last-child, .table-responsive > .table-bordered > tfoot > tr > th:last-child, .table-responsive > .table-bordered > thead > tr > td:last-child, .table-responsive > .table-bordered > tbody > tr > td:last-child, .table-responsive > .table-bordered > tfoot > tr > td:last-child { border-right: 0; } .table-responsive > .table-bordered > tbody > tr:last-child > th, .table-responsive > .table-bordered > tfoot > tr:last-child > th, .table-responsive > .table-bordered > tbody > tr:last-child > td, .table-responsive > .table-bordered > tfoot > tr:last-child > td { border-bottom: 0; } } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; padding: 0; margin-bottom: 20px; font-size: 21px; line-height: inherit; color: #333; border: 0; border-bottom: 1px solid #e5e5e5; } label { display: inline-block; margin-bottom: 5px; font-weight: bold; } input[type="search"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } input[type="radio"], input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; /* IE8-9 */ line-height: normal; } input[type="file"] { display: block; } input[type="range"] { display: block; width: 100%; } select[multiple], select[size] { height: auto; } input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } output { display: block; padding-top: 7px; font-size: 14px; line-height: 1.42857143; color: #555; } .form-control { display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } .form-control:focus { border-color: #66afe9; outline: 0; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); } .form-control::-moz-placeholder { color: #999; opacity: 1; } .form-control:-ms-input-placeholder { color: #999; } .form-control::-webkit-input-placeholder { color: #999; } .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { cursor: not-allowed; background-color: #eee; opacity: 1; } textarea.form-control { height: auto; } input[type="search"] { -webkit-appearance: none; } input[type="date"] { line-height: 34px; } .form-group { margin-bottom: 15px; } .radio, .checkbox { display: block; min-height: 20px; padding-left: 20px; margin-top: 10px; margin-bottom: 10px; } .radio label, .checkbox label { display: inline; font-weight: normal; cursor: pointer; } .radio input[type="radio"], .radio-inline input[type="radio"], .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { float: left; margin-left: -20px; } .radio + .radio, .checkbox + .checkbox { margin-top: -5px; } .radio-inline, .checkbox-inline { display: inline-block; padding-left: 20px; margin-bottom: 0; font-weight: normal; vertical-align: middle; cursor: pointer; } .radio-inline + .radio-inline, .checkbox-inline + .checkbox-inline { margin-top: 0; margin-left: 10px; } input[type="radio"][disabled], input[type="checkbox"][disabled], .radio[disabled], .radio-inline[disabled], .checkbox[disabled], .checkbox-inline[disabled], fieldset[disabled] input[type="radio"], fieldset[disabled] input[type="checkbox"], fieldset[disabled] .radio, fieldset[disabled] .radio-inline, fieldset[disabled] .checkbox, fieldset[disabled] .checkbox-inline { cursor: not-allowed; } .input-sm { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } select.input-sm { height: 30px; line-height: 30px; } textarea.input-sm, select[multiple].input-sm { height: auto; } .input-lg { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.33; border-radius: 6px; } select.input-lg { height: 46px; line-height: 46px; } textarea.input-lg, select[multiple].input-lg { height: auto; } .has-feedback { position: relative; } .has-feedback .form-control { padding-right: 42.5px; } .has-feedback .form-control-feedback { position: absolute; top: 25px; right: 0; display: block; width: 34px; height: 34px; line-height: 34px; text-align: center; } .has-success .help-block, .has-success .control-label, .has-success .radio, .has-success .checkbox, .has-success .radio-inline, .has-success .checkbox-inline { color: #3c763d; } .has-success .form-control { border-color: #3c763d; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } .has-success .form-control:focus { border-color: #2b542c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; } .has-success .input-group-addon { color: #3c763d; background-color: #dff0d8; border-color: #3c763d; } .has-success .form-control-feedback { color: #3c763d; } .has-warning .help-block, .has-warning .control-label, .has-warning .radio, .has-warning .checkbox, .has-warning .radio-inline, .has-warning .checkbox-inline { color: #8a6d3b; } .has-warning .form-control { border-color: #8a6d3b; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } .has-warning .form-control:focus { border-color: #66512c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; } .has-warning .input-group-addon { color: #8a6d3b; background-color: #fcf8e3; border-color: #8a6d3b; } .has-warning .form-control-feedback { color: #8a6d3b; } .has-error .help-block, .has-error .control-label, .has-error .radio, .has-error .checkbox, .has-error .radio-inline, .has-error .checkbox-inline { color: #a94442; } .has-error .form-control { border-color: #a94442; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } .has-error .form-control:focus { border-color: #843534; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; } .has-error .input-group-addon { color: #a94442; background-color: #f2dede; border-color: #a94442; } .has-error .form-control-feedback { color: #a94442; } .form-control-static { margin-bottom: 0; } .help-block { display: block; margin-top: 5px; margin-bottom: 10px; color: #737373; } @media (min-width: 768px) { .form-inline .form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .input-group > .form-control { width: 100%; } .form-inline .control-label { margin-bottom: 0; vertical-align: middle; } .form-inline .radio, .form-inline .checkbox { display: inline-block; padding-left: 0; margin-top: 0; margin-bottom: 0; vertical-align: middle; } .form-inline .radio input[type="radio"], .form-inline .checkbox input[type="checkbox"] { float: none; margin-left: 0; } .form-inline .has-feedback .form-control-feedback { top: 0; } } .form-horizontal .control-label, .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline { padding-top: 7px; margin-top: 0; margin-bottom: 0; } .form-horizontal .radio, .form-horizontal .checkbox { min-height: 27px; } .form-horizontal .form-group { margin-right: -15px; margin-left: -15px; } .form-horizontal .form-control-static { padding-top: 7px; } @media (min-width: 768px) { .form-horizontal .control-label { text-align: right; } } .form-horizontal .has-feedback .form-control-feedback { top: 0; right: 15px; } .btn { display: inline-block; padding: 6px 12px; margin-bottom: 0; font-size: 14px; font-weight: normal; line-height: 1.42857143; text-align: center; white-space: nowrap; vertical-align: middle; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-image: none; border: 1px solid transparent; border-radius: 4px; } .btn:focus, .btn:active:focus, .btn.active:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .btn:hover, .btn:focus { color: #333; text-decoration: none; } .btn:active, .btn.active { background-image: none; outline: 0; -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } .btn.disabled, .btn[disabled], fieldset[disabled] .btn { pointer-events: none; cursor: not-allowed; filter: alpha(opacity=65); -webkit-box-shadow: none; box-shadow: none; opacity: .65; } .btn-default { color: #333; background-color: #fff; border-color: #ccc; } .btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { color: #333; background-color: #ebebeb; border-color: #adadad; } .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { background-image: none; } .btn-default.disabled, .btn-default[disabled], fieldset[disabled] .btn-default, .btn-default.disabled:hover, .btn-default[disabled]:hover, fieldset[disabled] .btn-default:hover, .btn-default.disabled:focus, .btn-default[disabled]:focus, fieldset[disabled] .btn-default:focus, .btn-default.disabled:active, .btn-default[disabled]:active, fieldset[disabled] .btn-default:active, .btn-default.disabled.active, .btn-default[disabled].active, fieldset[disabled] .btn-default.active { background-color: #fff; border-color: #ccc; } .btn-default .badge { color: #fff; background-color: #333; } .btn-primary { color: #fff; background-color: #428bca; border-color: #357ebd; } .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { color: #fff; background-color: #3276b1; border-color: #285e8e; } .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { background-image: none; } .btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { background-color: #428bca; border-color: #357ebd; } .btn-primary .badge { color: #428bca; background-color: #fff; } .btn-success { color: #fff; background-color: #5cb85c; border-color: #4cae4c; } .btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { color: #fff; background-color: #47a447; border-color: #398439; } .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { background-image: none; } .btn-success.disabled, .btn-success[disabled], fieldset[disabled] .btn-success, .btn-success.disabled:hover, .btn-success[disabled]:hover, fieldset[disabled] .btn-success:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, fieldset[disabled] .btn-success:focus, .btn-success.disabled:active, .btn-success[disabled]:active, fieldset[disabled] .btn-success:active, .btn-success.disabled.active, .btn-success[disabled].active, fieldset[disabled] .btn-success.active { background-color: #5cb85c; border-color: #4cae4c; } .btn-success .badge { color: #5cb85c; background-color: #fff; } .btn-info { color: #fff; background-color: #5bc0de; border-color: #46b8da; } .btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { color: #fff; background-color: #39b3d7; border-color: #269abc; } .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { background-image: none; } .btn-info.disabled, .btn-info[disabled], fieldset[disabled] .btn-info, .btn-info.disabled:hover, .btn-info[disabled]:hover, fieldset[disabled] .btn-info:hover, .btn-info.disabled:focus, .btn-info[disabled]:focus, fieldset[disabled] .btn-info:focus, .btn-info.disabled:active, .btn-info[disabled]:active, fieldset[disabled] .btn-info:active, .btn-info.disabled.active, .btn-info[disabled].active, fieldset[disabled] .btn-info.active { background-color: #5bc0de; border-color: #46b8da; } .btn-info .badge { color: #5bc0de; background-color: #fff; } .btn-warning { color: #fff; background-color: #f0ad4e; border-color: #eea236; } .btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { color: #fff; background-color: #ed9c28; border-color: #d58512; } .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { background-image: none; } .btn-warning.disabled, .btn-warning[disabled], fieldset[disabled] .btn-warning, .btn-warning.disabled:hover, .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning:hover, .btn-warning.disabled:focus, .btn-warning[disabled]:focus, fieldset[disabled] .btn-warning:focus, .btn-warning.disabled:active, .btn-warning[disabled]:active, fieldset[disabled] .btn-warning:active, .btn-warning.disabled.active, .btn-warning[disabled].active, fieldset[disabled] .btn-warning.active { background-color: #f0ad4e; border-color: #eea236; } .btn-warning .badge { color: #f0ad4e; background-color: #fff; } .btn-danger { color: #fff; background-color: #d9534f; border-color: #d43f3a; } .btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { color: #fff; background-color: #d2322d; border-color: #ac2925; } .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { background-image: none; } .btn-danger.disabled, .btn-danger[disabled], fieldset[disabled] .btn-danger, .btn-danger.disabled:hover, .btn-danger[disabled]:hover, fieldset[disabled] .btn-danger:hover, .btn-danger.disabled:focus, .btn-danger[disabled]:focus, fieldset[disabled] .btn-danger:focus, .btn-danger.disabled:active, .btn-danger[disabled]:active, fieldset[disabled] .btn-danger:active, .btn-danger.disabled.active, .btn-danger[disabled].active, fieldset[disabled] .btn-danger.active { background-color: #d9534f; border-color: #d43f3a; } .btn-danger .badge { color: #d9534f; background-color: #fff; } .btn-link { font-weight: normal; color: #428bca; cursor: pointer; border-radius: 0; } .btn-link, .btn-link:active, .btn-link[disabled], fieldset[disabled] .btn-link { background-color: transparent; -webkit-box-shadow: none; box-shadow: none; } .btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active { border-color: transparent; } .btn-link:hover, .btn-link:focus { color: #2a6496; text-decoration: underline; background-color: transparent; } .btn-link[disabled]:hover, fieldset[disabled] .btn-link:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:focus { color: #999; text-decoration: none; } .btn-lg, .btn-group-lg > .btn { padding: 10px 16px; font-size: 18px; line-height: 1.33; border-radius: 6px; } .btn-sm, .btn-group-sm > .btn { padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .btn-xs, .btn-group-xs > .btn { padding: 1px 5px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .btn-block { display: block; width: 100%; padding-right: 0; padding-left: 0; } .btn-block + .btn-block { margin-top: 5px; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { opacity: 0; -webkit-transition: opacity .15s linear; transition: opacity .15s linear; } .fade.in { opacity: 1; } .collapse { display: none; } .collapse.in { display: block; } .collapsing { position: relative; height: 0; overflow: hidden; -webkit-transition: height .35s ease; transition: height .35s ease; } @font-face { font-family: 'Glyphicons Halflings'; src: url('../fonts/glyphicons-halflings-regular.eot'); src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); } .glyphicon { position: relative; top: 1px; display: inline-block; font-family: 'Glyphicons Halflings'; font-style: normal; font-weight: normal; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .glyphicon-asterisk:before { content: "\2a"; } .glyphicon-plus:before { content: "\2b"; } .glyphicon-euro:before { content: "\20ac"; } .glyphicon-minus:before { content: "\2212"; } .glyphicon-cloud:before { content: "\2601"; } .glyphicon-envelope:before { content: "\2709"; } .glyphicon-pencil:before { content: "\270f"; } .glyphicon-glass:before { content: "\e001"; } .glyphicon-music:before { content: "\e002"; } .glyphicon-search:before { content: "\e003"; } .glyphicon-heart:before { content: "\e005"; } .glyphicon-star:before { content: "\e006"; } .glyphicon-star-empty:before { content: "\e007"; } .glyphicon-user:before { content: "\e008"; } .glyphicon-film:before { content: "\e009"; } .glyphicon-th-large:before { content: "\e010"; } .glyphicon-th:before { content: "\e011"; } .glyphicon-th-list:before { content: "\e012"; } .glyphicon-ok:before { content: "\e013"; } .glyphicon-remove:before { content: "\e014"; } .glyphicon-zoom-in:before { content: "\e015"; } .glyphicon-zoom-out:before { content: "\e016"; } .glyphicon-off:before { content: "\e017"; } .glyphicon-signal:before { content: "\e018"; } .glyphicon-cog:before { content: "\e019"; } .glyphicon-trash:before { content: "\e020"; } .glyphicon-home:before { content: "\e021"; } .glyphicon-file:before { content: "\e022"; } .glyphicon-time:before { content: "\e023"; } .glyphicon-road:before { content: "\e024"; } .glyphicon-download-alt:before { content: "\e025"; } .glyphicon-download:before { content: "\e026"; } .glyphicon-upload:before { content: "\e027"; } .glyphicon-inbox:before { content: "\e028"; } .glyphicon-play-circle:before { content: "\e029"; } .glyphicon-repeat:before { content: "\e030"; } .glyphicon-refresh:before { content: "\e031"; } .glyphicon-list-alt:before { content: "\e032"; } .glyphicon-lock:before { content: "\e033"; } .glyphicon-flag:before { content: "\e034"; } .glyphicon-headphones:before { content: "\e035"; } .glyphicon-volume-off:before { content: "\e036"; } .glyphicon-volume-down:before { content: "\e037"; } .glyphicon-volume-up:before { content: "\e038"; } .glyphicon-qrcode:before { content: "\e039"; } .glyphicon-barcode:before { content: "\e040"; } .glyphicon-tag:before { content: "\e041"; } .glyphicon-tags:before { content: "\e042"; } .glyphicon-book:before { content: "\e043"; } .glyphicon-bookmark:before { content: "\e044"; } .glyphicon-print:before { content: "\e045"; } .glyphicon-camera:before { content: "\e046"; } .glyphicon-font:before { content: "\e047"; } .glyphicon-bold:before { content: "\e048"; } .glyphicon-italic:before { content: "\e049"; } .glyphicon-text-height:before { content: "\e050"; } .glyphicon-text-width:before { content: "\e051"; } .glyphicon-align-left:before { content: "\e052"; } .glyphicon-align-center:before { content: "\e053"; } .glyphicon-align-right:before { content: "\e054"; } .glyphicon-align-justify:before { content: "\e055"; } .glyphicon-list:before { content: "\e056"; } .glyphicon-indent-left:before { content: "\e057"; } .glyphicon-indent-right:before { content: "\e058"; } .glyphicon-facetime-video:before { content: "\e059"; } .glyphicon-picture:before { content: "\e060"; } .glyphicon-map-marker:before { content: "\e062"; } .glyphicon-adjust:before { content: "\e063"; } .glyphicon-tint:before { content: "\e064"; } .glyphicon-edit:before { content: "\e065"; } .glyphicon-share:before { content: "\e066"; } .glyphicon-check:before { content: "\e067"; } .glyphicon-move:before { content: "\e068"; } .glyphicon-step-backward:before { content: "\e069"; } .glyphicon-fast-backward:before { content: "\e070"; } .glyphicon-backward:before { content: "\e071"; } .glyphicon-play:before { content: "\e072"; } .glyphicon-pause:before { content: "\e073"; } .glyphicon-stop:before { content: "\e074"; } .glyphicon-forward:before { content: "\e075"; } .glyphicon-fast-forward:before { content: "\e076"; } .glyphicon-step-forward:before { content: "\e077"; } .glyphicon-eject:before { content: "\e078"; } .glyphicon-chevron-left:before { content: "\e079"; } .glyphicon-chevron-right:before { content: "\e080"; } .glyphicon-plus-sign:before { content: "\e081"; } .glyphicon-minus-sign:before { content: "\e082"; } .glyphicon-remove-sign:before { content: "\e083"; } .glyphicon-ok-sign:before { content: "\e084"; } .glyphicon-question-sign:before { content: "\e085"; } .glyphicon-info-sign:before { content: "\e086"; } .glyphicon-screenshot:before { content: "\e087"; } .glyphicon-remove-circle:before { content: "\e088"; } .glyphicon-ok-circle:before { content: "\e089"; } .glyphicon-ban-circle:before { content: "\e090"; } .glyphicon-arrow-left:before { content: "\e091"; } .glyphicon-arrow-right:before { content: "\e092"; } .glyphicon-arrow-up:before { content: "\e093"; } .glyphicon-arrow-down:before { content: "\e094"; } .glyphicon-share-alt:before { content: "\e095"; } .glyphicon-resize-full:before { content: "\e096"; } .glyphicon-resize-small:before { content: "\e097"; } .glyphicon-exclamation-sign:before { content: "\e101"; } .glyphicon-gift:before { content: "\e102"; } .glyphicon-leaf:before { content: "\e103"; } .glyphicon-fire:before { content: "\e104"; } .glyphicon-eye-open:before { content: "\e105"; } .glyphicon-eye-close:before { content: "\e106"; } .glyphicon-warning-sign:before { content: "\e107"; } .glyphicon-plane:before { content: "\e108"; } .glyphicon-calendar:before { content: "\e109"; } .glyphicon-random:before { content: "\e110"; } .glyphicon-comment:before { content: "\e111"; } .glyphicon-magnet:before { content: "\e112"; } .glyphicon-chevron-up:before { content: "\e113"; } .glyphicon-chevron-down:before { content: "\e114"; } .glyphicon-retweet:before { content: "\e115"; } .glyphicon-shopping-cart:before { content: "\e116"; } .glyphicon-folder-close:before { content: "\e117"; } .glyphicon-folder-open:before { content: "\e118"; } .glyphicon-resize-vertical:before { content: "\e119"; } .glyphicon-resize-horizontal:before { content: "\e120"; } .glyphicon-hdd:before { content: "\e121"; } .glyphicon-bullhorn:before { content: "\e122"; } .glyphicon-bell:before { content: "\e123"; } .glyphicon-certificate:before { content: "\e124"; } .glyphicon-thumbs-up:before { content: "\e125"; } .glyphicon-thumbs-down:before { content: "\e126"; } .glyphicon-hand-right:before { content: "\e127"; } .glyphicon-hand-left:before { content: "\e128"; } .glyphicon-hand-up:before { content: "\e129"; } .glyphicon-hand-down:before { content: "\e130"; } .glyphicon-circle-arrow-right:before { content: "\e131"; } .glyphicon-circle-arrow-left:before { content: "\e132"; } .glyphicon-circle-arrow-up:before { content: "\e133"; } .glyphicon-circle-arrow-down:before { content: "\e134"; } .glyphicon-globe:before { content: "\e135"; } .glyphicon-wrench:before { content: "\e136"; } .glyphicon-tasks:before { content: "\e137"; } .glyphicon-filter:before { content: "\e138"; } .glyphicon-briefcase:before { content: "\e139"; } .glyphicon-fullscreen:before { content: "\e140"; } .glyphicon-dashboard:before { content: "\e141"; } .glyphicon-paperclip:before { content: "\e142"; } .glyphicon-heart-empty:before { content: "\e143"; } .glyphicon-link:before { content: "\e144"; } .glyphicon-phone:before { content: "\e145"; } .glyphicon-pushpin:before { content: "\e146"; } .glyphicon-usd:before { content: "\e148"; } .glyphicon-gbp:before { content: "\e149"; } .glyphicon-sort:before { content: "\e150"; } .glyphicon-sort-by-alphabet:before { content: "\e151"; } .glyphicon-sort-by-alphabet-alt:before { content: "\e152"; } .glyphicon-sort-by-order:before { content: "\e153"; } .glyphicon-sort-by-order-alt:before { content: "\e154"; } .glyphicon-sort-by-attributes:before { content: "\e155"; } .glyphicon-sort-by-attributes-alt:before { content: "\e156"; } .glyphicon-unchecked:before { content: "\e157"; } .glyphicon-expand:before { content: "\e158"; } .glyphicon-collapse-down:before { content: "\e159"; } .glyphicon-collapse-up:before { content: "\e160"; } .glyphicon-log-in:before { content: "\e161"; } .glyphicon-flash:before { content: "\e162"; } .glyphicon-log-out:before { content: "\e163"; } .glyphicon-new-window:before { content: "\e164"; } .glyphicon-record:before { content: "\e165"; } .glyphicon-save:before { content: "\e166"; } .glyphicon-open:before { content: "\e167"; } .glyphicon-saved:before { content: "\e168"; } .glyphicon-import:before { content: "\e169"; } .glyphicon-export:before { content: "\e170"; } .glyphicon-send:before { content: "\e171"; } .glyphicon-floppy-disk:before { content: "\e172"; } .glyphicon-floppy-saved:before { content: "\e173"; } .glyphicon-floppy-remove:before { content: "\e174"; } .glyphicon-floppy-save:before { content: "\e175"; } .glyphicon-floppy-open:before { content: "\e176"; } .glyphicon-credit-card:before { content: "\e177"; } .glyphicon-transfer:before { content: "\e178"; } .glyphicon-cutlery:before { content: "\e179"; } .glyphicon-header:before { content: "\e180"; } .glyphicon-compressed:before { content: "\e181"; } .glyphicon-earphone:before { content: "\e182"; } .glyphicon-phone-alt:before { content: "\e183"; } .glyphicon-tower:before { content: "\e184"; } .glyphicon-stats:before { content: "\e185"; } .glyphicon-sd-video:before { content: "\e186"; } .glyphicon-hd-video:before { content: "\e187"; } .glyphicon-subtitles:before { content: "\e188"; } .glyphicon-sound-stereo:before { content: "\e189"; } .glyphicon-sound-dolby:before { content: "\e190"; } .glyphicon-sound-5-1:before { content: "\e191"; } .glyphicon-sound-6-1:before { content: "\e192"; } .glyphicon-sound-7-1:before { content: "\e193"; } .glyphicon-copyright-mark:before { content: "\e194"; } .glyphicon-registration-mark:before { content: "\e195"; } .glyphicon-cloud-download:before { content: "\e197"; } .glyphicon-cloud-upload:before { content: "\e198"; } .glyphicon-tree-conifer:before { content: "\e199"; } .glyphicon-tree-deciduous:before { content: "\e200"; } .caret { display: inline-block; width: 0; height: 0; margin-left: 2px; vertical-align: middle; border-top: 4px solid; border-right: 4px solid transparent; border-left: 4px solid transparent; } .dropdown { position: relative; } .dropdown-toggle:focus { outline: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; font-size: 14px; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, .15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); box-shadow: 0 6px 12px rgba(0, 0, 0, .175); } .dropdown-menu.pull-right { right: 0; left: auto; } .dropdown-menu .divider { height: 1px; margin: 9px 0; overflow: hidden; background-color: #e5e5e5; } .dropdown-menu > li > a { display: block; padding: 3px 20px; clear: both; font-weight: normal; line-height: 1.42857143; color: #333; white-space: nowrap; } .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { color: #262626; text-decoration: none; background-color: #f5f5f5; } .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { color: #fff; text-decoration: none; background-color: #428bca; outline: 0; } .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { color: #999; } .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { text-decoration: none; cursor: not-allowed; background-color: transparent; background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .open > .dropdown-menu { display: block; } .open > a { outline: 0; } .dropdown-menu-right { right: 0; left: auto; } .dropdown-menu-left { right: auto; left: 0; } .dropdown-header { display: block; padding: 3px 20px; font-size: 12px; line-height: 1.42857143; color: #999; } .dropdown-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 990; } .pull-right > .dropdown-menu { right: 0; left: auto; } .dropup .caret, .navbar-fixed-bottom .dropdown .caret { content: ""; border-top: 0; border-bottom: 4px solid; } .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { top: auto; bottom: 100%; margin-bottom: 1px; } @media (min-width: 768px) { .navbar-right .dropdown-menu { right: 0; left: auto; } .navbar-right .dropdown-menu-left { right: auto; left: 0; } } .btn-group, .btn-group-vertical { position: relative; display: inline-block; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; float: left; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover, .btn-group > .btn:focus, .btn-group-vertical > .btn:focus, .btn-group > .btn:active, .btn-group-vertical > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn.active { z-index: 2; } .btn-group > .btn:focus, .btn-group-vertical > .btn:focus { outline: none; } .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group { margin-left: -1px; } .btn-toolbar { margin-left: -5px; } .btn-toolbar .btn-group, .btn-toolbar .input-group { float: left; } .btn-toolbar > .btn, .btn-toolbar > .btn-group, .btn-toolbar > .input-group { margin-left: 5px; } .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { border-radius: 0; } .btn-group > .btn:first-child { margin-left: 0; } .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:last-child:not(:first-child), .btn-group > .dropdown-toggle:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group > .btn-group { float: left; } .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group > .btn-group:first-child > .btn:last-child, .btn-group > .btn-group:first-child > .dropdown-toggle { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn-group:last-child > .btn:first-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { outline: 0; } .btn-group > .btn + .dropdown-toggle { padding-right: 8px; padding-left: 8px; } .btn-group > .btn-lg + .dropdown-toggle { padding-right: 12px; padding-left: 12px; } .btn-group.open .dropdown-toggle { -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } .btn-group.open .dropdown-toggle.btn-link { -webkit-box-shadow: none; box-shadow: none; } .btn .caret { margin-left: 0; } .btn-lg .caret { border-width: 5px 5px 0; border-bottom-width: 0; } .dropup .btn-lg .caret { border-width: 0 5px 5px; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group, .btn-group-vertical > .btn-group > .btn { display: block; float: none; width: 100%; max-width: 100%; } .btn-group-vertical > .btn-group > .btn { float: none; } .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { margin-top: -1px; margin-left: 0; } .btn-group-vertical > .btn:not(:first-child):not(:last-child) { border-radius: 0; } .btn-group-vertical > .btn:first-child:not(:last-child) { border-top-right-radius: 4px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:last-child:not(:first-child) { border-top-left-radius: 0; border-top-right-radius: 0; border-bottom-left-radius: 4px; } .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-justified { display: table; width: 100%; table-layout: fixed; border-collapse: separate; } .btn-group-justified > .btn, .btn-group-justified > .btn-group { display: table-cell; float: none; width: 1%; } .btn-group-justified > .btn-group .btn { width: 100%; } [data-toggle="buttons"] > .btn > input[type="radio"], [data-toggle="buttons"] > .btn > input[type="checkbox"] { display: none; } .input-group { position: relative; display: table; border-collapse: separate; } .input-group[class*="col-"] { float: none; padding-right: 0; padding-left: 0; } .input-group .form-control { position: relative; z-index: 2; float: left; width: 100%; margin-bottom: 0; } .input-group-lg > .form-control, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .btn { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.33; border-radius: 6px; } select.input-group-lg > .form-control, select.input-group-lg > .input-group-addon, select.input-group-lg > .input-group-btn > .btn { height: 46px; line-height: 46px; } textarea.input-group-lg > .form-control, textarea.input-group-lg > .input-group-addon, textarea.input-group-lg > .input-group-btn > .btn, select[multiple].input-group-lg > .form-control, select[multiple].input-group-lg > .input-group-addon, select[multiple].input-group-lg > .input-group-btn > .btn { height: auto; } .input-group-sm > .form-control, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .btn { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } select.input-group-sm > .form-control, select.input-group-sm > .input-group-addon, select.input-group-sm > .input-group-btn > .btn { height: 30px; line-height: 30px; } textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-addon, textarea.input-group-sm > .input-group-btn > .btn, select[multiple].input-group-sm > .form-control, select[multiple].input-group-sm > .input-group-addon, select[multiple].input-group-sm > .input-group-btn > .btn { height: auto; } .input-group-addon, .input-group-btn, .input-group .form-control { display: table-cell; } .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child), .input-group .form-control:not(:first-child):not(:last-child) { border-radius: 0; } .input-group-addon, .input-group-btn { width: 1%; white-space: nowrap; vertical-align: middle; } .input-group-addon { padding: 6px 12px; font-size: 14px; font-weight: normal; line-height: 1; color: #555; text-align: center; background-color: #eee; border: 1px solid #ccc; border-radius: 4px; } .input-group-addon.input-sm { padding: 5px 10px; font-size: 12px; border-radius: 3px; } .input-group-addon.input-lg { padding: 10px 16px; font-size: 18px; border-radius: 6px; } .input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] { margin-top: 0; } .input-group .form-control:first-child, .input-group-addon:first-child, .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group > .btn, .input-group-btn:first-child > .dropdown-toggle, .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group-addon:first-child { border-right: 0; } .input-group .form-control:last-child, .input-group-addon:last-child, .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group > .btn, .input-group-btn:last-child > .dropdown-toggle, .input-group-btn:first-child > .btn:not(:first-child), .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group-addon:last-child { border-left: 0; } .input-group-btn { position: relative; font-size: 0; white-space: nowrap; } .input-group-btn > .btn { position: relative; } .input-group-btn > .btn + .btn { margin-left: -1px; } .input-group-btn > .btn:hover, .input-group-btn > .btn:focus, .input-group-btn > .btn:active { z-index: 2; } .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group { margin-right: -1px; } .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group { margin-left: -1px; } .nav { padding-left: 0; margin-bottom: 0; list-style: none; } .nav > li { position: relative; display: block; } .nav > li > a { position: relative; display: block; padding: 10px 15px; } .nav > li > a:hover, .nav > li > a:focus { text-decoration: none; background-color: #eee; } .nav > li.disabled > a { color: #999; } .nav > li.disabled > a:hover, .nav > li.disabled > a:focus { color: #999; text-decoration: none; cursor: not-allowed; background-color: transparent; } .nav .open > a, .nav .open > a:hover, .nav .open > a:focus { background-color: #eee; border-color: #428bca; } .nav .nav-divider { height: 1px; margin: 9px 0; overflow: hidden; background-color: #e5e5e5; } .nav > li > a > img { max-width: none; } .nav-tabs { border-bottom: 1px solid #ddd; } .nav-tabs > li { float: left; margin-bottom: -1px; } .nav-tabs > li > a { margin-right: 2px; line-height: 1.42857143; border: 1px solid transparent; border-radius: 4px 4px 0 0; } .nav-tabs > li > a:hover { border-color: #eee #eee #ddd; } .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { color: #555; cursor: default; background-color: #fff; border: 1px solid #ddd; border-bottom-color: transparent; } .nav-tabs.nav-justified { width: 100%; border-bottom: 0; } .nav-tabs.nav-justified > li { float: none; } .nav-tabs.nav-justified > li > a { margin-bottom: 5px; text-align: center; } .nav-tabs.nav-justified > .dropdown .dropdown-menu { top: auto; left: auto; } @media (min-width: 768px) { .nav-tabs.nav-justified > li { display: table-cell; width: 1%; } .nav-tabs.nav-justified > li > a { margin-bottom: 0; } } .nav-tabs.nav-justified > li > a { margin-right: 0; border-radius: 4px; } .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { border: 1px solid #ddd; } @media (min-width: 768px) { .nav-tabs.nav-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; } .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { border-bottom-color: #fff; } } .nav-pills > li { float: left; } .nav-pills > li > a { border-radius: 4px; } .nav-pills > li + li { margin-left: 2px; } .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { color: #fff; background-color: #428bca; } .nav-stacked > li { float: none; } .nav-stacked > li + li { margin-top: 2px; margin-left: 0; } .nav-justified { width: 100%; } .nav-justified > li { float: none; } .nav-justified > li > a { margin-bottom: 5px; text-align: center; } .nav-justified > .dropdown .dropdown-menu { top: auto; left: auto; } @media (min-width: 768px) { .nav-justified > li { display: table-cell; width: 1%; } .nav-justified > li > a { margin-bottom: 0; } } .nav-tabs-justified { border-bottom: 0; } .nav-tabs-justified > li > a { margin-right: 0; border-radius: 4px; } .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { border: 1px solid #ddd; } @media (min-width: 768px) { .nav-tabs-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; } .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { border-bottom-color: #fff; } } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .navbar { position: relative; min-height: 50px; margin-bottom: 20px; border: 1px solid transparent; } @media (min-width: 768px) { .navbar { border-radius: 4px; } } @media (min-width: 768px) { .navbar-header { float: left; } } .navbar-collapse { max-height: 340px; padding-right: 15px; padding-left: 15px; overflow-x: visible; -webkit-overflow-scrolling: touch; border-top: 1px solid transparent; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); } .navbar-collapse.in { overflow-y: auto; } @media (min-width: 768px) { .navbar-collapse { width: auto; border-top: 0; box-shadow: none; } .navbar-collapse.collapse { display: block !important; height: auto !important; padding-bottom: 0; overflow: visible !important; } .navbar-collapse.in { overflow-y: visible; } .navbar-fixed-top .navbar-collapse, .navbar-static-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { padding-right: 0; padding-left: 0; } } .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: -15px; margin-left: -15px; } @media (min-width: 768px) { .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: 0; margin-left: 0; } } .navbar-static-top { z-index: 1000; border-width: 0 0 1px; } @media (min-width: 768px) { .navbar-static-top { border-radius: 0; } } .navbar-fixed-top, .navbar-fixed-bottom { position: fixed; right: 0; left: 0; z-index: 1030; } @media (min-width: 768px) { .navbar-fixed-top, .navbar-fixed-bottom { border-radius: 0; } } .navbar-fixed-top { top: 0; border-width: 0 0 1px; } .navbar-fixed-bottom { bottom: 0; margin-bottom: 0; border-width: 1px 0 0; } .navbar-brand { float: left; height: 50px; padding: 15px 15px; font-size: 18px; line-height: 20px; } .navbar-brand:hover, .navbar-brand:focus { text-decoration: none; } @media (min-width: 768px) { .navbar > .container .navbar-brand, .navbar > .container-fluid .navbar-brand { margin-left: -15px; } } .navbar-toggle { position: relative; float: right; padding: 9px 10px; margin-top: 8px; margin-right: 15px; margin-bottom: 8px; background-color: transparent; background-image: none; border: 1px solid transparent; border-radius: 4px; } .navbar-toggle:focus { outline: none; } .navbar-toggle .icon-bar { display: block; width: 22px; height: 2px; border-radius: 1px; } .navbar-toggle .icon-bar + .icon-bar { margin-top: 4px; } @media (min-width: 768px) { .navbar-toggle { display: none; } } .navbar-nav { margin: 7.5px -15px; } .navbar-nav > li > a { padding-top: 10px; padding-bottom: 10px; line-height: 20px; } @media (max-width: 767px) { .navbar-nav .open .dropdown-menu { position: static; float: none; width: auto; margin-top: 0; background-color: transparent; border: 0; box-shadow: none; } .navbar-nav .open .dropdown-menu > li > a, .navbar-nav .open .dropdown-menu .dropdown-header { padding: 5px 15px 5px 25px; } .navbar-nav .open .dropdown-menu > li > a { line-height: 20px; } .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-nav .open .dropdown-menu > li > a:focus { background-image: none; } } @media (min-width: 768px) { .navbar-nav { float: left; margin: 0; } .navbar-nav > li { float: left; } .navbar-nav > li > a { padding-top: 15px; padding-bottom: 15px; } .navbar-nav.navbar-right:last-child { margin-right: -15px; } } @media (min-width: 768px) { .navbar-left { float: left !important; } .navbar-right { float: right !important; } } .navbar-form { padding: 10px 15px; margin-top: 8px; margin-right: -15px; margin-bottom: 8px; margin-left: -15px; border-top: 1px solid transparent; border-bottom: 1px solid transparent; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); } @media (min-width: 768px) { .navbar-form .form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .navbar-form .form-control { display: inline-block; width: auto; vertical-align: middle; } .navbar-form .input-group > .form-control { width: 100%; } .navbar-form .control-label { margin-bottom: 0; vertical-align: middle; } .navbar-form .radio, .navbar-form .checkbox { display: inline-block; padding-left: 0; margin-top: 0; margin-bottom: 0; vertical-align: middle; } .navbar-form .radio input[type="radio"], .navbar-form .checkbox input[type="checkbox"] { float: none; margin-left: 0; } .navbar-form .has-feedback .form-control-feedback { top: 0; } } @media (max-width: 767px) { .navbar-form .form-group { margin-bottom: 5px; } } @media (min-width: 768px) { .navbar-form { width: auto; padding-top: 0; padding-bottom: 0; margin-right: 0; margin-left: 0; border: 0; -webkit-box-shadow: none; box-shadow: none; } .navbar-form.navbar-right:last-child { margin-right: -15px; } } .navbar-nav > li > .dropdown-menu { margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .navbar-btn { margin-top: 8px; margin-bottom: 8px; } .navbar-btn.btn-sm { margin-top: 10px; margin-bottom: 10px; } .navbar-btn.btn-xs { margin-top: 14px; margin-bottom: 14px; } .navbar-text { margin-top: 15px; margin-bottom: 15px; } @media (min-width: 768px) { .navbar-text { float: left; margin-right: 15px; margin-left: 15px; } .navbar-text.navbar-right:last-child { margin-right: 0; } } .navbar-default { background-color: #f8f8f8; border-color: #e7e7e7; } .navbar-default .navbar-brand { color: #777; } .navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { color: #5e5e5e; background-color: transparent; } .navbar-default .navbar-text { color: #777; } .navbar-default .navbar-nav > li > a { color: #777; } .navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { color: #333; background-color: transparent; } .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { color: #555; background-color: #e7e7e7; } .navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus { color: #ccc; background-color: transparent; } .navbar-default .navbar-toggle { border-color: #ddd; } .navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { background-color: #ddd; } .navbar-default .navbar-toggle .icon-bar { background-color: #888; } .navbar-default .navbar-collapse, .navbar-default .navbar-form { border-color: #e7e7e7; } .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { color: #555; background-color: #e7e7e7; } @media (max-width: 767px) { .navbar-default .navbar-nav .open .dropdown-menu > li > a { color: #777; } .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { color: #333; background-color: transparent; } .navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { color: #555; background-color: #e7e7e7; } .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { color: #ccc; background-color: transparent; } } .navbar-default .navbar-link { color: #777; } .navbar-default .navbar-link:hover { color: #333; } .navbar-inverse { background-color: #222; border-color: #080808; } .navbar-inverse .navbar-brand { color: #999; } .navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-text { color: #999; } .navbar-inverse .navbar-nav > li > a { color: #999; } .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { color: #fff; background-color: #080808; } .navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus { color: #444; background-color: transparent; } .navbar-inverse .navbar-toggle { border-color: #333; } .navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { background-color: #333; } .navbar-inverse .navbar-toggle .icon-bar { background-color: #fff; } .navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { border-color: #101010; } .navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { color: #fff; background-color: #080808; } @media (max-width: 767px) { .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { border-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu .divider { background-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { color: #999; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { color: #fff; background-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { color: #444; background-color: transparent; } } .navbar-inverse .navbar-link { color: #999; } .navbar-inverse .navbar-link:hover { color: #fff; } .breadcrumb { padding: 8px 15px; margin-bottom: 20px; list-style: none; background-color: #f5f5f5; border-radius: 4px; } .breadcrumb > li { display: inline-block; } .breadcrumb > li + li:before { padding: 0 5px; color: #ccc; content: "/\00a0"; } .breadcrumb > .active { color: #999; } .pagination { display: inline-block; padding-left: 0; margin: 20px 0; border-radius: 4px; } .pagination > li { display: inline; } .pagination > li > a, .pagination > li > span { position: relative; float: left; padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; color: #428bca; text-decoration: none; background-color: #fff; border: 1px solid #ddd; } .pagination > li:first-child > a, .pagination > li:first-child > span { margin-left: 0; border-top-left-radius: 4px; border-bottom-left-radius: 4px; } .pagination > li:last-child > a, .pagination > li:last-child > span { border-top-right-radius: 4px; border-bottom-right-radius: 4px; } .pagination > li > a:hover, .pagination > li > span:hover, .pagination > li > a:focus, .pagination > li > span:focus { color: #2a6496; background-color: #eee; border-color: #ddd; } .pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, .pagination > .active > span:hover, .pagination > .active > a:focus, .pagination > .active > span:focus { z-index: 2; color: #fff; cursor: default; background-color: #428bca; border-color: #428bca; } .pagination > .disabled > span, .pagination > .disabled > span:hover, .pagination > .disabled > span:focus, .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { color: #999; cursor: not-allowed; background-color: #fff; border-color: #ddd; } .pagination-lg > li > a, .pagination-lg > li > span { padding: 10px 16px; font-size: 18px; } .pagination-lg > li:first-child > a, .pagination-lg > li:first-child > span { border-top-left-radius: 6px; border-bottom-left-radius: 6px; } .pagination-lg > li:last-child > a, .pagination-lg > li:last-child > span { border-top-right-radius: 6px; border-bottom-right-radius: 6px; } .pagination-sm > li > a, .pagination-sm > li > span { padding: 5px 10px; font-size: 12px; } .pagination-sm > li:first-child > a, .pagination-sm > li:first-child > span { border-top-left-radius: 3px; border-bottom-left-radius: 3px; } .pagination-sm > li:last-child > a, .pagination-sm > li:last-child > span { border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .pager { padding-left: 0; margin: 20px 0; text-align: center; list-style: none; } .pager li { display: inline; } .pager li > a, .pager li > span { display: inline-block; padding: 5px 14px; background-color: #fff; border: 1px solid #ddd; border-radius: 15px; } .pager li > a:hover, .pager li > a:focus { text-decoration: none; background-color: #eee; } .pager .next > a, .pager .next > span { float: right; } .pager .previous > a, .pager .previous > span { float: left; } .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { color: #999; cursor: not-allowed; background-color: #fff; } .label { display: inline; padding: .2em .6em .3em; font-size: 75%; font-weight: bold; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: .25em; } .label[href]:hover, .label[href]:focus { color: #fff; text-decoration: none; cursor: pointer; } .label:empty { display: none; } .btn .label { position: relative; top: -1px; } .label-default { background-color: #999; } .label-default[href]:hover, .label-default[href]:focus { background-color: #808080; } .label-primary { background-color: #428bca; } .label-primary[href]:hover, .label-primary[href]:focus { background-color: #3071a9; } .label-success { background-color: #5cb85c; } .label-success[href]:hover, .label-success[href]:focus { background-color: #449d44; } .label-info { background-color: #5bc0de; } .label-info[href]:hover, .label-info[href]:focus { background-color: #31b0d5; } .label-warning { background-color: #f0ad4e; } .label-warning[href]:hover, .label-warning[href]:focus { background-color: #ec971f; } .label-danger { background-color: #d9534f; } .label-danger[href]:hover, .label-danger[href]:focus { background-color: #c9302c; } .badge { display: inline-block; min-width: 10px; padding: 3px 7px; font-size: 12px; font-weight: bold; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: baseline; background-color: #999; border-radius: 10px; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .btn-xs .badge { top: 0; padding: 1px 5px; } a.badge:hover, a.badge:focus { color: #fff; text-decoration: none; cursor: pointer; } a.list-group-item.active > .badge, .nav-pills > .active > a > .badge { color: #428bca; background-color: #fff; } .nav-pills > li > a > .badge { margin-left: 3px; } .jumbotron { padding: 30px; margin-bottom: 30px; color: inherit; background-color: #eee; } .jumbotron h1, .jumbotron .h1 { color: inherit; } .jumbotron p { margin-bottom: 15px; font-size: 21px; font-weight: 200; } .container .jumbotron { border-radius: 6px; } .jumbotron .container { max-width: 100%; } @media screen and (min-width: 768px) { .jumbotron { padding-top: 48px; padding-bottom: 48px; } .container .jumbotron { padding-right: 60px; padding-left: 60px; } .jumbotron h1, .jumbotron .h1 { font-size: 63px; } } .thumbnail { display: block; padding: 4px; margin-bottom: 20px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; -webkit-transition: all .2s ease-in-out; transition: all .2s ease-in-out; } .thumbnail > img, .thumbnail a > img { margin-right: auto; margin-left: auto; } a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active { border-color: #428bca; } .thumbnail .caption { padding: 9px; color: #333; } .alert { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; } .alert h4 { margin-top: 0; color: inherit; } .alert .alert-link { font-weight: bold; } .alert > p, .alert > ul { margin-bottom: 0; } .alert > p + p { margin-top: 5px; } .alert-dismissable { padding-right: 35px; } .alert-dismissable .close { position: relative; top: -2px; right: -21px; color: inherit; } .alert-success { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; } .alert-success hr { border-top-color: #c9e2b3; } .alert-success .alert-link { color: #2b542c; } .alert-info { color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } .alert-info hr { border-top-color: #a6e1ec; } .alert-info .alert-link { color: #245269; } .alert-warning { color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc; } .alert-warning hr { border-top-color: #f7e1b5; } .alert-warning .alert-link { color: #66512c; } .alert-danger { color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .alert-danger hr { border-top-color: #e4b9c0; } .alert-danger .alert-link { color: #843534; } @-webkit-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } .progress { height: 20px; margin-bottom: 20px; overflow: hidden; background-color: #f5f5f5; border-radius: 4px; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); } .progress-bar { float: left; width: 0; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; background-color: #428bca; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); -webkit-transition: width .6s ease; transition: width .6s ease; } .progress-striped .progress-bar { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-size: 40px 40px; } .progress.active .progress-bar { -webkit-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .progress-bar-success { background-color: #5cb85c; } .progress-striped .progress-bar-success { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } .progress-bar-info { background-color: #5bc0de; } .progress-striped .progress-bar-info { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } .progress-bar-warning { background-color: #f0ad4e; } .progress-striped .progress-bar-warning { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } .progress-bar-danger { background-color: #d9534f; } .progress-striped .progress-bar-danger { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } .media, .media-body { overflow: hidden; zoom: 1; } .media, .media .media { margin-top: 15px; } .media:first-child { margin-top: 0; } .media-object { display: block; } .media-heading { margin: 0 0 5px; } .media > .pull-left { margin-right: 10px; } .media > .pull-right { margin-left: 10px; } .media-list { padding-left: 0; list-style: none; } .list-group { padding-left: 0; margin-bottom: 20px; } .list-group-item { position: relative; display: block; padding: 10px 15px; margin-bottom: -1px; background-color: #fff; border: 1px solid #ddd; } .list-group-item:first-child { border-top-left-radius: 4px; border-top-right-radius: 4px; } .list-group-item:last-child { margin-bottom: 0; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .list-group-item > .badge { float: right; } .list-group-item > .badge + .badge { margin-right: 5px; } a.list-group-item { color: #555; } a.list-group-item .list-group-item-heading { color: #333; } a.list-group-item:hover, a.list-group-item:focus { text-decoration: none; background-color: #f5f5f5; } a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus { z-index: 2; color: #fff; background-color: #428bca; border-color: #428bca; } a.list-group-item.active .list-group-item-heading, a.list-group-item.active:hover .list-group-item-heading, a.list-group-item.active:focus .list-group-item-heading { color: inherit; } a.list-group-item.active .list-group-item-text, a.list-group-item.active:hover .list-group-item-text, a.list-group-item.active:focus .list-group-item-text { color: #e1edf7; } .list-group-item-success { color: #3c763d; background-color: #dff0d8; } a.list-group-item-success { color: #3c763d; } a.list-group-item-success .list-group-item-heading { color: inherit; } a.list-group-item-success:hover, a.list-group-item-success:focus { color: #3c763d; background-color: #d0e9c6; } a.list-group-item-success.active, a.list-group-item-success.active:hover, a.list-group-item-success.active:focus { color: #fff; background-color: #3c763d; border-color: #3c763d; } .list-group-item-info { color: #31708f; background-color: #d9edf7; } a.list-group-item-info { color: #31708f; } a.list-group-item-info .list-group-item-heading { color: inherit; } a.list-group-item-info:hover, a.list-group-item-info:focus { color: #31708f; background-color: #c4e3f3; } a.list-group-item-info.active, a.list-group-item-info.active:hover, a.list-group-item-info.active:focus { color: #fff; background-color: #31708f; border-color: #31708f; } .list-group-item-warning { color: #8a6d3b; background-color: #fcf8e3; } a.list-group-item-warning { color: #8a6d3b; } a.list-group-item-warning .list-group-item-heading { color: inherit; } a.list-group-item-warning:hover, a.list-group-item-warning:focus { color: #8a6d3b; background-color: #faf2cc; } a.list-group-item-warning.active, a.list-group-item-warning.active:hover, a.list-group-item-warning.active:focus { color: #fff; background-color: #8a6d3b; border-color: #8a6d3b; } .list-group-item-danger { color: #a94442; background-color: #f2dede; } a.list-group-item-danger { color: #a94442; } a.list-group-item-danger .list-group-item-heading { color: inherit; } a.list-group-item-danger:hover, a.list-group-item-danger:focus { color: #a94442; background-color: #ebcccc; } a.list-group-item-danger.active, a.list-group-item-danger.active:hover, a.list-group-item-danger.active:focus { color: #fff; background-color: #a94442; border-color: #a94442; } .list-group-item-heading { margin-top: 0; margin-bottom: 5px; } .list-group-item-text { margin-bottom: 0; line-height: 1.3; } .panel { margin-bottom: 20px; background-color: #fff; border: 1px solid transparent; border-radius: 4px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); box-shadow: 0 1px 1px rgba(0, 0, 0, .05); } .panel-body { padding: 15px; } .panel-heading { padding: 10px 15px; border-bottom: 1px solid transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel-heading > .dropdown .dropdown-toggle { color: inherit; } .panel-title { margin-top: 0; margin-bottom: 0; font-size: 16px; color: inherit; } .panel-title > a { color: inherit; } .panel-footer { padding: 10px 15px; background-color: #f5f5f5; border-top: 1px solid #ddd; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .list-group { margin-bottom: 0; } .panel > .list-group .list-group-item { border-width: 1px 0; border-radius: 0; } .panel > .list-group:first-child .list-group-item:first-child { border-top: 0; border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .list-group:last-child .list-group-item:last-child { border-bottom: 0; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel-heading + .list-group .list-group-item:first-child { border-top-width: 0; } .panel > .table, .panel > .table-responsive > .table { margin-bottom: 0; } .panel > .table:first-child, .panel > .table-responsive:first-child > .table:first-child { border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, .panel > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { border-top-left-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, .panel > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { border-top-right-radius: 3px; } .panel > .table:last-child, .panel > .table-responsive:last-child > .table:last-child { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, .panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, .panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { border-bottom-right-radius: 3px; } .panel > .panel-body + .table, .panel > .panel-body + .table-responsive { border-top: 1px solid #ddd; } .panel > .table > tbody:first-child > tr:first-child th, .panel > .table > tbody:first-child > tr:first-child td { border-top: 0; } .panel > .table-bordered, .panel > .table-responsive > .table-bordered { border: 0; } .panel > .table-bordered > thead > tr > th:first-child, .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, .panel > .table-bordered > tbody > tr > th:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, .panel > .table-bordered > tfoot > tr > th:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, .panel > .table-bordered > thead > tr > td:first-child, .panel > .table-responsive > .table-bordered > thead > tr > td:first-child, .panel > .table-bordered > tbody > tr > td:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, .panel > .table-bordered > tfoot > tr > td:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { border-left: 0; } .panel > .table-bordered > thead > tr > th:last-child, .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, .panel > .table-bordered > tbody > tr > th:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, .panel > .table-bordered > tfoot > tr > th:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, .panel > .table-bordered > thead > tr > td:last-child, .panel > .table-responsive > .table-bordered > thead > tr > td:last-child, .panel > .table-bordered > tbody > tr > td:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, .panel > .table-bordered > tfoot > tr > td:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { border-right: 0; } .panel > .table-bordered > thead > tr:first-child > td, .panel > .table-responsive > .table-bordered > thead > tr:first-child > td, .panel > .table-bordered > tbody > tr:first-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, .panel > .table-bordered > thead > tr:first-child > th, .panel > .table-responsive > .table-bordered > thead > tr:first-child > th, .panel > .table-bordered > tbody > tr:first-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { border-bottom: 0; } .panel > .table-bordered > tbody > tr:last-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, .panel > .table-bordered > tfoot > tr:last-child > td, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, .panel > .table-bordered > tbody > tr:last-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, .panel > .table-bordered > tfoot > tr:last-child > th, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { border-bottom: 0; } .panel > .table-responsive { margin-bottom: 0; border: 0; } .panel-group { margin-bottom: 20px; } .panel-group .panel { margin-bottom: 0; overflow: hidden; border-radius: 4px; } .panel-group .panel + .panel { margin-top: 5px; } .panel-group .panel-heading { border-bottom: 0; } .panel-group .panel-heading + .panel-collapse .panel-body { border-top: 1px solid #ddd; } .panel-group .panel-footer { border-top: 0; } .panel-group .panel-footer + .panel-collapse .panel-body { border-bottom: 1px solid #ddd; } .panel-default { border-color: #ddd; } .panel-default > .panel-heading { color: #333; background-color: #f5f5f5; border-color: #ddd; } .panel-default > .panel-heading + .panel-collapse .panel-body { border-top-color: #ddd; } .panel-default > .panel-footer + .panel-collapse .panel-body { border-bottom-color: #ddd; } .panel-primary { border-color: #428bca; } .panel-primary > .panel-heading { color: #fff; background-color: #428bca; border-color: #428bca; } .panel-primary > .panel-heading + .panel-collapse .panel-body { border-top-color: #428bca; } .panel-primary > .panel-footer + .panel-collapse .panel-body { border-bottom-color: #428bca; } .panel-success { border-color: #d6e9c6; } .panel-success > .panel-heading { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; } .panel-success > .panel-heading + .panel-collapse .panel-body { border-top-color: #d6e9c6; } .panel-success > .panel-footer + .panel-collapse .panel-body { border-bottom-color: #d6e9c6; } .panel-info { border-color: #bce8f1; } .panel-info > .panel-heading { color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } .panel-info > .panel-heading + .panel-collapse .panel-body { border-top-color: #bce8f1; } .panel-info > .panel-footer + .panel-collapse .panel-body { border-bottom-color: #bce8f1; } .panel-warning { border-color: #faebcc; } .panel-warning > .panel-heading { color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc; } .panel-warning > .panel-heading + .panel-collapse .panel-body { border-top-color: #faebcc; } .panel-warning > .panel-footer + .panel-collapse .panel-body { border-bottom-color: #faebcc; } .panel-danger { border-color: #ebccd1; } .panel-danger > .panel-heading { color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .panel-danger > .panel-heading + .panel-collapse .panel-body { border-top-color: #ebccd1; } .panel-danger > .panel-footer + .panel-collapse .panel-body { border-bottom-color: #ebccd1; } .well { min-height: 20px; padding: 19px; margin-bottom: 20px; background-color: #f5f5f5; border: 1px solid #e3e3e3; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); } .well blockquote { border-color: #ddd; border-color: rgba(0, 0, 0, .15); } .well-lg { padding: 24px; border-radius: 6px; } .well-sm { padding: 9px; border-radius: 3px; } .close { float: right; font-size: 21px; font-weight: bold; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; filter: alpha(opacity=20); opacity: .2; } .close:hover, .close:focus { color: #000; text-decoration: none; cursor: pointer; filter: alpha(opacity=50); opacity: .5; } button.close { -webkit-appearance: none; padding: 0; cursor: pointer; background: transparent; border: 0; } .modal-open { overflow: hidden; } .modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1050; display: none; overflow: auto; overflow-y: scroll; -webkit-overflow-scrolling: touch; outline: 0; } .modal.fade .modal-dialog { -webkit-transition: -webkit-transform .3s ease-out; -moz-transition: -moz-transform .3s ease-out; -o-transition: -o-transform .3s ease-out; transition: transform .3s ease-out; -webkit-transform: translate(0, -25%); -ms-transform: translate(0, -25%); transform: translate(0, -25%); } .modal.in .modal-dialog { -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); } .modal-dialog { position: relative; width: auto; margin: 10px; } .modal-content { position: relative; background-color: #fff; background-clip: padding-box; border: 1px solid #999; border: 1px solid rgba(0, 0, 0, .2); border-radius: 6px; outline: none; -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); box-shadow: 0 3px 9px rgba(0, 0, 0, .5); } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000; } .modal-backdrop.fade { filter: alpha(opacity=0); opacity: 0; } .modal-backdrop.in { filter: alpha(opacity=50); opacity: .5; } .modal-header { min-height: 16.42857143px; padding: 15px; border-bottom: 1px solid #e5e5e5; } .modal-header .close { margin-top: -2px; } .modal-title { margin: 0; line-height: 1.42857143; } .modal-body { position: relative; padding: 20px; } .modal-footer { padding: 19px 20px 20px; margin-top: 15px; text-align: right; border-top: 1px solid #e5e5e5; } .modal-footer .btn + .btn { margin-bottom: 0; margin-left: 5px; } .modal-footer .btn-group .btn + .btn { margin-left: -1px; } .modal-footer .btn-block + .btn-block { margin-left: 0; } @media (min-width: 768px) { .modal-dialog { width: 600px; margin: 30px auto; } .modal-content { -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); box-shadow: 0 5px 15px rgba(0, 0, 0, .5); } .modal-sm { width: 300px; } } @media (min-width: 992px) { .modal-lg { width: 900px; } } .tooltip { position: absolute; z-index: 1030; display: block; font-size: 12px; line-height: 1.4; visibility: visible; filter: alpha(opacity=0); opacity: 0; } .tooltip.in { filter: alpha(opacity=90); opacity: .9; } .tooltip.top { padding: 5px 0; margin-top: -3px; } .tooltip.right { padding: 0 5px; margin-left: 3px; } .tooltip.bottom { padding: 5px 0; margin-top: 3px; } .tooltip.left { padding: 0 5px; margin-left: -3px; } .tooltip-inner { max-width: 200px; padding: 3px 8px; color: #fff; text-align: center; text-decoration: none; background-color: #000; border-radius: 4px; } .tooltip-arrow { position: absolute; width: 0; height: 0; border-color: transparent; border-style: solid; } .tooltip.top .tooltip-arrow { bottom: 0; left: 50%; margin-left: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.top-left .tooltip-arrow { bottom: 0; left: 5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.top-right .tooltip-arrow { right: 5px; bottom: 0; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.right .tooltip-arrow { top: 50%; left: 0; margin-top: -5px; border-width: 5px 5px 5px 0; border-right-color: #000; } .tooltip.left .tooltip-arrow { top: 50%; right: 0; margin-top: -5px; border-width: 5px 0 5px 5px; border-left-color: #000; } .tooltip.bottom .tooltip-arrow { top: 0; left: 50%; margin-left: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bottom-left .tooltip-arrow { top: 0; left: 5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bottom-right .tooltip-arrow { top: 0; right: 5px; border-width: 0 5px 5px; border-bottom-color: #000; } .popover { position: absolute; top: 0; left: 0; z-index: 1010; display: none; max-width: 276px; padding: 1px; text-align: left; white-space: normal; background-color: #fff; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, .2); border-radius: 6px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); box-shadow: 0 5px 10px rgba(0, 0, 0, .2); } .popover.top { margin-top: -10px; } .popover.right { margin-left: 10px; } .popover.bottom { margin-top: 10px; } .popover.left { margin-left: -10px; } .popover-title { padding: 8px 14px; margin: 0; font-size: 14px; font-weight: normal; line-height: 18px; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-radius: 5px 5px 0 0; } .popover-content { padding: 9px 14px; } .popover > .arrow, .popover > .arrow:after { position: absolute; display: block; width: 0; height: 0; border-color: transparent; border-style: solid; } .popover > .arrow { border-width: 11px; } .popover > .arrow:after { content: ""; border-width: 10px; } .popover.top > .arrow { bottom: -11px; left: 50%; margin-left: -11px; border-top-color: #999; border-top-color: rgba(0, 0, 0, .25); border-bottom-width: 0; } .popover.top > .arrow:after { bottom: 1px; margin-left: -10px; content: " "; border-top-color: #fff; border-bottom-width: 0; } .popover.right > .arrow { top: 50%; left: -11px; margin-top: -11px; border-right-color: #999; border-right-color: rgba(0, 0, 0, .25); border-left-width: 0; } .popover.right > .arrow:after { bottom: -10px; left: 1px; content: " "; border-right-color: #fff; border-left-width: 0; } .popover.bottom > .arrow { top: -11px; left: 50%; margin-left: -11px; border-top-width: 0; border-bottom-color: #999; border-bottom-color: rgba(0, 0, 0, .25); } .popover.bottom > .arrow:after { top: 1px; margin-left: -10px; content: " "; border-top-width: 0; border-bottom-color: #fff; } .popover.left > .arrow { top: 50%; right: -11px; margin-top: -11px; border-right-width: 0; border-left-color: #999; border-left-color: rgba(0, 0, 0, .25); } .popover.left > .arrow:after { right: 1px; bottom: -10px; content: " "; border-right-width: 0; border-left-color: #fff; } .carousel { position: relative; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner > .item { position: relative; display: none; -webkit-transition: .6s ease-in-out left; transition: .6s ease-in-out left; } .carousel-inner > .item > img, .carousel-inner > .item > a > img { line-height: 1; } .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { display: block; } .carousel-inner > .active { left: 0; } .carousel-inner > .next, .carousel-inner > .prev { position: absolute; top: 0; width: 100%; } .carousel-inner > .next { left: 100%; } .carousel-inner > .prev { left: -100%; } .carousel-inner > .next.left, .carousel-inner > .prev.right { left: 0; } .carousel-inner > .active.left { left: -100%; } .carousel-inner > .active.right { left: 100%; } .carousel-control { position: absolute; top: 0; bottom: 0; left: 0; width: 15%; font-size: 20px; color: #fff; text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, .6); filter: alpha(opacity=50); opacity: .5; } .carousel-control.left { background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%)); background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); background-repeat: repeat-x; } .carousel-control.right { right: 0; left: auto; background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%)); background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); background-repeat: repeat-x; } .carousel-control:hover, .carousel-control:focus { color: #fff; text-decoration: none; filter: alpha(opacity=90); outline: none; opacity: .9; } .carousel-control .icon-prev, .carousel-control .icon-next, .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right { position: absolute; top: 50%; z-index: 5; display: inline-block; } .carousel-control .icon-prev, .carousel-control .glyphicon-chevron-left { left: 50%; } .carousel-control .icon-next, .carousel-control .glyphicon-chevron-right { right: 50%; } .carousel-control .icon-prev, .carousel-control .icon-next { width: 20px; height: 20px; margin-top: -10px; margin-left: -10px; font-family: serif; } .carousel-control .icon-prev:before { content: '\2039'; } .carousel-control .icon-next:before { content: '\203a'; } .carousel-indicators { position: absolute; bottom: 10px; left: 50%; z-index: 15; width: 60%; padding-left: 0; margin-left: -30%; text-align: center; list-style: none; } .carousel-indicators li { display: inline-block; width: 10px; height: 10px; margin: 1px; text-indent: -999px; cursor: pointer; background-color: #000 \9; background-color: rgba(0, 0, 0, 0); border: 1px solid #fff; border-radius: 10px; } .carousel-indicators .active { width: 12px; height: 12px; margin: 0; background-color: #fff; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, .6); } .carousel-caption .btn { text-shadow: none; } @media screen and (min-width: 768px) { .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, .carousel-control .icon-prev, .carousel-control .icon-next { width: 30px; height: 30px; margin-top: -15px; margin-left: -15px; font-size: 30px; } .carousel-caption { right: 20%; left: 20%; padding-bottom: 30px; } .carousel-indicators { bottom: 20px; } } .clearfix:before, .clearfix:after, .container:before, .container:after, .container-fluid:before, .container-fluid:after, .row:before, .row:after, .form-horizontal .form-group:before, .form-horizontal .form-group:after, .btn-toolbar:before, .btn-toolbar:after, .btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after, .nav:before, .nav:after, .navbar:before, .navbar:after, .navbar-header:before, .navbar-header:after, .navbar-collapse:before, .navbar-collapse:after, .pager:before, .pager:after, .panel-body:before, .panel-body:after, .modal-footer:before, .modal-footer:after { display: table; content: " "; } .clearfix:after, .container:after, .container-fluid:after, .row:after, .form-horizontal .form-group:after, .btn-toolbar:after, .btn-group-vertical > .btn-group:after, .nav:after, .navbar:after, .navbar-header:after, .navbar-collapse:after, .pager:after, .panel-body:after, .modal-footer:after { clear: both; } .center-block { display: block; margin-right: auto; margin-left: auto; } .pull-right { float: right !important; } .pull-left { float: left !important; } .hide { display: none !important; } .show { display: block !important; } .invisible { visibility: hidden; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .hidden { display: none !important; visibility: hidden !important; } .affix { position: fixed; } @-ms-viewport { width: device-width; } .visible-xs, .visible-sm, .visible-md, .visible-lg { display: none !important; } @media (max-width: 767px) { .visible-xs { display: block !important; } table.visible-xs { display: table; } tr.visible-xs { display: table-row !important; } th.visible-xs, td.visible-xs { display: table-cell !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm { display: block !important; } table.visible-sm { display: table; } tr.visible-sm { display: table-row !important; } th.visible-sm, td.visible-sm { display: table-cell !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md { display: block !important; } table.visible-md { display: table; } tr.visible-md { display: table-row !important; } th.visible-md, td.visible-md { display: table-cell !important; } } @media (min-width: 1200px) { .visible-lg { display: block !important; } table.visible-lg { display: table; } tr.visible-lg { display: table-row !important; } th.visible-lg, td.visible-lg { display: table-cell !important; } } @media (max-width: 767px) { .hidden-xs { display: none !important; } } @media (min-width: 768px) and (max-width: 991px) { .hidden-sm { display: none !important; } } @media (min-width: 992px) and (max-width: 1199px) { .hidden-md { display: none !important; } } @media (min-width: 1200px) { .hidden-lg { display: none !important; } } .visible-print { display: none !important; } @media print { .visible-print { display: block !important; } table.visible-print { display: table; } tr.visible-print { display: table-row !important; } th.visible-print, td.visible-print { display: table-cell !important; } } @media print { .hidden-print { display: none !important; } } /*# sourceMappingURL=bootstrap.css.map */ ================================================ FILE: open-layui-web/src/main/view/static/pages/activiti/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js ================================================ /*! * Bootstrap v3.1.1 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } /* ======================================================================== * Bootstrap: transition.js v3.1.1 * http://getbootstrap.com/javascript/#transitions * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) // ============================================================ function transitionEnd() { var el = document.createElement('bootstrap') var transEndEventNames = { 'WebkitTransition' : 'webkitTransitionEnd', 'MozTransition' : 'transitionend', 'OTransition' : 'oTransitionEnd otransitionend', 'transition' : 'transitionend' } for (var name in transEndEventNames) { if (el.style[name] !== undefined) { return { end: transEndEventNames[name] } } } return false // explicit for ie8 ( ._.) } // http://blog.alexmaccaw.com/css-transitions $.fn.emulateTransitionEnd = function (duration) { var called = false, $el = this $(this).one($.support.transition.end, function () { called = true }) var callback = function () { if (!called) $($el).trigger($.support.transition.end) } setTimeout(callback, duration) return this } $(function () { $.support.transition = transitionEnd() }) }(jQuery); /* ======================================================================== * Bootstrap: alert.js v3.1.1 * http://getbootstrap.com/javascript/#alerts * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // ALERT CLASS DEFINITION // ====================== var dismiss = '[data-dismiss="alert"]' var Alert = function (el) { $(el).on('click', dismiss, this.close) } Alert.prototype.close = function (e) { var $this = $(this) var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } var $parent = $(selector) if (e) e.preventDefault() if (!$parent.length) { $parent = $this.hasClass('alert') ? $this : $this.parent() } $parent.trigger(e = $.Event('close.bs.alert')) if (e.isDefaultPrevented()) return $parent.removeClass('in') function removeElement() { $parent.trigger('closed.bs.alert').remove() } $.support.transition && $parent.hasClass('fade') ? $parent .one($.support.transition.end, removeElement) .emulateTransitionEnd(150) : removeElement() } // ALERT PLUGIN DEFINITION // ======================= var old = $.fn.alert $.fn.alert = function (option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.alert') if (!data) $this.data('bs.alert', (data = new Alert(this))) if (typeof option == 'string') data[option].call($this) }) } $.fn.alert.Constructor = Alert // ALERT NO CONFLICT // ================= $.fn.alert.noConflict = function () { $.fn.alert = old return this } // ALERT DATA-API // ============== $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) }(jQuery); /* ======================================================================== * Bootstrap: button.js v3.1.1 * http://getbootstrap.com/javascript/#buttons * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // BUTTON PUBLIC CLASS DEFINITION // ============================== var Button = function (element, options) { this.$element = $(element) this.options = $.extend({}, Button.DEFAULTS, options) this.isLoading = false } Button.DEFAULTS = { loadingText: 'loading...' } Button.prototype.setState = function (state) { var d = 'disabled' var $el = this.$element var val = $el.is('input') ? 'val' : 'html' var data = $el.data() state = state + 'Text' if (!data.resetText) $el.data('resetText', $el[val]()) $el[val](data[state] || this.options[state]) // push to event loop to allow forms to submit setTimeout($.proxy(function () { if (state == 'loadingText') { this.isLoading = true $el.addClass(d).attr(d, d) } else if (this.isLoading) { this.isLoading = false $el.removeClass(d).removeAttr(d) } }, this), 0) } Button.prototype.toggle = function () { var changed = true var $parent = this.$element.closest('[data-toggle="buttons"]') if ($parent.length) { var $input = this.$element.find('input') if ($input.prop('type') == 'radio') { if ($input.prop('checked') && this.$element.hasClass('active')) changed = false else $parent.find('.active').removeClass('active') } if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') } if (changed) this.$element.toggleClass('active') } // BUTTON PLUGIN DEFINITION // ======================== var old = $.fn.button $.fn.button = function (option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.button') var options = typeof option == 'object' && option if (!data) $this.data('bs.button', (data = new Button(this, options))) if (option == 'toggle') data.toggle() else if (option) data.setState(option) }) } $.fn.button.Constructor = Button // BUTTON NO CONFLICT // ================== $.fn.button.noConflict = function () { $.fn.button = old return this } // BUTTON DATA-API // =============== $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { var $btn = $(e.target) if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') $btn.button('toggle') e.preventDefault() }) }(jQuery); /* ======================================================================== * Bootstrap: carousel.js v3.1.1 * http://getbootstrap.com/javascript/#carousel * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CAROUSEL CLASS DEFINITION // ========================= var Carousel = function (element, options) { this.$element = $(element) this.$indicators = this.$element.find('.carousel-indicators') this.options = options this.paused = this.sliding = this.interval = this.$active = this.$items = null this.options.pause == 'hover' && this.$element .on('mouseenter', $.proxy(this.pause, this)) .on('mouseleave', $.proxy(this.cycle, this)) } Carousel.DEFAULTS = { interval: 5000, pause: 'hover', wrap: true } Carousel.prototype.cycle = function (e) { e || (this.paused = false) this.interval && clearInterval(this.interval) this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) return this } Carousel.prototype.getActiveIndex = function () { this.$active = this.$element.find('.item.active') this.$items = this.$active.parent().children() return this.$items.index(this.$active) } Carousel.prototype.to = function (pos) { var that = this var activeIndex = this.getActiveIndex() if (pos > (this.$items.length - 1) || pos < 0) return if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) if (activeIndex == pos) return this.pause().cycle() return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) } Carousel.prototype.pause = function (e) { e || (this.paused = true) if (this.$element.find('.next, .prev').length && $.support.transition) { this.$element.trigger($.support.transition.end) this.cycle(true) } this.interval = clearInterval(this.interval) return this } Carousel.prototype.next = function () { if (this.sliding) return return this.slide('next') } Carousel.prototype.prev = function () { if (this.sliding) return return this.slide('prev') } Carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.item.active') var $next = next || $active[type]() var isCycling = this.interval var direction = type == 'next' ? 'left' : 'right' var fallback = type == 'next' ? 'first' : 'last' var that = this if (!$next.length) { if (!this.options.wrap) return $next = this.$element.find('.item')[fallback]() } if ($next.hasClass('active')) return this.sliding = false var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) this.$element.trigger(e) if (e.isDefaultPrevented()) return this.sliding = true isCycling && this.pause() if (this.$indicators.length) { this.$indicators.find('.active').removeClass('active') this.$element.one('slid.bs.carousel', function () { var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) $nextIndicator && $nextIndicator.addClass('active') }) } if ($.support.transition && this.$element.hasClass('slide')) { $next.addClass(type) $next[0].offsetWidth // force reflow $active.addClass(direction) $next.addClass(direction) $active .one($.support.transition.end, function () { $next.removeClass([type, direction].join(' ')).addClass('active') $active.removeClass(['active', direction].join(' ')) that.sliding = false setTimeout(function () { that.$element.trigger('slid.bs.carousel') }, 0) }) .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) } else { $active.removeClass('active') $next.addClass('active') this.sliding = false this.$element.trigger('slid.bs.carousel') } isCycling && this.cycle() return this } // CAROUSEL PLUGIN DEFINITION // ========================== var old = $.fn.carousel $.fn.carousel = function (option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.carousel') var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) var action = typeof option == 'string' ? option : options.slide if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) if (typeof option == 'number') data.to(option) else if (action) data[action]() else if (options.interval) data.pause().cycle() }) } $.fn.carousel.Constructor = Carousel // CAROUSEL NO CONFLICT // ==================== $.fn.carousel.noConflict = function () { $.fn.carousel = old return this } // CAROUSEL DATA-API // ================= $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { var $this = $(this), href var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 var options = $.extend({}, $target.data(), $this.data()) var slideIndex = $this.attr('data-slide-to') if (slideIndex) options.interval = false $target.carousel(options) if (slideIndex = $this.attr('data-slide-to')) { $target.data('bs.carousel').to(slideIndex) } e.preventDefault() }) $(window).on('load', function () { $('[data-ride="carousel"]').each(function () { var $carousel = $(this) $carousel.carousel($carousel.data()) }) }) }(jQuery); /* ======================================================================== * Bootstrap: collapse.js v3.1.1 * http://getbootstrap.com/javascript/#collapse * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // COLLAPSE PUBLIC CLASS DEFINITION // ================================ var Collapse = function (element, options) { this.$element = $(element) this.options = $.extend({}, Collapse.DEFAULTS, options) this.transitioning = null if (this.options.parent) this.$parent = $(this.options.parent) if (this.options.toggle) this.toggle() } Collapse.DEFAULTS = { toggle: true } Collapse.prototype.dimension = function () { var hasWidth = this.$element.hasClass('width') return hasWidth ? 'width' : 'height' } Collapse.prototype.show = function () { if (this.transitioning || this.$element.hasClass('in')) return var startEvent = $.Event('show.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return var actives = this.$parent && this.$parent.find('> .panel > .in') if (actives && actives.length) { var hasData = actives.data('bs.collapse') if (hasData && hasData.transitioning) return actives.collapse('hide') hasData || actives.data('bs.collapse', null) } var dimension = this.dimension() this.$element .removeClass('collapse') .addClass('collapsing') [dimension](0) this.transitioning = 1 var complete = function () { this.$element .removeClass('collapsing') .addClass('collapse in') [dimension]('auto') this.transitioning = 0 this.$element.trigger('shown.bs.collapse') } if (!$.support.transition) return complete.call(this) var scrollSize = $.camelCase(['scroll', dimension].join('-')) this.$element .one($.support.transition.end, $.proxy(complete, this)) .emulateTransitionEnd(350) [dimension](this.$element[0][scrollSize]) } Collapse.prototype.hide = function () { if (this.transitioning || !this.$element.hasClass('in')) return var startEvent = $.Event('hide.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return var dimension = this.dimension() this.$element [dimension](this.$element[dimension]()) [0].offsetHeight this.$element .addClass('collapsing') .removeClass('collapse') .removeClass('in') this.transitioning = 1 var complete = function () { this.transitioning = 0 this.$element .trigger('hidden.bs.collapse') .removeClass('collapsing') .addClass('collapse') } if (!$.support.transition) return complete.call(this) this.$element [dimension](0) .one($.support.transition.end, $.proxy(complete, this)) .emulateTransitionEnd(350) } Collapse.prototype.toggle = function () { this[this.$element.hasClass('in') ? 'hide' : 'show']() } // COLLAPSE PLUGIN DEFINITION // ========================== var old = $.fn.collapse $.fn.collapse = function (option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.collapse') var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data && options.toggle && option == 'show') option = !option if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) } $.fn.collapse.Constructor = Collapse // COLLAPSE NO CONFLICT // ==================== $.fn.collapse.noConflict = function () { $.fn.collapse = old return this } // COLLAPSE DATA-API // ================= $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { var $this = $(this), href var target = $this.attr('data-target') || e.preventDefault() || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 var $target = $(target) var data = $target.data('bs.collapse') var option = data ? 'toggle' : $this.data() var parent = $this.attr('data-parent') var $parent = parent && $(parent) if (!data || !data.transitioning) { if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') } $target.collapse(option) }) }(jQuery); /* ======================================================================== * Bootstrap: dropdown.js v3.1.1 * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // DROPDOWN CLASS DEFINITION // ========================= var backdrop = '.dropdown-backdrop' var toggle = '[data-toggle=dropdown]' var Dropdown = function (element) { $(element).on('click.bs.dropdown', this.toggle) } Dropdown.prototype.toggle = function (e) { var $this = $(this) if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') clearMenus() if (!isActive) { if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { // if mobile we use a backdrop because click events don't delegate $('