Compare commits
33 Commits
5d49c82190
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eea6307c87 | ||
|
|
c5366e006b | ||
|
|
f0f295bfc9 | ||
|
|
e34c5d2e3e | ||
|
|
86d6fcaec7 | ||
|
|
2c09d97cec | ||
|
|
37ac0cd311 | ||
|
|
9fa38a3065 | ||
|
|
d908f99fbd | ||
|
|
5b0b23336c | ||
|
|
263b91c42a | ||
|
|
a53c90a348 | ||
|
|
e3583dad0c | ||
|
|
514a65a5e6 | ||
|
|
57a57ace77 | ||
|
|
1338e6458c | ||
|
|
9fd46b3a20 | ||
|
|
8e8b1a7684 | ||
|
|
4d8238dd7f | ||
|
|
73f7d3085a | ||
|
|
3f8652395c | ||
|
|
8c6e0aa353 | ||
|
|
e15dd6289d | ||
|
|
7d33227d70 | ||
|
|
8fda8f7669 | ||
|
|
57a828c5b4 | ||
|
|
b9f6aa0cc2 | ||
|
|
dcb9028d86 | ||
|
|
57a2787bf8 | ||
|
|
813ddfaeac | ||
|
|
0cbf6b28ef | ||
|
|
7efb2527d0 | ||
|
|
f085c9d506 |
2
pom.xml
2
pom.xml
@@ -8,7 +8,7 @@
|
||||
<artifactId>hudi-service</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>Hudi服务应用集合</description>
|
||||
<description>Hudi服务模块系列应用</description>
|
||||
<modules>
|
||||
<module>service-common</module>
|
||||
<module>service-dependencies</module>
|
||||
|
||||
84
service-ai/.gitignore
vendored
84
service-ai/.gitignore
vendored
@@ -1,84 +0,0 @@
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
.idea/**/aws.xml
|
||||
.idea/**/contentModel.xml
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
cmake-build-*/
|
||||
.idea/**/mongoSettings.xml
|
||||
*.iws
|
||||
out/
|
||||
.idea_modules/
|
||||
atlassian-ide-plugin.xml
|
||||
.idea/replstate.xml
|
||||
.idea/sonarlint/
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
.idea/httpRequests
|
||||
.idea/caches/build_file_checksums.ser
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
.project
|
||||
.classpath
|
||||
*~
|
||||
.fuse_hidden*
|
||||
.directory
|
||||
.Trash-*
|
||||
.nfs*
|
||||
.gradle
|
||||
**/build/
|
||||
!src/**/build/
|
||||
gradle-app.setting
|
||||
!gradle-wrapper.jar
|
||||
!gradle-wrapper.properties
|
||||
.gradletasknamecache
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
*.stackdump
|
||||
[Dd]esktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
*.lnk
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
._*
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
10
service-ai/.idea/.gitignore
generated
vendored
10
service-ai/.idea/.gitignore
generated
vendored
@@ -1,10 +0,0 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# 依赖于环境的 Maven 主目录路径
|
||||
/mavenHomeManager.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ApifoxUploaderProjectSetting">
|
||||
<option name="apiAccessToken" value="APS-0ZZaS4q0gUiFOlbBJMN8hAmS7viQNi4D" />
|
||||
</component>
|
||||
</project>
|
||||
8
service-ai/.idea/GitCommitMessageStorage.xml
generated
8
service-ai/.idea/GitCommitMessageStorage.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitCommitMessageStorage">
|
||||
<option name="messageStorage">
|
||||
<MessageStorage />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
29
service-ai/.idea/codeStyles/Project.xml
generated
29
service-ai/.idea/codeStyles/Project.xml
generated
@@ -1,29 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JavaCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||
<value />
|
||||
</option>
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="" withSubpackages="true" static="false" module="true" />
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
</value>
|
||||
</option>
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<ScalaCodeStyleSettings>
|
||||
<option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
|
||||
</ScalaCodeStyleSettings>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
service-ai/.idea/codeStyles/codeStyleConfig.xml
generated
5
service-ai/.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
15
service-ai/.idea/compiler.xml
generated
15
service-ai/.idea/compiler.xml
generated
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="service-ai-knowledge" />
|
||||
<module name="service-ai-chat" />
|
||||
<module name="service-ai-core" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
13
service-ai/.idea/encodings.xml
generated
13
service-ai/.idea/encodings.xml
generated
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/service-ai-chat/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/service-ai-chat/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/service-ai-core/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/service-ai-core/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/service-ai-knowledge/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/service-ai-knowledge/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
30
service-ai/.idea/jarRepositories.xml
generated
30
service-ai/.idea/jarRepositories.xml
generated
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="lanyuanxiaoyao-maven-central" />
|
||||
<option name="name" value="lanyuanxiaoyao-maven-central" />
|
||||
<option name="url" value="https://maven.lanyuanxiaoyao.com/central" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://maven.lanyuanxiaoyao.com/central" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
12
service-ai/.idea/misc.xml
generated
12
service-ai/.idea/misc.xml
generated
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="temurin-17" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
6
service-ai/.idea/vcs.xml
generated
6
service-ai/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
root_path=$(dirname $(cd $(dirname $0);pwd))
|
||||
source $(realpath $root_path/..)/bin/library.sh
|
||||
deploy service-ai-core
|
||||
package service-ai-chat
|
||||
upload $root_path/service-ai-chat/target/service-ai-chat-1.0.0-SNAPSHOT.jar
|
||||
@@ -1,172 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-ai</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>Hudi AI服务集合</description>
|
||||
<modules>
|
||||
<module>service-ai-core</module>
|
||||
<module>service-ai-chat</module>
|
||||
<module>service-ai-knowledge</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<build-tag>b2b12</build-tag>
|
||||
|
||||
<spring-boot.version>3.4.3</spring-boot.version>
|
||||
<spring-cloud.version>2024.0.1</spring-cloud.version>
|
||||
<spring-ai.version>1.0.0-M6</spring-ai.version>
|
||||
<eclipse-collections.version>11.1.0</eclipse-collections.version>
|
||||
<curator.version>5.1.0</curator.version>
|
||||
<hutool.version>5.8.27</hutool.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- 当前项目依赖 -->
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-configuration</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-dependencies</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-forest</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-ai-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring boot 相关依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-bom</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.dtflys.forest</groupId>
|
||||
<artifactId>forest-spring-boot3-starter</artifactId>
|
||||
<version>1.5.36</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-eclipse-collections</artifactId>
|
||||
<version>2.17.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ulisesbocchio</groupId>
|
||||
<artifactId>jasypt-spring-boot-starter</artifactId>
|
||||
<version>3.0.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 日志相关 -->
|
||||
<dependency>
|
||||
<groupId>pl.tkowalcz.tjahzi</groupId>
|
||||
<artifactId>logback-appender</artifactId>
|
||||
<version>0.9.23</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.loki4j</groupId>
|
||||
<artifactId>loki-logback-appender-jdk8</artifactId>
|
||||
<version>1.4.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 其他 -->
|
||||
<dependency>
|
||||
<groupId>dev.failsafe</groupId>
|
||||
<artifactId>failsafe</artifactId>
|
||||
<version>3.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.collections</groupId>
|
||||
<artifactId>eclipse-collections</artifactId>
|
||||
<version>${eclipse-collections.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.collections</groupId>
|
||||
<artifactId>eclipse-collections-api</artifactId>
|
||||
<version>${eclipse-collections.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>${releases.id}</id>
|
||||
<name>${releases.name}</name>
|
||||
<url>${releases.url}</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>${snapshots.id}</id>
|
||||
<name>${snapshots.name}</name>
|
||||
<url>${snapshots.url}</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
</project>
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-ai</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>service-ai-chat</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-ai-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.chat;
|
||||
|
||||
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250514
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = "com.lanyuanxiaoyao.service")
|
||||
@EnableDiscoveryClient
|
||||
@EnableConfigurationProperties
|
||||
@EnableEncryptableProperties
|
||||
@EnableRetry
|
||||
public class AiChatApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AiChatApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.chat.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.lanyuanxiaoyao.service.ai.chat.entity.MessageVO;
|
||||
import com.lanyuanxiaoyao.service.ai.chat.tools.DatetimeTools;
|
||||
import java.io.IOException;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.messages.AssistantMessage;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.ai.chat.messages.UserMessage;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
/**
|
||||
* 聊天
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250514
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("chat")
|
||||
public class ChatController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ChatController.class);
|
||||
|
||||
private final ChatClient chatClient;
|
||||
|
||||
public ChatController(ChatClient.Builder builder) {
|
||||
this.chatClient = builder
|
||||
.defaultSystem("始终在中文语境下进行对话")
|
||||
.build();
|
||||
}
|
||||
|
||||
private ChatClient.ChatClientRequestSpec buildRequest(ImmutableList<MessageVO> messages) {
|
||||
return chatClient.prompt()
|
||||
.messages(
|
||||
messages
|
||||
.collect(message -> StrUtil.equals(message.getRole(), "assistant")
|
||||
? new AssistantMessage(message.getContent())
|
||||
: new UserMessage(message.getContent()))
|
||||
.collect(message -> (Message) message)
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
|
||||
@PostMapping("sync")
|
||||
@ResponseBody
|
||||
public String chatSync(@RequestBody ImmutableList<MessageVO> messages) {
|
||||
return buildRequest(messages)
|
||||
.call()
|
||||
.content();
|
||||
}
|
||||
|
||||
@PostMapping("async")
|
||||
public SseEmitter chatAsync(@RequestBody ImmutableList<MessageVO> messages) {
|
||||
SseEmitter emitter = new SseEmitter();
|
||||
buildRequest(messages)
|
||||
.stream()
|
||||
.content()
|
||||
.subscribe(
|
||||
content -> {
|
||||
try {
|
||||
emitter.send(content);
|
||||
} catch (IOException e) {
|
||||
emitter.completeWithError(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
},
|
||||
emitter::completeWithError,
|
||||
emitter::complete
|
||||
);
|
||||
return emitter;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.chat.entity;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250516
|
||||
*/
|
||||
public class MessageVO {
|
||||
private String role;
|
||||
private String content;
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MessageVO{" +
|
||||
"role='" + role + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.chat.tools;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import org.springframework.ai.tool.annotation.Tool;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250516
|
||||
*/
|
||||
public class DatetimeTools {
|
||||
private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Tool(description = "获取当前时间")
|
||||
public String getCurrentTime() {
|
||||
return LocalDateTime.now().format(formatter);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
spring:
|
||||
application:
|
||||
name: service-ai-chat
|
||||
profiles:
|
||||
include: random-port,common,metrics,forest
|
||||
ai:
|
||||
openai:
|
||||
base-url: http://132.121.206.65:10086
|
||||
api-key: ENC(K+Hff9QGC+fcyi510VIDd9CaeK/IN5WBJ9rlkUsHEdDgIidW+stHHJlsK0lLPUXXREha+ToQZqqDXJrqSE+GUKCXklFhelD8bRHFXBIeP/ZzT2cxhzgKUXgjw3S0Qw2R)
|
||||
chat:
|
||||
options:
|
||||
model: 'Qwen3-1.7'
|
||||
mvc:
|
||||
async:
|
||||
request-timeout: 300000
|
||||
@@ -1,34 +0,0 @@
|
||||
<configuration>
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
|
||||
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
|
||||
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
|
||||
|
||||
<springProperty scope="context" name="LOKI_PUSH_URL" source="loki.url"/>
|
||||
<springProperty scope="context" name="LOGGING_PARENT" source="logging.parent"/>
|
||||
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
|
||||
|
||||
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %clr([${HOSTNAME}]){yellow} %clr([%t]){magenta} %clr(%logger{40}){cyan} #@# %m%n%wEx</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOGGING_PARENT:-.}/${APP_NAME:-run}.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOGGING_PARENT:-.}/archive/${APP_NAME:-run}-%d{yyyy-MM-dd}.gz</fileNamePattern>
|
||||
<MaxHistory>7</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [${HOSTNAME}] [%t] %logger #@# %m%n%wEx</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="com.zaxxer.hikari" level="ERROR"/>
|
||||
<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="WARN"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="Console"/>
|
||||
<!-- <appender-ref ref="RollingFile"/>-->
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.chat;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.openai.OpenAiChatModel;
|
||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import reactor.core.Disposable;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250514
|
||||
*/
|
||||
public class TestChat {
|
||||
public static void main(String[] args) {
|
||||
ChatClient client = ChatClient.builder(
|
||||
OpenAiChatModel.builder()
|
||||
.openAiApi(
|
||||
OpenAiApi.builder()
|
||||
.baseUrl("http://132.121.206.65:10086")
|
||||
.apiKey("*XMySqV%>hR&v>>g*NwCs3tpQ5FVMFEF2VHVTj<MYQd$&@$sY7CgqNyea4giJi4")
|
||||
.build()
|
||||
)
|
||||
.defaultOptions(
|
||||
OpenAiChatOptions.builder()
|
||||
.model("Qwen3-1.7")
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
String content = client.prompt()
|
||||
.user("你好")
|
||||
.call()
|
||||
.content();
|
||||
System.out.println(content);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-ai</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>service-ai-core</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-forest</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.dtflys.forest</groupId>
|
||||
<artifactId>forest-spring-boot-starter</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-sleuth</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.dtflys.forest</groupId>
|
||||
<artifactId>forest-spring-boot3-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.configuration;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
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.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250514
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
return http.authorizeHttpRequests(registry -> registry.anyRequest().authenticated())
|
||||
.httpBasic(Customizer.withDefaults())
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.cors(configurer -> configurer.configurationSource(corsConfigurationSource()))
|
||||
.formLogin(AbstractHttpConfigurer::disable)
|
||||
.build();
|
||||
}
|
||||
|
||||
private CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowCredentials(true);
|
||||
configuration.addAllowedHeader("*");
|
||||
configuration.addAllowedMethod("*");
|
||||
configuration.addAllowedOriginPattern("*");
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public InMemoryUserDetailsManager userDetailsService(SecurityProperties securityProperties) {
|
||||
UserDetails user = User.builder()
|
||||
.username(securityProperties.getUsername())
|
||||
.password("{noop}" + securityProperties.getDarkcode())
|
||||
.authorities(securityProperties.getAuthority())
|
||||
.build();
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-ai</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>service-ai-knowledge</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-ai-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-qdrant-store-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-markdown-document-reader</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.knowledge;
|
||||
|
||||
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250515
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = "com.lanyuanxiaoyao.service")
|
||||
@EnableDiscoveryClient
|
||||
@EnableConfigurationProperties
|
||||
@EnableEncryptableProperties
|
||||
@EnableRetry
|
||||
public class KnowledgeApplication implements ApplicationRunner {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(KnowledgeApplication.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.knowledge.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.service.ai.knowledge.entity.CollectionVO;
|
||||
import com.lanyuanxiaoyao.service.ai.knowledge.entity.PointVO;
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.grpc.Collections;
|
||||
import io.qdrant.client.grpc.Points;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
import org.eclipse.collections.api.factory.Lists;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.reader.markdown.MarkdownDocumentReader;
|
||||
import org.springframework.ai.reader.markdown.config.MarkdownDocumentReaderConfig;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250515
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("knowledge")
|
||||
public class KnowledgeController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(KnowledgeController.class);
|
||||
|
||||
private final QdrantClient client;
|
||||
private final EmbeddingModel embeddingModel;
|
||||
|
||||
public KnowledgeController(VectorStore vectorStore, EmbeddingModel embeddingModel) {
|
||||
client = (QdrantClient) vectorStore.getNativeClient().orElseThrow();
|
||||
this.embeddingModel = embeddingModel;
|
||||
}
|
||||
|
||||
@PostMapping("add")
|
||||
public void add(
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("strategy") String strategy
|
||||
) throws ExecutionException, InterruptedException {
|
||||
logger.info("Enter method: add[name, strategy]. name:{},strategy:{}", name, strategy);
|
||||
client.createCollectionAsync(
|
||||
name,
|
||||
Collections.VectorParams.newBuilder()
|
||||
.setDistance(Collections.Distance.valueOf(strategy))
|
||||
.setSize(embeddingModel.dimensions())
|
||||
.build()
|
||||
).get();
|
||||
}
|
||||
|
||||
@GetMapping("list")
|
||||
public ImmutableList<CollectionVO> list() throws ExecutionException, InterruptedException {
|
||||
return client.listCollectionsAsync()
|
||||
.get()
|
||||
.stream()
|
||||
.collect(Collectors.toCollection(Lists.mutable::empty))
|
||||
.collect(name -> {
|
||||
try {
|
||||
Collections.CollectionInfo info = client.getCollectionInfoAsync(name).get();
|
||||
CollectionVO vo = new CollectionVO();
|
||||
vo.setName(name);
|
||||
vo.setPoints(info.getPointsCount());
|
||||
vo.setSegments(info.getSegmentsCount());
|
||||
vo.setStatus(info.getStatus().name());
|
||||
Collections.VectorParams vectorParams = info.getConfig().getParams().getVectorsConfig().getParams();
|
||||
vo.setStrategy(vectorParams.getDistance().name());
|
||||
vo.setSize(vectorParams.getSize());
|
||||
return vo;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.toImmutable();
|
||||
}
|
||||
|
||||
@GetMapping("list_points")
|
||||
public ImmutableList<PointVO> listPoints(@RequestParam("name") String name) throws ExecutionException, InterruptedException {
|
||||
Points.ScrollResponse response = client.scrollAsync(
|
||||
Points.ScrollPoints.newBuilder()
|
||||
.setCollectionName(name)
|
||||
// .setLimit(2)
|
||||
.setWithPayload(Points.WithPayloadSelector.newBuilder().setEnable(true).build())
|
||||
.setWithVectors(Points.WithVectorsSelector.newBuilder().setEnable(false).build())
|
||||
.build()
|
||||
)
|
||||
.get();
|
||||
return response.getResultList()
|
||||
.stream()
|
||||
.collect(Collectors.toCollection(Lists.mutable::empty))
|
||||
.collect(point -> {
|
||||
PointVO vo = new PointVO();
|
||||
vo.setId(point.getId().getUuid());
|
||||
vo.setText(point.getPayloadMap().get("doc_content").getStringValue());
|
||||
return vo;
|
||||
})
|
||||
.toImmutable();
|
||||
}
|
||||
|
||||
@GetMapping("delete")
|
||||
public void delete(@RequestParam("name") String name) throws ExecutionException, InterruptedException {
|
||||
client.deleteCollectionAsync(name).get();
|
||||
}
|
||||
|
||||
@PostMapping(value = "preview_text", consumes = "text/plain;charset=utf-8")
|
||||
public ImmutableList<String> previewText(
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam(value = "mode", defaultValue = "normal") String mode,
|
||||
@RequestBody String text
|
||||
) {
|
||||
return Lists.immutable.empty();
|
||||
}
|
||||
|
||||
@PostMapping(value = "process_text", consumes = "text/plain;charset=utf-8")
|
||||
public void processText(
|
||||
@RequestParam("name") String name,
|
||||
@RequestBody String text
|
||||
) {
|
||||
VectorStore source = QdrantVectorStore.builder(client, embeddingModel)
|
||||
.collectionName(name)
|
||||
.initializeSchema(true)
|
||||
.build();
|
||||
MarkdownDocumentReader reader = new MarkdownDocumentReader(
|
||||
new ByteArrayResource(text.getBytes(StandardCharsets.UTF_8)),
|
||||
MarkdownDocumentReaderConfig.builder()
|
||||
.withHorizontalRuleCreateDocument(true)
|
||||
.withIncludeCodeBlock(false)
|
||||
.withIncludeBlockquote(false)
|
||||
.build()
|
||||
);
|
||||
source.add(reader.get());
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.knowledge.entity;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250516
|
||||
*/
|
||||
public class CollectionVO {
|
||||
private String name;
|
||||
private String strategy;
|
||||
private Long size;
|
||||
private Long points;
|
||||
private Long segments;
|
||||
private String status;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getStrategy() {
|
||||
return strategy;
|
||||
}
|
||||
|
||||
public void setStrategy(String strategy) {
|
||||
this.strategy = strategy;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public Long getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public void setPoints(Long points) {
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
public Long getSegments() {
|
||||
return segments;
|
||||
}
|
||||
|
||||
public void setSegments(Long segments) {
|
||||
this.segments = segments;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CollectionVO{" +
|
||||
"name='" + name + '\'' +
|
||||
", strategy='" + strategy + '\'' +
|
||||
", size=" + size +
|
||||
", points=" + points +
|
||||
", segments=" + segments +
|
||||
", status='" + status + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.ai.knowledge.entity;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250516
|
||||
*/
|
||||
public class PointVO {
|
||||
private String id;
|
||||
private String text;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PointVO{" +
|
||||
"id='" + id + '\'' +
|
||||
", text='" + text + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
spring:
|
||||
application:
|
||||
name: service-ai-knowledge
|
||||
profiles:
|
||||
include: common,metrics,forest
|
||||
cloud:
|
||||
zookeeper:
|
||||
enabled: true
|
||||
connect-string: b1m2.hdp.dc:2181,b1m3.hdp.dc:2181,b1m4.hdp.dc:2181,b1m5.hdp.dc:2181,b1m6.hdp.dc:2181
|
||||
discovery:
|
||||
enabled: ${spring.cloud.zookeeper.enabled}
|
||||
root: /hudi-services
|
||||
instance-id: ${spring.application.name}-127.0.0.1-${random.uuid}-20250514
|
||||
metadata:
|
||||
discovery: zookeeper
|
||||
ip: 127.0.0.1
|
||||
hostname: localhost
|
||||
hostname_full: localhost
|
||||
start_time: 20250514112750
|
||||
security:
|
||||
meta:
|
||||
authority: ENC(GXKnbq1LS11U2HaONspvH+D/TkIx13aWTaokdkzaF7HSvq6Z0Rv1+JUWFnYopVXu)
|
||||
username: ENC(moIO5mO39V1Z+RDwROK9JXY4GfM8ZjDgM6Si7wRZ1MPVjbhTpmLz3lz28rAiw7c2LeCmizfJzHkEXIwGlB280g==)
|
||||
darkcode: ENC(0jzpQ7T6S+P7bZrENgYsUoLhlqGvw7DA2MN3BRqEOwq7plhtg72vuuiPQNnr3DaYz0CpyTvxInhpx11W3VZ1trD6NINh7O3LN70ZqO5pWXk=)
|
||||
ai:
|
||||
openai:
|
||||
base-url: http://132.121.206.65:10086
|
||||
api-key: ENC(K+Hff9QGC+fcyi510VIDd9CaeK/IN5WBJ9rlkUsHEdDgIidW+stHHJlsK0lLPUXXREha+ToQZqqDXJrqSE+GUKCXklFhelD8bRHFXBIeP/ZzT2cxhzgKUXgjw3S0Qw2R)
|
||||
chat:
|
||||
options:
|
||||
model: 'Qwen3-1.7'
|
||||
embedding:
|
||||
options:
|
||||
model: 'Bge-m3'
|
||||
vectorstore:
|
||||
qdrant:
|
||||
api-key: lanyuanxiaoyao
|
||||
jasypt:
|
||||
encryptor:
|
||||
password: 'r#(R,P"Dp^A47>WSn:Wn].gs/+"v:q_Q*An~zF*g-@j@jtSTv5H/,S-3:R?r9R}.'
|
||||
server:
|
||||
port: 8080
|
||||
@@ -1,34 +0,0 @@
|
||||
<configuration>
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
|
||||
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
|
||||
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
|
||||
|
||||
<springProperty scope="context" name="LOKI_PUSH_URL" source="loki.url"/>
|
||||
<springProperty scope="context" name="LOGGING_PARENT" source="logging.parent"/>
|
||||
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
|
||||
|
||||
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %clr([${HOSTNAME}]){yellow} %clr([%t]){magenta} %clr(%logger{40}){cyan} #@# %m%n%wEx</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOGGING_PARENT:-.}/${APP_NAME:-run}.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOGGING_PARENT:-.}/archive/${APP_NAME:-run}-%d{yyyy-MM-dd}.gz</fileNamePattern>
|
||||
<MaxHistory>7</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [${HOSTNAME}] [%t] %logger #@# %m%n%wEx</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="com.zaxxer.hikari" level="ERROR"/>
|
||||
<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="WARN"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="Console"/>
|
||||
<!-- <appender-ref ref="RollingFile"/>-->
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -60,6 +60,10 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.juicefs</groupId>
|
||||
<artifactId>juicefs-hadoop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>service-configuration</artifactId>
|
||||
|
||||
@@ -168,8 +168,8 @@ public class RunnerApplication implements ApplicationRunner {
|
||||
MapUtil.builder()
|
||||
.put("currentPath", absolutRootPath)
|
||||
.put("hosts", hostInfoList
|
||||
.collect(HostInfoWrapper::getHostnameIp)
|
||||
.toSortedList((o1, o2) -> Comparator.<String>naturalOrder().compare(o1.getIp(), o2.getIp())))
|
||||
.collect(HostInfoWrapper::getHostnameIp)
|
||||
.toSortedList((o1, o2) -> Comparator.<String>naturalOrder().compare(o1.getIp(), o2.getIp())))
|
||||
.put("selectedHosts", selectedHosts)
|
||||
.put("runtime", runtimeInfo)
|
||||
.put("info", serviceInfo)
|
||||
@@ -187,8 +187,8 @@ public class RunnerApplication implements ApplicationRunner {
|
||||
MapUtil.builder()
|
||||
.put("currentPath", absolutRootPath)
|
||||
.put("hosts", hostInfoList
|
||||
.collect(HostInfoWrapper::getHostnameIp)
|
||||
.toSortedList((o1, o2) -> Comparator.<String>naturalOrder().compare(o1.getIp(), o2.getIp())))
|
||||
.collect(HostInfoWrapper::getIp)
|
||||
.toSortedList(Comparator.naturalOrder()))
|
||||
.put("runtime", runtimeInfo)
|
||||
.put("info", serviceInfo)
|
||||
.put("arguments", serviceInfo.getArguments())
|
||||
@@ -199,13 +199,13 @@ public class RunnerApplication implements ApplicationRunner {
|
||||
StrUtil.format("stop-{}.sh", serviceInfo.getName())
|
||||
)
|
||||
);
|
||||
generateTemplate(
|
||||
generateTemplate(
|
||||
"cloud/log.ftl",
|
||||
MapUtil.builder()
|
||||
.put("currentPath", absolutRootPath)
|
||||
.put("hosts", hostInfoList
|
||||
.collect(HostInfoWrapper::getHostnameIp)
|
||||
.toSortedList((o1, o2) -> Comparator.<String>naturalOrder().compare(o1.getIp(), o2.getIp())))
|
||||
.collect(HostInfoWrapper::getIp)
|
||||
.toSortedList(Comparator.naturalOrder()))
|
||||
.put("selectedHosts", selectedHosts)
|
||||
.put("runtime", runtimeInfo)
|
||||
.put("info", serviceInfo)
|
||||
@@ -228,18 +228,6 @@ public class RunnerApplication implements ApplicationRunner {
|
||||
Paths.get(root.toString(), "stop.sh")
|
||||
);
|
||||
|
||||
generateTemplate(
|
||||
"cloud/ssh-script.ftl",
|
||||
MapUtil.builder()
|
||||
.put("currentPath", absolutRootPath)
|
||||
.put("hosts", hostInfoList
|
||||
.collect(HostInfoWrapper::getHostnameIp)
|
||||
.toSortedList((o1, o2) -> Comparator.<String>naturalOrder().compare(o1.getIp(), o2.getIp())))
|
||||
.put("runtime", runtimeInfo)
|
||||
.build(),
|
||||
Paths.get(root.toString(), "ssh.sh")
|
||||
);
|
||||
|
||||
MutableMap<String, MutableList<ServiceInfoWrapper>> groups = Maps.mutable.empty();
|
||||
for (ServiceInfoWrapper service : serviceInfoList) {
|
||||
service.getGroups().add(0, "all");
|
||||
|
||||
@@ -13,5 +13,5 @@ for host in <#noparse>${hosts[@]}</#noparse>
|
||||
do
|
||||
hostname=`ssh $host 'echo $HOSTNAME'`
|
||||
echo "$host $hostname"
|
||||
scp $host:${runtime.logPath}/${info.name}.log ${currentPath}/logs/${info.name}/$hostname.log
|
||||
ssh $host "cat ${runtime.logPath}/${info.name}.log" > ${currentPath}/logs/${info.name}/$hostname.log
|
||||
done
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
command=$@
|
||||
|
||||
hosts=(
|
||||
<#list hosts as host>
|
||||
${host.ip}
|
||||
</#list>
|
||||
)
|
||||
|
||||
for host in <#noparse>${hosts[@]}</#noparse>
|
||||
do
|
||||
hostname=`ssh $host 'echo $HOSTNAME'`
|
||||
echo "$host $hostname"
|
||||
ssh $host $command
|
||||
done
|
||||
@@ -1,7 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
hosts=(
|
||||
<#list hosts as host>
|
||||
host=${host.ip}
|
||||
echo "${info.name} ${host.ip} ${host.hostname} $datetime"
|
||||
ssh $host 'bash -s' < ${currentPath}/stop.sh ${runtime.jarPath}/${info.name}.jar
|
||||
${host}
|
||||
</#list>
|
||||
)
|
||||
|
||||
for host in <#noparse>${hosts[@]}</#noparse>
|
||||
do
|
||||
hostname=`ssh $host 'echo $HOSTNAME'`
|
||||
echo "$host $hostname"
|
||||
ssh $host 'bash -s' < ${currentPath}/stop.sh ${runtime.jarPath}/${info.name}.jar
|
||||
done
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
<groupId>org.apache.hudi</groupId>
|
||||
<artifactId>hudi-flink${flink.major.version}-bundle</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.juicefs</groupId>
|
||||
<artifactId>juicefs-hadoop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-framework</artifactId>
|
||||
|
||||
@@ -72,6 +72,10 @@
|
||||
<groupId>org.apache.hudi</groupId>
|
||||
<artifactId>hudi-flink${flink.major.version}-bundle</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.juicefs</groupId>
|
||||
<artifactId>juicefs-hadoop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-framework</artifactId>
|
||||
|
||||
@@ -174,11 +174,6 @@ public class ExecutorService {
|
||||
}
|
||||
|
||||
private void setEnvironment(Configuration configuration, String key, String value) {
|
||||
logger.info("Setting environment variable {} = {}", key, value);
|
||||
if (ObjectUtil.isNull(value)) {
|
||||
logger.warn("Environment variable {} is null", key);
|
||||
return;
|
||||
}
|
||||
configuration.setString(ResourceManagerOptions.CONTAINERIZED_MASTER_ENV_PREFIX + key, value);
|
||||
configuration.setString(ResourceManagerOptions.CONTAINERIZED_TASK_MANAGER_ENV_PREFIX + key, value);
|
||||
}
|
||||
|
||||
90
service-web/client/.gitignore
vendored
90
service-web/client/.gitignore
vendored
@@ -1,90 +0,0 @@
|
||||
.idea/**
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
.idea/**/aws.xml
|
||||
.idea/**/contentModel.xml
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
cmake-build-*/
|
||||
.idea/**/mongoSettings.xml
|
||||
*.iws
|
||||
out/
|
||||
.idea_modules/
|
||||
atlassian-ide-plugin.xml
|
||||
.idea/replstate.xml
|
||||
.idea/sonarlint/
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
.idea/httpRequests
|
||||
.idea/caches/build_file_checksums.ser
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
lib-cov
|
||||
coverage
|
||||
*.lcov
|
||||
.nyc_output
|
||||
.grunt
|
||||
bower_components
|
||||
.lock-wscript
|
||||
build/Release
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
web_modules/
|
||||
*.tsbuildinfo
|
||||
.npm
|
||||
.eslintcache
|
||||
.stylelintcache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
.node_repl_history
|
||||
*.tgz
|
||||
.yarn-integrity
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
.cache
|
||||
.parcel-cache
|
||||
.next
|
||||
out
|
||||
.nuxt
|
||||
dist
|
||||
.cache/
|
||||
.vuepress/dist
|
||||
.temp
|
||||
.docusaurus
|
||||
.serverless/
|
||||
.fusebox/
|
||||
.dynamodb/
|
||||
.tern-port
|
||||
.vscode-test
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
@@ -1,22 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<link rel="icon" href="icon.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Hudi 服务总台</title>
|
||||
<style>
|
||||
html, body, #root {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "hudi-service-web-client",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@ant-design/pro-components": "^2.8.7",
|
||||
"@ant-design/x": "^1.2.0",
|
||||
"@echofly/fetch-event-source": "^3.0.2",
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
"@tinyflow-ai/react": "^0.1.6",
|
||||
"amis": "^6.12.0",
|
||||
"antd": "^5.25.0",
|
||||
"axios": "^1.9.0",
|
||||
"licia": "^1.48.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router": "^7.5.3",
|
||||
"styled-components": "^6.1.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/react": "^18.2.0",
|
||||
"@types/react-dom": "^18.2.0",
|
||||
"@vitejs/plugin-react-swc": "^3.9.0",
|
||||
"globals": "^16.0.0",
|
||||
"sass": "^1.87.0",
|
||||
"typescript": "~5.8.3",
|
||||
"typescript-eslint": "^8.30.1",
|
||||
"vite": "^6.3.5"
|
||||
}
|
||||
}
|
||||
6730
service-web/client/pnpm-lock.yaml
generated
6730
service-web/client/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB |
@@ -1,10 +0,0 @@
|
||||
import {createRoot} from 'react-dom/client'
|
||||
import {createHashRouter, RouterProvider} from 'react-router'
|
||||
|
||||
import './components/Registry.ts'
|
||||
|
||||
import {routes} from './route.tsx'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<RouterProvider router={createHashRouter(routes)}/>,
|
||||
)
|
||||
@@ -1,42 +0,0 @@
|
||||
import {ProLayout} from '@ant-design/pro-components'
|
||||
import React, {useEffect} from 'react'
|
||||
import {Outlet, useLocation, useNavigate} from 'react-router'
|
||||
import {menus} from '../route.tsx'
|
||||
|
||||
const App: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
return (
|
||||
<ProLayout
|
||||
token={{
|
||||
header: {
|
||||
colorBgHeader: '#292f33',
|
||||
colorHeaderTitle: '#ffffff',
|
||||
colorTextMenu: '#dfdfdf',
|
||||
colorTextMenuSecondary: '#dfdfdf',
|
||||
colorTextMenuSelected: '#ffffff',
|
||||
colorTextMenuActive: '#ffffff',
|
||||
colorBgMenuItemSelected: '#22272b',
|
||||
colorTextRightActionsItem: '#dfdfdf',
|
||||
},
|
||||
}}
|
||||
logo={<img src="icon.png" alt="logo"/>}
|
||||
title="Hudi 服务总台"
|
||||
route={menus}
|
||||
location={{pathname: location.pathname}}
|
||||
menu={{type: 'sub'}}
|
||||
menuItemRender={(item, dom) => {
|
||||
return <div onClick={() => navigate(item.path || '/')}>{dom}</div>
|
||||
}}
|
||||
fixSiderbar={true}
|
||||
layout="mix"
|
||||
splitMenus={true}
|
||||
style={{minHeight: '100vh'}}
|
||||
contentStyle={{backgroundColor: 'white', padding: '10px 10px 10px 20px'}}
|
||||
>
|
||||
<Outlet/>
|
||||
</ProLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
@@ -1,193 +0,0 @@
|
||||
import {ClearOutlined, UserOutlined} from '@ant-design/icons'
|
||||
import {Bubble, Sender, useXAgent, useXChat, Welcome} from '@ant-design/x'
|
||||
import {fetchEventSource} from '@echofly/fetch-event-source'
|
||||
import {Button, Divider, Flex, Switch, Tooltip, Typography} from 'antd'
|
||||
import markdownIt from 'markdown-it'
|
||||
import {useRef, useState} from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const md = markdownIt({html: true, breaks: true})
|
||||
const ConversationDiv = styled.div`
|
||||
height: calc(100vh - 76px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
|
||||
.conversation-welcome {
|
||||
flex: 1;
|
||||
width: 70%;
|
||||
margin: 30px auto 30px;
|
||||
}
|
||||
|
||||
.conversation-list {
|
||||
flex: 1;
|
||||
margin-bottom: 30px;
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
|
||||
think {
|
||||
color: gray;
|
||||
display: block;
|
||||
border-left: 3px solid;
|
||||
padding-left: 5px;
|
||||
margin-bottom: 10px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
}
|
||||
|
||||
.conversation-sender {
|
||||
height: 100px;
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
`
|
||||
|
||||
function Conversation() {
|
||||
const abortController = useRef<AbortController | null>(null)
|
||||
const [input, setInput] = useState<string>('')
|
||||
const [think, setThink] = useState<boolean>(true)
|
||||
|
||||
const [agent] = useXAgent<{ role: string, content: string }>({
|
||||
request: async (info, callbacks) => {
|
||||
await fetchEventSource('http://127.0.0.1:8080/chat/async', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(info.messages),
|
||||
signal: abortController.current?.signal,
|
||||
onmessage: ev => {
|
||||
console.log(ev)
|
||||
callbacks.onUpdate({
|
||||
id: ev.id,
|
||||
event: 'delta',
|
||||
data: ev.data,
|
||||
})
|
||||
},
|
||||
onclose: () => callbacks.onSuccess([]),
|
||||
})
|
||||
},
|
||||
})
|
||||
const {onRequest, messages, setMessages} = useXChat({
|
||||
agent,
|
||||
transformMessage: ({originMessage, chunk}) => {
|
||||
let text = ''
|
||||
try {
|
||||
if (chunk?.data) {
|
||||
text = chunk.data
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
return {
|
||||
content: (originMessage?.content || '') + text,
|
||||
role: 'assistant',
|
||||
}
|
||||
},
|
||||
resolveAbortController: controller => {
|
||||
abortController.current = controller
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<ConversationDiv>
|
||||
{messages.length > 0
|
||||
? (<Bubble.List
|
||||
className="conversation-list"
|
||||
roles={{
|
||||
assistant: {
|
||||
placement: 'start',
|
||||
avatar: {
|
||||
icon: <img src="icon.png" alt=""/>,
|
||||
style: {
|
||||
background: 'transparent',
|
||||
},
|
||||
},
|
||||
messageRender: content => {
|
||||
let split = content.split('</think>')
|
||||
if (split.length > 1) {
|
||||
content = `${split[0]}</think>${md.render(split[1])}`
|
||||
}
|
||||
return (
|
||||
<Typography>
|
||||
<div dangerouslySetInnerHTML={{__html: content}}/>
|
||||
</Typography>
|
||||
)
|
||||
},
|
||||
},
|
||||
user: {
|
||||
placement: 'end',
|
||||
avatar: {
|
||||
icon: <UserOutlined/>,
|
||||
},
|
||||
},
|
||||
}}
|
||||
items={messages.map(({id, message}) => ({
|
||||
key: id,
|
||||
...message,
|
||||
}))}
|
||||
/>)
|
||||
: (<div className="conversation-welcome">
|
||||
<Welcome
|
||||
variant="borderless"
|
||||
icon={<img src="icon.png" alt="icon"/>}
|
||||
title="你好,我是基于大模型深度思考技术构建的 AI 运营助手"
|
||||
description="我可以帮你查询、检索Hudi 服务的运行情况,分析、处理 Hudi 服务的运营故障,输出、解读 Hudi 系统整体运营报告"
|
||||
/>
|
||||
</div>)}
|
||||
<div className="conversation-sender">
|
||||
<Sender
|
||||
value={input}
|
||||
onChange={setInput}
|
||||
onSubmit={message => {
|
||||
onRequest({
|
||||
message: {
|
||||
role: 'user',
|
||||
content: (!think && messages.length === 0) ? `/no_think ${message}` : message,
|
||||
},
|
||||
stream: true,
|
||||
})
|
||||
setInput('')
|
||||
}}
|
||||
onCancel={() => abortController.current?.abort()}
|
||||
footer={({components}) => {
|
||||
const {SendButton, LoadingButton} = components
|
||||
return (
|
||||
<Flex justify="space-between" align="center">
|
||||
<Flex gap="small" align="center">
|
||||
深度思考
|
||||
<Switch
|
||||
size="small"
|
||||
value={think}
|
||||
onChange={setThink}
|
||||
disabled={messages.length > 0}
|
||||
/>
|
||||
<Divider type="vertical"/>
|
||||
<Tooltip title="清空对话">
|
||||
<Button
|
||||
icon={<ClearOutlined/>}
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={() => setMessages([])}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
<Flex align="center">
|
||||
{agent.isRequesting() ? (
|
||||
<LoadingButton type="default"/>
|
||||
) : (
|
||||
<SendButton type="primary" disabled={false}/>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}}
|
||||
actions={false}
|
||||
/>
|
||||
</div>
|
||||
</ConversationDiv>
|
||||
)
|
||||
}
|
||||
|
||||
export default Conversation
|
||||
@@ -1,9 +0,0 @@
|
||||
function Inspection() {
|
||||
return (
|
||||
<div className="inspection">
|
||||
逗你的,什么都没做,哎嘿!
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Inspection
|
||||
@@ -1,105 +0,0 @@
|
||||
import React from 'react'
|
||||
import {useParams} from 'react-router'
|
||||
import {amisRender, crudCommonOptions} from '../../../util/amis.tsx'
|
||||
|
||||
const DataDetail: React.FC = () => {
|
||||
const {name} = useParams()
|
||||
return (
|
||||
<div className="import-detail h-full">
|
||||
{amisRender(
|
||||
{
|
||||
className: 'h-full',
|
||||
type: 'page',
|
||||
title: `数据详情 (知识库:${name})`,
|
||||
size: 'lg',
|
||||
actions: [],
|
||||
body: [
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
url: 'http://127.0.0.1:8080/knowledge/list_points?name=${name}',
|
||||
headers: {
|
||||
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
|
||||
},
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
name: 'text',
|
||||
label: '内容',
|
||||
},
|
||||
{
|
||||
type: 'operation',
|
||||
label: '操作',
|
||||
width: 100,
|
||||
buttons: [
|
||||
{
|
||||
type: 'action',
|
||||
label: '编辑',
|
||||
level: 'link',
|
||||
size: 'lg',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '编辑文段',
|
||||
size: 'md',
|
||||
body: {
|
||||
type: 'form',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'id',
|
||||
disabled: true,
|
||||
label: '文段ID',
|
||||
},
|
||||
{
|
||||
type: 'editor',
|
||||
label: '内容',
|
||||
name: 'text',
|
||||
language: 'plaintext',
|
||||
options: {
|
||||
lineNumbers: 'off',
|
||||
wordWrap: 'bounded',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
label: '删除',
|
||||
className: 'text-danger hover:text-red-600',
|
||||
level: 'link',
|
||||
size: 'xs',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
|
||||
},
|
||||
},
|
||||
confirmText: '确认删除',
|
||||
confirmTitle: '删除',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: name,
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DataDetail
|
||||
@@ -1,144 +0,0 @@
|
||||
import React from 'react'
|
||||
import {useParams} from 'react-router'
|
||||
import styled from 'styled-components'
|
||||
import {amisRender} from '../../../util/amis.tsx'
|
||||
|
||||
const ImportDataDiv = styled.div`
|
||||
.antd-EditorControl {
|
||||
min-height: 500px !important;
|
||||
}
|
||||
`
|
||||
|
||||
const DataImport: React.FC = () => {
|
||||
const {name} = useParams()
|
||||
return (
|
||||
<ImportDataDiv className="import-data h-full">
|
||||
{amisRender({
|
||||
type: 'page',
|
||||
title: `数据导入 (知识库:${name})`,
|
||||
body: [
|
||||
[
|
||||
{
|
||||
className: 'h-full',
|
||||
type: 'grid',
|
||||
columns: [
|
||||
{
|
||||
body: [
|
||||
{
|
||||
type: 'form',
|
||||
wrapWithPanel: false,
|
||||
mode: 'horizontal',
|
||||
actions: [],
|
||||
body: [
|
||||
{
|
||||
name: 'mode',
|
||||
type: 'radios',
|
||||
label: '解析模式',
|
||||
value: 'normal',
|
||||
options: [
|
||||
{
|
||||
value: 'normal',
|
||||
label: '常规模式',
|
||||
},
|
||||
{
|
||||
value: 'llm',
|
||||
label: '智能模式',
|
||||
},
|
||||
{
|
||||
value: 'qa',
|
||||
label: 'Q/A模式',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
type: 'radios',
|
||||
label: '数据形式',
|
||||
value: 'text',
|
||||
options: [
|
||||
{
|
||||
value: 'text',
|
||||
label: '文本',
|
||||
},
|
||||
{
|
||||
value: 'file',
|
||||
label: '文件',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
visibleOn: 'type === \'text\'',
|
||||
type: 'editor',
|
||||
label: '数据内容',
|
||||
name: 'content',
|
||||
language: 'plaintext',
|
||||
options: {
|
||||
lineNumbers: 'off',
|
||||
wordWrap: 'bounded',
|
||||
},
|
||||
},
|
||||
{
|
||||
visibleOn: 'type === \'file\'',
|
||||
type: 'input-file',
|
||||
name: 'files',
|
||||
label: '数据文件',
|
||||
accept: '.txt,.csv',
|
||||
autoUpload: false,
|
||||
drag: true,
|
||||
multiple: true,
|
||||
},
|
||||
{
|
||||
className: 'text-right',
|
||||
type: 'button-toolbar',
|
||||
buttons: [
|
||||
{
|
||||
type: 'action',
|
||||
label: '预览',
|
||||
},
|
||||
{
|
||||
type: 'submit',
|
||||
label: '提交',
|
||||
level: 'primary',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
body: [
|
||||
{
|
||||
type: 'card',
|
||||
className: 'h-full',
|
||||
header: {
|
||||
title: '解析预览',
|
||||
subTitle: '截取部份文本进行解析预览',
|
||||
},
|
||||
body: [
|
||||
{
|
||||
type: 'list',
|
||||
source: '${rows}',
|
||||
listItem: [
|
||||
{
|
||||
body: {
|
||||
type: 'tpl',
|
||||
tpl: '${content}',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
})}
|
||||
</ImportDataDiv>
|
||||
)
|
||||
}
|
||||
|
||||
export default DataImport
|
||||
@@ -1,176 +0,0 @@
|
||||
import React from 'react'
|
||||
import {useNavigate} from 'react-router'
|
||||
import {amisRender, crudCommonOptions, mappingField, mappingItem} from '../../../util/amis.tsx'
|
||||
|
||||
const strategyMapping = [
|
||||
mappingItem('文本', 'Cosine'),
|
||||
mappingItem('图片', 'Euclid'),
|
||||
]
|
||||
|
||||
const statusMapping = [
|
||||
mappingItem('正常', 'Green', 'label-success'),
|
||||
mappingItem('优化中', 'Yellow', 'label-warning'),
|
||||
mappingItem('错误', 'Red', 'label-danger'),
|
||||
mappingItem('等待中', 'Grey', 'label-primary'),
|
||||
]
|
||||
|
||||
const Knowledge: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
return (
|
||||
<div className="knowledge">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'page',
|
||||
title: '知识库',
|
||||
body: [
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
url: 'http://127.0.0.1:8080/knowledge/list',
|
||||
headers: {
|
||||
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
|
||||
},
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
{
|
||||
type: 'action',
|
||||
label: '',
|
||||
icon: 'fa fa-plus',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '新增知识库',
|
||||
size: 'md',
|
||||
body: {
|
||||
type: 'form',
|
||||
api: {
|
||||
url: 'http://127.0.0.1:8080/knowledge/add',
|
||||
dataType: 'form',
|
||||
headers: {
|
||||
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
|
||||
},
|
||||
},
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
name: 'strategy',
|
||||
label: '类型',
|
||||
value: 'Cosine',
|
||||
options: [
|
||||
{
|
||||
label: '文本',
|
||||
value: 'Cosine',
|
||||
},
|
||||
{
|
||||
label: '图片',
|
||||
value: 'Euclid',
|
||||
disabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
},
|
||||
{
|
||||
label: '类型',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
...mappingField('strategy', strategyMapping),
|
||||
},
|
||||
{
|
||||
name: 'points',
|
||||
label: '文本数',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
...mappingField('status', statusMapping),
|
||||
},
|
||||
{
|
||||
type: 'operation',
|
||||
label: '操作',
|
||||
width: 150,
|
||||
buttons: [
|
||||
{
|
||||
type: 'action',
|
||||
label: '详情',
|
||||
level: 'link',
|
||||
size: 'xs',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
// @ts-ignore
|
||||
script: (context, action, event) => {
|
||||
navigate(`/ai/knowledge/detail/${context.props.data['name']}`)
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
label: '导入',
|
||||
level: 'link',
|
||||
size: 'xs',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
// @ts-ignore
|
||||
script: (context, action, event) => {
|
||||
navigate(`/ai/knowledge/import/${context.props.data['name']}`)
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
label: '删除',
|
||||
className: 'text-danger hover:text-red-600',
|
||||
level: 'link',
|
||||
size: 'xs',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: 'http://127.0.0.1:8080/knowledge/delete?name=${name}',
|
||||
headers: {
|
||||
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
|
||||
},
|
||||
},
|
||||
confirmText: '确认删除',
|
||||
confirmTitle: '删除',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Knowledge
|
||||
@@ -1,96 +0,0 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
amisRender,
|
||||
commonInfo,
|
||||
crudCommonOptions,
|
||||
serviceLogByAppName,
|
||||
serviceLogByAppNameAndHost,
|
||||
time,
|
||||
} from '../../util/amis.tsx'
|
||||
|
||||
const cloudCrud = (title: string, path: string) => {
|
||||
return {
|
||||
type: 'crud',
|
||||
title: title,
|
||||
api: `${commonInfo.baseUrl}${path}`,
|
||||
...crudCommonOptions(),
|
||||
interval: 2000,
|
||||
headerToolbar: ['reload'],
|
||||
loadDataOnce: true,
|
||||
perPage: 100,
|
||||
columns: [
|
||||
{
|
||||
label: '名称',
|
||||
type: 'tpl',
|
||||
tpl: `\${name} \${IF(size === undefined, '', '<span class="font-bold label label-primary">' + size + '</span>')}`,
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
label: '状态',
|
||||
align: 'center',
|
||||
width: 60,
|
||||
},
|
||||
{
|
||||
name: 'serviceUpTime',
|
||||
label: '启动时间',
|
||||
...time('serviceUpTime'),
|
||||
align: 'center',
|
||||
width: 160,
|
||||
},
|
||||
{name: 'url', label: '地址'},
|
||||
{
|
||||
type: 'operation',
|
||||
label: '操作',
|
||||
width: 100,
|
||||
fixed: 'right',
|
||||
className: 'nowrap',
|
||||
buttons: [
|
||||
{
|
||||
label: '日志',
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
tooltip: '打开Grafana日志',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
// @ts-ignore
|
||||
script: (context, doAction, event) => {
|
||||
let data = context.props.data
|
||||
let url = ''
|
||||
if (data['metadata']) {
|
||||
url = serviceLogByAppNameAndHost(data.serviceId, data.metadata.hostname)
|
||||
} else if (data['name']) {
|
||||
url = serviceLogByAppName(data.name)
|
||||
}
|
||||
window.open(url, '_blank')
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
const Cloud: React.FC = () => {
|
||||
return (
|
||||
<div className="hudi-cloud">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
cloudCrud('服务列表', '/cloud/list'),
|
||||
cloudCrud('服务列表 (IP)', '/cloud/list_ip'),
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Cloud
|
||||
@@ -1,635 +0,0 @@
|
||||
import React from 'react'
|
||||
import {amisRender, commonInfo, crudCommonOptions, readOnlyDialogOptions} from '../../util/amis.tsx'
|
||||
|
||||
const color = (number: number) => {
|
||||
let color = 'text-success'
|
||||
if (number > 30) {
|
||||
color = 'text-primary'
|
||||
}
|
||||
if (number > 90) {
|
||||
color = 'text-danger'
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
const versionDetailDialog = (variable: string, target: string) => {
|
||||
return {
|
||||
disabledOn: `${variable} === 0`,
|
||||
type: 'action',
|
||||
label: '详情',
|
||||
level: 'link',
|
||||
size: 'sm',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '详情',
|
||||
actions: [],
|
||||
size: 'md',
|
||||
closeOnEsc: false,
|
||||
closeOnOutside: false,
|
||||
body: [
|
||||
{
|
||||
type: 'service',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/overview/version_detail`,
|
||||
data: {
|
||||
target: target,
|
||||
version: '${version}',
|
||||
},
|
||||
},
|
||||
body: [
|
||||
{
|
||||
type: 'table',
|
||||
source: '${items}',
|
||||
affixHeader: false,
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${id}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${id}',
|
||||
tooltip: '复制 ID',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${alias}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const tableDetailDialog = (variable: string, targetList: any) => {
|
||||
return {
|
||||
disabledOn: `${variable} === 0`,
|
||||
type: 'action',
|
||||
label: '详情',
|
||||
level: 'link',
|
||||
size: 'sm',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '详情',
|
||||
size: 'md',
|
||||
...readOnlyDialogOptions(),
|
||||
body: [
|
||||
{
|
||||
type: 'table',
|
||||
source: `\${${targetList}}`,
|
||||
affixHeader: false,
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${id}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${id}',
|
||||
tooltip: '复制 ID',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${alias}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const overviewYarnJob = (cluster: string, search: string, queue: string | undefined, yarnQueue: string) => {
|
||||
return {
|
||||
className: 'text-base leading-none',
|
||||
type: 'table-view',
|
||||
border: false,
|
||||
padding: '0 10px 0 15px',
|
||||
trs: [
|
||||
{
|
||||
tds: [
|
||||
{
|
||||
body: `${cluster}`,
|
||||
},
|
||||
{
|
||||
padding: '0px',
|
||||
body: queue === undefined ? {} : {
|
||||
type: 'service',
|
||||
api: `${commonInfo.baseUrl}/overview/queue?queue=${queue}`,
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${size}',
|
||||
},
|
||||
],
|
||||
},
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
padding: '0px',
|
||||
width: 200,
|
||||
body: {
|
||||
type: 'service',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/overview/yarn-cluster`,
|
||||
data: {
|
||||
cluster: cluster,
|
||||
queue: yarnQueue,
|
||||
},
|
||||
// @ts-ignore
|
||||
adaptor: function (payload, response) {
|
||||
let rootUsed = (payload['data']['root']['usedCapacity'] * 100 / payload['data']['root']['capacity'])
|
||||
let targetUsed = (payload['data']['target']['absoluteUsedCapacity'] * 100 / payload['data']['target']['absoluteMaxCapacity'])
|
||||
return {
|
||||
...payload,
|
||||
data: {
|
||||
...payload.data,
|
||||
rootUsed: rootUsed,
|
||||
rootUsedColor: color(rootUsed),
|
||||
targetUsed: targetUsed,
|
||||
targetUsedColor: color(targetUsed),
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: {
|
||||
type: 'table-view',
|
||||
border: false,
|
||||
trs: [
|
||||
{
|
||||
tds: [
|
||||
{
|
||||
body: {
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold ${rootUsedColor}">${ROUND(rootUsed, 0)}%</span>',
|
||||
},
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
body: {
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold ${targetUsedColor}">${ROUND(targetUsed, 0)}%</span>',
|
||||
},
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
padding: '0px',
|
||||
width: 200,
|
||||
body: {
|
||||
type: 'service',
|
||||
api: {
|
||||
url: `${commonInfo.baseUrl}/overview/yarn-job`,
|
||||
data: {
|
||||
cluster: cluster,
|
||||
search: search,
|
||||
},
|
||||
},
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: {
|
||||
type: 'table-view',
|
||||
border: false,
|
||||
trs: [
|
||||
{
|
||||
tds: [
|
||||
{
|
||||
body: {
|
||||
type: 'tpl',
|
||||
tpl: '<span class=\'font-bold text-cyan-300\'>${scheduling}</span>',
|
||||
},
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
body: {
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-success">${running}</span>',
|
||||
},
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
const Overview: React.FC = () => {
|
||||
return (
|
||||
<div className="hudi-overview">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
{
|
||||
type: 'service',
|
||||
// language=JavaScript
|
||||
dataProvider: 'const timer = setInterval(() => {\n setData({date: new Date().toLocaleString()})\n}, 1000)\nreturn () => {\n clearInterval(timer)\n}',
|
||||
body: [
|
||||
'当前时间:',
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'font-bold',
|
||||
tpl: '${date}',
|
||||
},
|
||||
],
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'crud',
|
||||
title: '同步表数量',
|
||||
api: `${commonInfo.baseUrl}/overview`,
|
||||
...crudCommonOptions(),
|
||||
interval: 60000,
|
||||
columns: [
|
||||
{
|
||||
name: 'type',
|
||||
label: '表类型',
|
||||
},
|
||||
{
|
||||
name: 'total',
|
||||
label: '总表数',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'focus',
|
||||
label: '重点表',
|
||||
className: 'text-danger font-bold',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: '普通表',
|
||||
type: 'tpl',
|
||||
tpl: '${total - focus}',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'crud',
|
||||
title: '同步表数量',
|
||||
api: `${commonInfo.baseUrl}/overview/sync_running_status`,
|
||||
...crudCommonOptions(),
|
||||
interval: 10000,
|
||||
columns: [
|
||||
{
|
||||
name: 'type',
|
||||
label: '类型',
|
||||
},
|
||||
{
|
||||
name: 'total',
|
||||
label: '任务数',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'running',
|
||||
label: '运行中',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'stopped',
|
||||
label: '已停止',
|
||||
className: 'text-danger font-bold',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
type: 'operation',
|
||||
label: '操作',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
buttons: [
|
||||
tableDetailDialog('stopped', 'list'),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
className: 'pl-2 my-5',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: {
|
||||
type: 'tpl',
|
||||
tpl: '同步集群资源用量情况',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'table-view',
|
||||
border: false,
|
||||
trs: [
|
||||
{
|
||||
background: '#F9F9F9',
|
||||
tds: [
|
||||
{
|
||||
bold: true,
|
||||
body: '集群',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '集群资源',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '队列资源',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '调度中',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '运行中',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
overviewYarnJob(commonInfo.clusters.sync_names(), 'Sync', undefined, 'default'),
|
||||
{type: 'divider'},
|
||||
{
|
||||
className: 'pl-2 my-5',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '压缩集群资源用量情况',
|
||||
},
|
||||
{
|
||||
className: 'mt-2',
|
||||
type: 'service',
|
||||
api: `${commonInfo.baseUrl}/overview/queue?queue=compaction-queue-pre`,
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '预调度队列:<span class="font-bold">${size}</span>',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'table-view',
|
||||
border: false,
|
||||
bold: true,
|
||||
trs: [
|
||||
{
|
||||
background: '#F9F9F9',
|
||||
tds: [
|
||||
{
|
||||
bold: true,
|
||||
body: '集群',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '队列',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '集群资源',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '队列资源',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '调度中',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
bold: true,
|
||||
body: '运行中',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// @ts-ignore
|
||||
...Object.keys(commonInfo.clusters.compaction).map(name => overviewYarnJob(name, 'Compaction', `compaction-queue-${name}`, commonInfo.clusters.compaction[name])),
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'service',
|
||||
api: `${commonInfo.baseUrl}/overview/version`,
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'table',
|
||||
title: '跨天情况 (${version})',
|
||||
source: '${items}',
|
||||
...crudCommonOptions(),
|
||||
headerToolbar: [
|
||||
'${version}',
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'type',
|
||||
label: '类型',
|
||||
},
|
||||
{
|
||||
name: 'unReceive',
|
||||
label: '未接收',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
type: 'operation',
|
||||
label: '操作',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
buttons: [
|
||||
versionDetailDialog('unReceive', 'unReceive_${key}'),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'unScheduled',
|
||||
label: '未跨天',
|
||||
className: 'text-danger font-bold',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
type: 'operation',
|
||||
label: '操作',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
buttons: [
|
||||
versionDetailDialog('unScheduled', 'unScheduled_${key}'),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'crud',
|
||||
title: '调度策略',
|
||||
api: `${commonInfo.baseUrl}/overview/schedule_jobs`,
|
||||
...crudCommonOptions(),
|
||||
interval: 60000,
|
||||
loadDataOnce: true,
|
||||
columns: [
|
||||
{
|
||||
name: 'job',
|
||||
label: '策略描述',
|
||||
},
|
||||
{
|
||||
name: 'trigger',
|
||||
label: 'Cron表达式',
|
||||
className: 'font-mono',
|
||||
width: 250,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'crud',
|
||||
title: '监控指标运行进度',
|
||||
api: `${commonInfo.baseUrl}/overview/monitor_progress`,
|
||||
...crudCommonOptions(),
|
||||
interval: 2000,
|
||||
loadDataOnce: true,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
name: 'running',
|
||||
label: '状态',
|
||||
type: 'mapping',
|
||||
width: 70,
|
||||
map: {
|
||||
'true': '运行中',
|
||||
'false': '未运行',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '进度',
|
||||
type: 'progress',
|
||||
value: '${ROUND(progress * 100)}',
|
||||
map: 'bg-primary',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Overview
|
||||
@@ -1,96 +0,0 @@
|
||||
import {
|
||||
amisRender,
|
||||
commonInfo,
|
||||
copyField,
|
||||
crudCommonOptions,
|
||||
paginationCommonOptions,
|
||||
time,
|
||||
yarnQueueCrud,
|
||||
} from '../../util/amis.tsx'
|
||||
|
||||
const queueCrud = (name: string) => {
|
||||
return {
|
||||
type: 'crud',
|
||||
title: name,
|
||||
api: `${commonInfo.baseUrl}/queue/all?name=${name}`,
|
||||
...crudCommonOptions(),
|
||||
interval: 10000,
|
||||
loadDataOnce: true,
|
||||
perPage: 5,
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
'filter-toggler',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '共 <span class=\'text-primary font-bold\'>${total|default:0}</span> 个任务',
|
||||
},
|
||||
paginationCommonOptions(false),
|
||||
],
|
||||
footerToolbar: [],
|
||||
columns: [
|
||||
{
|
||||
name: 'data.flinkJobId',
|
||||
label: '任务 ID',
|
||||
width: 190,
|
||||
...copyField('data.flinkJobId'),
|
||||
},
|
||||
{
|
||||
name: 'data.alias',
|
||||
label: '别名',
|
||||
className: 'nowrap',
|
||||
...copyField('data.alias'),
|
||||
},
|
||||
{
|
||||
name: 'data.batch',
|
||||
label: '批次',
|
||||
width: 100,
|
||||
type: 'tpl',
|
||||
tpl: '<span class="label label-warning">${data.batch}</span>',
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
label: '优先级',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
type: 'tpl',
|
||||
tpl: '<span class="label bg-info">${priority}</span>',
|
||||
},
|
||||
{
|
||||
name: 'data.comment',
|
||||
label: '备注',
|
||||
className: 'nowrap',
|
||||
},
|
||||
{
|
||||
name: 'createTime',
|
||||
label: '任务提交时间',
|
||||
...time('createTime'),
|
||||
width: 160,
|
||||
fixed: 'right',
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
const Queue = () => {
|
||||
let items = []
|
||||
for (let name of Object.keys(commonInfo.clusters.compaction)) {
|
||||
// @ts-ignore
|
||||
items.push(yarnQueueCrud(name, commonInfo.clusters.compaction[name]))
|
||||
items.push(queueCrud(`compaction-queue-${name}`))
|
||||
}
|
||||
return (
|
||||
<div className="hudi-queue">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
queueCrud('compaction-queue-pre'),
|
||||
...items,
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Queue
|
||||
@@ -1,256 +0,0 @@
|
||||
import {
|
||||
aliasTextInput,
|
||||
amisRender,
|
||||
commonInfo,
|
||||
compactionStatusMapping,
|
||||
crudCommonOptions,
|
||||
filterableField,
|
||||
flinkJobDialog,
|
||||
flinkJobIdTextInput,
|
||||
hudiTableTypeMapping,
|
||||
mappingField,
|
||||
paginationCommonOptions,
|
||||
runModeMapping,
|
||||
tableMetaDialog,
|
||||
tableRunningStateMapping,
|
||||
timeAndFrom,
|
||||
} from '../../util/amis.tsx'
|
||||
|
||||
function Table() {
|
||||
return (
|
||||
<div className="hudi-table">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
id: 'table-service',
|
||||
type: 'service',
|
||||
data: {},
|
||||
body: [
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/table/list`,
|
||||
data: {
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
search_flink_job_id: '${flinkJobId|default:undefined}',
|
||||
search_alias: '${alias|default:undefined}',
|
||||
filter_hudi_table_type: '${tableMeta\\.hudi\\.targetTableType|default:undefined}',
|
||||
filter_run_mode: '${flinkJob\\.runMode|default:undefined}',
|
||||
filter_compaction_status: '${syncState\\.compactionStatus|default:undefined}',
|
||||
},
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
// interval: 10000,
|
||||
filter: {
|
||||
title: '表筛选',
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
...flinkJobIdTextInput('58d0da94-1b3c-4234-948d-482ae3425e70'),
|
||||
size: 'lg',
|
||||
},
|
||||
{
|
||||
...aliasTextInput('58d0da94-1b3c-4234-948d-482ae3425e70'),
|
||||
size: 'lg',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
level: 'primary',
|
||||
label: '查询',
|
||||
},
|
||||
{
|
||||
type: 'reset',
|
||||
label: '重置',
|
||||
},
|
||||
],
|
||||
},
|
||||
filterTogglable: true,
|
||||
filterDefaultVisible: true,
|
||||
perPage: 20,
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
'filter-toggler',
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
width: 195,
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${flinkJobId}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: flinkJobDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${flinkJobId}',
|
||||
tooltip: '复制 ID',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${tableMeta.alias}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: tableMetaDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${tableMeta.alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'tableMeta.hudi.targetTableType',
|
||||
label: '表类型',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
...mappingField('tableMeta.hudi.targetTableType', hudiTableTypeMapping),
|
||||
filterable: filterableField(hudiTableTypeMapping, true),
|
||||
},
|
||||
{
|
||||
name: 'flinkJob.runMode',
|
||||
label: '任务类型',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
...mappingField('flinkJob.runMode', runModeMapping),
|
||||
filterable: filterableField(runModeMapping, true),
|
||||
},
|
||||
{
|
||||
name: 'syncRunning',
|
||||
label: '同步运行状态',
|
||||
align: 'center',
|
||||
...mappingField('syncRunning', tableRunningStateMapping),
|
||||
className: 'bg-green-50',
|
||||
width: 75,
|
||||
},
|
||||
{
|
||||
name: 'source_start_time',
|
||||
label: '同步启动时间',
|
||||
...timeAndFrom('syncState.sourceStartTime', 'syncState.sourceStartTimeFromNow', '未启动'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_receive_time',
|
||||
label: '同步接收时间',
|
||||
...timeAndFrom('syncState.sourceReceiveTime', 'syncState.sourceReceiveTimeFromNow', '无数据'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_checkpoint_time',
|
||||
label: '同步心跳时间',
|
||||
...timeAndFrom('syncState.sourceCheckpointTime', 'syncState.sourceCheckpointTimeFromNow', '未启动'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_publish_time',
|
||||
label: '源端发布时间',
|
||||
...timeAndFrom('syncState.sourcePublishTime', 'syncState.sourcePublishTimeFromNow', '无增量'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_operation_time',
|
||||
label: '源端业务时间',
|
||||
...timeAndFrom('syncState.sourceOperationTime', 'syncState.sourceOperationTimeFromNow', '无增量'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'compactionRunning',
|
||||
label: '压缩运行状态',
|
||||
align: 'center',
|
||||
...mappingField('compactionRunning', tableRunningStateMapping),
|
||||
className: 'bg-cyan-50',
|
||||
width: 75,
|
||||
},
|
||||
{
|
||||
name: 'syncState.compactionStatus',
|
||||
label: '压缩状态',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
...mappingField('syncState.compactionStatus', compactionStatusMapping),
|
||||
filterable: filterableField(compactionStatusMapping, true),
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
{
|
||||
name: 'compaction_start_time',
|
||||
label: '压缩启动时间',
|
||||
...timeAndFrom('syncState.compactionStartTime', 'syncState.compactionStartTimeFromNow'),
|
||||
sortable: true,
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
{
|
||||
name: 'compaction_latest_operation_time',
|
||||
label: '压缩业务时间',
|
||||
...timeAndFrom('syncState.compactionLatestOperationTime', 'syncState.compactionLatestOperationTimeFromNow', '无'),
|
||||
sortable: true,
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
{
|
||||
name: 'compaction_finish_time',
|
||||
label: '压缩完成时间',
|
||||
...timeAndFrom('syncState.compactionFinishTime', 'syncState.compactionFinishTimeFromNow'),
|
||||
sortable: true,
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Table
|
||||
@@ -1,195 +0,0 @@
|
||||
import React from 'react'
|
||||
import {amisRender, commonInfo, paginationCommonOptions, serviceLogByAppName, yarnCrudColumns} from '../../util/amis.tsx'
|
||||
|
||||
const Task: React.FC = () => {
|
||||
return (
|
||||
<div className="hudi-task">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
{
|
||||
type: 'form',
|
||||
title: '检索文件',
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
label: '提交任务',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/task/scan`,
|
||||
data: {
|
||||
key: '${key|default:undefined}',
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
pulsar: '${pulsar|default:undefined}',
|
||||
topic: '${topic|default:undefined}',
|
||||
mode: '${scan_mode|default:undefined}',
|
||||
fields: '${fields|default:undefined}',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
body: [
|
||||
{
|
||||
name: 'scan_mode',
|
||||
type: 'checkboxes',
|
||||
label: '检索范围',
|
||||
checkAll: true,
|
||||
required: true,
|
||||
value: 'log',
|
||||
options: [
|
||||
{label: '消息队列', value: 'queue'},
|
||||
{label: '日志文件', value: 'log'},
|
||||
{label: '数据文件', value: 'base'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'key',
|
||||
label: '检索字段',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '检索带有该字符的记录',
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS路经',
|
||||
requiredOn: '${CONTAINS(scan_mode, \'log\') || CONTAINS(scan_mode, \'base\')}',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'log\') || CONTAINS(scan_mode, \'base\')}',
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: `${commonInfo.baseUrl}/table/all_hdfs?key=$term`,
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'fields',
|
||||
label: '指定字段',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'base\')}',
|
||||
clearable: true,
|
||||
description: '逗号分隔,可以大幅提高parquet文件检索速度,但无法获取指定字段外的字段内容',
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'topic',
|
||||
label: 'Pulsar主题',
|
||||
requiredOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
clearable: true,
|
||||
description: '输入Pulsar主题',
|
||||
autoComplete: `${commonInfo.baseUrl}/table/all_pulsar_topic?key=$term`,
|
||||
columnRatio: 4,
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'pulsar',
|
||||
label: 'Pulsar地址',
|
||||
requiredOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
clearable: true,
|
||||
description: '输入Pulsar地址',
|
||||
autoComplete: `${commonInfo.baseUrl}/table/all_pulsar?key=$term`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '综合查询',
|
||||
actions: [
|
||||
{
|
||||
type: 'action',
|
||||
label: '总数&最后操作时间',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/task/table_summary`,
|
||||
data: {
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
label: '最后10条记录',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/task/table_sampling`,
|
||||
data: {
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS路经',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: `${commonInfo.baseUrl}/table/all_hdfs?key=$term`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/yarn/job_list`,
|
||||
data: {
|
||||
clusters: commonInfo.clusters.sync_names(),
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
filter_state: '${state|default:undefined}',
|
||||
filter_final_status: '${finalStatus|default:undefined}',
|
||||
search_id: '${id|default:undefined}',
|
||||
search_name: 'Service_Task',
|
||||
precise: false,
|
||||
},
|
||||
},
|
||||
affixHeader: false,
|
||||
interval: 10000,
|
||||
syncLocation: false,
|
||||
silentPolling: true,
|
||||
resizable: false,
|
||||
perPage: 10,
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
{
|
||||
label: '任务管理器日志',
|
||||
type: 'action',
|
||||
tooltip: '打开Grafana日志',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
script: () => window.open(serviceLogByAppName('service-executor-manager'), '_blank'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [],
|
||||
columns: yarnCrudColumns(),
|
||||
},
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Task
|
||||
@@ -1,316 +0,0 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
aliasTextInput,
|
||||
amisRender,
|
||||
commonInfo,
|
||||
crudCommonOptions,
|
||||
flinkJobIdTextInput,
|
||||
formReloadFlinkJobIdTextInputAndAliasTextInput,
|
||||
hdfsDialog,
|
||||
paginationCommonOptions,
|
||||
readOnlyDialogOptions,
|
||||
timelineColumns,
|
||||
} from '../../util/amis.tsx'
|
||||
|
||||
const Tool: React.FC = () => {
|
||||
return (
|
||||
<div className="hudi-tool">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
{
|
||||
type: 'panel',
|
||||
title: '乱七八糟小工具',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
label: 'SQL日志',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '日志',
|
||||
...readOnlyDialogOptions(),
|
||||
size: 'lg',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: `${commonInfo.baseUrl}/log/query_sql_log`,
|
||||
...crudCommonOptions(),
|
||||
loadDataOnce: true,
|
||||
perPage: 50,
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'sql',
|
||||
label: 'SQL',
|
||||
},
|
||||
{
|
||||
name: 'createTime',
|
||||
label: '执行时间',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
label: 'ZK节点',
|
||||
className: 'ml-2',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '日志',
|
||||
...readOnlyDialogOptions(),
|
||||
size: 'lg',
|
||||
body: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: 'HDFS文件管理器',
|
||||
actions: [
|
||||
{
|
||||
label: '直接下载',
|
||||
type: 'action',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
// @ts-ignore
|
||||
script: (context, action, event) => {
|
||||
let downloadUrl = `${event.data.base}/hudi/hdfs_download?root=${encodeURI(event.data.hdfs)}`
|
||||
window.open(downloadUrl, '_blank')
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'submit',
|
||||
label: '查看',
|
||||
actionType: 'dialog',
|
||||
dialog: hdfsDialog('hdfs'),
|
||||
},
|
||||
],
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS根路经',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: `${commonInfo.baseUrl}/table/all_hdfs?key=$term`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '查询时间线',
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
label: '查询时间线',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: 'Hudi 表时间线',
|
||||
actions: [],
|
||||
size: 'lg',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/hudi/timeline/list_hdfs`,
|
||||
data: {
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
filter_type: '${type|default:active}',
|
||||
filter_action: '${action|default:undefined}',
|
||||
filter_state: '${state|default:undefined}',
|
||||
},
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
perPage: 50,
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
columns: timelineColumns(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'submit',
|
||||
label: '查询表结构',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: 'Hudi 表结构',
|
||||
actions: [],
|
||||
size: 'lg',
|
||||
body: {
|
||||
type: 'service',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/hudi/schema`,
|
||||
data: {
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
},
|
||||
},
|
||||
body: {
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'json',
|
||||
source: '${detail}',
|
||||
levelExpand: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS路经',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: `${commonInfo.baseUrl}/table/all_hdfs?key=$term`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '提交压缩任务',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/schedule/table`,
|
||||
data: {
|
||||
flink_job_id: '${flinkJobId|default:undefined}',
|
||||
alias: '${alias|default:undefined}',
|
||||
recommend: '${recommend === \'undefined\' ? undefined : recommend|default:undefined}',
|
||||
force: '${force === \'undefined\' ? undefined : force|default:undefined}',
|
||||
},
|
||||
},
|
||||
...formReloadFlinkJobIdTextInputAndAliasTextInput('0fe6a96c-6b6e-4346-b18e-c631c2389f48'),
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
flinkJobIdTextInput('0fe6a96c-6b6e-4346-b18e-c631c2389f48', true),
|
||||
aliasTextInput('0fe6a96c-6b6e-4346-b18e-c631c2389f48', true),
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
name: 'recommend',
|
||||
type: 'radios',
|
||||
label: '优先指定集群',
|
||||
selectFirst: true,
|
||||
options: [
|
||||
{label: '无', value: 'undefined'},
|
||||
...Object.keys(commonInfo.clusters.compaction)
|
||||
.map(name => {
|
||||
return {label: name, value: name}
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'force',
|
||||
type: 'radios',
|
||||
label: '强制指定集群',
|
||||
selectFirst: true,
|
||||
options: [
|
||||
{label: '无', value: 'undefined'},
|
||||
...Object.keys(commonInfo.clusters.compaction)
|
||||
.map(name => {
|
||||
return {label: name, value: name}
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '批量提交压缩任务',
|
||||
api: {
|
||||
method: 'post',
|
||||
url: `${commonInfo.baseUrl}/schedule/table_batch`,
|
||||
dataType: 'form',
|
||||
},
|
||||
body: [
|
||||
{
|
||||
name: 'lines',
|
||||
type: 'textarea',
|
||||
label: '表信息 (flink_job_id alias\\n)',
|
||||
clearable: true,
|
||||
minRows: 5,
|
||||
maxRows: 5,
|
||||
className: 'no-resize',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '停止所有压缩任务',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/schedule/stop_all`,
|
||||
data: {
|
||||
flink_job_id: '${flinkJobId|default:undefined}',
|
||||
alias: '${alias|default:undefined}',
|
||||
disable_meta: '${disableMeta|default:undefined}',
|
||||
},
|
||||
},
|
||||
...formReloadFlinkJobIdTextInputAndAliasTextInput('163e043e-8cee-41fd-b5a4-0442ac682aec'),
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
...flinkJobIdTextInput('163e043e-8cee-41fd-b5a4-0442ac682aec', true),
|
||||
columnRatio: 5,
|
||||
},
|
||||
{
|
||||
...aliasTextInput('163e043e-8cee-41fd-b5a4-0442ac682aec', true),
|
||||
columnRatio: 5,
|
||||
},
|
||||
{
|
||||
name: 'disableMeta',
|
||||
type: 'checkbox',
|
||||
label: '是否禁用表',
|
||||
option: '表status设为n',
|
||||
columnRatio: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tool
|
||||
@@ -1,185 +0,0 @@
|
||||
import {
|
||||
aliasTextInput,
|
||||
amisRender,
|
||||
commonInfo,
|
||||
crudCommonOptions,
|
||||
filterableField,
|
||||
flinkJobDialog,
|
||||
flinkJobIdTextInput,
|
||||
mappingField,
|
||||
paginationCommonOptions,
|
||||
tableMetaDialog,
|
||||
versionUpdateStateMapping,
|
||||
} from '../../util/amis.tsx'
|
||||
|
||||
function Version() {
|
||||
return (
|
||||
<div className="hudi-version">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/version_update/list`,
|
||||
data: {
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
search_flink_job_id: '${flinkJobId|default:undefined}',
|
||||
search_alias: '${alias|default:undefined}',
|
||||
search_version: '${version|default:undefined}',
|
||||
filter_schedules: '${updated|default:undefined}',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
now: '${DATETOSTR(DATEMODIFY(NOW(), -1, \'days\'), \'YYYYMMDD\')}',
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
interval: 10000,
|
||||
filter: {
|
||||
mode: 'inline',
|
||||
title: '表筛选',
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
...flinkJobIdTextInput('c5cac9d3-844a-4d86-b2c5-0c10f2283667'),
|
||||
size: 'md',
|
||||
},
|
||||
{
|
||||
...aliasTextInput('c5cac9d3-844a-4d86-b2c5-0c10f2283667'),
|
||||
size: 'md',
|
||||
},
|
||||
{
|
||||
type: 'input-date',
|
||||
name: 'version',
|
||||
label: '版本',
|
||||
clearable: true,
|
||||
placeholder: '通过版本搜索',
|
||||
size: 'md',
|
||||
format: 'YYYYMMDD',
|
||||
inputFormat: 'YYYYMMDD',
|
||||
value: '${now}',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
level: 'primary',
|
||||
label: '查询',
|
||||
},
|
||||
{
|
||||
type: 'reset',
|
||||
label: '重置',
|
||||
},
|
||||
],
|
||||
},
|
||||
filterTogglable: true,
|
||||
filterDefaultVisible: true,
|
||||
perPage: 20,
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
'filter-toggler',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '共 <span class=\'text-primary font-bold\'>${total|default:0}</span> 个表,其中 <span class=\'text-success font-bold\'>${scheduled|default:0}</span> 个表已跨天,<span class=\'text-danger font-bold\'>${unScheduled|default:0}</span> 个表未跨天',
|
||||
},
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
width: 195,
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${flinkJobId}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: flinkJobDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${flinkJobId}',
|
||||
tooltip: '复制 ID',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${tableMeta.alias}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: tableMetaDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${tableMeta.alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
label: '表优先级',
|
||||
align: 'center',
|
||||
width: 75,
|
||||
sortable: true,
|
||||
}, {
|
||||
name: 'version',
|
||||
label: '版本',
|
||||
align: 'center',
|
||||
width: 75,
|
||||
},
|
||||
{
|
||||
name: 'updated',
|
||||
label: '状态',
|
||||
align: 'center',
|
||||
...mappingField('updated', versionUpdateStateMapping),
|
||||
filterable: filterableField(versionUpdateStateMapping, true),
|
||||
width: 70,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Version
|
||||
@@ -1,123 +0,0 @@
|
||||
import React from 'react'
|
||||
import {useLocation, useParams} from 'react-router'
|
||||
import {
|
||||
amisRender,
|
||||
commonInfo,
|
||||
crudCommonOptions,
|
||||
paginationCommonOptions,
|
||||
yarnCrudColumns,
|
||||
yarnQueueCrud,
|
||||
} from '../../util/amis.tsx'
|
||||
|
||||
const Yarn: React.FC = () => {
|
||||
const {clusters, queue, search} = useParams()
|
||||
const location = useLocation()
|
||||
return (
|
||||
<div key={location.key} className="hudi-yarn">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
{
|
||||
id: `${clusters}-yarn-service`,
|
||||
name: `${clusters}-yarn-service`,
|
||||
type: 'service',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-xl">集群资源</span>',
|
||||
},
|
||||
yarnQueueCrud(clusters, queue),
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-xl">集群任务</span>',
|
||||
// className: 'mb-2 block',
|
||||
},
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `${commonInfo.baseUrl}/yarn/job_list`,
|
||||
data: {
|
||||
clusters: `${clusters}`,
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
filter_state: '${state|default:undefined}',
|
||||
filter_final_status: '${finalStatus|default:undefined}',
|
||||
search_id: '${id|default:undefined}',
|
||||
search_name: '${name|default:undefined}',
|
||||
completion: 'true',
|
||||
},
|
||||
},
|
||||
defaultParams: {
|
||||
name: search,
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
interval: 10000,
|
||||
filter: {
|
||||
mode: 'inline',
|
||||
title: '任务筛选',
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'id',
|
||||
label: 'ID',
|
||||
clearable: true,
|
||||
placeholder: '通过 ID 搜索',
|
||||
size: 'md',
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
clearable: true,
|
||||
placeholder: '通过名称搜索',
|
||||
size: 'md',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
level: 'primary',
|
||||
label: '查询',
|
||||
},
|
||||
{
|
||||
type: 'reset',
|
||||
label: '重置',
|
||||
},
|
||||
],
|
||||
},
|
||||
filterTogglable: true,
|
||||
filterDefaultVisible: false,
|
||||
perPage: 20,
|
||||
headerToolbar: [
|
||||
'reload',
|
||||
'filter-toggler',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '共 <span class=\'text-primary font-bold\'>${total|default:0}</span> 个任务,其中 <span class=\'text-success font-bold\'>${running|default:0}</span> 个任务运行中,<span class=\'text-danger font-bold\'>${unRunning|default:0}</span> 个任务处于非运行状态',
|
||||
},
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
columns: yarnCrudColumns(),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Yarn
|
||||
@@ -1,19 +0,0 @@
|
||||
import React from 'react'
|
||||
import {amisRender, commonInfo, yarnQueueCrud} from '../../util/amis.tsx'
|
||||
|
||||
const YarnCluster: React.FC = () => {
|
||||
return (
|
||||
<div className="hudi-yarn-cluster">
|
||||
{amisRender(
|
||||
{
|
||||
type: 'wrapper',
|
||||
body: [
|
||||
...Object.keys(commonInfo.clusters.compaction).map(name => yarnQueueCrud(name)),
|
||||
],
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default YarnCluster
|
||||
@@ -1,206 +0,0 @@
|
||||
import {
|
||||
CheckSquareOutlined,
|
||||
CloudOutlined,
|
||||
ClusterOutlined,
|
||||
CompressOutlined,
|
||||
DatabaseOutlined,
|
||||
InfoCircleOutlined,
|
||||
OpenAIOutlined,
|
||||
QuestionOutlined,
|
||||
SunOutlined,
|
||||
SyncOutlined,
|
||||
TableOutlined,
|
||||
ToolOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import {Navigate, type RouteObject} from 'react-router'
|
||||
import Conversation from './pages/ai/Conversation.tsx'
|
||||
import Inspection from './pages/ai/Inspection.tsx'
|
||||
import DataDetail from './pages/ai/knowledge/DataDetail.tsx'
|
||||
import DataImport from './pages/ai/knowledge/DataImport.tsx'
|
||||
import Knowledge from './pages/ai/knowledge/Knowledge.tsx'
|
||||
import App from './pages/App.tsx'
|
||||
import Cloud from './pages/overview/Cloud.tsx'
|
||||
import Overview from './pages/overview/Overview.tsx'
|
||||
import Queue from './pages/overview/Queue.tsx'
|
||||
import Table from './pages/overview/Table.tsx'
|
||||
import Task from './pages/overview/Task.tsx'
|
||||
import Tool from './pages/overview/Tool.tsx'
|
||||
import Version from './pages/overview/Version.tsx'
|
||||
import Yarn from './pages/overview/Yarn.tsx'
|
||||
import YarnCluster from './pages/overview/YarnCluster.tsx'
|
||||
import {commonInfo} from './util/amis.tsx'
|
||||
|
||||
export const routes: RouteObject[] = [
|
||||
{
|
||||
path: '/',
|
||||
Component: App,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Navigate to="/overview" replace/>,
|
||||
},
|
||||
{
|
||||
path: 'overview',
|
||||
Component: Overview,
|
||||
},
|
||||
{
|
||||
path: 'table',
|
||||
Component: Table,
|
||||
},
|
||||
{
|
||||
path: 'queue',
|
||||
Component: Queue,
|
||||
},
|
||||
{
|
||||
path: 'version',
|
||||
Component: Version,
|
||||
},
|
||||
{
|
||||
path: 'yarn/:clusters/:queue/:search?',
|
||||
Component: Yarn,
|
||||
},
|
||||
{
|
||||
path: 'cloud',
|
||||
Component: Cloud,
|
||||
},
|
||||
{
|
||||
path: 'yarn_cluster',
|
||||
Component: YarnCluster,
|
||||
},
|
||||
{
|
||||
path: 'tool',
|
||||
Component: Tool,
|
||||
},
|
||||
{
|
||||
path: 'task',
|
||||
Component: Task,
|
||||
},
|
||||
{
|
||||
path: 'ai',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Navigate to="/ai/conversation" replace/>,
|
||||
},
|
||||
{
|
||||
path: 'inspection',
|
||||
Component: Inspection,
|
||||
},
|
||||
{
|
||||
path: 'conversation',
|
||||
Component: Conversation,
|
||||
},
|
||||
{
|
||||
path: 'knowledge',
|
||||
Component: Knowledge,
|
||||
},
|
||||
{
|
||||
path: 'knowledge/import/:name',
|
||||
Component: DataImport,
|
||||
},
|
||||
{
|
||||
path: 'knowledge/detail/:name',
|
||||
Component: DataDetail,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
export const menus = {
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: '概览',
|
||||
icon: <InfoCircleOutlined/>,
|
||||
routes: [
|
||||
{
|
||||
path: '/overview',
|
||||
name: '概览',
|
||||
icon: <InfoCircleOutlined/>,
|
||||
},
|
||||
{
|
||||
path: '/table',
|
||||
name: '表任务',
|
||||
icon: <TableOutlined/>,
|
||||
},
|
||||
{
|
||||
path: '/queue',
|
||||
name: '压缩队列',
|
||||
icon: <CompressOutlined/>,
|
||||
},
|
||||
{
|
||||
path: '/version',
|
||||
name: '跨天',
|
||||
icon: <SunOutlined/>,
|
||||
},
|
||||
{
|
||||
path: `/yarn/${commonInfo.clusters.sync_names()}/root/Sync`,
|
||||
name: '同步集群',
|
||||
icon: <SyncOutlined/>,
|
||||
},
|
||||
{
|
||||
path: `/yarn/${commonInfo.clusters.compaction_names()}/default/Compaction`,
|
||||
name: '压缩集群',
|
||||
icon: <SyncOutlined/>,
|
||||
},
|
||||
{
|
||||
path: '/cloud',
|
||||
name: '服务',
|
||||
icon: <CloudOutlined/>,
|
||||
},
|
||||
{
|
||||
path: 'a86f7c51-ae60-4ca4-8c4d-40b86b445a04',
|
||||
name: '集群',
|
||||
icon: <ClusterOutlined/>,
|
||||
routes: [
|
||||
{
|
||||
path: '/yarn_cluster',
|
||||
name: '概览',
|
||||
icon: <InfoCircleOutlined/>,
|
||||
},
|
||||
...Object.keys(commonInfo.clusters.compaction).map(name => ({
|
||||
// @ts-ignore
|
||||
path: `/yarn/${name}/${commonInfo.clusters.compaction[name]}`,
|
||||
name: `${name} 集群`,
|
||||
icon: <ClusterOutlined/>,
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/tool',
|
||||
name: '工具',
|
||||
icon: <ToolOutlined/>,
|
||||
},
|
||||
{
|
||||
path: '/task',
|
||||
name: '任务',
|
||||
icon: <CheckSquareOutlined/>,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/ai',
|
||||
name: 'AI',
|
||||
icon: <OpenAIOutlined/>,
|
||||
routes: [
|
||||
{
|
||||
path: '/ai/conversation',
|
||||
name: '智慧问答',
|
||||
icon: <QuestionOutlined/>,
|
||||
},
|
||||
{
|
||||
path: '/ai/inspection',
|
||||
name: '智能巡检',
|
||||
icon: <CheckSquareOutlined/>,
|
||||
},
|
||||
{
|
||||
path: '/ai/knowledge',
|
||||
name: '知识库',
|
||||
icon: <DatabaseOutlined/>,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
1
service-web/client/src/vite-env.d.ts
vendored
1
service-web/client/src/vite-env.d.ts
vendored
@@ -1 +0,0 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": [
|
||||
"ESNext",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
import {defineConfig, UserConfig} from 'vite'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig(({mode}) => {
|
||||
let config: UserConfig = {
|
||||
plugins: [react()],
|
||||
}
|
||||
if (mode === 'production') {
|
||||
config.base = '/hudi_services/service_web'
|
||||
}
|
||||
return config
|
||||
})
|
||||
@@ -28,29 +28,6 @@
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-web-dist</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${project.basedir}/client/dist</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="AdditionalModuleElements">
|
||||
<content url="file://$MODULE_DIR$" dumb="true">
|
||||
<excludeFolder url="file://$MODULE_DIR$/client/dist" />
|
||||
</content>
|
||||
</component>
|
||||
</module>
|
||||
@@ -8,26 +8,27 @@ import com.lanyuanxiaoyao.service.configuration.ExecutorProvider;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.monitor.MetricsProgress;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnApplication;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnRootQueue;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.zookeeper.ZookeeperNode;
|
||||
import com.lanyuanxiaoyao.service.forest.service.*;
|
||||
import com.lanyuanxiaoyao.service.forest.service.InfoService;
|
||||
import com.lanyuanxiaoyao.service.forest.service.MonitorService;
|
||||
import com.lanyuanxiaoyao.service.forest.service.QueueService;
|
||||
import com.lanyuanxiaoyao.service.forest.service.ScheduleService;
|
||||
import com.lanyuanxiaoyao.service.forest.service.YarnService;
|
||||
import com.lanyuanxiaoyao.service.forest.service.ZookeeperService;
|
||||
import com.lanyuanxiaoyao.service.web.controller.base.AmisCrudResponse;
|
||||
import com.lanyuanxiaoyao.service.web.controller.base.AmisMapResponse;
|
||||
import com.lanyuanxiaoyao.service.web.controller.base.AmisResponse;
|
||||
import com.lanyuanxiaoyao.service.web.controller.base.BaseController;
|
||||
import com.lanyuanxiaoyao.service.web.entity.JobIdAndAliasVO;
|
||||
import com.lanyuanxiaoyao.service.web.entity.ScheduleTimeVO;
|
||||
import com.lanyuanxiaoyao.service.web.entity.overview.TableCountVO;
|
||||
import com.lanyuanxiaoyao.service.web.entity.overview.TaskCountVO;
|
||||
import com.lanyuanxiaoyao.service.web.entity.overview.VersionCountVO;
|
||||
import com.lanyuanxiaoyao.service.web.entity.overview.YarnCountVO;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import org.eclipse.collections.api.factory.Lists;
|
||||
import org.eclipse.collections.api.factory.Maps;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
import org.eclipse.collections.api.list.MutableList;
|
||||
import org.slf4j.Logger;
|
||||
@@ -66,7 +67,7 @@ public class OverviewController extends BaseController {
|
||||
}
|
||||
|
||||
@GetMapping("")
|
||||
public AmisCrudResponse overview() throws ExecutionException, InterruptedException {
|
||||
public AmisMapResponse overview() throws ExecutionException, InterruptedException {
|
||||
CompletableFuture<Long> tableCountFuture = CompletableFuture.supplyAsync(infoService::tableCount, ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> tableFocusCountFuture = CompletableFuture.supplyAsync(infoService::tableFocusCount, ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> hudiCountFuture = CompletableFuture.supplyAsync(infoService::hudiCount, ExecutorProvider.EXECUTORS);
|
||||
@@ -81,12 +82,13 @@ public class OverviewController extends BaseController {
|
||||
hiveCountFuture,
|
||||
hiveFocusCountFuture
|
||||
).get();
|
||||
ImmutableList<TableCountVO> list = Lists.immutable.of(
|
||||
new TableCountVO("逻辑表", tableCountFuture.get(), tableFocusCountFuture.get()),
|
||||
new TableCountVO("湖底表", hudiCountFuture.get(), hudiFocusCountFuture.get()),
|
||||
new TableCountVO("嗨福表", hiveCountFuture.get(), hiveFocusCountFuture.get())
|
||||
);
|
||||
return AmisResponse.responseCrudData(list);
|
||||
return AmisResponse.responseMapData()
|
||||
.setData("table_count", tableCountFuture.get())
|
||||
.setData("table_focus_count", tableFocusCountFuture.get())
|
||||
.setData("hudi_count", hudiCountFuture.get())
|
||||
.setData("hudi_focus_count", hudiFocusCountFuture.get())
|
||||
.setData("hive_count", hiveCountFuture.get())
|
||||
.setData("hive_focus_count", hiveFocusCountFuture.get());
|
||||
}
|
||||
|
||||
@GetMapping("yarn-job")
|
||||
@@ -97,6 +99,7 @@ public class OverviewController extends BaseController {
|
||||
.setData("name", cluster)
|
||||
.setData("total", applications.size())
|
||||
.setData("running", applications.count(app -> StrUtil.equals(app.getState(), "RUNNING")))
|
||||
.setData("running", applications.count(app -> StrUtil.equals(app.getState(), "RUNNING")))
|
||||
.setData("scheduling", applications.count(app -> StrUtil.equals(app.getState(), "ACCEPTED")))
|
||||
.setData("failure", applications.count(app -> StrUtil.equals(app.getState(), "FAILED")));
|
||||
}
|
||||
@@ -128,13 +131,10 @@ public class OverviewController extends BaseController {
|
||||
CompletableFuture<Long> unScheduledNormalTableCount = CompletableFuture.supplyAsync(() -> infoService.unScheduledNormalTableCount(version), ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture<Long> unScheduledFocusTableCount = CompletableFuture.supplyAsync(() -> infoService.unScheduledFocusTableCount(version), ExecutorProvider.EXECUTORS);
|
||||
CompletableFuture.allOf(unReceiveNormalTableCount, unReceiveFocusCount, unScheduledNormalTableCount, unScheduledFocusTableCount).get();
|
||||
ImmutableList<VersionCountVO> list = Lists.immutable.of(
|
||||
new VersionCountVO("focus", "重点表", unReceiveFocusCount.get(), unScheduledFocusTableCount.get()),
|
||||
new VersionCountVO("normal", "普通表", unReceiveNormalTableCount.get(), unScheduledNormalTableCount.get())
|
||||
);
|
||||
return AmisResponse.responseMapData()
|
||||
.setData("version", version)
|
||||
.setData("items", list);
|
||||
.setData("unReceive", Maps.immutable.of("normal", unReceiveNormalTableCount.get(), "focus", unReceiveFocusCount.get()))
|
||||
.setData("unSchedule", Maps.immutable.of("normal", unScheduledNormalTableCount.get(), "focus", unScheduledFocusTableCount.get()));
|
||||
}
|
||||
|
||||
@GetMapping("version_detail")
|
||||
@@ -175,7 +175,7 @@ public class OverviewController extends BaseController {
|
||||
}
|
||||
|
||||
@GetMapping("sync_running_status")
|
||||
public AmisCrudResponse syncRunningStatus() {
|
||||
public AmisMapResponse syncRunningStatus() {
|
||||
ImmutableList<String> locks = zookeeperService.getChildren(NameHelper.ZK_SYNC_RUNNING_LOCK_PATH).collect(ZookeeperNode::getPath);
|
||||
MutableList<JobIdAndAlias> runningJob = Lists.mutable.<JobIdAndAlias>empty().asSynchronized();
|
||||
MutableList<JobIdAndAlias> unRunningJob = Lists.mutable.<JobIdAndAlias>empty().asSynchronized();
|
||||
@@ -203,11 +203,17 @@ public class OverviewController extends BaseController {
|
||||
unRunningTable.add(ia);
|
||||
}
|
||||
});
|
||||
ImmutableList<TaskCountVO> list = Lists.immutable.of(
|
||||
new TaskCountVO("同步任务数", ids.size(), runningJob.size(), unRunningJob.size(), unRunningJob.toImmutable()),
|
||||
new TaskCountVO("同步表数", idAliases.size(), runningTable.size(), unRunningTable.size(), unRunningTable.toImmutable())
|
||||
);
|
||||
return AmisResponse.responseCrudData(list);
|
||||
return AmisResponse.responseMapData()
|
||||
.setData("totalJob", ids.size())
|
||||
.setData("runningJob", runningJob.size())
|
||||
.setData("runningJobList", runningJob)
|
||||
.setData("unRunningJob", unRunningJob.size())
|
||||
.setData("unRunningJobList", unRunningJob)
|
||||
.setData("totalTable", idAliases.size())
|
||||
.setData("runningTable", runningTable.size())
|
||||
.setData("runningTableList", runningTable)
|
||||
.setData("unRunningTable", unRunningTable.size())
|
||||
.setData("unRunningTableList", unRunningTable);
|
||||
}
|
||||
|
||||
@GetMapping("monitor_progress")
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.web.entity.overview;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250509
|
||||
*/
|
||||
public class TableCountVO {
|
||||
private final String type;
|
||||
private final Long total;
|
||||
private final Long focus;
|
||||
|
||||
public TableCountVO(String type, Long total, Long focus) {
|
||||
this.type = type;
|
||||
this.total = total;
|
||||
this.focus = focus;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public Long getFocus() {
|
||||
return focus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TableCountVO{" +
|
||||
"type='" + type + '\'' +
|
||||
", total=" + total +
|
||||
", focus=" + focus +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.web.entity.overview;
|
||||
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.info.JobIdAndAlias;
|
||||
import org.eclipse.collections.api.list.ImmutableList;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250509
|
||||
*/
|
||||
public class TaskCountVO {
|
||||
private final String type;
|
||||
private final Integer total;
|
||||
private final Integer running;
|
||||
private final Integer stopped;
|
||||
private final ImmutableList<JobIdAndAlias> list;
|
||||
|
||||
public TaskCountVO(String type, Integer total, Integer running, Integer stopped, ImmutableList<JobIdAndAlias> list) {
|
||||
this.type = type;
|
||||
this.total = total;
|
||||
this.running = running;
|
||||
this.stopped = stopped;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Integer getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public Integer getRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public Integer getStopped() {
|
||||
return stopped;
|
||||
}
|
||||
|
||||
public ImmutableList<JobIdAndAlias> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TaskCountVO{" +
|
||||
"type='" + type + '\'' +
|
||||
", total=" + total +
|
||||
", running=" + running +
|
||||
", stopped=" + stopped +
|
||||
", list=" + list +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.web.entity.overview;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250509
|
||||
*/
|
||||
public class VersionCountVO {
|
||||
private final String key;
|
||||
private final String type;
|
||||
private final Long unReceive;
|
||||
private final Long unScheduled;
|
||||
|
||||
public VersionCountVO(String key, String type, Long unReceive, Long unScheduled) {
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
this.unReceive = unReceive;
|
||||
this.unScheduled = unScheduled;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Long getUnReceive() {
|
||||
return unReceive;
|
||||
}
|
||||
|
||||
public Long getUnScheduled() {
|
||||
return unScheduled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VersionCountVO{" +
|
||||
"key='" + key + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", unReceive=" + unReceive +
|
||||
", unScheduled=" + unScheduled +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package com.lanyuanxiaoyao.service.web.entity.overview;
|
||||
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnQueue;
|
||||
import com.lanyuanxiaoyao.service.configuration.entity.yarn.YarnRootQueue;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250509
|
||||
*/
|
||||
public class YarnCountVO {
|
||||
private final String cluster;
|
||||
private final Integer total;
|
||||
private final Integer running;
|
||||
private final Integer scheduling;
|
||||
private final Integer failure;
|
||||
private final YarnRootQueue root;
|
||||
private final YarnQueue target;
|
||||
private final Integer queue;
|
||||
|
||||
public YarnCountVO(String cluster, Integer total, Integer running, Integer scheduling, Integer failure, YarnRootQueue root, YarnQueue target, Integer queue) {
|
||||
this.cluster = cluster;
|
||||
this.total = total;
|
||||
this.running = running;
|
||||
this.scheduling = scheduling;
|
||||
this.failure = failure;
|
||||
this.root = root;
|
||||
this.target = target;
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
public String getCluster() {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
public Integer getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public Integer getRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public Integer getScheduling() {
|
||||
return scheduling;
|
||||
}
|
||||
|
||||
public Integer getFailure() {
|
||||
return failure;
|
||||
}
|
||||
|
||||
public YarnRootQueue getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
public YarnQueue getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public Integer getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "YarnCountVO{" +
|
||||
"cluster='" + cluster + '\'' +
|
||||
", total=" + total +
|
||||
", running=" + running +
|
||||
", scheduling=" + scheduling +
|
||||
", failure=" + failure +
|
||||
", root=" + root +
|
||||
", target=" + target +
|
||||
", queue=" + queue +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,23 @@
|
||||
<springProperty scope="context" name="LOGGING_PARENT" source="logging.parent"/>
|
||||
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
|
||||
|
||||
<appender name="Loki" class="com.github.loki4j.logback.Loki4jAppender">
|
||||
<metricsEnabled>true</metricsEnabled>
|
||||
<http class="com.github.loki4j.logback.ApacheHttpSender">
|
||||
<url>${LOKI_PUSH_URL:-http://localhost/loki/api/v1/push}</url>
|
||||
</http>
|
||||
<format>
|
||||
<label>
|
||||
<pattern>app=${APP_NAME:-none},host=${HOSTNAME:-none},level=%level</pattern>
|
||||
<readMarkers>true</readMarkers>
|
||||
</label>
|
||||
<message>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [${HOSTNAME}] [%t] %logger #@# %m%n%wEx</pattern>
|
||||
</message>
|
||||
<sortByTime>true</sortByTime>
|
||||
</format>
|
||||
</appender>
|
||||
|
||||
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %clr([${HOSTNAME}]){yellow} %clr([%t]){magenta} %clr(%logger{40}){cyan} #@# %m%n%wEx</pattern>
|
||||
@@ -28,6 +45,7 @@
|
||||
<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="WARN"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="Loki"/>
|
||||
<appender-ref ref="Console"/>
|
||||
<appender-ref ref="RollingFile"/>
|
||||
</root>
|
||||
|
||||
BIN
service-web/src/main/resources/static/assets/icon.png
Normal file
BIN
service-web/src/main/resources/static/assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
150
service-web/src/main/resources/static/common/info.js
Normal file
150
service-web/src/main/resources/static/common/info.js
Normal file
@@ -0,0 +1,150 @@
|
||||
const commonInfo = {
|
||||
baseUrl: 'http://132.126.207.130:35690/hudi_services/service_web',
|
||||
// baseUrl: '/hudi_services/service_web',
|
||||
clusters: {
|
||||
// hudi同步运行集群和yarn队列名称
|
||||
sync: {
|
||||
'b12': 'default',
|
||||
},
|
||||
sync_names() {
|
||||
return Object.keys(this.sync).join(',')
|
||||
},
|
||||
// hudi压缩运行集群和yarn队列名称
|
||||
compaction: {
|
||||
'b12': 'default',
|
||||
'b1': 'datalake',
|
||||
'a4': 'ten_iap.datalake',
|
||||
},
|
||||
compaction_names() {
|
||||
return Object.keys(this.compaction).join(',')
|
||||
},
|
||||
},
|
||||
loki: {
|
||||
// grafana链接,用于直接打开grafana日志查看
|
||||
grafanaUrl: 'http://132.126.207.125:35700',
|
||||
// grafana对应hudi使用的loki配置的datasource id
|
||||
hudi: {
|
||||
datasource: 'f648174e-7593-45cf-8fe8-8f8d5cf0fdde',
|
||||
},
|
||||
// grafana对应服务使用的loki配置的datasource id
|
||||
service: {
|
||||
datasource: 'b6fee51c-facd-4261-a0eb-8c69a975fba3',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries
|
||||
* {datasource, queryMap}
|
||||
*/
|
||||
function generateLokiPanel(queries) {
|
||||
return {
|
||||
LWF: {
|
||||
queries: [
|
||||
...queries.map(item => {
|
||||
let name = item['name']
|
||||
let datasource = item['datasource']
|
||||
let queryMap = item['queryMap']
|
||||
let query = Object.keys(queryMap)
|
||||
.sort()
|
||||
.map(key => `${key}="${queryMap[key]}"`)
|
||||
let match = "\\d{4}-(?P<time>\\d{2}-\\d{2}\\s*\\d{2}:\\d{2}:\\d{2}).+#@#\\s*(?P<content>[\\w\\W]+)"
|
||||
let format = "{{.time}} [{{.host}}] [{{.level}}] [{{.app}}] {{.content}}"
|
||||
// language=TEXT
|
||||
let expression = `{${query.join(",")}}\n| regexp "${match.replaceAll('\\', '\\\\')}"\n| line_format \`${format}\``
|
||||
return {
|
||||
refId: name,
|
||||
expr: expression,
|
||||
queryType: "range",
|
||||
datasource: {
|
||||
type: "loki",
|
||||
uid: datasource
|
||||
},
|
||||
editorMode: "code"
|
||||
}
|
||||
})
|
||||
],
|
||||
range: {
|
||||
from: "now-1h",
|
||||
to: "now"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateQuery(name, datasource, queryMap) {
|
||||
return {
|
||||
name: name,
|
||||
datasource: datasource,
|
||||
queryMap: queryMap,
|
||||
}
|
||||
}
|
||||
|
||||
function generateLokiUrl(baseUrl, queries) {
|
||||
return `${baseUrl}/explore?panes=${encodeURIComponent(JSON.stringify(generateLokiPanel(queries)))}&schemaVersion=1&orgId=1`
|
||||
}
|
||||
|
||||
function targetHudiSyncLokiUrlByAlias(flinkJobId) {
|
||||
return generateLokiUrl(
|
||||
commonInfo.loki.grafanaUrl,
|
||||
[
|
||||
generateQuery(
|
||||
"Hudi 运行日志",
|
||||
commonInfo.loki.hudi.datasource,
|
||||
{"flink_job_id": flinkJobId}
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
function targetHudiCompactionLokiUrlByAlias(alias) {
|
||||
return generateLokiUrl(
|
||||
commonInfo.loki.grafanaUrl,
|
||||
[
|
||||
generateQuery(
|
||||
"Hudi 运行日志",
|
||||
commonInfo.loki.hudi.datasource,
|
||||
{"alias": alias}
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
function targetYarnApplicationLokiUrlByAppId(applicationId) {
|
||||
return generateLokiUrl(
|
||||
commonInfo.loki.grafanaUrl,
|
||||
[
|
||||
generateQuery(
|
||||
"Hudi 运行日志",
|
||||
commonInfo.loki.hudi.datasource,
|
||||
{"app_id": applicationId}
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
function serviceLogByAppName(name) {
|
||||
return generateLokiUrl(
|
||||
commonInfo.loki.grafanaUrl,
|
||||
[
|
||||
generateQuery(
|
||||
"Service 运行日志",
|
||||
commonInfo.loki.service.datasource,
|
||||
{"app": name}
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
function serviceLogByAppNameAndHost(name, host) {
|
||||
return generateLokiUrl(
|
||||
commonInfo.loki.grafanaUrl,
|
||||
[
|
||||
generateQuery(
|
||||
"Service 运行日志",
|
||||
commonInfo.loki.service.datasource,
|
||||
{"app": name, "host": host}
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
function time(field) {
|
||||
return {
|
||||
type: 'tpl',
|
||||
tpl: `\${IF(${field}, DATETOSTR(${field}, 'YYYY-MM-DD HH:mm:ss'), undefined)}`
|
||||
}
|
||||
}
|
||||
|
||||
function cloudCrud(title, path) {
|
||||
return {
|
||||
type: 'crud',
|
||||
title: title,
|
||||
api: `\${base}${path}`,
|
||||
...crudCommonOptions(),
|
||||
interval: 2000,
|
||||
headerToolbar: ['reload'],
|
||||
loadDataOnce: true,
|
||||
perPage: 100,
|
||||
columns: [
|
||||
{
|
||||
label: '名称',
|
||||
type: 'tpl',
|
||||
tpl: `\${name} \${IF(size === undefined, '', '<span class="font-bold label label-primary">' + size + '</span>')}`
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
label: '状态',
|
||||
align: 'center',
|
||||
width: 60,
|
||||
},
|
||||
{
|
||||
name: 'serviceUpTime',
|
||||
label: '启动时间',
|
||||
...time('serviceUpTime'),
|
||||
align: 'center',
|
||||
width: 160,
|
||||
},
|
||||
{name: 'url', label: '地址'},
|
||||
{
|
||||
type: 'operation',
|
||||
label: '操作',
|
||||
width: 100,
|
||||
fixed: 'right',
|
||||
className: 'nowrap',
|
||||
buttons: [
|
||||
{
|
||||
label: "日志",
|
||||
type: "action",
|
||||
level: "link",
|
||||
tooltip: '打开Grafana日志',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
script: (context, doAction, event) => {
|
||||
let data = context.props.data
|
||||
let url = ''
|
||||
if (data['metadata']) {
|
||||
url = serviceLogByAppNameAndHost(data.serviceId, data.metadata.hostname)
|
||||
} else if (data['name']) {
|
||||
url = serviceLogByAppName(data.name)
|
||||
}
|
||||
window.open(url, '_blank')
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function cloudTab() {
|
||||
return {
|
||||
title: 'Cloud',
|
||||
icon: 'fa fa-cloud',
|
||||
tab: [
|
||||
/*{
|
||||
type: 'service',
|
||||
silentPolling: true,
|
||||
schemaApi: 'get:${base}/cloud/deploy_plan',
|
||||
},*/
|
||||
cloudCrud('服务列表', '/cloud/list'),
|
||||
cloudCrud('服务列表 (IP)', '/cloud/list_ip'),
|
||||
],
|
||||
}
|
||||
}
|
||||
2217
service-web/src/main/resources/static/components/common.js
Normal file
2217
service-web/src/main/resources/static/components/common.js
Normal file
File diff suppressed because it is too large
Load Diff
445
service-web/src/main/resources/static/components/overview-tab.js
Normal file
445
service-web/src/main/resources/static/components/overview-tab.js
Normal file
@@ -0,0 +1,445 @@
|
||||
function color(number) {
|
||||
let color = 'text-success'
|
||||
if (number > 30) {
|
||||
color = 'text-primary'
|
||||
}
|
||||
if (number > 90) {
|
||||
color = 'text-danger'
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
function versionDetailDialog(variable, target) {
|
||||
return {
|
||||
disabledOn: `${variable} === 0`,
|
||||
type: 'action',
|
||||
label: '详情',
|
||||
level: 'link',
|
||||
size: 'sm',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '详情',
|
||||
actions: [],
|
||||
size: 'md',
|
||||
closeOnEsc: false,
|
||||
closeOnOutside: false,
|
||||
body: [
|
||||
{
|
||||
type: 'service',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/overview/version_detail',
|
||||
data: {
|
||||
target: `${target}`,
|
||||
version: '${version}',
|
||||
}
|
||||
},
|
||||
body: [
|
||||
{
|
||||
type: "table",
|
||||
source: "${items}",
|
||||
affixHeader: false,
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${id}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${id}',
|
||||
tooltip: '复制 ID',
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${alias}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tableDetailDialog(variable, targetList) {
|
||||
return {
|
||||
disabledOn: `${variable} === 0`,
|
||||
type: 'action',
|
||||
label: '详情',
|
||||
level: 'link',
|
||||
size: 'sm',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '详情',
|
||||
size: 'md',
|
||||
...readOnlyDialogOptions(),
|
||||
body: [
|
||||
{
|
||||
type: "table",
|
||||
source: `\${${targetList}}`,
|
||||
affixHeader: false,
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${id}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${id}',
|
||||
tooltip: '复制 ID',
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '${alias}',
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function overviewYarnJob(cluster, search, queue, yarnQueue) {
|
||||
return {
|
||||
className: 'font-mono',
|
||||
type: 'service',
|
||||
api: `\${base}/overview/yarn-job?cluster=${cluster}&search=${search}`,
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'mr-1 font-bold',
|
||||
tpl: `\${PADSTART('${cluster}', 3)}`,
|
||||
},
|
||||
queue === undefined ? {} : {
|
||||
type: 'service',
|
||||
className: 'inline ml-2',
|
||||
api: `\${base}/overview/queue?queue=compaction-queue-${cluster}`,
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: "${PADSTART(size, 2)}",
|
||||
}
|
||||
]
|
||||
},
|
||||
' ',
|
||||
{
|
||||
type: 'service',
|
||||
className: 'inline',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `\${base}/overview/yarn-cluster`,
|
||||
data: {
|
||||
cluster: cluster,
|
||||
queue: yarnQueue,
|
||||
},
|
||||
adaptor: function (payload, response) {
|
||||
let rootUsed = (payload['data']['root']['usedCapacity'] * 100 / payload['data']['root']['capacity']).toFixed(0)
|
||||
let targetUsed = (payload['data']['target']['absoluteUsedCapacity'] * 100 / payload['data']['target']['absoluteMaxCapacity']).toFixed(0)
|
||||
return {
|
||||
...payload,
|
||||
data: {
|
||||
...payload.data,
|
||||
rootUsed: rootUsed,
|
||||
rootUsedColor: color(rootUsed),
|
||||
targetUsed: targetUsed,
|
||||
targetUsedColor: color(targetUsed),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
'(',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold ${rootUsedColor}">${PADSTART(ROUND(rootUsed), 3)}%</span>',
|
||||
},
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold ${targetUsedColor}">${PADSTART(ROUND(targetUsed), 3)}%</span>',
|
||||
},
|
||||
')'
|
||||
],
|
||||
},
|
||||
'(',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: "<span class='font-bold text-cyan-300'>${PADSTART(scheduling, 2)}</span>",
|
||||
},
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-success">${PADSTART(running, 3)}</span>',
|
||||
},
|
||||
')',
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function overviewTab() {
|
||||
return {
|
||||
className: 'white-space-pre',
|
||||
title: '概览',
|
||||
icon: 'fa fa-circle-info',
|
||||
tab: [
|
||||
{
|
||||
type: 'service',
|
||||
// language=JavaScript
|
||||
dataProvider: 'const timer = setInterval(() => {\n setData({date: new Date().toLocaleString()})\n}, 1000)\nreturn () => {\n clearInterval(timer)\n}',
|
||||
body: [
|
||||
'当前时间:',
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'font-bold',
|
||||
tpl: '${date}'
|
||||
}
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
'<span class="italic text-gray-500 my-2">表数量 (重点表数量, 普通表数量)</span>',
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/overview',
|
||||
interval: 60000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '逻辑表:<span class="font-bold mr-1 font-mono">${PADSTART(table_count, 4)} (<span class="text-primary">${PADSTART(table_focus_count, 4)}</span>, ${PADSTART(table_count - table_focus_count, 4)})</span>',
|
||||
},
|
||||
'<br>',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '湖底表:<span class="font-bold mr-1 font-mono">${PADSTART(hudi_count, 4)} (<span class="text-primary">${PADSTART(hudi_focus_count, 4)}</span>, ${PADSTART(hudi_count - hudi_focus_count, 4)})</span>',
|
||||
},
|
||||
'<br>',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '嗨福表:<span class="font-bold mr-1 font-mono">${PADSTART(hive_count, 4)} (<span class="text-primary">${PADSTART(hive_focus_count, 4)}</span>, ${PADSTART(hive_count - hive_focus_count, 4)})</span>',
|
||||
},
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/overview/sync_running_status',
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '任务数<span class="font-bold m-2 font-mono">${totalJob}</span>'
|
||||
},
|
||||
{
|
||||
className: 'mx-2',
|
||||
type: 'tpl',
|
||||
tpl: '运行中<span class="font-bold m-2 font-mono">${PADSTART(runningJob, 3)}</span>'
|
||||
},
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '已停止<span class="font-bold m-2 font-mono text-danger">${PADSTART(unRunningJob, 3)}</span>'
|
||||
},
|
||||
tableDetailDialog('unRunningJob', 'unRunningJobList'),
|
||||
'<br/>',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '总表数<span class="font-bold m-2 font-mono">${totalTable}</span>'
|
||||
},
|
||||
{
|
||||
className: 'mx-2',
|
||||
type: 'tpl',
|
||||
tpl: '运行中<span class="font-bold m-2 font-mono">${PADSTART(runningTable, 3)}</span>'
|
||||
},
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '已停止<span class="font-bold m-2 font-mono text-danger">${PADSTART(unRunningTable, 3)}</span>'
|
||||
},
|
||||
tableDetailDialog('unRunningTable', 'unRunningTableList'),
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
'<span class="italic text-gray-500 my-2">集群 (集群总资源使用,队列资源使用)(调度中任务数,运行中任务数)</span>',
|
||||
overviewYarnJob(commonInfo.clusters.sync_names(), 'Sync', undefined, 'default'),
|
||||
{type: 'divider'},
|
||||
{
|
||||
className: 'my-2',
|
||||
type: 'service',
|
||||
api: `\${base}/overview/queue?queue=compaction-queue-pre`,
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '预调度队列:<span class="font-bold">${size}</span>',
|
||||
}
|
||||
]
|
||||
},
|
||||
'<span class="italic text-gray-500 my-2">集群 压缩队列任务数(集群总资源使用,队列资源使用)(调度中任务数,运行中任务数)</span>',
|
||||
...Object.keys(commonInfo.clusters.compaction).map(name => overviewYarnJob(name, 'Compaction', `compaction-queue-${name}`, commonInfo.clusters.compaction[name])),
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/overview/version',
|
||||
interval: 10000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
'版本:',
|
||||
{
|
||||
type: 'tpl',
|
||||
className: 'font-bold',
|
||||
tpl: '${version}',
|
||||
},
|
||||
'<br/>',
|
||||
'<span class="italic text-gray-500 my-2">未接收, 未跨天</span>',
|
||||
'<br/>',
|
||||
'重点表:',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold font-mono">${PADSTART(unReceive.focus, 3)}</span>',
|
||||
},
|
||||
versionDetailDialog('unReceive.focus', 'unReceive_focus'),
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold font-mono">${PADSTART(unSchedule.focus, 3)}</span>',
|
||||
},
|
||||
versionDetailDialog('unSchedule.focus', 'unScheduled_focus'),
|
||||
'<br/>',
|
||||
'普通表:',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold font-mono">${PADSTART(unReceive.normal, 3)}</span>',
|
||||
},
|
||||
versionDetailDialog('unReceive.normal', 'unReceive_normal'),
|
||||
',',
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold font-mono">${PADSTART(unSchedule.normal, 3)}</span>',
|
||||
},
|
||||
versionDetailDialog('unSchedule.normal', 'unScheduled_normal'),
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/overview/schedule_jobs',
|
||||
interval: 60000,
|
||||
silentPolling: true,
|
||||
body: [
|
||||
'调度策略',
|
||||
{
|
||||
type: 'each',
|
||||
name: 'items',
|
||||
items: {
|
||||
type: 'tpl',
|
||||
tpl: '<div class="font-mono"><span class="font-bold">${trigger}</span> <span class="text-gray-500">(${job})</span></div>'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
type: 'crud',
|
||||
title: '监控指标运行进度',
|
||||
api: `\${base}/overview/monitor_progress`,
|
||||
...crudCommonOptions(),
|
||||
interval: 2000,
|
||||
loadDataOnce: true,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
name: 'running',
|
||||
label: '状态',
|
||||
type: 'mapping',
|
||||
width: 50,
|
||||
map: {
|
||||
'true': '运行中',
|
||||
'false': '未运行',
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '进度',
|
||||
type: 'progress',
|
||||
value: '${ROUND(progress * 100)}',
|
||||
map: 'bg-primary',
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
function queueCrud(name) {
|
||||
return {
|
||||
type: 'crud',
|
||||
title: name,
|
||||
api: `\${base}/queue/all?name=${name}`,
|
||||
...crudCommonOptions(),
|
||||
interval: 10000,
|
||||
loadDataOnce: true,
|
||||
perPage: 5,
|
||||
headerToolbar: [
|
||||
"reload",
|
||||
'filter-toggler',
|
||||
{
|
||||
type: "tpl",
|
||||
tpl: "共 <span class='text-primary font-bold'>${total|default:0}</span> 个任务"
|
||||
},
|
||||
paginationCommonOptions(false)
|
||||
],
|
||||
footerToolbar: [],
|
||||
columns: [
|
||||
{
|
||||
name: 'data.flinkJobId',
|
||||
label: '任务 ID',
|
||||
width: 190,
|
||||
...copyField('data.flinkJobId')
|
||||
},
|
||||
{
|
||||
name: 'data.alias',
|
||||
label: '别名',
|
||||
className: 'nowrap',
|
||||
...copyField('data.alias')
|
||||
},
|
||||
{
|
||||
name: 'data.batch',
|
||||
label: '批次',
|
||||
width: 100,
|
||||
type: 'tpl',
|
||||
tpl: '<span class="label label-warning">${data.batch}</span>'
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
label: '优先级',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
type: 'tpl',
|
||||
tpl: '<span class="label bg-info">${priority}</span>'
|
||||
},
|
||||
{
|
||||
name: 'data.comment',
|
||||
label: '备注',
|
||||
className: 'nowrap',
|
||||
},
|
||||
{
|
||||
name: 'createTime',
|
||||
label: '任务提交时间',
|
||||
...time('createTime'),
|
||||
width: 160,
|
||||
fixed: 'right'
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function queueTab() {
|
||||
let items = []
|
||||
for (let name of Object.keys(commonInfo.clusters.compaction)) {
|
||||
items.push(yarnQueueCrud(name, commonInfo.clusters.compaction[name]))
|
||||
items.push(queueCrud(`compaction-queue-${name}`))
|
||||
}
|
||||
return {
|
||||
title: '压缩队列',
|
||||
icon: 'fa fa-van-shuttle',
|
||||
tab: [
|
||||
queueCrud('compaction-queue-pre'),
|
||||
...items
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
function runningTable(name) {
|
||||
return {
|
||||
type: 'table',
|
||||
title: `${name}`,
|
||||
itemAction: {
|
||||
type: 'button',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: 'Path',
|
||||
body: '${path}',
|
||||
actions: [],
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{name: 'label', label: '名称'},
|
||||
{
|
||||
name: 'createTime',
|
||||
label: '创建时间',
|
||||
...timeAndFrom('createTime', 'createTimeFromNow', undefined, false),
|
||||
width: 70,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function runningTab() {
|
||||
return {
|
||||
title: '运行中',
|
||||
tab: [
|
||||
{
|
||||
type: 'grid',
|
||||
columns: [
|
||||
{
|
||||
body: [
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/running/sync',
|
||||
body: runningTable('同步')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
body: [
|
||||
{
|
||||
type: 'service',
|
||||
api: '${base}/running/compaction',
|
||||
body: runningTable('压缩')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
230
service-web/src/main/resources/static/components/table-tab.js
Normal file
230
service-web/src/main/resources/static/components/table-tab.js
Normal file
@@ -0,0 +1,230 @@
|
||||
function tableTab() {
|
||||
return {
|
||||
title: `表任务`,
|
||||
icon: 'fa fa-table',
|
||||
tab: [
|
||||
{
|
||||
id: 'table-service',
|
||||
type: 'service',
|
||||
data: {},
|
||||
body: [
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `\${base}/table/list`,
|
||||
data: {
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
search_flink_job_id: '${flinkJobId|default:undefined}',
|
||||
search_alias: '${alias|default:undefined}',
|
||||
filter_hudi_table_type: '${tableMeta\\.hudi\\.targetTableType|default:undefined}',
|
||||
filter_run_mode: '${flinkJob\\.runMode|default:undefined}',
|
||||
filter_compaction_status: '${syncState\\.compactionStatus|default:undefined}'
|
||||
}
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
// interval: 10000,
|
||||
filter: {
|
||||
title: '表筛选',
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
...flinkJobIdTextInput("58d0da94-1b3c-4234-948d-482ae3425e70"),
|
||||
size: 'lg',
|
||||
},
|
||||
{
|
||||
...aliasTextInput("58d0da94-1b3c-4234-948d-482ae3425e70"),
|
||||
size: 'lg',
|
||||
},
|
||||
]
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: "submit",
|
||||
level: "primary",
|
||||
label: "查询",
|
||||
},
|
||||
{
|
||||
type: "reset",
|
||||
label: "重置",
|
||||
},
|
||||
]
|
||||
},
|
||||
filterTogglable: true,
|
||||
filterDefaultVisible: true,
|
||||
perPage: 20,
|
||||
headerToolbar: [
|
||||
"reload",
|
||||
'filter-toggler',
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
width: 195,
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${flinkJobId}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: flinkJobDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${flinkJobId}',
|
||||
tooltip: '复制 ID',
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${tableMeta.alias}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: tableMetaDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${tableMeta.alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'tableMeta.hudi.targetTableType',
|
||||
label: '表类型',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
...mappingField('tableMeta.hudi.targetTableType', hudiTableTypeMapping),
|
||||
filterable: filterableField(hudiTableTypeMapping, true)
|
||||
},
|
||||
{
|
||||
name: 'flinkJob.runMode',
|
||||
label: '任务类型',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
...mappingField('flinkJob.runMode', runModeMapping),
|
||||
filterable: filterableField(runModeMapping, true)
|
||||
},
|
||||
{
|
||||
name: 'syncRunning',
|
||||
label: '同步运行状态',
|
||||
align: 'center',
|
||||
...mappingField('syncRunning', tableRunningStateMapping),
|
||||
className: 'bg-green-50',
|
||||
width: 75,
|
||||
},
|
||||
{
|
||||
name: 'source_start_time',
|
||||
label: '同步启动时间',
|
||||
...timeAndFrom('syncState.sourceStartTime', 'syncState.sourceStartTimeFromNow', '未启动'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_receive_time',
|
||||
label: '同步接收时间',
|
||||
...timeAndFrom('syncState.sourceReceiveTime', 'syncState.sourceReceiveTimeFromNow', '无数据'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_checkpoint_time',
|
||||
label: '同步心跳时间',
|
||||
...timeAndFrom('syncState.sourceCheckpointTime', 'syncState.sourceCheckpointTimeFromNow', '未启动'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_publish_time',
|
||||
label: '源端发布时间',
|
||||
...timeAndFrom('syncState.sourcePublishTime', 'syncState.sourcePublishTimeFromNow', '无增量'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'source_operation_time',
|
||||
label: '源端业务时间',
|
||||
...timeAndFrom('syncState.sourceOperationTime', 'syncState.sourceOperationTimeFromNow', '无增量'),
|
||||
sortable: true,
|
||||
className: 'bg-green-50',
|
||||
},
|
||||
{
|
||||
name: 'compactionRunning',
|
||||
label: '压缩运行状态',
|
||||
align: 'center',
|
||||
...mappingField('compactionRunning', tableRunningStateMapping),
|
||||
className: 'bg-cyan-50',
|
||||
width: 75,
|
||||
},
|
||||
{
|
||||
name: 'syncState.compactionStatus',
|
||||
label: '压缩状态',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
...mappingField('syncState.compactionStatus', compactionStatusMapping),
|
||||
filterable: filterableField(compactionStatusMapping, true),
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
{
|
||||
name: 'compaction_start_time',
|
||||
label: '压缩启动时间',
|
||||
...timeAndFrom('syncState.compactionStartTime', 'syncState.compactionStartTimeFromNow'),
|
||||
sortable: true,
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
{
|
||||
name: 'compaction_latest_operation_time',
|
||||
label: '压缩业务时间',
|
||||
...timeAndFrom('syncState.compactionLatestOperationTime', 'syncState.compactionLatestOperationTimeFromNow', '无'),
|
||||
sortable: true,
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
{
|
||||
name: 'compaction_finish_time',
|
||||
label: '压缩完成时间',
|
||||
...timeAndFrom('syncState.compactionFinishTime', 'syncState.compactionFinishTimeFromNow'),
|
||||
sortable: true,
|
||||
className: 'bg-cyan-50',
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
185
service-web/src/main/resources/static/components/task-tab.js
Normal file
185
service-web/src/main/resources/static/components/task-tab.js
Normal file
@@ -0,0 +1,185 @@
|
||||
function taskTab() {
|
||||
return {
|
||||
title: `离线检索`,
|
||||
icon: 'fa fa-magnifying-glass',
|
||||
tab: [
|
||||
{
|
||||
type: 'form',
|
||||
title: '检索文件',
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
label: '提交任务',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/task/scan',
|
||||
data: {
|
||||
key: '${key|default:undefined}',
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
pulsar: '${pulsar|default:undefined}',
|
||||
topic: '${topic|default:undefined}',
|
||||
mode: '${scan_mode|default:undefined}',
|
||||
fields: '${fields|default:undefined}',
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
body: [
|
||||
{
|
||||
name: 'scan_mode',
|
||||
type: 'checkboxes',
|
||||
label: '检索范围',
|
||||
checkAll: true,
|
||||
required: true,
|
||||
value: 'log',
|
||||
options: [
|
||||
{label: '消息队列', value: 'queue'},
|
||||
{label: '日志文件', value: 'log'},
|
||||
{label: '数据文件', value: 'base'},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'key',
|
||||
label: '检索字段',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '检索带有该字符的记录',
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS路经',
|
||||
requiredOn: '${CONTAINS(scan_mode, \'log\') || CONTAINS(scan_mode, \'base\')}',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'log\') || CONTAINS(scan_mode, \'base\')}',
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: '${base}/table/all_hdfs?key=$term',
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'fields',
|
||||
label: '指定字段',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'base\')}',
|
||||
clearable: true,
|
||||
description: '逗号分隔,可以大幅提高parquet文件检索速度,但无法获取指定字段外的字段内容',
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'topic',
|
||||
label: 'Pulsar主题',
|
||||
requiredOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
clearable: true,
|
||||
description: '输入Pulsar主题',
|
||||
autoComplete: '${base}/table/all_pulsar_topic?key=$term',
|
||||
columnRatio: 4,
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'pulsar',
|
||||
label: 'Pulsar地址',
|
||||
requiredOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
visibleOn: '${CONTAINS(scan_mode, \'queue\')}',
|
||||
clearable: true,
|
||||
description: '输入Pulsar地址',
|
||||
autoComplete: '${base}/table/all_pulsar?key=$term',
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '综合查询',
|
||||
actions: [
|
||||
{
|
||||
type: 'action',
|
||||
label: '总数&最后操作时间',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/task/table_summary',
|
||||
data: {
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
label: '最后10条记录',
|
||||
actionType: 'ajax',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/task/table_sampling',
|
||||
data: {
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS路经',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: '${base}/table/all_hdfs?key=$term',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `\${base}/yarn/job_list`,
|
||||
data: {
|
||||
clusters: commonInfo.clusters.sync_names(),
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
filter_state: '${state|default:undefined}',
|
||||
filter_final_status: '${finalStatus|default:undefined}',
|
||||
search_id: '${id|default:undefined}',
|
||||
search_name: 'Service_Task',
|
||||
precise: false,
|
||||
}
|
||||
},
|
||||
affixHeader: false,
|
||||
interval: 10000,
|
||||
syncLocation: false,
|
||||
silentPolling: true,
|
||||
resizable: false,
|
||||
perPage: 10,
|
||||
headerToolbar: [
|
||||
"reload",
|
||||
{
|
||||
label: "任务管理器日志",
|
||||
type: "action",
|
||||
tooltip: '打开Grafana日志',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
script: () => window.open(serviceLogByAppName("service-executor-manager"), '_blank'),
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [],
|
||||
columns: yarnCrudColumns(),
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
294
service-web/src/main/resources/static/components/tool-tab.js
Normal file
294
service-web/src/main/resources/static/components/tool-tab.js
Normal file
@@ -0,0 +1,294 @@
|
||||
function toolTab() {
|
||||
return {
|
||||
title: `小工具`,
|
||||
icon: 'fa fa-toolbox',
|
||||
tab: [
|
||||
{
|
||||
type: 'panel',
|
||||
title: '乱七八糟小工具',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
label: 'SQL日志',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '日志',
|
||||
...readOnlyDialogOptions(),
|
||||
size: 'lg',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: '${base}/log/query_sql_log',
|
||||
...crudCommonOptions(),
|
||||
loadDataOnce: true,
|
||||
perPage: 50,
|
||||
headerToolbar: [
|
||||
"reload",
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
name: 'sql',
|
||||
label: 'SQL',
|
||||
},
|
||||
{
|
||||
name: 'createTime',
|
||||
label: '执行时间',
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
label: 'ZK节点',
|
||||
className: 'ml-2',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '日志',
|
||||
...readOnlyDialogOptions(),
|
||||
size: 'lg',
|
||||
body: {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: 'HDFS文件管理器',
|
||||
actions: [
|
||||
{
|
||||
label: '直接下载',
|
||||
type: 'action',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'custom',
|
||||
script: (context, action, event) => {
|
||||
let downloadUrl = `${event.data.base}/hudi/hdfs_download?root=${encodeURI(event.data.hdfs)}`
|
||||
window.open(downloadUrl, '_blank')
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'submit',
|
||||
label: '查看',
|
||||
actionType: 'dialog',
|
||||
dialog: hdfsDialog('hdfs'),
|
||||
}
|
||||
],
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS根路经',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: '${base}/table/all_hdfs?key=$term',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '查询时间线',
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
label: '查询时间线',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: 'Hudi 表时间线',
|
||||
actions: [],
|
||||
size: 'lg',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/hudi/timeline/list_hdfs',
|
||||
data: {
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
filter_type: "${type|default:active}",
|
||||
filter_action: '${action|default:undefined}',
|
||||
filter_state: '${state|default:undefined}',
|
||||
},
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
perPage: 50,
|
||||
headerToolbar: [
|
||||
"reload",
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(undefined, 10),
|
||||
],
|
||||
columns: timelineColumns(),
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'submit',
|
||||
label: '查询表结构',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: 'Hudi 表结构',
|
||||
actions: [],
|
||||
size: 'lg',
|
||||
body: {
|
||||
type: 'service',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/hudi/schema',
|
||||
data: {
|
||||
hdfs: '${hdfs|default:undefined}',
|
||||
},
|
||||
},
|
||||
body: {
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'json',
|
||||
source: '${detail}',
|
||||
levelExpand: 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'hdfs',
|
||||
label: 'HDFS路经',
|
||||
required: true,
|
||||
clearable: true,
|
||||
description: '输入表HDFS路径',
|
||||
autoComplete: '${base}/table/all_hdfs?key=$term',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '提交压缩任务',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/schedule/table',
|
||||
data: {
|
||||
flink_job_id: '${flinkJobId|default:undefined}',
|
||||
alias: '${alias|default:undefined}',
|
||||
recommend: "${recommend === 'undefined' ? undefined : recommend|default:undefined}",
|
||||
force: "${force === 'undefined' ? undefined : force|default:undefined}",
|
||||
}
|
||||
},
|
||||
...formReloadFlinkJobIdTextInputAndAliasTextInput("0fe6a96c-6b6e-4346-b18e-c631c2389f48"),
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
flinkJobIdTextInput("0fe6a96c-6b6e-4346-b18e-c631c2389f48", true),
|
||||
aliasTextInput("0fe6a96c-6b6e-4346-b18e-c631c2389f48", true),
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
name: 'recommend',
|
||||
type: 'radios',
|
||||
label: '优先指定集群',
|
||||
selectFirst: true,
|
||||
options: [
|
||||
{label: '无', value: 'undefined'},
|
||||
...Object.keys(commonInfo.clusters.compaction)
|
||||
.map(name => {
|
||||
return {label: name, value: name}
|
||||
}),
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'force',
|
||||
type: 'radios',
|
||||
label: '强制指定集群',
|
||||
selectFirst: true,
|
||||
options: [
|
||||
{label: '无', value: 'undefined'},
|
||||
...Object.keys(commonInfo.clusters.compaction)
|
||||
.map(name => {
|
||||
return {label: name, value: name}
|
||||
}),
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '批量提交压缩任务',
|
||||
api: {
|
||||
method: 'post',
|
||||
url: '${base}/schedule/table_batch',
|
||||
dataType: 'form',
|
||||
},
|
||||
body: [
|
||||
{
|
||||
name: 'lines',
|
||||
type: 'textarea',
|
||||
label: '表信息 (flink_job_id alias\\n)',
|
||||
clearable: true,
|
||||
minRows: 5,
|
||||
maxRows: 5,
|
||||
className: 'no-resize',
|
||||
required: true,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
title: '停止所有压缩任务',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/schedule/stop_all',
|
||||
data: {
|
||||
flink_job_id: '${flinkJobId|default:undefined}',
|
||||
alias: '${alias|default:undefined}',
|
||||
disable_meta: "${disableMeta|default:undefined}",
|
||||
}
|
||||
},
|
||||
...formReloadFlinkJobIdTextInputAndAliasTextInput("163e043e-8cee-41fd-b5a4-0442ac682aec"),
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
...flinkJobIdTextInput("163e043e-8cee-41fd-b5a4-0442ac682aec", true),
|
||||
columnRatio: 5
|
||||
},
|
||||
{
|
||||
...aliasTextInput("163e043e-8cee-41fd-b5a4-0442ac682aec", true),
|
||||
columnRatio: 5
|
||||
},
|
||||
{
|
||||
name: 'disableMeta',
|
||||
type: 'checkbox',
|
||||
label: '是否禁用表',
|
||||
option: '表status设为n',
|
||||
columnRatio: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
164
service-web/src/main/resources/static/components/version-tab.js
Normal file
164
service-web/src/main/resources/static/components/version-tab.js
Normal file
@@ -0,0 +1,164 @@
|
||||
function versionTab() {
|
||||
return {
|
||||
title: '跨天',
|
||||
icon: 'fa fa-cloud-sun',
|
||||
tab: [
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: `\${base}/version_update/list`,
|
||||
data: {
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
search_flink_job_id: '${flinkJobId|default:undefined}',
|
||||
search_alias: '${alias|default:undefined}',
|
||||
search_version: '${version|default:undefined}',
|
||||
filter_schedules: '${updated|default:undefined}'
|
||||
}
|
||||
},
|
||||
data: {
|
||||
now: "${DATETOSTR(DATEMODIFY(NOW(), -1, 'days'), 'YYYYMMDD')}"
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
interval: 10000,
|
||||
filter: {
|
||||
mode: 'inline',
|
||||
title: '表筛选',
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
...flinkJobIdTextInput('c5cac9d3-844a-4d86-b2c5-0c10f2283667'),
|
||||
size: 'md'
|
||||
},
|
||||
{
|
||||
...aliasTextInput('c5cac9d3-844a-4d86-b2c5-0c10f2283667'),
|
||||
size: 'md'
|
||||
},
|
||||
{
|
||||
type: 'input-date',
|
||||
name: 'version',
|
||||
label: '版本',
|
||||
clearable: true,
|
||||
placeholder: '通过版本搜索',
|
||||
size: 'md',
|
||||
format: 'YYYYMMDD',
|
||||
inputFormat: 'YYYYMMDD',
|
||||
value: '${now}',
|
||||
},
|
||||
]
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: "submit",
|
||||
level: "primary",
|
||||
label: "查询",
|
||||
},
|
||||
{
|
||||
type: "reset",
|
||||
label: "重置",
|
||||
},
|
||||
]
|
||||
},
|
||||
filterTogglable: true,
|
||||
filterDefaultVisible: true,
|
||||
perPage: 20,
|
||||
headerToolbar: [
|
||||
"reload",
|
||||
'filter-toggler',
|
||||
{
|
||||
type: "tpl",
|
||||
tpl: "共 <span class='text-primary font-bold'>${total|default:0}</span> 个表,其中 <span class='text-success font-bold'>${scheduled|default:0}</span> 个表已跨天,<span class='text-danger font-bold'>${unScheduled|default:0}</span> 个表未跨天"
|
||||
},
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
label: 'Flink job id',
|
||||
width: 195,
|
||||
fixed: 'left',
|
||||
type: 'wrapper',
|
||||
size: 'none',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${flinkJobId}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: flinkJobDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${flinkJobId}',
|
||||
tooltip: '复制 ID',
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '别名',
|
||||
type: 'wrapper',
|
||||
fixed: 'left',
|
||||
size: 'none',
|
||||
className: 'nowrap',
|
||||
body: [
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '${tableMeta.alias}',
|
||||
size: 'xs',
|
||||
actionType: 'dialog',
|
||||
tooltip: '查看详情',
|
||||
dialog: tableMetaDialog(),
|
||||
},
|
||||
{
|
||||
type: 'action',
|
||||
level: 'link',
|
||||
label: '',
|
||||
icon: 'fa fa-copy',
|
||||
size: 'xs',
|
||||
actionType: 'copy',
|
||||
content: '${tableMeta.alias}',
|
||||
tooltip: '复制别名',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
label: '表优先级',
|
||||
align: 'center',
|
||||
width: 75,
|
||||
sortable: true,
|
||||
}, {
|
||||
name: 'version',
|
||||
label: '版本',
|
||||
align: 'center',
|
||||
width: 75,
|
||||
},
|
||||
{
|
||||
name: 'updated',
|
||||
label: '状态',
|
||||
align: 'center',
|
||||
...mappingField('updated', versionUpdateStateMapping),
|
||||
filterable: filterableField(versionUpdateStateMapping, true),
|
||||
width: 70,
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
function yarnClusterTab() {
|
||||
return {
|
||||
title: '集群概览',
|
||||
icon: 'fa fa-circle-nodes',
|
||||
tab: [
|
||||
{
|
||||
type: 'tabs',
|
||||
mountOnEnter: true,
|
||||
unmountOnExit: true,
|
||||
tabsMode: 'line',
|
||||
tabs: [
|
||||
{
|
||||
title: '总体情况',
|
||||
tab: [
|
||||
...Object.keys(commonInfo.clusters.compaction).map(name => yarnQueueCrud(name))
|
||||
],
|
||||
},
|
||||
...Object.keys(commonInfo.clusters.compaction).map(name => yarnTab(name, name)),
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
103
service-web/src/main/resources/static/components/yarn-tab.js
Normal file
103
service-web/src/main/resources/static/components/yarn-tab.js
Normal file
@@ -0,0 +1,103 @@
|
||||
function yarnTab(cluster, title, queueNames = 'root', searchName = undefined) {
|
||||
return {
|
||||
title: `${title}集群`,
|
||||
icon: 'fa fa-rotate',
|
||||
tab: [
|
||||
{
|
||||
id: `${cluster}-yarn-service`,
|
||||
name: `${cluster}-yarn-service`,
|
||||
type: 'service',
|
||||
body: [
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-xl">集群资源</span>',
|
||||
},
|
||||
yarnQueueCrud(cluster, queueNames),
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '<span class="font-bold text-xl">集群任务</span>',
|
||||
// className: 'mb-2 block',
|
||||
},
|
||||
{
|
||||
type: 'crud',
|
||||
api: {
|
||||
method: 'get',
|
||||
url: '${base}/yarn/job_list',
|
||||
data: {
|
||||
clusters: `${cluster}`,
|
||||
page: '${page|default:undefined}',
|
||||
count: '${perPage|default:undefined}',
|
||||
order: '${orderBy|default:undefined}',
|
||||
direction: '${orderDir|default:undefined}',
|
||||
filter_state: '${state|default:undefined}',
|
||||
filter_final_status: '${finalStatus|default:undefined}',
|
||||
search_id: '${id|default:undefined}',
|
||||
search_name: '${name|default:undefined}',
|
||||
completion: 'true',
|
||||
}
|
||||
},
|
||||
defaultParams: {
|
||||
name: searchName
|
||||
},
|
||||
...crudCommonOptions(),
|
||||
interval: 10000,
|
||||
filter: {
|
||||
mode: 'inline',
|
||||
title: '任务筛选',
|
||||
body: [
|
||||
{
|
||||
type: 'group',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'id',
|
||||
label: 'ID',
|
||||
clearable: true,
|
||||
placeholder: '通过 ID 搜索',
|
||||
size: 'md'
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
clearable: true,
|
||||
placeholder: '通过名称搜索',
|
||||
size: 'md'
|
||||
},
|
||||
]
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: "submit",
|
||||
level: "primary",
|
||||
label: "查询",
|
||||
},
|
||||
{
|
||||
type: "reset",
|
||||
label: "重置",
|
||||
},
|
||||
]
|
||||
},
|
||||
filterTogglable: true,
|
||||
filterDefaultVisible: false,
|
||||
perPage: 20,
|
||||
headerToolbar: [
|
||||
"reload",
|
||||
'filter-toggler',
|
||||
{
|
||||
type: "tpl",
|
||||
tpl: "共 <span class='text-primary font-bold'>${total|default:0}</span> 个任务,其中 <span class='text-success font-bold'>${running|default:0}</span> 个任务运行中,<span class='text-danger font-bold'>${unRunning|default:0}</span> 个任务处于非运行状态"
|
||||
},
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
footerToolbar: [
|
||||
paginationCommonOptions(),
|
||||
],
|
||||
columns: yarnCrudColumns(),
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
94
service-web/src/main/resources/static/extra.html
Normal file
94
service-web/src/main/resources/static/extra.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta
|
||||
content="IE=edge"
|
||||
http-equiv="X-UA-Compatible"
|
||||
/>
|
||||
<meta
|
||||
content="width=device-width, initial-scale=1.0"
|
||||
name="viewport"
|
||||
/>
|
||||
<title>Hudi 服务页面</title>
|
||||
<link rel="icon" href="assets/icon.png"/>
|
||||
<link href="sdk/antd.css" rel="stylesheet"/>
|
||||
<link href="sdk/helper.css" rel="stylesheet"/>
|
||||
<link href="sdk/iconfont.css" rel="stylesheet"/>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.no-resize textarea {
|
||||
resize: none !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="sdk/sdk.js"></script>
|
||||
<script src="common/info.js"></script>
|
||||
<script src="components/common.js"></script>
|
||||
<script src="components/table-tab.js"></script>
|
||||
<script src="components/yarn-tab.js"></script>
|
||||
<script src="components/yarn-cluster-tab.js"></script>
|
||||
<script src="components/cloud-tab.js"></script>
|
||||
<script src="components/queue-tab.js"></script>
|
||||
<script src="components/running-tab.js"></script>
|
||||
<script src="components/version-tab.js"></script>
|
||||
<script src="components/overview-tab.js"></script>
|
||||
<script src="components/tool-tab.js"></script>
|
||||
<script src="components/task-tab.js"></script>
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
let amis = amisRequire('amis/embed')
|
||||
let amisJSON = {
|
||||
type: 'page',
|
||||
title: 'Hudi 服务总台',
|
||||
subTitle: 'Hudi 全链路服务监控和控制台',
|
||||
body: {
|
||||
type: 'tabs',
|
||||
mountOnEnter: true,
|
||||
unmountOnExit: true,
|
||||
tabsMode: 'strong',
|
||||
tabs: [
|
||||
overviewTab(),
|
||||
tableTab(),
|
||||
queueTab(),
|
||||
versionTab(),
|
||||
yarnTab(commonInfo.clusters.sync_names(), '同步', undefined, 'Sync'),
|
||||
yarnTab(commonInfo.clusters.compaction_names(), '压缩', 'default', 'Compaction'),
|
||||
cloudTab(),
|
||||
yarnClusterTab(),
|
||||
toolTab(),
|
||||
taskTab(),
|
||||
]
|
||||
}
|
||||
}
|
||||
let debug = false
|
||||
let server = amis.embed(
|
||||
'#root',
|
||||
amisJSON,
|
||||
{
|
||||
data: {
|
||||
base: commonInfo.baseUrl
|
||||
},
|
||||
},
|
||||
{
|
||||
theme: 'antd',
|
||||
enableAMISDebug: debug,
|
||||
},
|
||||
);
|
||||
if (debug) {
|
||||
console.log('Source', amisJSON)
|
||||
}
|
||||
})()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
90
service-web/src/main/resources/static/index.html
Normal file
90
service-web/src/main/resources/static/index.html
Normal file
@@ -0,0 +1,90 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta
|
||||
content="IE=edge"
|
||||
http-equiv="X-UA-Compatible"
|
||||
/>
|
||||
<meta
|
||||
content="width=device-width, initial-scale=1.0"
|
||||
name="viewport"
|
||||
/>
|
||||
<title>Hudi 服务页面</title>
|
||||
<link rel="icon" href="assets/icon.png"/>
|
||||
<link href="sdk/antd.css" rel="stylesheet"/>
|
||||
<link href="sdk/helper.css" rel="stylesheet"/>
|
||||
<link href="sdk/iconfont.css" rel="stylesheet"/>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.no-resize textarea {
|
||||
resize: none !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="sdk/sdk.js"></script>
|
||||
<script src="common/info.js"></script>
|
||||
<script src="components/common.js"></script>
|
||||
<script src="components/table-tab.js"></script>
|
||||
<script src="components/yarn-tab.js"></script>
|
||||
<script src="components/yarn-cluster-tab.js"></script>
|
||||
<script src="components/cloud-tab.js"></script>
|
||||
<script src="components/queue-tab.js"></script>
|
||||
<script src="components/running-tab.js"></script>
|
||||
<script src="components/version-tab.js"></script>
|
||||
<script src="components/overview-tab.js"></script>
|
||||
<script src="components/tool-tab.js"></script>
|
||||
<script src="components/task-tab.js"></script>
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
let amis = amisRequire('amis/embed')
|
||||
let amisJSON = {
|
||||
type: 'page',
|
||||
title: 'Hudi 服务总台',
|
||||
subTitle: 'Hudi 全链路服务监控和控制台',
|
||||
body: {
|
||||
type: 'tabs',
|
||||
mountOnEnter: true,
|
||||
unmountOnExit: true,
|
||||
tabsMode: 'strong',
|
||||
tabs: [
|
||||
overviewTab(),
|
||||
tableTab(),
|
||||
queueTab(),
|
||||
versionTab(),
|
||||
yarnTab(commonInfo.clusters.sync_names(), '同步', undefined, 'Sync'),
|
||||
yarnTab(commonInfo.clusters.compaction_names(), '压缩', 'default', 'Compaction')
|
||||
]
|
||||
}
|
||||
}
|
||||
let debug = false
|
||||
let server = amis.embed(
|
||||
'#root',
|
||||
amisJSON,
|
||||
{
|
||||
data: {
|
||||
base: commonInfo.baseUrl
|
||||
},
|
||||
},
|
||||
{
|
||||
theme: 'antd',
|
||||
enableAMISDebug: debug,
|
||||
},
|
||||
);
|
||||
if (debug) {
|
||||
console.log('Source', amisJSON)
|
||||
}
|
||||
})()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
356
service-web/src/main/resources/static/sdk/ang-ie11.css
Normal file
356
service-web/src/main/resources/static/sdk/ang-ie11.css
Normal file
File diff suppressed because one or more lines are too long
292
service-web/src/main/resources/static/sdk/ang.css
Normal file
292
service-web/src/main/resources/static/sdk/ang.css
Normal file
File diff suppressed because one or more lines are too long
355
service-web/src/main/resources/static/sdk/antd-ie11.css
Normal file
355
service-web/src/main/resources/static/sdk/antd-ie11.css
Normal file
File diff suppressed because one or more lines are too long
291
service-web/src/main/resources/static/sdk/antd.css
Normal file
291
service-web/src/main/resources/static/sdk/antd.css
Normal file
File diff suppressed because one or more lines are too long
100
service-web/src/main/resources/static/sdk/barcode.js
Normal file
100
service-web/src/main/resources/static/sdk/barcode.js
Normal file
@@ -0,0 +1,100 @@
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/Barcode.js*/
|
||||
amis.define("0066873",(function(t,e,n,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.default=function t(e,n){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.data=e,this.text=n.text||e,this.options=n}}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE39/index.js*/
|
||||
amis.define("f3f69cf",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.CODE39=void 0;var o,u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("0066873");var a=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),e=e.toUpperCase(),n.mod43&&(e+=function(e){return f[e]}(function(e){for(var t=0,n=0;n<e.length;n++)t+=s(e[n]);return t%=43}(e))),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),u(t,[{key:"encode",value:function(){for(var e=l("*"),t=0;t<this.data.length;t++)e+=l(this.data[t])+"0";return{data:e+=l("*"),text:this.text}}},{key:"valid",value:function(){return-1!==this.data.search(/^[0-9A-Z\-\.\ \$\/\+\%]+$/)}}]),t}(((o=i)&&o.__esModule?o:{default:o}).default),f=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","-","."," ","$","/","+","%","*"],c=[20957,29783,23639,30485,20951,29813,23669,20855,29789,23645,29975,23831,30533,22295,30149,24005,21623,29981,23837,22301,30023,23879,30545,22343,30161,24017,21959,30065,23921,22385,29015,18263,29141,17879,29045,18293,17783,29021,18269,17477,17489,17681,20753,35770];function l(e){return function(e){return c[e].toString(2)}(s(e))}function s(e){return f.indexOf(e)}t.CODE39=a}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/constants.js*/
|
||||
amis.define("555ccbc",(function(e,r,S,_){"use strict";var A;function C(e,r,S){return r in e?Object.defineProperty(e,r,{value:S,enumerable:!0,configurable:!0,writable:!0}):e[r]=S,e}Object.defineProperty(r,"__esModule",{value:!0});var T=r.SET_A=0,n=r.SET_B=1,i=r.SET_C=2,t=(r.SHIFT=98,r.START_A=103),R=r.START_B=104,o=r.START_C=105;r.MODULO=103,r.STOP=106,r.FNC1=207,r.SET_BY_CODE=(C(A={},t,T),C(A,R,n),C(A,o,i),A),r.SWAP={101:T,100:n,99:i},r.A_START_CHAR=String.fromCharCode(208),r.B_START_CHAR=String.fromCharCode(209),r.C_START_CHAR=String.fromCharCode(210),r.A_CHARS="[\0-_È-Ï]",r.B_CHARS="[ -È-Ï]",r.C_CHARS="(Ï*[0-9]{2}Ï*)",r.BARS=[11011001100,11001101100,11001100110,10010011e3,10010001100,10001001100,10011001e3,10011000100,10001100100,11001001e3,11001000100,11000100100,10110011100,10011011100,10011001110,10111001100,10011101100,10011100110,11001110010,11001011100,11001001110,11011100100,11001110100,11101101110,11101001100,11100101100,11100100110,11101100100,11100110100,11100110010,11011011e3,11011000110,11000110110,10100011e3,10001011e3,10001000110,10110001e3,10001101e3,10001100010,11010001e3,11000101e3,11000100010,10110111e3,10110001110,10001101110,10111011e3,10111000110,10001110110,11101110110,11010001110,11000101110,11011101e3,11011100010,11011101110,11101011e3,11101000110,11100010110,11101101e3,11101100010,11100011010,11101111010,11001000010,11110001010,1010011e4,10100001100,1001011e4,10010000110,10000101100,10000100110,1011001e4,10110000100,1001101e4,10011000010,10000110100,10000110010,11000010010,1100101e4,11110111010,11000010100,10001111010,10100111100,10010111100,10010011110,10111100100,10011110100,10011110010,11110100100,11110010100,11110010010,11011011110,11011110110,11110110110,10101111e3,10100011110,10001011110,10111101e3,10111100010,11110101e3,11110100010,10111011110,10111101110,11101011110,11110101110,11010000100,1101001e4,11010011100,1100011101011]}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/CODE128.js*/
|
||||
amis.define("aee9dc4",(function(e,t,r,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,i=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),u=e("0066873"),a=(o=u)&&o.__esModule?o:{default:o},c=e("555ccbc");var s=function(e){function t(e,r){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var n=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e.substring(1),r));return n.bytes=e.split("").map((function(e){return e.charCodeAt(0)})),n}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),i(t,[{key:"valid",value:function(){return/^[\x00-\x7F\xC8-\xD3]+$/.test(this.data)}},{key:"encode",value:function(){var e=this.bytes,r=e.shift()-105,n=c.SET_BY_CODE[r];if(void 0===n)throw new RangeError("The encoding does not start with a start character.");!0===this.shouldEncodeAsEan128()&&e.unshift(c.FNC1);var o=t.next(e,1,n);return{text:this.text===this.data?this.text.replace(/[^\x20-\x7E]/g,""):this.text,data:t.getBar(r)+o.result+t.getBar((o.checksum+r)%c.MODULO)+t.getBar(c.STOP)}}},{key:"shouldEncodeAsEan128",value:function(){var e=this.options.ean128||!1;return"string"==typeof e&&(e="true"===e.toLowerCase()),e}}],[{key:"getBar",value:function(e){return c.BARS[e]?c.BARS[e].toString():""}},{key:"correctIndex",value:function(e,t){if(t===c.SET_A){var r=e.shift();return r<32?r+64:r-32}return t===c.SET_B?e.shift()-32:10*(e.shift()-48)+e.shift()-48}},{key:"next",value:function(e,r,n){if(!e.length)return{result:"",checksum:0};var o=void 0,i=void 0;if(e[0]>=200){i=e.shift()-105;var u=c.SWAP[i];void 0!==u?o=t.next(e,r+1,u):(n!==c.SET_A&&n!==c.SET_B||i!==c.SHIFT||(e[0]=n===c.SET_A?e[0]>95?e[0]-96:e[0]:e[0]<32?e[0]+96:e[0]),o=t.next(e,r+1,n))}else i=t.correctIndex(e,n),o=t.next(e,r+1,n);var a=i*r;return{result:t.getBar(i)+o.result,checksum:a+o.checksum}}}]),t}(a.default);t.default=s}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/auto.js*/
|
||||
amis.define("c05cae2",(function(e,n,r,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var u=e("555ccbc"),i=function(e){return e.match(new RegExp("^"+u.A_CHARS+"*"))[0].length},C=function(e){return e.match(new RegExp("^"+u.B_CHARS+"*"))[0].length},a=function(e){return e.match(new RegExp("^"+u.C_CHARS+"*"))[0]};function c(e,n){var r=n?u.A_CHARS:u.B_CHARS,t=e.match(new RegExp("^("+r+"+?)(([0-9]{2}){2,})([^0-9]|$)"));if(t)return t[1]+String.fromCharCode(204)+g(e.substring(t[1].length));var i=e.match(new RegExp("^"+r+"+"))[0];return i.length===e.length?e:i+String.fromCharCode(n?205:206)+c(e.substring(i.length),!n)}function g(e){var n=a(e),r=n.length;if(r===e.length)return e;e=e.substring(r);var t=i(e)>=C(e);return n+String.fromCharCode(t?206:205)+c(e,t)}n.default=function(e){var n=void 0;if(a(e).length>=2)n=u.C_START_CHAR+g(e);else{var r=i(e)>C(e);n=(r?u.A_START_CHAR:u.B_START_CHAR)+c(e,r)}return n.replace(/[\xCD\xCE]([^])[\xCD\xCE]/,(function(e,n){return String.fromCharCode(203)+n}))}}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/CODE128_AUTO.js*/
|
||||
amis.define("2e27535",(function(e,t,o,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=c(e("aee9dc4")),i=c(e("c05cae2"));function c(e){return e&&e.__esModule?e:{default:e}}function f(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}var u=function(e){function t(e,o){if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),/^[\x00-\x7F\xC8-\xD3]+$/.test(e))var n=f(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,(0,i.default)(e),o));else n=f(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,o));return f(n)}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t}(r.default);t.default=u}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/CODE128A.js*/
|
||||
amis.define("e99aefe",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("aee9dc4"),a=(o=i)&&o.__esModule?o:{default:o},c=e("555ccbc");var f=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,c.A_START_CHAR+e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),u(t,[{key:"valid",value:function(){return new RegExp("^"+c.A_CHARS+"+$").test(this.data)}}]),t}(a.default);t.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/CODE128B.js*/
|
||||
amis.define("286477e",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("aee9dc4"),a=(o=i)&&o.__esModule?o:{default:o},c=e("555ccbc");var f=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,c.B_START_CHAR+e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),u(t,[{key:"valid",value:function(){return new RegExp("^"+c.B_CHARS+"+$").test(this.data)}}]),t}(a.default);t.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/CODE128C.js*/
|
||||
amis.define("518ea87",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("aee9dc4"),a=(o=i)&&o.__esModule?o:{default:o},c=e("555ccbc");var f=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,c.C_START_CHAR+e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),u(t,[{key:"valid",value:function(){return new RegExp("^"+c.C_CHARS+"+$").test(this.data)}}]),t}(a.default);t.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/CODE128/index.js*/
|
||||
amis.define("8bfc7dc",(function(e,t,u,d){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.CODE128C=t.CODE128B=t.CODE128A=t.CODE128=void 0;var f=l(e("2e27535")),a=l(e("e99aefe")),C=l(e("286477e")),O=l(e("518ea87"));function l(e){return e&&e.__esModule?e:{default:e}}t.CODE128=f.default,t.CODE128A=a.default,t.CODE128B=C.default,t.CODE128C=O.default}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/constants.js*/
|
||||
amis.define("15fbfb2",(function(L,G,e,E){"use strict";Object.defineProperty(G,"__esModule",{value:!0});G.SIDE_BIN="101",G.MIDDLE_BIN="01010",G.BINARIES={L:["0001101","0011001","0010011","0111101","0100011","0110001","0101111","0111011","0110111","0001011"],G:["0100111","0110011","0011011","0100001","0011101","0111001","0000101","0010001","0001001","0010111"],R:["1110010","1100110","1101100","1000010","1011100","1001110","1010000","1000100","1001000","1110100"],O:["0001101","0011001","0010011","0111101","0100011","0110001","0101111","0111011","0110111","0001011"],E:["0100111","0110011","0011011","0100001","0011101","0111001","0000101","0010001","0001001","0010111"]},G.EAN2_STRUCTURE=["LL","LG","GL","GG"],G.EAN5_STRUCTURE=["GGLLL","GLGLL","GLLGL","GLLLG","LGGLL","LLGGL","LLLGG","LGLGL","LGLLG","LLGLG"],G.EAN13_STRUCTURE=["LLLLLL","LLGLGG","LLGGLG","LLGGGL","LGLLGG","LGGLLG","LGGGLL","LGLGLG","LGLGGL","LGGLGL"]}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/encoder.js*/
|
||||
amis.define("8b3d10d",(function(n,e,t,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var u=n("15fbfb2");e.default=function(n,e,t){var r=n.split("").map((function(n,t){return u.BINARIES[e[t]]})).map((function(e,t){return e?e[n[t]]:""}));if(t){var i=n.length-1;r=r.map((function(n,e){return e<i?n+t:n}))}return r.join("")}}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/EAN.js*/
|
||||
amis.define("86352b0",(function(t,e,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}(),i=t("15fbfb2"),u=a(t("8b3d10d"));function a(t){return t&&t.__esModule?t:{default:t}}var f=function(t){function e(t,n){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e);var o=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,t,n));return o.fontSize=!n.flat&&n.fontSize>10*n.width?10*n.width:n.fontSize,o.guardHeight=n.height+o.fontSize/2+n.textMargin,o}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(e,t),r(e,[{key:"encode",value:function(){return this.options.flat?this.encodeFlat():this.encodeGuarded()}},{key:"leftText",value:function(t,e){return this.text.substr(t,e)}},{key:"leftEncode",value:function(t,e){return(0,u.default)(t,e)}},{key:"rightText",value:function(t,e){return this.text.substr(t,e)}},{key:"rightEncode",value:function(t,e){return(0,u.default)(t,e)}},{key:"encodeGuarded",value:function(){var t={fontSize:this.fontSize},e={height:this.guardHeight};return[{data:i.SIDE_BIN,options:e},{data:this.leftEncode(),text:this.leftText(),options:t},{data:i.MIDDLE_BIN,options:e},{data:this.rightEncode(),text:this.rightText(),options:t},{data:i.SIDE_BIN,options:e}]}},{key:"encodeFlat",value:function(){return{data:[i.SIDE_BIN,this.leftEncode(),i.MIDDLE_BIN,this.rightEncode(),i.SIDE_BIN].join(""),text:this.text}}}]),e}(a(t("0066873")).default);e.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/EAN13.js*/
|
||||
amis.define("2482046",(function(t,e,o,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n,i=function(){function t(t,e){for(var o=0;o<e.length;o++){var r=e[o];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,o,r){return o&&t(e.prototype,o),r&&t(e,r),e}}(),a=function t(e,o,r){null===e&&(e=Function.prototype);var n=Object.getOwnPropertyDescriptor(e,o);if(void 0===n){var i=Object.getPrototypeOf(e);return null===i?void 0:t(i,o,r)}if("value"in n)return n.value;var a=n.get;return void 0!==a?a.call(r):void 0},u=t("15fbfb2"),s=t("86352b0"),p=(n=s)&&n.__esModule?n:{default:n};var c=function(t){return(10-t.substr(0,12).split("").map((function(t){return+t})).reduce((function(t,e,o){return o%2?t+3*e:t+e}),0)%10)%10},l=function(t){function e(t,o){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),-1!==t.search(/^[0-9]{12}$/)&&(t+=c(t));var r=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,t,o));return r.lastChar=o.lastChar,r}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(e,t),i(e,[{key:"valid",value:function(){return-1!==this.data.search(/^[0-9]{13}$/)&&+this.data[12]===c(this.data)}},{key:"leftText",value:function(){return a(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"leftText",this).call(this,1,6)}},{key:"leftEncode",value:function(){var t=this.data.substr(1,6),o=u.EAN13_STRUCTURE[this.data[0]];return a(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"leftEncode",this).call(this,t,o)}},{key:"rightText",value:function(){return a(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"rightText",this).call(this,7,6)}},{key:"rightEncode",value:function(){var t=this.data.substr(7,6);return a(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"rightEncode",this).call(this,t,"RRRRRR")}},{key:"encodeGuarded",value:function(){var t=a(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"encodeGuarded",this).call(this);return this.options.displayValue&&(t.unshift({data:"000000000000",text:this.text.substr(0,1),options:{textAlign:"left",fontSize:this.fontSize}}),this.options.lastChar&&(t.push({data:"00"}),t.push({data:"00000",text:this.options.lastChar,options:{fontSize:this.fontSize}}))),t}}]),e}(p.default);e.default=l}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/EAN8.js*/
|
||||
amis.define("ef05be9",(function(t,e,r,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n,i=function(){function t(t,e){for(var r=0;r<e.length;r++){var o=e[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,r,o){return r&&t(e.prototype,r),o&&t(e,o),e}}(),u=function t(e,r,o){null===e&&(e=Function.prototype);var n=Object.getOwnPropertyDescriptor(e,r);if(void 0===n){var i=Object.getPrototypeOf(e);return null===i?void 0:t(i,r,o)}if("value"in n)return n.value;var u=n.get;return void 0!==u?u.call(o):void 0},a=t("86352b0"),c=(n=a)&&n.__esModule?n:{default:n};var f=function(t){return(10-t.substr(0,7).split("").map((function(t){return+t})).reduce((function(t,e,r){return r%2?t+e:t+3*e}),0)%10)%10},l=function(t){function e(t,r){return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),-1!==t.search(/^[0-9]{7}$/)&&(t+=f(t)),function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,t,r))}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(e,t),i(e,[{key:"valid",value:function(){return-1!==this.data.search(/^[0-9]{8}$/)&&+this.data[7]===f(this.data)}},{key:"leftText",value:function(){return u(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"leftText",this).call(this,0,4)}},{key:"leftEncode",value:function(){var t=this.data.substr(0,4);return u(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"leftEncode",this).call(this,t,"LLLL")}},{key:"rightText",value:function(){return u(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"rightText",this).call(this,4,4)}},{key:"rightEncode",value:function(){var t=this.data.substr(4,4);return u(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"rightEncode",this).call(this,t,"RRRR")}}]),e}(c.default);e.default=l}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/EAN5.js*/
|
||||
amis.define("863b430",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),u=e("15fbfb2"),i=f(e("8b3d10d")),a=f(e("0066873"));function f(e){return e&&e.__esModule?e:{default:e}}var c=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),o(t,[{key:"valid",value:function(){return-1!==this.data.search(/^[0-9]{5}$/)}},{key:"encode",value:function(){var e,t=u.EAN5_STRUCTURE[(e=this.data,e.split("").map((function(e){return+e})).reduce((function(e,t,n){return n%2?e+9*t:e+3*t}),0)%10)];return{data:"1011"+(0,i.default)(this.data,t,"01"),text:this.text}}}]),t}(a.default);t.default=c}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/EAN2.js*/
|
||||
amis.define("95bb041",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=e("15fbfb2"),u=i(e("8b3d10d"));function i(e){return e&&e.__esModule?e:{default:e}}var f=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),o(t,[{key:"valid",value:function(){return-1!==this.data.search(/^[0-9]{2}$/)}},{key:"encode",value:function(){var e=a.EAN2_STRUCTURE[parseInt(this.data)%4];return{data:"1011"+(0,u.default)(this.data,e,"01"),text:this.text}}}]),t}(i(e("0066873")).default);t.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/UPC.js*/
|
||||
amis.define("ab9f86d",(function(t,e,i,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=function(){function t(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,i,n){return i&&t(e.prototype,i),n&&t(e,n),e}}();e.checksum=u;var o=r(t("8b3d10d"));function r(t){return t&&t.__esModule?t:{default:t}}var s=function(t){function e(t,i){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),-1!==t.search(/^[0-9]{11}$/)&&(t+=u(t));var n=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,t,i));return n.displayValue=i.displayValue,i.fontSize>10*i.width?n.fontSize=10*i.width:n.fontSize=i.fontSize,n.guardHeight=i.height+n.fontSize/2+i.textMargin,n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(e,t),a(e,[{key:"valid",value:function(){return-1!==this.data.search(/^[0-9]{12}$/)&&this.data[11]==u(this.data)}},{key:"encode",value:function(){return this.options.flat?this.flatEncoding():this.guardedEncoding()}},{key:"flatEncoding",value:function(){var t="";return t+="101",t+=(0,o.default)(this.data.substr(0,6),"LLLLLL"),t+="01010",t+=(0,o.default)(this.data.substr(6,6),"RRRRRR"),{data:t+="101",text:this.text}}},{key:"guardedEncoding",value:function(){var t=[];return this.displayValue&&t.push({data:"00000000",text:this.text.substr(0,1),options:{textAlign:"left",fontSize:this.fontSize}}),t.push({data:"101"+(0,o.default)(this.data[0],"L"),options:{height:this.guardHeight}}),t.push({data:(0,o.default)(this.data.substr(1,5),"LLLLL"),text:this.text.substr(1,5),options:{fontSize:this.fontSize}}),t.push({data:"01010",options:{height:this.guardHeight}}),t.push({data:(0,o.default)(this.data.substr(6,5),"RRRRR"),text:this.text.substr(6,5),options:{fontSize:this.fontSize}}),t.push({data:(0,o.default)(this.data[11],"R")+"101",options:{height:this.guardHeight}}),this.displayValue&&t.push({data:"00000000",text:this.text.substr(11,1),options:{textAlign:"right",fontSize:this.fontSize}}),t}}]),e}(r(t("0066873")).default);function u(t){var e,i=0;for(e=1;e<11;e+=2)i+=parseInt(t[e]);for(e=0;e<11;e+=2)i+=3*parseInt(t[e]);return(10-i%10)%10}e.default=s}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/UPCE.js*/
|
||||
amis.define("9e23739",(function(t,e,i,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=function(){function t(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,i,n){return i&&t(e.prototype,i),n&&t(e,n),e}}(),o=s(t("8b3d10d")),u=s(t("0066873")),a=t("ab9f86d");function s(t){return t&&t.__esModule?t:{default:t}}function O(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}var l=["XX00000XXX","XX10000XXX","XX20000XXX","XXX00000XX","XXXX00000X","XXXXX00005","XXXXX00006","XXXXX00007","XXXXX00008","XXXXX00009"],E=[["EEEOOO","OOOEEE"],["EEOEOO","OOEOEE"],["EEOOEO","OOEEOE"],["EEOOOE","OOEEEO"],["EOEEOO","OEOOEE"],["EOOEEO","OEEOOE"],["EOOOEE","OEEEOO"],["EOEOEO","OEOEOE"],["EOEOOE","OEOEEO"],["EOOEOE","OEEOEO"]],f=function(t){function e(t,i){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e);var n=O(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,t,i));if(n.isValid=!1,-1!==t.search(/^[0-9]{6}$/))n.middleDigits=t,n.upcA=c(t,"0"),n.text=i.text||""+n.upcA[0]+t+n.upcA[n.upcA.length-1],n.isValid=!0;else{if(-1===t.search(/^[01][0-9]{7}$/))return O(n);if(n.middleDigits=t.substring(1,t.length-1),n.upcA=c(n.middleDigits,t[0]),n.upcA[n.upcA.length-1]!==t[t.length-1])return O(n);n.isValid=!0}return n.displayValue=i.displayValue,i.fontSize>10*i.width?n.fontSize=10*i.width:n.fontSize=i.fontSize,n.guardHeight=i.height+n.fontSize/2+i.textMargin,n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(e,t),r(e,[{key:"valid",value:function(){return this.isValid}},{key:"encode",value:function(){return this.options.flat?this.flatEncoding():this.guardedEncoding()}},{key:"flatEncoding",value:function(){var t="";return t+="101",t+=this.encodeMiddleDigits(),{data:t+="010101",text:this.text}}},{key:"guardedEncoding",value:function(){var t=[];return this.displayValue&&t.push({data:"00000000",text:this.text[0],options:{textAlign:"left",fontSize:this.fontSize}}),t.push({data:"101",options:{height:this.guardHeight}}),t.push({data:this.encodeMiddleDigits(),text:this.text.substring(1,7),options:{fontSize:this.fontSize}}),t.push({data:"010101",options:{height:this.guardHeight}}),this.displayValue&&t.push({data:"00000000",text:this.text[7],options:{textAlign:"right",fontSize:this.fontSize}}),t}},{key:"encodeMiddleDigits",value:function(){var t=this.upcA[0],e=this.upcA[this.upcA.length-1],i=E[parseInt(e)][parseInt(t)];return(0,o.default)(this.middleDigits,i)}}]),e}(u.default);function c(t,e){for(var i=parseInt(t[t.length-1]),n=l[i],r="",o=0,u=0;u<n.length;u++){var s=n[u];r+="X"===s?t[o++]:s}return""+(r=""+e+r)+(0,a.checksum)(r)}e.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/EAN_UPC/index.js*/
|
||||
amis.define("4f36e44",(function(e,f,t,u){"use strict";Object.defineProperty(f,"__esModule",{value:!0}),f.UPCE=f.UPC=f.EAN2=f.EAN5=f.EAN8=f.EAN13=void 0;var d=i(e("2482046")),a=i(e("ef05be9")),l=i(e("863b430")),E=i(e("95bb041")),A=i(e("ab9f86d")),N=i(e("9e23739"));function i(e){return e&&e.__esModule?e:{default:e}}f.EAN13=d.default,f.EAN8=a.default,f.EAN5=l.default,f.EAN2=E.default,f.UPC=A.default,f.UPCE=N.default}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/ITF/constants.js*/
|
||||
amis.define("36aaa8a",(function(e,a,i,t){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.START_BIN="1010",a.END_BIN="11101",a.BINARIES=["00110","10001","01001","11000","00101","10100","01100","00011","10010","01010"]}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/ITF/ITF.js*/
|
||||
amis.define("9ee8c21",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,a=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("36aaa8a"),u=e("0066873");function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function f(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}var l=function(e){function t(){return c(this,t),f(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),a(t,[{key:"valid",value:function(){return-1!==this.data.search(/^([0-9]{2})+$/)}},{key:"encode",value:function(){var e=this,t=this.data.match(/.{2}/g).map((function(t){return e.encodePair(t)})).join("");return{data:i.START_BIN+t+i.END_BIN,text:this.text}}},{key:"encodePair",value:function(e){var t=i.BINARIES[e[1]];return i.BINARIES[e[0]].split("").map((function(e,n){return("1"===e?"111":"1")+("1"===t[n]?"000":"0")})).join("")}}]),t}(((o=u)&&o.__esModule?o:{default:o}).default);t.default=l}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/ITF/ITF14.js*/
|
||||
amis.define("bb51808",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("9ee8c21"),a=(o=i)&&o.__esModule?o:{default:o};var c=function(e){var t=e.substr(0,13).split("").map((function(e){return parseInt(e,10)})).reduce((function(e,t,n){return e+t*(3-n%2*2)}),0);return 10*Math.ceil(t/10)-t},f=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),-1!==e.search(/^[0-9]{13}$/)&&(e+=c(e)),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),u(t,[{key:"valid",value:function(){return-1!==this.data.search(/^[0-9]{14}$/)&&+this.data[13]===c(this.data)}}]),t}(a.default);t.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/ITF/index.js*/
|
||||
amis.define("95f71b3",(function(e,t,u,d){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ITF14=t.ITF=void 0;var f=n(e("9ee8c21")),i=n(e("bb51808"));function n(e){return e&&e.__esModule?e:{default:e}}t.ITF=f.default,t.ITF14=i.default}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/MSI/MSI.js*/
|
||||
amis.define("c5c608e",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,a=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("0066873");var u=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),a(t,[{key:"encode",value:function(){for(var e="110",t=0;t<this.data.length;t++){var n=parseInt(this.data[t]).toString(2);n=f(n,4-n.length);for(var r=0;r<n.length;r++)e+="0"==n[r]?"100":"110"}return{data:e+="1001",text:this.text}}},{key:"valid",value:function(){return-1!==this.data.search(/^[0-9]+$/)}}]),t}(((o=i)&&o.__esModule?o:{default:o}).default);function f(e,t){for(var n=0;n<t;n++)e="0"+e;return e}t.default=u}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/MSI/checksums.js*/
|
||||
amis.define("e892ab5",(function(e,n,t,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.mod10=function(e){for(var n=0,t=0;t<e.length;t++){var r=parseInt(e[t]);(t+e.length)%2==0?n+=r:n+=2*r%10+Math.floor(2*r/10)}return(10-n%10)%10},n.mod11=function(e){for(var n=0,t=[2,3,4,5,6,7],r=0;r<e.length;r++){var o=parseInt(e[e.length-1-r]);n+=t[r%t.length]*o}return(11-n%11)%11}}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/MSI/MSI10.js*/
|
||||
amis.define("fd64aa4",(function(e,t,o,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,i=e("c5c608e"),c=(r=i)&&r.__esModule?r:{default:r},f=e("e892ab5");var u=function(e){function t(e,o){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e+(0,f.mod10)(e),o))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t}(c.default);t.default=u}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/MSI/MSI11.js*/
|
||||
amis.define("4c3deb2",(function(e,t,o,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,c=e("c5c608e"),i=(r=c)&&r.__esModule?r:{default:r},u=e("e892ab5");var f=function(e){function t(e,o){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e+(0,u.mod11)(e),o))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t}(i.default);t.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/MSI/MSI1010.js*/
|
||||
amis.define("1d2817f",(function(e,t,o,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,i=e("c5c608e"),c=(r=i)&&r.__esModule?r:{default:r},f=e("e892ab5");var u=function(e){function t(e,o){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),e+=(0,f.mod10)(e),e+=(0,f.mod10)(e),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,o))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t}(c.default);t.default=u}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/MSI/MSI1110.js*/
|
||||
amis.define("c0cc622",(function(e,t,o,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,c=e("c5c608e"),i=(r=c)&&r.__esModule?r:{default:r},u=e("e892ab5");var f=function(e){function t(e,o){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),e+=(0,u.mod11)(e),e+=(0,u.mod10)(e),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,o))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t}(i.default);t.default=f}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/MSI/index.js*/
|
||||
amis.define("e699b6e",(function(e,d,t,u){"use strict";Object.defineProperty(d,"__esModule",{value:!0}),d.MSI1110=d.MSI1010=d.MSI11=d.MSI10=d.MSI=void 0;var f=S(e("c5c608e")),M=S(e("fd64aa4")),a=S(e("4c3deb2")),c=S(e("1d2817f")),I=S(e("c0cc622"));function S(e){return e&&e.__esModule?e:{default:e}}d.MSI=f.default,d.MSI10=M.default,d.MSI11=a.default,d.MSI1010=c.default,d.MSI1110=I.default}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/pharmacode/index.js*/
|
||||
amis.define("f5140b4",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.pharmacode=void 0;var o,i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),u=e("0066873");var a=function(e){function t(e,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var r=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n));return r.number=parseInt(e,10),r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),i(t,[{key:"encode",value:function(){for(var e=this.number,t="";!isNaN(e)&&0!=e;)e%2==0?(t="11100"+t,e=(e-2)/2):(t="100"+t,e=(e-1)/2);return{data:t=t.slice(0,-2),text:this.text}}},{key:"valid",value:function(){return this.number>=3&&this.number<=131070}}]),t}(((o=u)&&o.__esModule?o:{default:o}).default);t.pharmacode=a}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/codabar/index.js*/
|
||||
amis.define("7d225bf",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.codabar=void 0;var o,a=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=e("0066873");var u=function(e){function t(e,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),0===e.search(/^[0-9\-\$\:\.\+\/]+$/)&&(e="A"+e+"A");var r=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e.toUpperCase(),n));return r.text=r.options.text||r.text.replace(/[A-D]/g,""),r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),a(t,[{key:"valid",value:function(){return-1!==this.data.search(/^[A-D][0-9\-\$\:\.\+\/]+[A-D]$/)}},{key:"encode",value:function(){for(var e=[],t=this.getEncodings(),n=0;n<this.data.length;n++)e.push(t[this.data.charAt(n)]),n!==this.data.length-1&&e.push("0");return{text:this.text,data:e.join("")}}},{key:"getEncodings",value:function(){return{0:"101010011",1:"101011001",2:"101001011",3:"110010101",4:"101101001",5:"110101001",6:"100101011",7:"100101101",8:"100110101",9:"110100101","-":"101001101",$:"101100101",":":"1101011011","/":"1101101011",".":"1101101101","+":"1011011011",A:"1011001001",B:"1001001011",C:"1010010011",D:"1010011001"}}}]),t}(((o=i)&&o.__esModule?o:{default:o}).default);t.codabar=u}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/GenericBarcode/index.js*/
|
||||
amis.define("bf352be",(function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.GenericBarcode=void 0;var o,i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),u=e("0066873");var c=function(e){function t(e,n){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),i(t,[{key:"encode",value:function(){return{data:"10101010101010101010101010101010101010101",text:this.text}}},{key:"valid",value:function(){return!0}}]),t}(((o=u)&&o.__esModule?o:{default:o}).default);t.GenericBarcode=c}));
|
||||
;/*!node_modules/jsbarcode/bin/barcodes/index.js*/
|
||||
amis.define("aef9ccb",(function(e,E,c,C){"use strict";Object.defineProperty(E,"__esModule",{value:!0});var a=e("f3f69cf"),f=e("8bfc7dc"),I=e("4f36e44"),d=e("95f71b3"),r=e("e699b6e"),b=e("f5140b4"),M=e("7d225bf"),O=e("bf352be");E.default={CODE39:a.CODE39,CODE128:f.CODE128,CODE128A:f.CODE128A,CODE128B:f.CODE128B,CODE128C:f.CODE128C,EAN13:I.EAN13,EAN8:I.EAN8,EAN5:I.EAN5,EAN2:I.EAN2,UPC:I.UPC,UPCE:I.UPCE,ITF14:d.ITF14,ITF:d.ITF,MSI:r.MSI,MSI10:r.MSI10,MSI11:r.MSI11,MSI1010:r.MSI1010,MSI1110:r.MSI1110,pharmacode:b.pharmacode,codabar:M.codabar,GenericBarcode:O.GenericBarcode}}));
|
||||
;/*!node_modules/jsbarcode/bin/help/merge.js*/
|
||||
amis.define("3ab5a26",(function(e,r,t,n){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var a=Object.assign||function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e};r.default=function(e,r){return a({},e,r)}}));
|
||||
;/*!node_modules/jsbarcode/bin/help/linearizeEncodings.js*/
|
||||
amis.define("3d98e11",(function(e,t,r,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=[];return function e(r){if(Array.isArray(r))for(var a=0;a<r.length;a++)e(r[a]);else r.text=r.text||"",r.data=r.data||"",t.push(r)}(e),t}}));
|
||||
;/*!node_modules/jsbarcode/bin/help/fixOptions.js*/
|
||||
amis.define("d56d516",(function(i,n,r,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.default=function(i){return i.marginTop=i.marginTop||i.margin,i.marginBottom=i.marginBottom||i.margin,i.marginRight=i.marginRight||i.margin,i.marginLeft=i.marginLeft||i.margin,i}}));
|
||||
;/*!node_modules/jsbarcode/bin/help/optionsFromStrings.js*/
|
||||
amis.define("f2a46ae",(function(e,t,a,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=["width","height","textMargin","fontSize","margin","marginTop","marginBottom","marginLeft","marginRight"];for(var a in t)t.hasOwnProperty(a)&&(a=t[a],"string"==typeof e[a]&&(e[a]=parseInt(e[a],10)));"string"==typeof e.displayValue&&(e.displayValue="false"!=e.displayValue);return e}}));
|
||||
;/*!node_modules/jsbarcode/bin/options/defaults.js*/
|
||||
amis.define("2822867",(function(t,i,o,e){"use strict";Object.defineProperty(i,"__esModule",{value:!0});var n={width:2,height:100,format:"auto",displayValue:!0,fontOptions:"",font:"monospace",text:void 0,textAlign:"center",textPosition:"bottom",textMargin:2,fontSize:20,background:"#ffffff",lineColor:"#000000",margin:10,marginTop:void 0,marginBottom:void 0,marginLeft:void 0,marginRight:void 0,valid:function(){}};i.default=n}));
|
||||
;/*!node_modules/jsbarcode/bin/help/getOptionsFromElement.js*/
|
||||
amis.define("432cb14",(function(e,t,a,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var u=d(e("f2a46ae")),o=d(e("2822867"));function d(e){return e&&e.__esModule?e:{default:e}}t.default=function(e){var t={};for(var a in o.default)o.default.hasOwnProperty(a)&&(e.hasAttribute("jsbarcode-"+a.toLowerCase())&&(t[a]=e.getAttribute("jsbarcode-"+a.toLowerCase())),e.hasAttribute("data-"+a.toLowerCase())&&(t[a]=e.getAttribute("data-"+a.toLowerCase())));return t.value=e.getAttribute("jsbarcode-value")||e.getAttribute("data-value"),t=(0,u.default)(t)}}));
|
||||
;/*!node_modules/jsbarcode/bin/renderers/shared.js*/
|
||||
amis.define("279197b",(function(t,e,n,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getTotalWidthOfEncodings=e.calculateEncodingAttributes=e.getBarcodePadding=e.getEncodingHeight=e.getMaximumHeightOfEncodings=void 0;var a,o=t("3ab5a26"),r=(a=o)&&a.__esModule?a:{default:a};function g(t,e){return e.height+(e.displayValue&&t.text.length>0?e.fontSize+e.textMargin:0)+e.marginTop+e.marginBottom}function d(t,e,n){if(n.displayValue&&e<t){if("center"==n.textAlign)return Math.floor((t-e)/2);if("left"==n.textAlign)return 0;if("right"==n.textAlign)return Math.floor(t-e)}return 0}function u(t,e,n){var i;if(n)i=n;else{if("undefined"==typeof document)return 0;i=document.createElement("canvas").getContext("2d")}i.font=e.fontOptions+" "+e.fontSize+"px "+e.font;var a=i.measureText(t);return a?a.width:0}e.getMaximumHeightOfEncodings=function(t){for(var e=0,n=0;n<t.length;n++)t[n].height>e&&(e=t[n].height);return e},e.getEncodingHeight=g,e.getBarcodePadding=d,e.calculateEncodingAttributes=function(t,e,n){for(var i=0;i<t.length;i++){var a,o=t[i],f=(0,r.default)(e,o.options);a=f.displayValue?u(o.text,f,n):0;var l=o.data.length*f.width;o.width=Math.ceil(Math.max(a,l)),o.height=g(o,f),o.barcodePadding=d(a,l,f)}},e.getTotalWidthOfEncodings=function(t){for(var e=0,n=0;n<t.length;n++)e+=t[n].width;return e}}));
|
||||
;/*!node_modules/jsbarcode/bin/renderers/canvas.js*/
|
||||
amis.define("a98feb3",(function(t,n,e,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var a,s=function(){function t(t,n){for(var e=0;e<n.length;e++){var i=n[e];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(n,e,i){return e&&t(n.prototype,e),i&&t(n,i),n}}(),o=t("3ab5a26"),r=(a=o)&&a.__esModule?a:{default:a},h=t("279197b");var c=function(){function t(n,e,i){!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.canvas=n,this.encodings=e,this.options=i}return s(t,[{key:"render",value:function(){if(!this.canvas.getContext)throw new Error("The browser does not support canvas.");this.prepareCanvas();for(var t=0;t<this.encodings.length;t++){var n=(0,r.default)(this.options,this.encodings[t].options);this.drawCanvasBarcode(n,this.encodings[t]),this.drawCanvasText(n,this.encodings[t]),this.moveCanvasDrawing(this.encodings[t])}this.restoreCanvas()}},{key:"prepareCanvas",value:function(){var t=this.canvas.getContext("2d");t.save(),(0,h.calculateEncodingAttributes)(this.encodings,this.options,t);var n=(0,h.getTotalWidthOfEncodings)(this.encodings),e=(0,h.getMaximumHeightOfEncodings)(this.encodings);this.canvas.width=n+this.options.marginLeft+this.options.marginRight,this.canvas.height=e,t.clearRect(0,0,this.canvas.width,this.canvas.height),this.options.background&&(t.fillStyle=this.options.background,t.fillRect(0,0,this.canvas.width,this.canvas.height)),t.translate(this.options.marginLeft,0)}},{key:"drawCanvasBarcode",value:function(t,n){var e,i=this.canvas.getContext("2d"),a=n.data;e="top"==t.textPosition?t.marginTop+t.fontSize+t.textMargin:t.marginTop,i.fillStyle=t.lineColor;for(var s=0;s<a.length;s++){var o=s*t.width+n.barcodePadding;"1"===a[s]?i.fillRect(o,e,t.width,t.height):a[s]&&i.fillRect(o,e,t.width,t.height*a[s])}}},{key:"drawCanvasText",value:function(t,n){var e,i,a=this.canvas.getContext("2d"),s=t.fontOptions+" "+t.fontSize+"px "+t.font;t.displayValue&&(i="top"==t.textPosition?t.marginTop+t.fontSize-t.textMargin:t.height+t.textMargin+t.marginTop+t.fontSize,a.font=s,"left"==t.textAlign||n.barcodePadding>0?(e=0,a.textAlign="left"):"right"==t.textAlign?(e=n.width-1,a.textAlign="right"):(e=n.width/2,a.textAlign="center"),a.fillText(n.text,e,i))}},{key:"moveCanvasDrawing",value:function(t){this.canvas.getContext("2d").translate(t.width,0)}},{key:"restoreCanvas",value:function(){this.canvas.getContext("2d").restore()}}]),t}();n.default=c}));
|
||||
;/*!node_modules/jsbarcode/bin/renderers/svg.js*/
|
||||
amis.define("1880ba9",(function(t,e,i,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r,s=function(){function t(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,i,n){return i&&t(e.prototype,i),n&&t(e,n),e}}(),o=t("3ab5a26"),a=(r=o)&&r.__esModule?r:{default:r},u=t("279197b");var h="http://www.w3.org/2000/svg",d=function(){function t(e,i,n){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.svg=e,this.encodings=i,this.options=n,this.document=n.xmlDocument||document}return s(t,[{key:"render",value:function(){var t=this.options.marginLeft;this.prepareSVG();for(var e=0;e<this.encodings.length;e++){var i=this.encodings[e],n=(0,a.default)(this.options,i.options),r=this.createGroup(t,n.marginTop,this.svg);this.setGroupOptions(r,n),this.drawSvgBarcode(r,n,i),this.drawSVGText(r,n,i),t+=i.width}}},{key:"prepareSVG",value:function(){for(;this.svg.firstChild;)this.svg.removeChild(this.svg.firstChild);(0,u.calculateEncodingAttributes)(this.encodings,this.options);var t=(0,u.getTotalWidthOfEncodings)(this.encodings),e=(0,u.getMaximumHeightOfEncodings)(this.encodings),i=t+this.options.marginLeft+this.options.marginRight;this.setSvgAttributes(i,e),this.options.background&&this.drawRect(0,0,i,e,this.svg).setAttribute("style","fill:"+this.options.background+";")}},{key:"drawSvgBarcode",value:function(t,e,i){var n,r=i.data;n="top"==e.textPosition?e.fontSize+e.textMargin:0;for(var s=0,o=0,a=0;a<r.length;a++)o=a*e.width+i.barcodePadding,"1"===r[a]?s++:s>0&&(this.drawRect(o-e.width*s,n,e.width*s,e.height,t),s=0);s>0&&this.drawRect(o-e.width*(s-1),n,e.width*s,e.height,t)}},{key:"drawSVGText",value:function(t,e,i){var n,r,s=this.document.createElementNS(h,"text");e.displayValue&&(s.setAttribute("style","font:"+e.fontOptions+" "+e.fontSize+"px "+e.font),r="top"==e.textPosition?e.fontSize-e.textMargin:e.height+e.textMargin+e.fontSize,"left"==e.textAlign||i.barcodePadding>0?(n=0,s.setAttribute("text-anchor","start")):"right"==e.textAlign?(n=i.width-1,s.setAttribute("text-anchor","end")):(n=i.width/2,s.setAttribute("text-anchor","middle")),s.setAttribute("x",n),s.setAttribute("y",r),s.appendChild(this.document.createTextNode(i.text)),t.appendChild(s))}},{key:"setSvgAttributes",value:function(t,e){var i=this.svg;i.setAttribute("width",t+"px"),i.setAttribute("height",e+"px"),i.setAttribute("x","0px"),i.setAttribute("y","0px"),i.setAttribute("viewBox","0 0 "+t+" "+e),i.setAttribute("xmlns",h),i.setAttribute("version","1.1"),i.setAttribute("style","transform: translate(0,0)")}},{key:"createGroup",value:function(t,e,i){var n=this.document.createElementNS(h,"g");return n.setAttribute("transform","translate("+t+", "+e+")"),i.appendChild(n),n}},{key:"setGroupOptions",value:function(t,e){t.setAttribute("style","fill:"+e.lineColor+";")}},{key:"drawRect",value:function(t,e,i,n,r){var s=this.document.createElementNS(h,"rect");return s.setAttribute("x",t),s.setAttribute("y",e),s.setAttribute("width",i),s.setAttribute("height",n),r.appendChild(s),s}}]),t}();e.default=d}));
|
||||
;/*!node_modules/jsbarcode/bin/renderers/object.js*/
|
||||
amis.define("a69cf15",(function(e,n,t,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o=function(){function e(e,n){for(var t=0;t<n.length;t++){var i=n[t];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(n,t,i){return t&&e(n.prototype,t),i&&e(n,i),n}}();var r=function(){function e(n,t,i){!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,e),this.object=n,this.encodings=t,this.options=i}return o(e,[{key:"render",value:function(){this.object.encodings=this.encodings}}]),e}();n.default=r}));
|
||||
;/*!node_modules/jsbarcode/bin/renderers/index.js*/
|
||||
amis.define("1973ca7",(function(e,a,t,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var r=n(e("a98feb3")),u=n(e("1880ba9")),f=n(e("a69cf15"));function n(e){return e&&e.__esModule?e:{default:e}}a.default={CanvasRenderer:r.default,SVGRenderer:u.default,ObjectRenderer:f.default}}));
|
||||
;/*!node_modules/jsbarcode/bin/exceptions/exceptions.js*/
|
||||
amis.define("ade2392",(function(t,e,n,o){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var a=function(t){function e(t,n){r(this,e);var o=i(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return o.name="InvalidInputException",o.symbology=t,o.input=n,o.message='"'+o.input+'" is not a valid input for '+o.symbology,o}return c(e,Error),e}(),u=function(t){function e(){r(this,e);var t=i(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return t.name="InvalidElementException",t.message="Not supported type to render on",t}return c(e,Error),e}(),s=function(t){function e(){r(this,e);var t=i(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return t.name="NoElementException",t.message="No element to render on.",t}return c(e,Error),e}();e.InvalidInputException=a,e.InvalidElementException=u,e.NoElementException=s}));
|
||||
;/*!node_modules/jsbarcode/bin/help/getRenderProperties.js*/
|
||||
amis.define("6521707",(function(e,n,t,r){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a=d(e("432cb14")),f=d(e("1973ca7")),u=e("ade2392");function d(e){return e&&e.__esModule?e:{default:e}}function l(e){if("string"==typeof e)return function(e){var n=document.querySelectorAll(e);if(0===n.length)return;for(var t=[],r=0;r<n.length;r++)t.push(l(n[r]));return t}(e);if(Array.isArray(e)){for(var n=[],t=0;t<e.length;t++)n.push(l(e[t]));return n}if("undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLImageElement)return r=e,{element:d=document.createElement("canvas"),options:(0,a.default)(r),renderer:f.default.CanvasRenderer,afterRender:function(){r.setAttribute("src",d.toDataURL())}};if(e&&e.nodeName&&"svg"===e.nodeName.toLowerCase()||"undefined"!=typeof SVGElement&&e instanceof SVGElement)return{element:e,options:(0,a.default)(e),renderer:f.default.SVGRenderer};if("undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement)return{element:e,options:(0,a.default)(e),renderer:f.default.CanvasRenderer};if(e&&e.getContext)return{element:e,renderer:f.default.CanvasRenderer};if(e&&"object"===(void 0===e?"undefined":o(e))&&!e.nodeName)return{element:e,renderer:f.default.ObjectRenderer};throw new u.InvalidElementException;var r,d}n.default=l}));
|
||||
;/*!node_modules/jsbarcode/bin/exceptions/ErrorHandler.js*/
|
||||
amis.define("51e0b19",(function(t,e,n,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}();var r=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.api=e}return a(t,[{key:"handleCatch",value:function(t){if("InvalidInputException"!==t.name)throw t;if(this.api._options.valid===this.api._defaults.valid)throw t.message;this.api._options.valid(!1),this.api.render=function(){}}},{key:"wrapBarcodeCall",value:function(t){try{var e=t.apply(void 0,arguments);return this.api._options.valid(!0),e}catch(t){return this.handleCatch(t),this.api}}}]),t}();e.default=r}));
|
||||
;/*!node_modules/jsbarcode/bin/JsBarcode.js*/
|
||||
amis.define("c4d188f",(function(e,r,t,o){"use strict";var n=c(e("aef9ccb")),i=c(e("3ab5a26")),a=c(e("3d98e11")),s=c(e("d56d516")),d=c(e("6521707")),f=c(e("f2a46ae")),u=c(e("51e0b19")),p=e("ade2392"),l=c(e("2822867"));function c(e){return e&&e.__esModule?e:{default:e}}var h=function(){},_=function(e,r,t){var o=new h;if(void 0===e)throw Error("No element to render on was provided.");return o._renderProperties=(0,d.default)(e),o._encodings=[],o._options=l.default,o._errorHandler=new u.default(o),void 0!==r&&((t=t||{}).format||(t.format=P()),o.options(t)[t.format](r,t).render()),o};for(var v in _.getModule=function(e){return n.default[e]},n.default)n.default.hasOwnProperty(v)&&y(n.default,v);function y(e,r){h.prototype[r]=h.prototype[r.toUpperCase()]=h.prototype[r.toLowerCase()]=function(t,o){var n=this;return n._errorHandler.wrapBarcodeCall((function(){o.text=void 0===o.text?void 0:""+o.text;var a=(0,i.default)(n._options,o);a=(0,f.default)(a);var s=e[r],d=w(t,s,a);return n._encodings.push(d),n}))}}function w(e,r,t){var o=new r(e=""+e,t);if(!o.valid())throw new p.InvalidInputException(o.constructor.name,e);var n=o.encode();n=(0,a.default)(n);for(var s=0;s<n.length;s++)n[s].options=(0,i.default)(t,n[s].options);return n}function P(){return n.default.CODE128?"CODE128":Object.keys(n.default)[0]}function m(e,r,t){r=(0,a.default)(r);for(var o=0;o<r.length;o++)r[o].options=(0,i.default)(t,r[o].options),(0,s.default)(r[o].options);(0,s.default)(t),new(0,e.renderer)(e.element,r,t).render(),e.afterRender&&e.afterRender()}h.prototype.options=function(e){return this._options=(0,i.default)(this._options,e),this},h.prototype.blank=function(e){var r=new Array(e+1).join("0");return this._encodings.push({data:r}),this},h.prototype.init=function(){var e;if(this._renderProperties)for(var r in Array.isArray(this._renderProperties)||(this._renderProperties=[this._renderProperties]),this._renderProperties){e=this._renderProperties[r];var t=(0,i.default)(this._options,e.options);"auto"==t.format&&(t.format=P()),this._errorHandler.wrapBarcodeCall((function(){var r=w(t.value,n.default[t.format.toUpperCase()],t);m(e,r,t)}))}},h.prototype.render=function(){if(!this._renderProperties)throw new p.NoElementException;if(Array.isArray(this._renderProperties))for(var e=0;e<this._renderProperties.length;e++)m(this._renderProperties[e],this._encodings,this._options);else m(this._renderProperties,this._encodings,this._options);return this},h.prototype._defaults=l.default,"undefined"!=typeof window&&(window.JsBarcode=_),"undefined"!=typeof jQuery&&(jQuery.fn.JsBarcode=function(e,r){var t=[];return jQuery(this).each((function(){t.push(this)})),_(t,e,r)}),t.exports=_}));
|
||||
93
service-web/src/main/resources/static/sdk/charts.js
Normal file
93
service-web/src/main/resources/static/sdk/charts.js
Normal file
File diff suppressed because one or more lines are too long
16
service-web/src/main/resources/static/sdk/codemirror.js
Normal file
16
service-web/src/main/resources/static/sdk/codemirror.js
Normal file
File diff suppressed because one or more lines are too long
130
service-web/src/main/resources/static/sdk/color-picker.js
Normal file
130
service-web/src/main/resources/static/sdk/color-picker.js
Normal file
File diff suppressed because one or more lines are too long
14
service-web/src/main/resources/static/sdk/cropperjs.js
Normal file
14
service-web/src/main/resources/static/sdk/cropperjs.js
Normal file
File diff suppressed because one or more lines are too long
355
service-web/src/main/resources/static/sdk/cxd-ie11.css
Normal file
355
service-web/src/main/resources/static/sdk/cxd-ie11.css
Normal file
File diff suppressed because one or more lines are too long
291
service-web/src/main/resources/static/sdk/cxd.css
Normal file
291
service-web/src/main/resources/static/sdk/cxd.css
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user