From f1949464924983128a80313d9279d4e7213582bb Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 15 May 2025 15:00:34 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/run-all/docker-compose.yml | 31 ++++--- .../web/SystemResourcesController.java | 11 +++ .../dashboard/measurements/sys/CpuInfo.java | 7 ++ .../sys/SystemMonitorMeasurementProvider.java | 54 ++++++++---- .../community/auth/entity/MenuEntity.java | 14 +++- .../community/auth/entity/MenuView.java | 82 ++++++++++++++++--- .../auth/initialize/UserAutoInitialize.java | 1 - jetlinks-standalone/pom.xml | 8 +- .../src/main/resources/application.yml | 1 + .../src/main/resources/index.html | 13 --- .../src/main/resources/logback-spring.xml | 3 +- run.sh | 2 +- 12 files changed, 173 insertions(+), 54 deletions(-) delete mode 100644 jetlinks-standalone/src/main/resources/index.html diff --git a/docker/run-all/docker-compose.yml b/docker/run-all/docker-compose.yml index 07628f3d..5b79cf1b 100644 --- a/docker/run-all/docker-compose.yml +++ b/docker/run-all/docker-compose.yml @@ -1,20 +1,25 @@ -version: '2' +version: '3' services: redis: image: redis:6 container_name: jetlinks-ce-redis # ports: - # - "6379:6379" + # - "6379:6379" # 仅供jetlinks-ce访问 volumes: - "./data/redis:/data" command: redis-server --appendonly yes --requirepass "JetLinks@redis" environment: - TZ=Asia/Shanghai + healthcheck: + test: ["CMD", "redis-cli", "-h", "localhost", "-p", "6379", "-a", "JetLinks@redis", "ping"] + interval: 10s + timeout: 5s + retries: 3 postgres: image: timescale/timescaledb:latest-pg16 - container_name: jetlinks-postgres-16 - ports: - - "5432:5432" + container_name: jetlinks-ce-postgres +# ports: +# - "5432:5432" # 仅供jetlinks-ce访问 volumes: - "./data/postgres:/var/lib/postgresql/data" environment: @@ -22,6 +27,11 @@ services: POSTGRES_DB: jetlinks POSTGRES_HOST_AUTH_METHOD: trust TZ: Asia/Shanghai + healthcheck: + test: ["CMD", "pg_isready", "-U", "postgres"] + interval: 10s + timeout: 5s + retries: 5 jetlinks: image: registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-community:2.10.0-SNAPSHOT container_name: jetlinks-ce @@ -31,19 +41,18 @@ services: - "8800-8810:8800-8810" # 预留 - "5060-5061:5060-5061" # 预留 volumes: - - "./data/jetlinks/upload:/application/static/upload" - "./data/jetlinks:/application/data" environment: - "JAVA_OPTS=-Duser.language=zh" - "TZ=Asia/Shanghai" - - "hsweb.file.upload.static-location=http://127.0.0.1:8848/upload" #上传的静态文件访问根地址,为ui的地址. + - "ADMIN_USER_PASSWORD=JetLinks.C0mmVn1ty" # admin用户的初始密码 - "spring.r2dbc.url=r2dbc:postgresql://postgres:5432/jetlinks" #数据库连接地址 - "spring.r2dbc.username=postgres" - "spring.r2dbc.password=JetLinks@postgres" - "spring.data.redis.host=redis" - "spring.data.redis.port=6379" - "file.manager.storage-base-path=/application/data/files" - - "spring.redis.password=JetLinks@redis" + - "spring.data.redis.password=JetLinks@redis" - "logging.level.io.r2dbc=warn" - "logging.level.org.springframework.data=warn" - "logging.level.org.springframework=warn" @@ -67,5 +76,7 @@ services: - redis:redis - postgres:postgres depends_on: - - postgres - - redis + postgres: + condition: service_healthy + redis: + condition: service_healthy diff --git a/jetlinks-components/common-component/src/main/java/org/jetlinks/community/web/SystemResourcesController.java b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/web/SystemResourcesController.java index ee6c9157..f33f9665 100644 --- a/jetlinks-components/common-component/src/main/java/org/jetlinks/community/web/SystemResourcesController.java +++ b/jetlinks-components/common-component/src/main/java/org/jetlinks/community/web/SystemResourcesController.java @@ -9,6 +9,7 @@ import org.hswebframework.web.authorization.exception.UnAuthorizedException; import org.jetlinks.community.resource.Resource; import org.jetlinks.community.resource.ResourceManager; import org.jetlinks.community.resource.TypeScriptDeclareResourceProvider; +import org.jetlinks.community.resource.ui.UiResourceProvider; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -17,6 +18,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Collections; +import java.util.HashMap; @RestController @RequestMapping("/system/resources") @@ -26,6 +28,15 @@ public class SystemResourcesController { private final ResourceManager resourceManager; + @GetMapping("/ui") + @SneakyThrows + @Authorize(merge = false) + public Flux getUIResources() { + return resourceManager + .getResources(UiResourceProvider.TYPE) + .map(resource->resource.as(HashMap.class)); + } + @GetMapping("/{type}") @SneakyThrows public Flux getResources(@PathVariable String type) { diff --git a/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/CpuInfo.java b/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/CpuInfo.java index cd2ed442..1955d9b2 100644 --- a/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/CpuInfo.java +++ b/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/CpuInfo.java @@ -33,4 +33,11 @@ public class CpuInfo implements MonitorInfo { ); } + public CpuInfo max(CpuInfo cpu) { + return new CpuInfo( + Math.max(this.jvmUsage, cpu.jvmUsage), + Math.max(this.systemUsage, cpu.systemUsage) + ); + } + } diff --git a/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/SystemMonitorMeasurementProvider.java b/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/SystemMonitorMeasurementProvider.java index 5f88664c..f363207f 100644 --- a/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/SystemMonitorMeasurementProvider.java +++ b/jetlinks-components/dashboard-component/src/main/java/org/jetlinks/community/dashboard/measurements/sys/SystemMonitorMeasurementProvider.java @@ -3,6 +3,7 @@ package org.jetlinks.community.dashboard.measurements.sys; import com.google.common.collect.Maps; +import lombok.extern.slf4j.Slf4j; import org.hswebframework.web.api.crud.entity.QueryParamEntity; import org.hswebframework.web.bean.FastBeanCopier; import org.jetlinks.community.dashboard.*; @@ -113,6 +114,7 @@ import java.util.Map; * @since 2.0 */ @Component +@Slf4j public class SystemMonitorMeasurementProvider extends StaticMeasurementProvider { private static final String SYSTEM_MONITOR_REAL_TIME_TOPIC = "/_sys/monitor/info"; @@ -161,17 +163,39 @@ public class SystemMonitorMeasurementProvider extends StaticMeasurementProvider .block(Duration.ofSeconds(10)); //定时收集监控信息 - disposable.add(Flux - .interval(collectInterval, scheduler) - .flatMap(ignore -> monitorService - .system() - .map(this::systemInfoToMap) - .flatMap(data -> timeSeriesManager - .getService(metric) - .commit(data) - .then(eventBus.publish(SYSTEM_MONITOR_REAL_TIME_TOPIC,data))) - .onErrorResume(err -> Mono.empty())) - .subscribe() + //定时收集监控信息 + disposable.add( + Flux + .interval(Duration.ofSeconds(1), scheduler) + .onBackpressureDrop() + //每秒采集一次 + .concatMap(l -> monitorService.cpu()) + //收集每个窗口的结果 + .window(collectInterval) + .onBackpressureDrop(dropped -> log.warn("system monitor collect data dropped")) + .concatMap(window -> Mono + .zip( + window + .window(5) + //5秒cpu平均值 + .flatMap(flx -> flx + .reduce(CpuInfo::add) + .map(cpu -> cpu.division(5))) + //记录1分钟内最大平均值 + .reduce(CpuInfo::max), + monitorService.memory(), + monitorService.disk() + ) + .map(tp3 -> this.systemInfoToMap(tp3.getT1(), tp3.getT2(), tp3.getT3())) + .flatMap(timeSeriesManager.getService(metric)::commit) + .onErrorResume(err -> { + log.warn("collect system monitor data error", err); + return Mono.empty(); + }), 1 + ) + .subscribe(null, error -> { + log.warn("start system monitor task failed", error); + }) ); } @@ -184,11 +208,11 @@ public class SystemMonitorMeasurementProvider extends StaticMeasurementProvider }); } - public TimeSeriesData systemInfoToMap(SystemInfo info) { + public TimeSeriesData systemInfoToMap(CpuInfo cpu, MemoryInfo memory, DiskInfo disk) { Map map = Maps.newLinkedHashMapWithExpectedSize(12); - putTo("cpu", info.getCpu(), map); - putTo("disk", info.getDisk(), map); - putTo("memory", info.getMemory(), map); + putTo("cpu", cpu, map); + putTo("disk", disk, map); + putTo("memory", memory, map); return TimeSeriesData.of(System.currentTimeMillis(), map); } diff --git a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java index 4c0e2725..542ba446 100755 --- a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java +++ b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java @@ -14,6 +14,7 @@ import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity; import org.hswebframework.web.api.crud.entity.RecordCreationEntity; import org.hswebframework.web.crud.annotation.EnableEntityEvent; import org.hswebframework.web.crud.generator.Generators; +import org.hswebframework.web.i18n.MultipleI18nSupportEntity; import org.hswebframework.web.utils.DigestUtils; import org.hswebframework.web.validator.CreateGroup; @@ -40,7 +41,7 @@ import java.util.stream.Collectors; @Comment("菜单信息表") @EnableEntityEvent public class MenuEntity - extends GenericTreeSortSupportEntity implements RecordCreationEntity { + extends GenericTreeSortSupportEntity implements RecordCreationEntity, MultipleI18nSupportEntity { /** * 在多应用集成运行时使用此字段来区分菜单属于哪个系统 @@ -123,6 +124,17 @@ public class MenuEntity ) private Long createTime; + @Schema(title = "国际化信息定义") + @Column + @JsonCodec + @ColumnType(jdbcType = JDBCType.LONGVARCHAR, javaType = String.class) + private Map> i18nMessages; + + + public String getI18nName() { + return getI18nMessage("name", name); + } + public boolean isSupportDataAccess() { return false; } diff --git a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuView.java b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuView.java index 5fdc32e5..372c6363 100644 --- a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuView.java +++ b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuView.java @@ -1,14 +1,15 @@ package org.jetlinks.community.auth.entity; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.hswebframework.web.api.crud.entity.EntityFactoryHolder; import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity; import org.hswebframework.web.bean.FastBeanCopier; +import org.hswebframework.web.i18n.MultipleI18nSupportEntity; +import org.hswebframework.web.i18n.SingleI18nSupportEntity; import java.io.Serializable; import java.util.*; @@ -17,8 +18,12 @@ import java.util.stream.Collectors; @Getter @Setter -public class MenuView extends GenericTreeSortSupportEntity { +public class MenuView extends GenericTreeSortSupportEntity implements MultipleI18nSupportEntity { + /** + * 在多应用集成运行时使用此字段来区分菜单属于哪个系统 + * 具体标识由各应用前端进行定义 + */ @Schema(description = "菜单所有者") private String owner; @@ -37,6 +42,9 @@ public class MenuView extends GenericTreeSortSupportEntity { @Schema(description = "父节点") private String parentId; + @Schema(description = "描述") + private String describe; + @Schema(description = "按钮") private List buttons; @@ -55,6 +63,22 @@ public class MenuView extends GenericTreeSortSupportEntity { @Schema(description = "是否已授权") private boolean granted; + @Schema(title = "国际化信息定义") + private Map> i18nMessages; + + + public String getI18nName() { + return getI18nMessage("name", name); + } + + public String getI18nName(Locale locale) { + return getI18nMessage("name", locale, name); + } + + public static MenuView create() { + return EntityFactoryHolder.newInstance(MenuView.class, MenuView::new); + } + public MenuView withGranted(MenuView granted) { if (granted == null) { return this; @@ -104,6 +128,7 @@ public class MenuView extends GenericTreeSortSupportEntity { button.granted = true; } } + } public void resetGrant() { @@ -117,9 +142,7 @@ public class MenuView extends GenericTreeSortSupportEntity { @Getter @Setter - @AllArgsConstructor(staticName = "of") - @NoArgsConstructor - public static class ButtonView implements Serializable { + public static class ButtonView implements SingleI18nSupportEntity, Serializable { private static final long serialVersionUID = 1L; @Schema(description = "按钮ID") @@ -141,18 +164,48 @@ public class MenuView extends GenericTreeSortSupportEntity { @Schema(description = "是否已授权") private boolean granted; + @Schema(title = "国际化信息定义") + private Map i18nMessages; + + + public String getI18nName() { + return getI18nMessage("name", name); + } + + public ButtonView() { + } + + public static ButtonView create() { + return EntityFactoryHolder.newInstance(ButtonView.class, ButtonView::new); + } + public static ButtonView of(String id, String name, String description, Map options) { return ButtonView.of(id, name, description, options, true, true); } + public static ButtonView copy(ButtonView button) { + return ButtonView.of(button.getId(), button.getName(), button.getDescription(), button.getOptions()); + } + + public static ButtonView of(String id, String name, String description, Map options, boolean enabled, boolean granted) { + ButtonView view = ButtonView.create(); + view.setId(id); + view.setName(name); + view.setDescription(description); + view.setOptions(options); + view.setEnabled(enabled); + view.setGranted(granted); + return view; + } public ButtonView copy() { - return FastBeanCopier.copy(this, new ButtonView()); + return FastBeanCopier.copy(this, create()); } + } public static MenuView of(MenuEntity entity) { - return FastBeanCopier.copy(entity, new MenuView()); + return FastBeanCopier.copy(entity, MenuView.create()); } public static MenuView of(MenuEntity entity, List binds) { @@ -166,8 +219,14 @@ public class MenuView extends GenericTreeSortSupportEntity { } //重新排序 binds.sort(Comparator.comparing(MenuBindEntity::getPriority)); - Map buttons = new LinkedHashMap<>(); + Map buttons = new LinkedHashMap<>(); + Map buttonViewMap = Optional + .ofNullable(view.getButtons()) + .map(list -> list + .stream() + .collect(Collectors.toMap(ButtonView::getId, Function.identity()))) + .orElse(new HashMap<>()); for (MenuBindEntity bind : binds) { //不合并则清空之前的配置 if (!bind.getMerge()) { @@ -180,8 +239,9 @@ public class MenuView extends GenericTreeSortSupportEntity { //按钮权限 if (CollectionUtils.isNotEmpty(bind.getButtons())) { for (ButtonView button : bind.getButtons()) { - if (button.isGranted()) { - buttons.put(button.getId(), button); + ButtonView buttonView = buttonViewMap.get(button.getId()); + if (button.isGranted() && buttonView != null) { + buttons.put(buttonView.getId(), ButtonView.copy(buttonView)); } } } diff --git a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/initialize/UserAutoInitialize.java b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/initialize/UserAutoInitialize.java index cf0a61a6..592de194 100644 --- a/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/initialize/UserAutoInitialize.java +++ b/jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/initialize/UserAutoInitialize.java @@ -56,7 +56,6 @@ public class UserAutoInitialize implements CommandLineRunner { } private Mono initAdminUser(UserEntity entity) { - entity.setCreatorId("system"); if (entity.getName() == null) { entity.setName(entity.getUsername()); diff --git a/jetlinks-standalone/pom.xml b/jetlinks-standalone/pom.xml index 14fcd034..2818fa83 100644 --- a/jetlinks-standalone/pom.xml +++ b/jetlinks-standalone/pom.xml @@ -14,7 +14,7 @@ registry.cn-shenzhen.aliyuncs.com/jetlinks/${project.artifactId} yyyy-MM-dd HH:mm:ss - 2.3.0-SNAPSHOT + ${project.version} @@ -315,6 +315,12 @@ org.springdoc springdoc-openapi-starter-webflux-ui + + + org.webjars + swagger-ui + + diff --git a/jetlinks-standalone/src/main/resources/application.yml b/jetlinks-standalone/src/main/resources/application.yml index 6ed9cc30..d3a14466 100644 --- a/jetlinks-standalone/src/main/resources/application.yml +++ b/jetlinks-standalone/src/main/resources/application.yml @@ -181,6 +181,7 @@ logging: "io.vertx.core.impl.ContextImpl": off "org.hswebframework.web.starter.jackson": warn "org.jetlinks.community.timescaledb.impl.DefaultTimescaleDBDataWriter": warn + "io.scalecube": warn config: classpath:logback-spring.xml vertx: max-event-loop-execute-time-unit: seconds diff --git a/jetlinks-standalone/src/main/resources/index.html b/jetlinks-standalone/src/main/resources/index.html deleted file mode 100644 index b68fa9f6..00000000 --- a/jetlinks-standalone/src/main/resources/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/jetlinks-standalone/src/main/resources/logback-spring.xml b/jetlinks-standalone/src/main/resources/logback-spring.xml index aedcff2f..19aa51db 100644 --- a/jetlinks-standalone/src/main/resources/logback-spring.xml +++ b/jetlinks-standalone/src/main/resources/logback-spring.xml @@ -7,11 +7,12 @@ - + + diff --git a/run.sh b/run.sh index dac8c111..f375a441 100755 --- a/run.sh +++ b/run.sh @@ -4,5 +4,5 @@ if [ $? -ne 0 ];then echo "构建失败!" else - java -jar "$(pwd)/jetlinks-standalone/target/jetlinks-standalone.jar" + java -jar "$(pwd)/jetlinks-standalone/target/application.jar" fi \ No newline at end of file