mirror of
https://github.com/dromara/hertzbeat.git
synced 2026-09-17 09:40:58 +00:00
Merge branch 'master' into feature/angular-three-signals
This commit is contained in:
@@ -17,7 +17,6 @@
|
||||
|
||||
/home export-ignore
|
||||
/hip export-ignore
|
||||
/template-marketplace export-ignore
|
||||
/.github export-ignore
|
||||
/.idea export-ignore
|
||||
/.devcontainer export-ignore
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
|
||||
- name: Build the Backend
|
||||
run: |
|
||||
mvnd -B clean package -Prelease,Pcluster -Dmaven.test.skip=false --file pom.xml
|
||||
mvnd -B clean package -Prelease,cluster -Dmaven.test.skip=false --file pom.xml
|
||||
|
||||
- uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a
|
||||
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ public class ChatClientProviderServiceImpl implements ChatClientProviderService
|
||||
return chatClient.prompt()
|
||||
.messages(messages)
|
||||
.system(systemPrompt)
|
||||
.toolCallbacks(toolCallbackProvider)
|
||||
.tools(toolCallbackProvider)
|
||||
.stream()
|
||||
.content()
|
||||
.doOnComplete(() -> log.info("Streaming completed for conversation: {}", context.getConversationId()))
|
||||
|
||||
+1
-3
@@ -34,7 +34,6 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.codec.ServerSentEvent;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -99,8 +98,7 @@ public class ConversationServiceImpl implements ConversationService {
|
||||
ChatRequestContext context = ChatRequestContext.builder()
|
||||
.message(message)
|
||||
.conversationId(conversationId)
|
||||
.conversationHistory(CollectionUtils.isEmpty(conversation.getMessages()) ? null
|
||||
: conversation.getMessages().subList(0, conversation.getMessages().size() - 1))
|
||||
.conversationHistory(messages)
|
||||
.build();
|
||||
|
||||
// Stream response from AI service
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.ai.service.impl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.apache.hertzbeat.ai.dao.ChatConversationDao;
|
||||
import org.apache.hertzbeat.ai.dao.ChatMessageDao;
|
||||
import org.apache.hertzbeat.ai.pojo.dto.ChatRequestContext;
|
||||
import org.apache.hertzbeat.ai.pojo.dto.ChatResponseChunk;
|
||||
import org.apache.hertzbeat.ai.service.ChatClientProviderService;
|
||||
import org.apache.hertzbeat.common.entity.ai.ChatConversation;
|
||||
import org.apache.hertzbeat.common.entity.ai.ChatMessage;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.codec.ServerSentEvent;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* Tests multi-turn conversation context handling in {@link ConversationServiceImpl}.
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ConversationServiceImplTest {
|
||||
|
||||
private static final long CONVERSATION_ID = 1L;
|
||||
|
||||
@Mock
|
||||
private ChatConversationDao conversationDao;
|
||||
|
||||
@Mock
|
||||
private ChatMessageDao messageDao;
|
||||
|
||||
@Mock
|
||||
private ChatClientProviderService chatClientProviderService;
|
||||
|
||||
@InjectMocks
|
||||
private ConversationServiceImpl conversationService;
|
||||
|
||||
@Test
|
||||
void streamChatShouldKeepCompleteConversationHistory() {
|
||||
ChatConversation conversation = ChatConversation.builder()
|
||||
.id(CONVERSATION_ID)
|
||||
.title("已命名会话")
|
||||
.build();
|
||||
List<ChatMessage> history = List.of(
|
||||
ChatMessage.builder()
|
||||
.id(11L)
|
||||
.conversationId(CONVERSATION_ID)
|
||||
.role("user")
|
||||
.content("上一轮问题")
|
||||
.build(),
|
||||
ChatMessage.builder()
|
||||
.id(12L)
|
||||
.conversationId(CONVERSATION_ID)
|
||||
.role("assistant")
|
||||
.content("上一轮回答")
|
||||
.build());
|
||||
AtomicLong messageId = new AtomicLong(20L);
|
||||
|
||||
when(chatClientProviderService.isConfigured()).thenReturn(true);
|
||||
when(conversationDao.findById(CONVERSATION_ID)).thenReturn(Optional.of(conversation));
|
||||
when(messageDao.findByConversationIdOrderByGmtCreateAsc(CONVERSATION_ID)).thenReturn(history);
|
||||
when(messageDao.save(any(ChatMessage.class))).thenAnswer(invocation -> {
|
||||
ChatMessage savedMessage = invocation.getArgument(0);
|
||||
savedMessage.setId(messageId.getAndIncrement());
|
||||
return savedMessage;
|
||||
});
|
||||
when(chatClientProviderService.streamChat(any(ChatRequestContext.class)))
|
||||
.thenReturn(Flux.just("本轮回答"));
|
||||
|
||||
List<ServerSentEvent<ChatResponseChunk>> events = conversationService
|
||||
.streamChat("本轮问题", CONVERSATION_ID)
|
||||
.collectList()
|
||||
.block();
|
||||
|
||||
assertNotNull(events);
|
||||
assertEquals(2, events.size());
|
||||
ArgumentCaptor<ChatRequestContext> contextCaptor = ArgumentCaptor.forClass(ChatRequestContext.class);
|
||||
verify(chatClientProviderService).streamChat(contextCaptor.capture());
|
||||
assertEquals(history, contextCaptor.getValue().getConversationHistory());
|
||||
}
|
||||
}
|
||||
+18
-11
@@ -19,9 +19,11 @@ package org.apache.hertzbeat.alert.reduce;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.hertzbeat.alert.dao.AlertSilenceDao;
|
||||
import org.apache.hertzbeat.alert.notice.AlertNoticeDispatch;
|
||||
@@ -44,6 +46,7 @@ public class AlarmSilenceReduce {
|
||||
/**
|
||||
* Process alert with silence rules
|
||||
* If alert matches any active silence rule, it will be silenced
|
||||
*
|
||||
* @param groupAlert The alert to be processed
|
||||
*/
|
||||
public void silenceAlarm(GroupAlert groupAlert) {
|
||||
@@ -52,7 +55,7 @@ public class AlarmSilenceReduce {
|
||||
alertSilenceList = alertSilenceDao.findAlertSilencesByEnableTrue();
|
||||
CacheFactory.setAlertSilenceCache(alertSilenceList);
|
||||
}
|
||||
|
||||
|
||||
// Check each silence rule
|
||||
for (AlertSilence alertSilence : alertSilenceList) {
|
||||
// Check if alert matches silence rule
|
||||
@@ -60,10 +63,10 @@ public class AlarmSilenceReduce {
|
||||
if (!match && groupAlert.getGroupLabels() != null) {
|
||||
Map<String, String> labels = alertSilence.getLabels();
|
||||
Map<String, String> alertLabels = groupAlert.getGroupLabels();
|
||||
match = labels.entrySet().stream().anyMatch(item ->
|
||||
match = labels.entrySet().stream().anyMatch(item ->
|
||||
alertLabels.containsKey(item.getKey()) && item.getValue().equals(alertLabels.get(item.getKey())));
|
||||
}
|
||||
|
||||
|
||||
if (match) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (alertSilence.getType() == 0) {
|
||||
@@ -76,22 +79,23 @@ public class AlarmSilenceReduce {
|
||||
} else if (alertSilence.getType() == 1) {
|
||||
// Cyclic silence rule
|
||||
int currentDayOfWeek = now.getDayOfWeek().getValue();
|
||||
if (alertSilence.getDays() != null && alertSilence.getDays().contains((byte) currentDayOfWeek)
|
||||
&& !checkAndSave(now, alertSilence)) {
|
||||
if (alertSilence.getDays() != null && alertSilence.getDays().contains((byte) currentDayOfWeek)
|
||||
&& !checkAndSave(now, alertSilence)) {
|
||||
// Alert is silenced
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// No matching silence rule, forward the alert
|
||||
dispatcherAlarm.dispatchAlarm(groupAlert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if alert time is within silence period and update silence rule counter
|
||||
* @param now Current time
|
||||
*
|
||||
* @param now Current time
|
||||
* @param alertSilence Silence rule to check
|
||||
* @return true if alert should not be silenced, false if alert should be silenced
|
||||
*/
|
||||
@@ -100,8 +104,11 @@ public class AlarmSilenceReduce {
|
||||
boolean endMatch;
|
||||
if (alertSilence.getType() == 1) {
|
||||
LocalTime nowTime = now.toLocalTime();
|
||||
LocalTime startTime = alertSilence.getPeriodStart() == null ? null : alertSilence.getPeriodStart().toLocalTime();
|
||||
LocalTime endTime = alertSilence.getPeriodEnd() == null ? null : alertSilence.getPeriodEnd().toLocalTime();
|
||||
// compare wall-clock times in the server time zone, the stored offset may differ from it
|
||||
LocalTime startTime = alertSilence.getPeriodStart() == null
|
||||
? null : alertSilence.getPeriodStart().withZoneSameInstant(ZoneId.systemDefault()).toLocalTime();
|
||||
LocalTime endTime = alertSilence.getPeriodEnd() == null
|
||||
? null : alertSilence.getPeriodEnd().withZoneSameInstant(ZoneId.systemDefault()).toLocalTime();
|
||||
if (startTime == null && endTime == null) {
|
||||
startMatch = true;
|
||||
endMatch = true;
|
||||
@@ -121,9 +128,9 @@ public class AlarmSilenceReduce {
|
||||
}
|
||||
} else {
|
||||
startMatch = alertSilence.getPeriodStart() == null
|
||||
|| now.isAfter(alertSilence.getPeriodStart().toLocalDateTime());
|
||||
|| now.isAfter(alertSilence.getPeriodStart().withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
|
||||
endMatch = alertSilence.getPeriodEnd() == null
|
||||
|| now.isBefore(alertSilence.getPeriodEnd().toLocalDateTime());
|
||||
|| now.isBefore(alertSilence.getPeriodEnd().withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime());
|
||||
}
|
||||
|
||||
if (startMatch && endMatch) {
|
||||
|
||||
+75
-64
@@ -52,6 +52,7 @@ import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
@@ -91,7 +92,7 @@ public class NoticeConfigServiceImpl implements NoticeConfigService, CommandLine
|
||||
Predicate predicate = criteriaBuilder.conjunction();
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
Predicate predicateName = criteriaBuilder.like(
|
||||
criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"
|
||||
criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"
|
||||
);
|
||||
predicate = criteriaBuilder.and(predicateName);
|
||||
}
|
||||
@@ -113,9 +114,9 @@ public class NoticeConfigServiceImpl implements NoticeConfigService, CommandLine
|
||||
|
||||
// Filter by name (case-insensitive)
|
||||
List<NoticeTemplate> filteredDefaultTemplates = defaultTemplates.stream()
|
||||
.filter(template -> StringUtils.isBlank(name)
|
||||
|| template.getName().toLowerCase().contains(name.toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
.filter(template -> StringUtils.isBlank(name)
|
||||
|| template.getName().toLowerCase().contains(name.toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Pagination logic
|
||||
int totalItems = filteredDefaultTemplates.size();
|
||||
@@ -134,7 +135,7 @@ public class NoticeConfigServiceImpl implements NoticeConfigService, CommandLine
|
||||
Predicate predicate = criteriaBuilder.conjunction();
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
Predicate predicateName = criteriaBuilder.like(
|
||||
criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"
|
||||
criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"
|
||||
);
|
||||
predicate = criteriaBuilder.and(predicateName);
|
||||
}
|
||||
@@ -146,7 +147,6 @@ public class NoticeConfigServiceImpl implements NoticeConfigService, CommandLine
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<NoticeTemplate> getAllNoticeTemplates() {
|
||||
List<NoticeTemplate> defaultTemplates = new LinkedList<>(PRESET_TEMPLATE.values());
|
||||
@@ -160,7 +160,7 @@ public class NoticeConfigServiceImpl implements NoticeConfigService, CommandLine
|
||||
Predicate predicate = criteriaBuilder.conjunction();
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
Predicate predicateName = criteriaBuilder.like(
|
||||
criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"
|
||||
criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"
|
||||
);
|
||||
predicate = criteriaBuilder.and(predicateName);
|
||||
}
|
||||
@@ -217,45 +217,56 @@ public class NoticeConfigServiceImpl implements NoticeConfigService, CommandLine
|
||||
// one alert still notifies the whole group. The ideal design is route-then-group (like Alertmanager):
|
||||
// route each single alert by its labels first, then group per receiver. Tracked as a follow-up to #3852.
|
||||
return rules.stream()
|
||||
.filter(rule -> {
|
||||
if (!rule.isFilterAll()) {
|
||||
// filter labels: a rule matches when ANY single alert in the group carries
|
||||
if (rule.getLabels() != null && !rule.getLabels().isEmpty()) {
|
||||
List<SingleAlert> singleAlerts = alert.getAlerts();
|
||||
boolean labelMatch = singleAlerts != null && singleAlerts.stream().anyMatch(singleAlert -> {
|
||||
Map<String, String> alertLabels = singleAlert.getLabels();
|
||||
if (alertLabels == null) {
|
||||
return false;
|
||||
}
|
||||
return rule.getLabels().entrySet().stream().allMatch(labelItem ->
|
||||
Objects.equals(labelItem.getValue(), alertLabels.get(labelItem.getKey())));
|
||||
});
|
||||
if (!labelMatch) {
|
||||
.filter(rule -> {
|
||||
if (!rule.isFilterAll()) {
|
||||
// filter labels: a rule matches when ANY single alert in the group carries
|
||||
if (rule.getLabels() != null && !rule.getLabels().isEmpty()) {
|
||||
List<SingleAlert> singleAlerts = alert.getAlerts();
|
||||
boolean labelMatch = singleAlerts != null && singleAlerts.stream().anyMatch(singleAlert -> {
|
||||
Map<String, String> alertLabels = singleAlert.getLabels();
|
||||
if (alertLabels == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalDateTime nowDate = LocalDateTime.now();
|
||||
// filter day
|
||||
int currentDayOfWeek = nowDate.toLocalDate().getDayOfWeek().getValue();
|
||||
if (rule.getDays() != null && !rule.getDays().isEmpty()) {
|
||||
boolean dayMatch = rule.getDays().stream().anyMatch(item -> item == currentDayOfWeek);
|
||||
if (!dayMatch) {
|
||||
return rule.getLabels().entrySet().stream().allMatch(labelItem ->
|
||||
Objects.equals(labelItem.getValue(), alertLabels.get(labelItem.getKey())));
|
||||
});
|
||||
if (!labelMatch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// filter time
|
||||
LocalTime nowTime = nowDate.toLocalTime();
|
||||
boolean startMatch = rule.getPeriodStart() == null
|
||||
|| nowTime.isAfter(rule.getPeriodStart().toLocalTime())
|
||||
|| (rule.getPeriodEnd() != null && rule.getPeriodStart().isAfter(rule.getPeriodEnd())
|
||||
&& nowTime.isBefore(rule.getPeriodStart().toLocalTime()));
|
||||
boolean endMatch = rule.getPeriodEnd() == null
|
||||
|| nowTime.isBefore(rule.getPeriodEnd().toLocalTime());
|
||||
return startMatch && endMatch;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
LocalDateTime nowDate = LocalDateTime.now();
|
||||
// filter day
|
||||
int currentDayOfWeek = nowDate.toLocalDate().getDayOfWeek().getValue();
|
||||
if (rule.getDays() != null && !rule.getDays().isEmpty()) {
|
||||
boolean dayMatch = rule.getDays().stream().anyMatch(item -> item == currentDayOfWeek);
|
||||
if (!dayMatch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// filter time, compare wall-clock times in the server time zone,
|
||||
// the stored date part is meaningless (it is the day the user picked the time on the ui)
|
||||
LocalTime nowTime = nowDate.toLocalTime();
|
||||
LocalTime startTime = rule.getPeriodStart() == null
|
||||
? null : rule.getPeriodStart().withZoneSameInstant(ZoneId.systemDefault()).toLocalTime();
|
||||
LocalTime endTime = rule.getPeriodEnd() == null
|
||||
? null : rule.getPeriodEnd().withZoneSameInstant(ZoneId.systemDefault()).toLocalTime();
|
||||
if (startTime == null && endTime == null) {
|
||||
return true;
|
||||
}
|
||||
if (startTime == null) {
|
||||
return !nowTime.isAfter(endTime);
|
||||
}
|
||||
if (endTime == null) {
|
||||
return !nowTime.isBefore(startTime);
|
||||
}
|
||||
if (!startTime.isAfter(endTime)) {
|
||||
return !nowTime.isBefore(startTime) && !nowTime.isAfter(endTime);
|
||||
}
|
||||
// cross-midnight window, e.g. 22:00-06:00
|
||||
return !nowTime.isBefore(startTime) || !nowTime.isAfter(endTime);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -314,31 +325,31 @@ public class NoticeConfigServiceImpl implements NoticeConfigService, CommandLine
|
||||
Map<String, String> annotations = new HashMap<>(8);
|
||||
annotations.put("suggest", "Please check the CPU usage of the server");
|
||||
SingleAlert singleAlert1 = SingleAlert.builder()
|
||||
.labels(labels)
|
||||
.content("test send msg! \\n This is the test data. It is proved that it can be received successfully")
|
||||
.startAt(System.currentTimeMillis())
|
||||
.activeAt(System.currentTimeMillis())
|
||||
.endAt(System.currentTimeMillis())
|
||||
.triggerTimes(2)
|
||||
.annotations(annotations)
|
||||
.status("firing")
|
||||
.build();
|
||||
.labels(labels)
|
||||
.content("test send msg! \\n This is the test data. It is proved that it can be received successfully")
|
||||
.startAt(System.currentTimeMillis())
|
||||
.activeAt(System.currentTimeMillis())
|
||||
.endAt(System.currentTimeMillis())
|
||||
.triggerTimes(2)
|
||||
.annotations(annotations)
|
||||
.status("firing")
|
||||
.build();
|
||||
SingleAlert singleAlert2 = SingleAlert.builder()
|
||||
.labels(labels)
|
||||
.content("test send msg! \\n This is the test data. It is proved that it can be received successfully")
|
||||
.startAt(System.currentTimeMillis())
|
||||
.activeAt(System.currentTimeMillis())
|
||||
.endAt(System.currentTimeMillis())
|
||||
.triggerTimes(4)
|
||||
.annotations(annotations)
|
||||
.status("firing")
|
||||
.build();
|
||||
.labels(labels)
|
||||
.content("test send msg! \\n This is the test data. It is proved that it can be received successfully")
|
||||
.startAt(System.currentTimeMillis())
|
||||
.activeAt(System.currentTimeMillis())
|
||||
.endAt(System.currentTimeMillis())
|
||||
.triggerTimes(4)
|
||||
.annotations(annotations)
|
||||
.status("firing")
|
||||
.build();
|
||||
GroupAlert groupAlert = GroupAlert.builder()
|
||||
.commonLabels(Map.of(CommonConstants.LABEL_ALERT_NAME, "CPU Usage Alert"))
|
||||
.commonAnnotations(annotations)
|
||||
.alerts(List.of(singleAlert1, singleAlert2))
|
||||
.status("firing")
|
||||
.build();
|
||||
.commonLabels(Map.of(CommonConstants.LABEL_ALERT_NAME, "CPU Usage Alert"))
|
||||
.commonAnnotations(annotations)
|
||||
.alerts(List.of(singleAlert1, singleAlert2))
|
||||
.status("firing")
|
||||
.build();
|
||||
return dispatcherAlarm.sendNoticeMsg(noticeReceiver, null, groupAlert);
|
||||
}
|
||||
|
||||
|
||||
+45
@@ -41,7 +41,10 @@ import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -379,4 +382,46 @@ class NoticeConfigServiceTest {
|
||||
assertEquals(1, matched.size());
|
||||
assertEquals(4L, matched.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getReceiverFilterRuleMatchesPeriodContainingNow() {
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
List<NoticeRule> matched = filterWithPeriod(now.minusHours(6), now.plusHours(6));
|
||||
assertEquals(1, matched.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getReceiverFilterRuleFiltersPeriodExcludingNow() {
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
List<NoticeRule> matched = filterWithPeriod(now.plusHours(1), now.plusHours(2));
|
||||
assertEquals(0, matched.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getReceiverFilterRuleMatchesCrossMidnightPeriod() {
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
List<NoticeRule> matched = filterWithPeriod(now.minusHours(1), now.minusHours(2).plusDays(1));
|
||||
assertEquals(1, matched.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getReceiverFilterRuleNormalizesStoredOffsetToServerZone() {
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
List<NoticeRule> matched = filterWithPeriod(
|
||||
now.minusHours(6).withZoneSameInstant(ZoneOffset.ofHours(-7)),
|
||||
now.plusHours(6).withZoneSameInstant(ZoneOffset.ofHours(9)));
|
||||
assertEquals(1, matched.size());
|
||||
}
|
||||
|
||||
private List<NoticeRule> filterWithPeriod(ZonedDateTime periodStart, ZonedDateTime periodEnd) {
|
||||
NoticeRule rule = new NoticeRule();
|
||||
rule.setId(10L);
|
||||
rule.setName("PeriodRule");
|
||||
rule.setFilterAll(true);
|
||||
rule.setPeriodStart(periodStart);
|
||||
rule.setPeriodEnd(periodEnd);
|
||||
CacheFactory.clearNoticeCache();
|
||||
when(noticeRuleDao.findNoticeRulesByEnableTrue()).thenReturn(Collections.singletonList(rule));
|
||||
return noticeConfigService.getReceiverFilterRule(new GroupAlert());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,32 @@
|
||||
|
||||
<build>
|
||||
<finalName>apache-hertzbeat-collector-${hzb.version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${maven-jar-plugin.version}</version>
|
||||
<configuration>
|
||||
<classesDirectory>target/classes/</classesDirectory>
|
||||
<archive>
|
||||
<!--Generated JAR does not include Maven descriptor-related files-->
|
||||
<addMavenDescriptor>false</addMavenDescriptor>
|
||||
<manifest>
|
||||
<!--Project startup class-->
|
||||
<mainClass>org.apache.hertzbeat.collector.Collector</mainClass>
|
||||
<useUniqueVersions>false</useUniqueVersions>
|
||||
<!--Third-party JARs are added to the classpath using maven-dependency-plugin-->
|
||||
<addClasspath>true</addClasspath>
|
||||
<!--Location of external dependency JARs-->
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Class-Path>. config</Class-Path>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
@@ -181,30 +207,6 @@
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${maven-jar-plugin.version}</version>
|
||||
<configuration>
|
||||
<classesDirectory>target/classes/</classesDirectory>
|
||||
<archive>
|
||||
<!--Generated JAR does not include Maven descriptor-related files-->
|
||||
<addMavenDescriptor>false</addMavenDescriptor>
|
||||
<manifest>
|
||||
<!--Project startup class-->
|
||||
<mainClass>org.apache.hertzbeat.collector.Collector</mainClass>
|
||||
<useUniqueVersions>false</useUniqueVersions>
|
||||
<!--Third-party JARs are added to the classpath using maven-dependency-plugin-->
|
||||
<addClasspath>true</addClasspath>
|
||||
<!--Location of external dependency JARs-->
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Class-Path>. config</Class-Path>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
@@ -255,30 +257,6 @@
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${maven-jar-plugin.version}</version>
|
||||
<configuration>
|
||||
<classesDirectory>target/classes/</classesDirectory>
|
||||
<archive>
|
||||
<!--Generated JAR does not include Maven descriptor-related files-->
|
||||
<addMavenDescriptor>false</addMavenDescriptor>
|
||||
<manifest>
|
||||
<!--Project startup class-->
|
||||
<mainClass>org.apache.hertzbeat.collector.Collector</mainClass>
|
||||
<useUniqueVersions>false</useUniqueVersions>
|
||||
<!--Third-party JARs are added to the classpath using maven-dependency-plugin-->
|
||||
<addClasspath>true</addClasspath>
|
||||
<!--Location of external dependency JARs-->
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Class-Path>. config</Class-Path>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
|
||||
+3
@@ -175,6 +175,9 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
|
||||
.setId(job.getMonitorId())
|
||||
.setTenantId(job.getTenantId())
|
||||
.setApp(job.getApp())
|
||||
.setLabels(job.getLabels())
|
||||
.setAnnotations(job.getAnnotations())
|
||||
.addMetadataAll(job.getMetadata())
|
||||
.setMetrics(metricsTime.getMetrics().getName())
|
||||
.setPriority(metricsTime.getMetrics().getPriority())
|
||||
.setTime(System.currentTimeMillis())
|
||||
|
||||
+8
-2
@@ -40,6 +40,7 @@ class BackoffUtilsTest {
|
||||
ExponentialBackoff backoff = new ExponentialBackoff(10L, 100L);
|
||||
boolean shouldContinue = BackoffUtils.shouldContinueAfterBackoff(backoff);
|
||||
assertFalse(shouldContinue);
|
||||
assertTrue(Thread.interrupted());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,9 +61,14 @@ class BackoffUtilsTest {
|
||||
|
||||
boolean shouldContinue = BackoffUtils.shouldContinueAfterBackoff(backoff);
|
||||
|
||||
// read and clear the restored interrupt status before join(),
|
||||
// otherwise join() throws InterruptedException when the
|
||||
// interrupting thread is still alive at this point
|
||||
boolean interrupted = Thread.interrupted();
|
||||
|
||||
interruptingThread.join();
|
||||
|
||||
assertFalse(shouldContinue);
|
||||
assertTrue(Thread.currentThread().isInterrupted());
|
||||
assertTrue(interrupted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -18,6 +18,7 @@
|
||||
package org.apache.hertzbeat.common.entity.ai;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
@@ -61,12 +62,13 @@ public class ChatMessage {
|
||||
private Long id;
|
||||
|
||||
@Schema(title = "conversation id")
|
||||
@Column(name = "conversation_id", insertable = false, updatable = false)
|
||||
@Column(name = "conversation_id")
|
||||
private Long conversationId;
|
||||
|
||||
@JsonIgnore
|
||||
@Schema(title = "conversation", hidden = true)
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "conversation_id")
|
||||
@JoinColumn(name = "conversation_id", insertable = false, updatable = false)
|
||||
private ChatConversation conversation;
|
||||
|
||||
@Schema(title = "message content")
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.common.entity.ai;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests AI conversation message serialization.
|
||||
*/
|
||||
class ChatMessageTest {
|
||||
|
||||
@Test
|
||||
void serializationShouldNotRecurseThroughConversation() {
|
||||
ChatConversation conversation = ChatConversation.builder()
|
||||
.id(1L)
|
||||
.title("序列化测试会话")
|
||||
.build();
|
||||
ChatMessage message = ChatMessage.builder()
|
||||
.id(2L)
|
||||
.conversationId(conversation.getId())
|
||||
.conversation(conversation)
|
||||
.role("assistant")
|
||||
.content("序列化测试消息")
|
||||
.build();
|
||||
conversation.setMessages(List.of(message));
|
||||
|
||||
String json = JsonUtil.toJson(conversation);
|
||||
|
||||
assertNotNull(json);
|
||||
assertFalse(json.contains("\"conversation\""));
|
||||
}
|
||||
}
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.collector.collect.basic.http;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.collector.collect.AbstractCollectE2eTest;
|
||||
import org.apache.hertzbeat.collector.collect.http.HttpCollectImpl;
|
||||
import org.apache.hertzbeat.collector.util.CollectUtil;
|
||||
import org.apache.hertzbeat.common.entity.job.Configmap;
|
||||
import org.apache.hertzbeat.common.entity.job.Job;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.Protocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* E2E test for PrestoDB monitor with HTTP Basic Auth enabled (issue #2838).
|
||||
* Unlike other http monitor tests, the protocol is taken from the template definition
|
||||
* after placeholder replacement (mirroring WheelTimerTask#initJobMetrics), so a metric
|
||||
* whose http section lacks the authorization wiring fails this test with a 401.
|
||||
*/
|
||||
@Slf4j
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class PrestodbMonitorE2eTest extends AbstractCollectE2eTest {
|
||||
|
||||
private static final int MOCK_SERVER_PORT = 52390;
|
||||
private static final String LOCALHOST = "127.0.0.1";
|
||||
private static final String USERNAME = "presto-admin";
|
||||
private static final String PASSWORD = "presto-secret";
|
||||
private static final Gson GSON = new Gson();
|
||||
private static HttpServer mockServer;
|
||||
|
||||
private static final String CLUSTER_JSON = """
|
||||
{"activeWorkers": 3, "runningQueries": 2, "queuedQueries": 1,
|
||||
"blockedQueries": 0, "runningDrivers": 12, "runningTasks": 5}""";
|
||||
|
||||
private static final String NODE_JSON = """
|
||||
[{"uri": "http://127.0.0.1:8080", "recentRequests": 25.3, "recentFailures": 0.0,
|
||||
"recentSuccesses": 25.3, "lastRequestTime": "2026-07-08T10:00:00.000Z",
|
||||
"lastResponseTime": "2026-07-08T10:00:00.100Z", "age": "5.20d", "recentFailureRatio": 0.0}]""";
|
||||
|
||||
private static final String STATUS_JSON = """
|
||||
{"nodeId": "coordinator-1", "nodeVersion": {"version": "0.289"}, "environment": "production",
|
||||
"coordinator": true, "uptime": "5.20d", "externalAddress": "127.0.0.1",
|
||||
"internalAddress": "127.0.0.1", "processors": 8, "processCpuLoad": 0.35,
|
||||
"systemCpuLoad": 0.42, "heapUsed": 1073741824, "heapAvailable": 4294967296, "nonHeapUsed": 268435456}""";
|
||||
|
||||
private static final String TASK_JSON = """
|
||||
[{"taskId": "20260708_100000_00001_abcde.1.0.0", "version": 42, "state": "RUNNING",
|
||||
"self": "http://127.0.0.1:8080/v1/task/20260708_100000_00001_abcde.1.0.0",
|
||||
"lastHeartbeat": "2026-07-08T10:00:00.000Z"}]""";
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
if (mockServer != null) {
|
||||
mockServer.stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
collect = new HttpCollectImpl();
|
||||
|
||||
mockServer = HttpServer.create(new InetSocketAddress(MOCK_SERVER_PORT), 0);
|
||||
mockServer.setExecutor(null);
|
||||
mockServer.start();
|
||||
mockServer.createContext("/v1/cluster", exchange -> sendAuthenticatedJson(exchange, CLUSTER_JSON));
|
||||
mockServer.createContext("/v1/node", exchange -> sendAuthenticatedJson(exchange, NODE_JSON));
|
||||
mockServer.createContext("/v1/status", exchange -> sendAuthenticatedJson(exchange, STATUS_JSON));
|
||||
mockServer.createContext("/v1/task", exchange -> sendAuthenticatedJson(exchange, TASK_JSON));
|
||||
}
|
||||
|
||||
private void sendAuthenticatedJson(HttpExchange exchange, String response) throws IOException {
|
||||
String expected = "Basic " + Base64.getEncoder()
|
||||
.encodeToString((USERNAME + ":" + PASSWORD).getBytes(StandardCharsets.UTF_8));
|
||||
if (!expected.equals(exchange.getRequestHeaders().getFirst("Authorization"))) {
|
||||
exchange.getResponseHeaders().set("WWW-Authenticate", "Basic realm=\"presto\"");
|
||||
exchange.sendResponseHeaders(401, -1);
|
||||
exchange.close();
|
||||
return;
|
||||
}
|
||||
exchange.getResponseHeaders().set("Content-Type", "application/json");
|
||||
final byte[] array = response.getBytes(StandardCharsets.UTF_8);
|
||||
exchange.sendResponseHeaders(200, array.length);
|
||||
try (OutputStream os = exchange.getResponseBody()) {
|
||||
os.write(array);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrestodbMonitorWithBasicAuth() {
|
||||
Job prestodbJob = appService.getAppDefine("prestodb");
|
||||
Map<String, Configmap> configmap = buildParamConfigmap(true);
|
||||
for (Metrics metricsDef : prestodbJob.getMetrics()) {
|
||||
metricsDef = replaceJobPlaceholder(metricsDef, configmap);
|
||||
validateMetricsCollection(metricsDef, metricsDef.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrestodbMonitorWithoutAuthIsRejected() {
|
||||
Job prestodbJob = appService.getAppDefine("prestodb");
|
||||
Map<String, Configmap> configmap = buildParamConfigmap(false);
|
||||
Metrics availabilityMetric = prestodbJob.getMetrics().stream()
|
||||
.filter(m -> "cluster".equals(m.getName()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException("prestodb template has no cluster metric"));
|
||||
availabilityMetric = replaceJobPlaceholder(availabilityMetric, configmap);
|
||||
CollectRep.MetricsData.Builder metricsData = collectMetrics(availabilityMetric);
|
||||
Assertions.assertNotEquals(CollectRep.Code.SUCCESS, metricsData.getCode(),
|
||||
"collection against an auth-protected endpoint must fail when no credentials are configured");
|
||||
}
|
||||
|
||||
private Map<String, Configmap> buildParamConfigmap(boolean withAuth) {
|
||||
Map<String, Configmap> configmap = new HashMap<>();
|
||||
configmap.put("host", new Configmap("host", LOCALHOST, (byte) 1));
|
||||
configmap.put("port", new Configmap("port", String.valueOf(MOCK_SERVER_PORT), (byte) 1));
|
||||
configmap.put("ssl", new Configmap("ssl", "false", (byte) 1));
|
||||
configmap.put("timeout", new Configmap("timeout", "6000", (byte) 1));
|
||||
if (withAuth) {
|
||||
configmap.put("authType", new Configmap("authType", "Basic Auth", (byte) 1));
|
||||
configmap.put("username", new Configmap("username", USERNAME, (byte) 1));
|
||||
configmap.put("password", new Configmap("password", PASSWORD, (byte) 1));
|
||||
}
|
||||
return configmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors WheelTimerTask#initJobMetrics: replace ^_^param^_^ placeholders
|
||||
* in the whole metric definition, keeping the template's http authorization wiring.
|
||||
*/
|
||||
private Metrics replaceJobPlaceholder(Metrics metricsDef, Map<String, Configmap> configmap) {
|
||||
JsonElement jsonElement = GSON.toJsonTree(metricsDef);
|
||||
CollectUtil.replaceSmilingPlaceholder(jsonElement, configmap);
|
||||
return GSON.fromJson(jsonElement, Metrics.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Protocol buildProtocol(Metrics metricsDef) {
|
||||
return metricsDef.getHttp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CollectRep.MetricsData.Builder collectMetrics(Metrics metricsDef) {
|
||||
metrics.setHttp(metricsDef.getHttp());
|
||||
return collectMetricsData(metrics, metricsDef);
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,36 @@ params:
|
||||
ja-JP: HTTPS
|
||||
type: boolean
|
||||
required: true
|
||||
- field: authType
|
||||
name:
|
||||
zh-CN: 认证方式
|
||||
en-US: Auth Type
|
||||
ja-JP: 認証方法
|
||||
type: radio
|
||||
required: false
|
||||
hide: true
|
||||
options:
|
||||
- label: Basic Auth
|
||||
value: Basic Auth
|
||||
- label: Digest Auth
|
||||
value: Digest Auth
|
||||
- field: username
|
||||
name:
|
||||
zh-CN: 用户名
|
||||
en-US: Username
|
||||
ja-JP: ユーザー名
|
||||
type: text
|
||||
limit: 50
|
||||
required: false
|
||||
hide: true
|
||||
- field: password
|
||||
name:
|
||||
zh-CN: 密码
|
||||
en-US: Password
|
||||
ja-JP: パスワード
|
||||
type: password
|
||||
required: false
|
||||
hide: true
|
||||
- field: timeout
|
||||
name:
|
||||
zh-CN: 超时时间(ms)
|
||||
@@ -115,6 +145,12 @@ metrics:
|
||||
timeout: ^_^timeout^_^
|
||||
method: GET
|
||||
ssl: ^_^ssl^_^
|
||||
authorization:
|
||||
type: ^_^authType^_^
|
||||
basicAuthUsername: ^_^username^_^
|
||||
basicAuthPassword: ^_^password^_^
|
||||
digestAuthUsername: ^_^username^_^
|
||||
digestAuthPassword: ^_^password^_^
|
||||
parseType: jsonPath
|
||||
parseScript: '$'
|
||||
|
||||
@@ -182,6 +218,12 @@ metrics:
|
||||
timeout: ^_^timeout^_^
|
||||
method: GET
|
||||
ssl: ^_^ssl^_^
|
||||
authorization:
|
||||
type: ^_^authType^_^
|
||||
basicAuthUsername: ^_^username^_^
|
||||
basicAuthPassword: ^_^password^_^
|
||||
digestAuthUsername: ^_^username^_^
|
||||
digestAuthPassword: ^_^password^_^
|
||||
parseType: jsonPath
|
||||
parseScript: '$[*]'
|
||||
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.startup.dao;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.ai.dao.ChatConversationDao;
|
||||
import org.apache.hertzbeat.ai.dao.ChatMessageDao;
|
||||
import org.apache.hertzbeat.common.entity.ai.ChatConversation;
|
||||
import org.apache.hertzbeat.common.entity.ai.ChatMessage;
|
||||
import org.apache.hertzbeat.startup.AbstractSpringIntegrationTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Tests persistence mapping for AI conversation messages.
|
||||
*/
|
||||
@Transactional
|
||||
class ChatMessageDaoTest extends AbstractSpringIntegrationTest {
|
||||
|
||||
@Resource
|
||||
private ChatConversationDao conversationDao;
|
||||
|
||||
@Resource
|
||||
private ChatMessageDao messageDao;
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Test
|
||||
void saveMessageShouldPersistConversationId() {
|
||||
ChatConversation conversation = conversationDao.saveAndFlush(
|
||||
ChatConversation.builder().title("映射测试会话").build());
|
||||
messageDao.saveAndFlush(ChatMessage.builder()
|
||||
.conversationId(conversation.getId())
|
||||
.role("user")
|
||||
.content("映射测试消息")
|
||||
.build());
|
||||
entityManager.clear();
|
||||
|
||||
List<ChatMessage> messages = messageDao
|
||||
.findByConversationIdOrderByGmtCreateAsc(conversation.getId());
|
||||
|
||||
assertEquals(1, messages.size());
|
||||
assertEquals(conversation.getId(), messages.getFirst().getConversationId());
|
||||
}
|
||||
}
|
||||
@@ -54,8 +54,11 @@ Parameters explanation:
|
||||
- `-e MODE=public`: Set the running mode (public or private), for public cluster or private cloud-edge mode.
|
||||
- `-e MANAGER_HOST=192.168.1.100`: Important! Set the IP address of the main HertzBeat server. Replace with your actual server IP.
|
||||
- `-e MANAGER_PORT=1158`: (Optional) Set the port of the main HertzBeat server, default is 1158.
|
||||
- `-v $(pwd)/ext-lib:/opt/hertzbeat-collector/ext-lib`: (Optional) Mount external JDBC driver jars to the local collector.
|
||||
- `-v $(pwd)/logs:/opt/hertzbeat-collector/logs`: (Optional) Mount the log files to the local host.
|
||||
|
||||
The collector image keeps `/opt/hertzbeat-collector` as a version-independent root path, so `logs` and `ext-lib` mounts remain stable across upgrades.
|
||||
|
||||
## Operating Modes
|
||||
|
||||
HertzBeat Collector supports two operating modes:
|
||||
|
||||
@@ -13,6 +13,10 @@ keywords: [ open source monitoring system, open source database monitoring, pres
|
||||
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Target Host | The IP address, IPv4, IPv6, or domain name of the target to be monitored. Note: ⚠️ Do not include protocol headers (e.g., https://, http://). |
|
||||
| port | Port |
|
||||
| HTTPS | Whether to enable HTTPS for the PrestoDB API endpoint. |
|
||||
| Auth Type | Optional HTTP authentication mode. Supported values are `Basic Auth` and `Digest Auth`. |
|
||||
| Username | Username used when `Basic Auth` or `Digest Auth` is enabled. |
|
||||
| Password | Password used when `Basic Auth` or `Digest Auth` is enabled. |
|
||||
| Task Name | The name identifying this monitor, which must be unique. |
|
||||
| Connection Timeout | Timeout for PrestoDB connection when no response is received, in milliseconds (ms). Default is 6000 ms. |
|
||||
| Collection Interval | Interval for periodic data collection, in seconds. The minimum interval is 30 seconds. |
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
---
|
||||
id: template_marketplace
|
||||
title: Template Marketplace
|
||||
sidebar_label: Template Marketplace
|
||||
---
|
||||
|
||||
> HertzBeat official template marketplace: users can freely upload, download, view, search and share monitoring template files.
|
||||
|
||||
## Basic Functions
|
||||
|
||||
### Search
|
||||
|
||||
💡 Guest availability
|
||||
|
||||
> Display template name, brief description, favorites, downloads, views and other information
|
||||
|
||||
1. **No filter: displayed in order of upload**
|
||||
|
||||

|
||||
|
||||
2. **Filtering by category: currently divided into six categories**
|
||||
|
||||
> **📋Todo:** develop tag function, subdivided within the category, such as database monitoring template can be divided into MySQL, Oracle, etc.
|
||||
|
||||

|
||||
|
||||
3. **Fuzzy search by Title**
|
||||
|
||||

|
||||
|
||||
4. **Hover window function: download the latest version, view details, favorite/un-favorite**
|
||||
|
||||
> Show if the user has favorites after logging in
|
||||
|
||||

|
||||
|
||||
5. **Sort: Eight Sorting Methods**
|
||||
|
||||
> **📋Todo:** Waiting for the actual installation
|
||||
|
||||
### Template Detail
|
||||
|
||||
💡 Guest availability
|
||||
|
||||
> Display basic information about the template, such as name, author, update time, version information, etc.
|
||||
|
||||
1. **Info: Summary information, detailed information and other information**
|
||||
|
||||
> **📋Todo:** Upgrade to MarkDown format
|
||||
|
||||

|
||||
|
||||
2. **Version: Historical version download, sharing and basic information display**
|
||||
|
||||
> **📋Todo:** Set up a view function for each historical version to display information such as the version description.
|
||||
|
||||

|
||||
|
||||
3. **FAQ**
|
||||
|
||||
> **📋Todo:** Discussion or issue Q&A section
|
||||
|
||||

|
||||
|
||||
4. **Download**
|
||||
|
||||
> The latest version can be downloaded directly from the list hover window.
|
||||
> The latest version can also be downloaded directly from the template detail page.
|
||||
> The historical version can be downloaded from the version page.
|
||||
|
||||

|
||||
|
||||
5. **Share**
|
||||
|
||||
> Template details page to share the latest version.
|
||||
> Version page to share historical versions.
|
||||
> Sharing will automatically copy the sharing URL to the clipboard, and the person being shared can download the file via that URL
|
||||
>
|
||||
> **📋Todo:** Shared template detail page is accessed through the URL of the shared template, and the shared person is free to choose whether to download or not.
|
||||
|
||||

|
||||
|
||||
### User Center
|
||||
|
||||
💡 User availability
|
||||
|
||||
> Provide asset management, collection management and upload function
|
||||
>
|
||||
> **📋Todo:** Overview page, notification page, user settings page
|
||||
|
||||
1. **Asset: Manage all templates uploaded by user themselves**
|
||||
|
||||
> Provides the ability to download the latest version and view details
|
||||
>
|
||||
> **📋Todo:** Function to update template information
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
2. **Version Upgrade**
|
||||
|
||||
> The user defines the new version number under this template family, updates the version information, and uploads the latest version of the file
|
||||
|
||||

|
||||
|
||||
3. **Star**
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
4. **Upload**
|
||||
|
||||
> Create a new template series and upload the first version of the file
|
||||
>
|
||||
> Fill in the template name, select the template category, fill in the description information and version information, and upload files
|
||||
|
||||

|
||||
|
||||
### Sign Up & Login
|
||||
|
||||
💡 Guest availability
|
||||
|
||||
1. **Sign up**
|
||||
|
||||
> Usernames can be duplicated, but email addresses are unique
|
||||
>
|
||||
> **📋Todo:** Captcha function, email verification function
|
||||
|
||||

|
||||
|
||||
2. **Login**
|
||||
|
||||
> **📋Todo:** Captcha function and forgot password function
|
||||
|
||||

|
||||
|
||||
## Development Steps
|
||||
|
||||
> Download `template-marketplace/hertzbeat-template-hub` and `template-marketplace/hertzbeat-template-hub-web-app` projects respectively
|
||||
|
||||
The front-end project in accordance with README.md directly start
|
||||
|
||||
The back-end project steps:
|
||||
|
||||
1. Run the `sql` script in the `template-marketplace/hertzbeat-template-hub/sql` to create database tables
|
||||
2. Install MinIO
|
||||
3. Config `MySQL` and `MinIO` in the `application.yml`
|
||||
4. Start the back-end project
|
||||
|
||||
Other issues can be fed back through the communication group ISSUE!
|
||||
@@ -85,6 +85,7 @@ By deploying multiple HertzBeat Collectors, high availability, load balancing, a
|
||||
- `-e MANAGER_HOST=127.0.0.1` : Important, Set the main hertzbeat server ip host, must use the server host instead of 127.0.0.1.
|
||||
- `-e MANAGER_PORT=1158` : (optional) Set the main hertzbeat server port, default 1158.
|
||||
- `-e HERTZBEAT_COLLECTOR_MYSQL_QUERY_ENGINE=auto` : (optional) Override the MySQL-compatible monitoring query path. Supported values: `auto`, `jdbc`, `r2dbc`.
|
||||
- `-v $(pwd)/ext-lib:/opt/hertzbeat-collector/ext-lib` : (optional) Mount external JDBC driver jars to the collector.
|
||||
- `-v $(pwd)/logs:/opt/hertzbeat-collector/logs` : (optional) Mount the log file to the local host to facilitate viewing.
|
||||
- `--name hertzbeat-collector` : Naming container name hertzbeat-collector
|
||||
- `apache/hertzbeat-collector` : Use the [official application mirror](https://hub.docker.com/r/apache/hertzbeat-collector) to start the container, if the network times out, use `quay.io/tancloud/hertzbeat-collector` instead.
|
||||
@@ -95,6 +96,7 @@ By deploying multiple HertzBeat Collectors, high availability, load balancing, a
|
||||
- Marked as optional parameters, non-mandatory items, if not needed, delete them.
|
||||
- The `127.0.0.1` in `MANAGER_HOST` needs to be replaced with the external IP address of the HertzBeat Server.
|
||||
- When mounting files, the first parameter is your custom local file address, and the second parameter is the container file address. Make sure you have this file locally when mounting.
|
||||
- The collector keeps `/opt/hertzbeat-collector` as the stable container root path across upgrades.
|
||||
- You can execute `docker update --restart=always hertzbeat-collector` to configure the container to restart automatically.
|
||||
- If you want to use the host network mode to start Docker, you can use `docker run -d --network host .....`
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ keywords: [ 开源监控系统, 开源数据库监控, Presto数据库监控 ]
|
||||
| 目标Host | 被监控的对端IPV4,IPV6或域名。注意⚠️不带协议头(eg: https://, http://)。 |
|
||||
| 任务名称 | 标识此监控的名称,名称需要保证唯一性。 |
|
||||
| 端口 | 被监控的平台端口。 |
|
||||
| 启用HTTPS | 是否启用 PrestoDB API 的 HTTPS 访问。 |
|
||||
| 认证方式 | 可选的 HTTP 认证方式,支持 `Basic Auth` 和 `Digest Auth`。 |
|
||||
| 用户名 | 启用 `Basic Auth` 或 `Digest Auth` 后使用的用户名。 |
|
||||
| 密码 | 启用 `Basic Auth` 或 `Digest Auth` 后使用的密码。 |
|
||||
| 连接超时时间 | 设置连接PrestoDB未响应数据时的超时时间,单位ms毫秒,默认6000毫秒。 |
|
||||
| 采集间隔 | 监控周期性采集数据间隔时间,单位秒,可设置的最小间隔为30秒。 |
|
||||
| 绑定标签 | 用于对监控资源进行分类管理。 |
|
||||
|
||||
@@ -83,6 +83,7 @@ HertzBeat Collector 是一个轻量级的数据采集器,用于采集并将数
|
||||
- `-e MANAGER_HOST=127.0.0.1` : 重要, 配置连接的 HertzBeat Server 地址,127.0.0.1 需替换为 HertzBeat Server 对外 IP 地址。
|
||||
- `-e MANAGER_PORT=1158` : (可选) 配置连接的 HertzBeat Server 端口,默认 1158.
|
||||
- `-e HERTZBEAT_COLLECTOR_MYSQL_QUERY_ENGINE=auto` : (可选) 覆盖 MySQL 兼容监控查询链路。可选值:`auto`、`jdbc`、`r2dbc`。
|
||||
- `-v $(pwd)/ext-lib:/opt/hertzbeat-collector/ext-lib` : (可选) 挂载外部 JDBC 驱动到采集器。
|
||||
- `-v $(pwd)/logs:/opt/hertzbeat-collector/logs` : (可选)挂载日志文件到本地主机方便查看
|
||||
- `--name hertzbeat-collector` : 命名容器名称为 hertzbeat-collector
|
||||
- `apache/hertzbeat-collector` : 使用[官方应用镜像](https://hub.docker.com/r/apache/hertzbeat-collector)来启动容器, 若网络超时可用`quay.io/tancloud/hertzbeat-collector`代替。
|
||||
@@ -92,6 +93,7 @@ HertzBeat Collector 是一个轻量级的数据采集器,用于采集并将数
|
||||
- `MANAGER_HOST=127.0.0.1` 中的 `127.0.0.1` 需被替换为 HertzBeat Server 对外 IP 地址。
|
||||
- 标记为可选的参数,非必填项,若不需要则删除。
|
||||
- 挂载文件时,前面参数为你自定义本地文件地址,后面参数为容器内文件地址。挂载时请确保你本地已有此文件。
|
||||
- 采集器容器会将 `/opt/hertzbeat-collector` 保持为稳定根路径,升级版本时无需调整 `logs` 和 `ext-lib` 的挂载目标。
|
||||
- 可执行```docker update --restart=always hertzbeat-collector```配置容器自动重启。
|
||||
|
||||
:::
|
||||
|
||||
@@ -35,7 +35,8 @@ DEPLOY_DIR=`pwd`
|
||||
CONF_DIR=$DEPLOY_DIR/config
|
||||
MAIN_CLASS="org.apache.hertzbeat.collector.Collector"
|
||||
EXT_LIB_PATH="$DEPLOY_DIR/ext-lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$EXT_LIB_PATH/*"
|
||||
LIB_PATH="$DEPLOY_DIR/lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$LIB_PATH/*:$EXT_LIB_PATH/*"
|
||||
# log dir
|
||||
LOGS_DIR=$DEPLOY_DIR/logs
|
||||
# create logs dir when not exist
|
||||
|
||||
@@ -44,7 +44,8 @@ for /f "tokens=1-5" %%i in ('netstat -ano^|findstr "0.0.0.0:%SERVER_PORT%"') do
|
||||
set MAIN_CLASS=org.apache.hertzbeat.collector.Collector
|
||||
set LOGS_DIR=%DEPLOY_DIR%\logs
|
||||
set EXT_LIB_PATH=%DEPLOY_DIR%\ext-lib
|
||||
set CLASSPATH=%DEPLOY_DIR%\%JAR_NAME%;%EXT_LIB_PATH%\*
|
||||
set LIB_PATH=%DEPLOY_DIR%\lib
|
||||
set CLASSPATH=%DEPLOY_DIR%\%JAR_NAME%;%LIB_PATH%\*;%EXT_LIB_PATH%\*
|
||||
|
||||
if not exist %LOGS_DIR% (
|
||||
mkdir %LOGS_DIR%
|
||||
|
||||
@@ -73,7 +73,8 @@ if [ -n "$SERVER_PORT" ]; then
|
||||
fi
|
||||
MAIN_CLASS="org.apache.hertzbeat.collector.Collector"
|
||||
EXT_LIB_PATH="$DEPLOY_DIR/ext-lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$EXT_LIB_PATH/*"
|
||||
LIB_PATH="$DEPLOY_DIR/lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$LIB_PATH/*:$EXT_LIB_PATH/*"
|
||||
# log dir
|
||||
LOGS_DIR=$DEPLOY_DIR/logs
|
||||
# create logs dir when not exist
|
||||
|
||||
@@ -37,7 +37,8 @@ DEPLOY_DIR=`pwd`
|
||||
CONF_DIR=$DEPLOY_DIR/config
|
||||
MAIN_CLASS="org.apache.hertzbeat.startup.HertzBeatApplication"
|
||||
EXT_LIB_PATH="$DEPLOY_DIR/ext-lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$EXT_LIB_PATH/*"
|
||||
LIB_PATH="$DEPLOY_DIR/lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$LIB_PATH/*:$EXT_LIB_PATH/*"
|
||||
# log dir
|
||||
LOGS_DIR=$DEPLOY_DIR/logs
|
||||
# create logs dir when not exist
|
||||
|
||||
@@ -44,7 +44,8 @@ for /f "tokens=1-5" %%i in ('netstat -ano^|findstr "0.0.0.0:%SERVER_PORT%"') do
|
||||
set MAIN_CLASS=org.apache.hertzbeat.startup.HertzBeatApplication
|
||||
set LOGS_DIR=%DEPLOY_DIR%\logs
|
||||
set EXT_LIB_PATH=%DEPLOY_DIR%\ext-lib
|
||||
set CLASSPATH=%DEPLOY_DIR%\%JAR_NAME%;%EXT_LIB_PATH%\*
|
||||
set LIB_PATH=%DEPLOY_DIR%\lib
|
||||
set CLASSPATH=%DEPLOY_DIR%\%JAR_NAME%;%LIB_PATH%\*;%EXT_LIB_PATH%\*
|
||||
|
||||
if not exist %LOGS_DIR% (
|
||||
mkdir %LOGS_DIR%
|
||||
|
||||
@@ -75,7 +75,8 @@ if [ -n "$SERVER_PORT" ]; then
|
||||
fi
|
||||
MAIN_CLASS="org.apache.hertzbeat.startup.HertzBeatApplication"
|
||||
EXT_LIB_PATH="$DEPLOY_DIR/ext-lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$EXT_LIB_PATH/*"
|
||||
LIB_PATH="$DEPLOY_DIR/lib"
|
||||
CLASSPATH="$DEPLOY_DIR/$JAR_NAME:$LIB_PATH/*:$EXT_LIB_PATH/*"
|
||||
# log dir
|
||||
LOGS_DIR=$DEPLOY_DIR/logs
|
||||
# create logs dir when not exist
|
||||
|
||||
@@ -17,21 +17,21 @@
|
||||
|
||||
FROM eclipse-temurin:25-jdk
|
||||
|
||||
MAINTAINER Apache HertzBeat "dev@hertzbeat.apache.org"
|
||||
|
||||
ARG VERSION
|
||||
LABEL maintainer="Apache HertzBeat <dev@hertzbeat.apache.org>"
|
||||
|
||||
# Install SSH
|
||||
RUN sed -i 's#http://#https://#g' /etc/apt/sources.list.d/ubuntu.sources && \
|
||||
apt-get update && apt-get install -y openssh-server
|
||||
RUN mkdir -p /var/run/sshd
|
||||
|
||||
ADD apache-hertzbeat-collector-${VERSION}-bin.tar.gz /opt/
|
||||
ADD apache-hertzbeat-collector-[0-9]*-bin.tar.gz /opt/
|
||||
|
||||
RUN mv /opt/apache-hertzbeat-collector-[0-9]*-bin /opt/hertzbeat-collector
|
||||
|
||||
ENV JAVA_OPTS ""
|
||||
ENV TZ=Asia/Shanghai
|
||||
ENV LANG=en_US.UTF-8
|
||||
|
||||
WORKDIR /opt/apache-hertzbeat-collector-${VERSION}-bin/
|
||||
WORKDIR /opt/hertzbeat-collector/
|
||||
|
||||
ENTRYPOINT ["./bin/entrypoint.sh"]
|
||||
|
||||
@@ -38,17 +38,17 @@ fi
|
||||
# docker compile context
|
||||
CONTEXT_DIR=`pwd`
|
||||
|
||||
COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t apache/hertzbeat-collector:$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" --push"
|
||||
COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t apache/hertzbeat-collector:$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --push"
|
||||
|
||||
#COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t apache/hertzbeat-collector:latest -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" --push"
|
||||
#COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t apache/hertzbeat-collector:latest -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --push"
|
||||
|
||||
#COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t quay.io/tancloud/hertzbeat-collector:$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" --push"
|
||||
#COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t quay.io/tancloud/hertzbeat-collector:$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --push"
|
||||
|
||||
#COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t quay.io/tancloud/hertzbeat-collector:latest -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" --push"
|
||||
#COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t quay.io/tancloud/hertzbeat-collector:latest -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --push"
|
||||
|
||||
# Build Local
|
||||
|
||||
#COMMAND="docker build -t apache/hertzbeat-collector:$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" "
|
||||
#COMMAND="docker build -t apache/hertzbeat-collector:$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR"
|
||||
|
||||
echo "$COMMAND"
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,42 +0,0 @@
|
||||
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||
|
||||
# Compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
/bazel-out
|
||||
|
||||
# Node
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# IDEs and editors
|
||||
.idea/
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# Miscellaneous
|
||||
/.angular/cache
|
||||
.sass-cache/
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
module.exports = {
|
||||
singleQuote: true,
|
||||
useTabs: false,
|
||||
printWidth: 140,
|
||||
tabWidth: 2,
|
||||
semi: true,
|
||||
htmlWhitespaceSensitivity: 'strict',
|
||||
arrowParens: 'avoid',
|
||||
bracketSpacing: true,
|
||||
proseWrap: 'preserve',
|
||||
trailingComma: 'none',
|
||||
endOfLine: 'lf'
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
# HertzBeat Template Hub Web App
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.2.5.
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
||||
@@ -1,186 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"hertzbeat-template-hub-web-app": {
|
||||
"projectType": "application",
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "css"
|
||||
},
|
||||
"@schematics/angular:application": {
|
||||
"strict": true
|
||||
}
|
||||
},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"preserveSymlinks": true,
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
],
|
||||
"assets": [
|
||||
"src/assets",
|
||||
"src/favicon.ico",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
|
||||
"output": "/assets/"
|
||||
},
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "node_modules/monaco-editor/min/vs",
|
||||
"output": "/assets/vs/"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css",
|
||||
"node_modules/ng-zorro-antd/ng-zorro-antd.min.css",
|
||||
"node_modules/slick-carousel/slick/slick.scss",
|
||||
"node_modules/slick-carousel/slick/slick-theme.scss"
|
||||
],
|
||||
"scripts": [
|
||||
"node_modules/jquery/dist/jquery.min.js",
|
||||
"node_modules/slick-carousel/slick/slick.min.js"
|
||||
],
|
||||
"allowedCommonJsDependencies": [
|
||||
"ajv",
|
||||
"ajv-formats",
|
||||
"mockjs",
|
||||
"date-fns",
|
||||
"file-saver",
|
||||
"extend"
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"node_modules/"
|
||||
]
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"extractLicenses": false,
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all",
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "6mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"proxyConfig": "proxy.conf.json",
|
||||
"buildTarget": "hertzbeat-template-hub-web-app:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "hertzbeat-template-hub-web-app:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "hertzbeat-template-hub-web-app:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "hertzbeat-template-hub-web-app:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"assets": [
|
||||
"src/assets",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "hertzbeat-template-hub-web-app:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "hertzbeat-template-hub-web-app:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"packageManager": "yarn",
|
||||
"schematicCollections": [
|
||||
"@schematics/angular",
|
||||
"hertzbeat-template-hub-web-app"
|
||||
],
|
||||
"analytics": false
|
||||
},
|
||||
"schematics": {
|
||||
"@angular-eslint/schematics:application": {
|
||||
"setParserOptionsProject": true
|
||||
},
|
||||
"@angular-eslint/schematics:library": {
|
||||
"setParserOptionsProject": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/ng-alain/schema.json",
|
||||
"theme": {
|
||||
"list": [
|
||||
{
|
||||
"theme": "dark"
|
||||
},
|
||||
{
|
||||
"theme": "compact"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
{
|
||||
"name": "hertzbeat-template-hub-web-app",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^18.2.5",
|
||||
"@angular/common": "^18.2.0",
|
||||
"@angular/compiler": "^18.2.0",
|
||||
"@angular/core": "^18.2.5",
|
||||
"@angular/forms": "^18.2.0",
|
||||
"@angular/platform-browser": "^18.2.0",
|
||||
"@angular/platform-browser-dynamic": "^18.2.0",
|
||||
"@angular/router": "^18.2.0",
|
||||
"@delon/abc": "^18.1.0",
|
||||
"@delon/cache": "^18.1.0",
|
||||
"@delon/form": "^18.1.0",
|
||||
"@delon/theme": "^18.1.0",
|
||||
"@delon/util": "^18.1.0",
|
||||
"ajv": "^8.17.1",
|
||||
"ajv-formats": "^3.0.1",
|
||||
"angular-tag-cloud-module": "^17.0.1",
|
||||
"echarts": "^5.5.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"jquery": "^3.7.1",
|
||||
"ng-zorro-antd": "^18.1.1",
|
||||
"ngx-color-picker": "^17.0.0",
|
||||
"ngx-echarts": "^18.0.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"screenfull": "^6.0.2",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"tslib": "^2.7.0",
|
||||
"zone.js": "~0.14.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^18.2.5",
|
||||
"@angular/cli": "^18.2.5",
|
||||
"@angular/compiler-cli": "^18.2.0",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"@types/node": "^22.7.7",
|
||||
"jasmine-core": "~5.2.0",
|
||||
"jasmine-spec-reporter": "^7.0.0",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.0",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.1.0",
|
||||
"ng-alain": "^18.1.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"prettier": "^3.3.3",
|
||||
"purgecss": "^6.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "~5.5.2"
|
||||
},
|
||||
"description": "This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.2.5.",
|
||||
"main": "index.js",
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"/api/*": {
|
||||
"target": "http://localhost:8080/api",
|
||||
"secure": false,
|
||||
"changeOrigin": true,
|
||||
"logLevel": "debug"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1,20 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {RouterOutlet} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterOutlet
|
||||
]
|
||||
})
|
||||
|
||||
export class AppComponent implements OnInit {
|
||||
title = 'hertzbeat-template-hub-web-app';
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {ApplicationConfig, importProvidersFrom, provideZoneChangeDetection} from '@angular/core';
|
||||
import {provideRouter} from '@angular/router';
|
||||
|
||||
import {routes} from './routes/routes-routing.module';
|
||||
import {HTTP_INTERCEPTORS, HttpClientModule} from "@angular/common/http";
|
||||
import {DefaultInterceptor} from "@core";
|
||||
import {provideAnimations} from "@angular/platform-browser/animations";
|
||||
import {TemplateService} from "./service/template.service";
|
||||
import {LocalStorageService} from "./service/local-storage.service";
|
||||
import {DataService} from "./service/data.service";
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideZoneChangeDetection({eventCoalescing: true}),
|
||||
provideRouter(routes),
|
||||
provideAnimations(),
|
||||
importProvidersFrom(HttpClientModule),
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: DefaultInterceptor,
|
||||
multi: true,
|
||||
},
|
||||
TemplateService,
|
||||
LocalStorageService,
|
||||
DataService
|
||||
]
|
||||
};
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {NgModule} from '@angular/core';
|
||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {NzMessageModule} from 'ng-zorro-antd/message';
|
||||
import {NzNotificationModule} from 'ng-zorro-antd/notification';
|
||||
import {AppComponent} from "./app.component";
|
||||
import {RouterOutlet} from "@angular/router";
|
||||
import {NgxEchartsModule} from "ngx-echarts";
|
||||
import {GlobalConfigModule} from "./global-config.module";
|
||||
import {CoreModule} from "./core/core.module";
|
||||
import {NzIconModule} from "ng-zorro-antd/icon";
|
||||
|
||||
// const INTERCEPTOR_PROVIDES = [{ provide: HTTP_INTERCEPTORS, useClass: DefaultInterceptor, multi: true }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
NzMessageModule,
|
||||
NzNotificationModule,
|
||||
RouterOutlet,
|
||||
AppComponent,
|
||||
ReactiveFormsModule,
|
||||
CoreModule,
|
||||
NzIconModule,
|
||||
GlobalConfigModule.forRoot(),
|
||||
NgxEchartsModule.forRoot({
|
||||
echarts: () => import((`echarts`))
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { NgModule, Optional, SkipSelf } from '@angular/core';
|
||||
|
||||
import { throwIfAlreadyLoaded } from './module-import-guard';
|
||||
|
||||
@NgModule({
|
||||
providers: []
|
||||
})
|
||||
export class CoreModule {
|
||||
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
|
||||
throwIfAlreadyLoaded(parentModule, 'CoreModule');
|
||||
}
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
|
||||
import {NzNotificationService} from 'ng-zorro-antd/notification';
|
||||
import {Observable} from 'rxjs';
|
||||
|
||||
import {LocalStorageService} from '../../service/local-storage.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DetectAuthGuard implements CanActivate {
|
||||
constructor(
|
||||
private localStorageSvc: LocalStorageService,
|
||||
private notifySvc: NzNotificationService,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
||||
let activate = this.localStorageSvc.hasAuthorizationToken();
|
||||
if (!activate) {
|
||||
setTimeout(() => {
|
||||
this.notifySvc.warning('登录', '');
|
||||
this.router.navigateByUrl('/passport/login');
|
||||
});
|
||||
}
|
||||
return activate;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export * from './module-import-guard';
|
||||
export * from './interceptor/default.interceptor';
|
||||
-223
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
HttpErrorResponse,
|
||||
HttpEvent,
|
||||
HttpHandler,
|
||||
HttpHeaders,
|
||||
HttpInterceptor,
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
HttpResponseBase
|
||||
} from '@angular/common/http';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { ALAIN_I18N_TOKEN, _HttpClient } from '@delon/theme';
|
||||
import { environment } from '@env/environment';
|
||||
import { NzNotificationService } from 'ng-zorro-antd/notification';
|
||||
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, filter, mergeMap, switchMap, take } from 'rxjs/operators';
|
||||
|
||||
import {Message} from "../../pojo/Message";
|
||||
import {AuthService} from '../../service/auth.service';
|
||||
import {LocalStorageService} from '../../service/local-storage.service';
|
||||
|
||||
const CODE_MESSAGE: { [key: number]: string } = {
|
||||
400: 'Request Illegal Content, No Response.',
|
||||
401: 'Auth Error.',
|
||||
403: 'No Permission For This Request.',
|
||||
404: 'Not Found.',
|
||||
406: 'Request Illegal Content.',
|
||||
409: 'Request Conflict.',
|
||||
410: 'Request Resource Already Deleted.',
|
||||
422: 'Validate Error.',
|
||||
500: 'Server Error Happen.',
|
||||
502: 'Gateway Error.',
|
||||
503: 'Service Not Available, Try After.',
|
||||
504: 'Gateway Timeout.'
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class DefaultInterceptor implements HttpInterceptor {
|
||||
private notified = false;
|
||||
// Whether token is refreshing
|
||||
private refreshToking = false;
|
||||
private refreshToken$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
|
||||
|
||||
constructor(private injector: Injector, private authSvc: AuthService, private storageSvc: LocalStorageService) {}
|
||||
|
||||
private get notification(): NzNotificationService {
|
||||
return this.injector.get(NzNotificationService);
|
||||
}
|
||||
|
||||
private get http(): _HttpClient {
|
||||
return this.injector.get(_HttpClient);
|
||||
}
|
||||
|
||||
private goTo(url: string): void {
|
||||
setTimeout(() => {
|
||||
this.injector.get(Router).navigateByUrl(url);
|
||||
this.notified = false;
|
||||
});
|
||||
}
|
||||
|
||||
private checkStatus(ev: HttpResponseBase): void {
|
||||
const errorText = CODE_MESSAGE[ev.status] || ev.statusText;
|
||||
console.warn(` ${ev.status}: ${ev.url}`, errorText);
|
||||
if (ev.status == 403) {
|
||||
this.notification.error(` ${ev.status}: ${errorText}`, '');
|
||||
} else {
|
||||
this.notification.error(` ${ev.status}: ${ev.url}`, errorText);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* refresh Token request
|
||||
*/
|
||||
private refreshTokenRequest(): Observable<Message<any>> {
|
||||
const refreshToken = this.storageSvc.getRefreshToken();
|
||||
if (refreshToken == null) {
|
||||
return throwError('refreshToken is null.');
|
||||
}
|
||||
return this.authSvc.refreshToken(refreshToken);
|
||||
}
|
||||
|
||||
private tryRefreshToken(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
|
||||
// 1, redirect to login page if this request is used for refreshing token
|
||||
if ([`/api/auth/refresh`].some(url => req.url.includes(url))) {
|
||||
this.toLogin();
|
||||
return throwError(ev);
|
||||
}
|
||||
// 2, if `refreshToking` is true, means that the refreshing token request is in progress
|
||||
// All requests will be suspended and wait for the refreshing token request to complete
|
||||
if (this.refreshToking) {
|
||||
return this.refreshToken$.pipe(
|
||||
filter(v => !!v),
|
||||
take(1),
|
||||
switchMap(() => next.handle(this.reAttachToken(req)))
|
||||
);
|
||||
}
|
||||
// 3、try refreshing Token
|
||||
this.refreshToking = true;
|
||||
this.refreshToken$.next(null);
|
||||
return this.refreshTokenRequest().pipe(
|
||||
switchMap(res => {
|
||||
// Check whether the TOKEN is correct
|
||||
this.refreshToking = false;
|
||||
if (res.code === 0 && res.data != undefined) {
|
||||
let token = res.data.token;
|
||||
let refreshToken = res.data.refreshToken;
|
||||
if (token != undefined) {
|
||||
this.storageSvc.storageAuthorizationToken(token);
|
||||
this.storageSvc.storageRefreshToken(refreshToken);
|
||||
// notifies subsequent requests to continue
|
||||
this.refreshToken$.next(token);
|
||||
return next.handle(this.reAttachToken(req));
|
||||
} else {
|
||||
console.warn(`flush new token failed. ${res.msg}`);
|
||||
return throwError('flush new token failed.');
|
||||
}
|
||||
} else {
|
||||
console.warn(`flush new token failed. ${res.msg}`);
|
||||
return throwError('flush new token failed.');
|
||||
}
|
||||
}),
|
||||
catchError(err => {
|
||||
// refreshing token is failed, redirect to login page
|
||||
console.warn(`flush new token failed. ${err.msg}`);
|
||||
this.refreshToking = false;
|
||||
this.toLogin();
|
||||
return throwError(err);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private reAttachToken(req: HttpRequest<any>): HttpRequest<any> {
|
||||
let token = this.storageSvc.getAuthorizationToken();
|
||||
return req.clone({
|
||||
setHeaders: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private toLogin(): void {
|
||||
if (!this.notified) {
|
||||
this.notified = true;
|
||||
this.goTo('/login');
|
||||
}
|
||||
}
|
||||
|
||||
private fillHeaders(headers?: HttpHeaders): { [name: string]: string } {
|
||||
const res: { [name: string]: string } = {};
|
||||
const lang = this.injector.get(ALAIN_I18N_TOKEN).currentLang;
|
||||
if (!headers?.has('Accept-Language') && lang) {
|
||||
res['Accept-Language'] = lang;
|
||||
}
|
||||
let token = this.storageSvc.getAuthorizationToken();
|
||||
if (token !== null) {
|
||||
res['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
let url = req.url;
|
||||
if (!url.startsWith('https://') && !url.startsWith('http://') && !url.startsWith('.')) {
|
||||
const { baseUrl } = environment.api;
|
||||
url = baseUrl + (baseUrl?.endsWith('/') && url.startsWith('/') ? url.substring(1) : url);
|
||||
}
|
||||
const newReq = req.clone({ url, setHeaders: this.fillHeaders(req.headers) });
|
||||
return next.handle(newReq).pipe(
|
||||
mergeMap(httpEvent => {
|
||||
if (httpEvent instanceof HttpResponseBase) {
|
||||
return of(httpEvent);
|
||||
} else {
|
||||
return of(httpEvent);
|
||||
}
|
||||
}),
|
||||
catchError((err: any) => {
|
||||
console.error("err:",err);
|
||||
// handle failed response and token expired
|
||||
switch (err.status) {
|
||||
case 401:
|
||||
console.log('检测到401了')
|
||||
return this.tryRefreshToken(err, newReq, next);
|
||||
case 404:
|
||||
case 500:
|
||||
this.goTo(`/exception/${err.status}?url=${req.urlWithParams}`);
|
||||
break;
|
||||
case 400:
|
||||
let resp = new HttpResponse({
|
||||
body: err.error,
|
||||
headers: err.headers,
|
||||
status: err.status,
|
||||
statusText: err.statusText
|
||||
});
|
||||
return of(resp);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.checkStatus(err);
|
||||
return throwError(err.error);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export function throwIfAlreadyLoaded(parentModule: any, moduleName: string): void {
|
||||
if (parentModule) {
|
||||
throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
||||
import { DelonACLModule } from '@delon/acl';
|
||||
import { AlainThemeModule } from '@delon/theme';
|
||||
|
||||
import { throwIfAlreadyLoaded } from '@core';
|
||||
|
||||
import { environment } from '@env/environment';
|
||||
|
||||
const alainModules: any[] = [AlainThemeModule.forRoot(), DelonACLModule];
|
||||
import { NzConfig, NZ_CONFIG } from 'ng-zorro-antd/core/config';
|
||||
|
||||
const ngZorroConfig: NzConfig = {};
|
||||
|
||||
const zorroProvides = [{ provide: NZ_CONFIG, useValue: ngZorroConfig }];
|
||||
|
||||
@NgModule({
|
||||
imports: [...alainModules, ...(environment.modules || [])]
|
||||
})
|
||||
export class GlobalConfigModule {
|
||||
constructor(@Optional() @SkipSelf() parentModule: GlobalConfigModule) {
|
||||
throwIfAlreadyLoaded(parentModule, 'GlobalConfigModule');
|
||||
}
|
||||
|
||||
static forRoot(): ModuleWithProviders<GlobalConfigModule> {
|
||||
return {
|
||||
ngModule: GlobalConfigModule,
|
||||
providers: [...zorroProvides]
|
||||
};
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'layout-blank',
|
||||
template: `<router-outlet></router-outlet> `,
|
||||
host: {
|
||||
'[class.alain-blank]': 'true'
|
||||
}
|
||||
})
|
||||
export class LayoutBlankComponent {}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GlobalFooterModule } from '@delon/abc/global-footer';
|
||||
import { NoticeIconModule } from '@delon/abc/notice-icon';
|
||||
import { AlainThemeModule } from '@delon/theme';
|
||||
import { LayoutDefaultModule } from '@delon/theme/layout-default';
|
||||
import { SettingDrawerModule } from '@delon/theme/setting-drawer';
|
||||
import { ThemeBtnModule } from '@delon/theme/theme-btn';
|
||||
import { NzAutocompleteModule } from 'ng-zorro-antd/auto-complete';
|
||||
import { NzAvatarModule } from 'ng-zorro-antd/avatar';
|
||||
import { NzBadgeModule } from 'ng-zorro-antd/badge';
|
||||
import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
|
||||
import { NzFormModule } from 'ng-zorro-antd/form';
|
||||
import { NzGridModule } from 'ng-zorro-antd/grid';
|
||||
import { NzIconModule } from 'ng-zorro-antd/icon';
|
||||
import { NzInputModule } from 'ng-zorro-antd/input';
|
||||
import { NzSpinModule } from 'ng-zorro-antd/spin';
|
||||
|
||||
import { LayoutMarketComponent } from './market/market.component';
|
||||
import { LayoutBlankComponent } from './blank/blank.component';
|
||||
|
||||
const COMPONENTS = [LayoutBlankComponent];
|
||||
|
||||
const MARKET = [LayoutMarketComponent];
|
||||
|
||||
import { NzModalModule } from 'ng-zorro-antd/modal';
|
||||
import { NzTagModule } from 'ng-zorro-antd/tag';
|
||||
import { NzDividerModule } from 'ng-zorro-antd/divider';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
RouterModule,
|
||||
AlainThemeModule.forChild(),
|
||||
ThemeBtnModule,
|
||||
SettingDrawerModule,
|
||||
LayoutDefaultModule,
|
||||
NoticeIconModule,
|
||||
GlobalFooterModule,
|
||||
NzDropDownModule,
|
||||
NzInputModule,
|
||||
NzAutocompleteModule,
|
||||
NzGridModule,
|
||||
NzFormModule,
|
||||
NzSpinModule,
|
||||
NzBadgeModule,
|
||||
NzAvatarModule,
|
||||
NzIconModule,
|
||||
NzModalModule,
|
||||
NzTagModule,
|
||||
NzDividerModule,
|
||||
RouterModule,
|
||||
MARKET
|
||||
],
|
||||
declarations: [...COMPONENTS],
|
||||
exports: [...COMPONENTS, ...MARKET,RouterModule]
|
||||
})
|
||||
export class LayoutModule {}
|
||||
-227
@@ -1,227 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
<header class="tp-header-height" style="height: 151px;">
|
||||
<div class="tp-header-top__area theme-bg tp-header-top__space">
|
||||
<div class="container container-large">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-xxl-4 col-xl-4 col-lg-6 col-md-6 col-sm-6">
|
||||
<div class="tp-header-top__left-box text-center text-md-start">
|
||||
<img src="assets/svg/hand.svg" alt="">
|
||||
<span>Welcome to HertzBeat 监控模版市场!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xxl-4 col-xl-5 d-xl-block">
|
||||
<div class="tp-header-top__shop-box text-xl-start text-end">
|
||||
<span>目前共有{{ count }}个模版</span>
|
||||
<a href="#">搜索!</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="header-sticky" class="tp-header__area">
|
||||
<div class="container container-large">
|
||||
<div class="row align-items-center">
|
||||
<!--logo-->
|
||||
<div class="col-xl-3 col-lg-6 col-md-6 col-sm-6 col-6">
|
||||
<div class="tp-header__left-box d-flex align-items-center">
|
||||
<div class="tp-header__logo">
|
||||
<a href="/home-page">
|
||||
<img src="../../../assets/svg/brand.svg" alt="">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-7 d-none d-xl-block">
|
||||
<div class="tp-header__main-menu">
|
||||
<nav class="tp-main-menu-content">
|
||||
<ul>
|
||||
<li class="has-dropdown">
|
||||
<a href="/home-page">主页</a>
|
||||
</li>
|
||||
<li class="has-dropdown">
|
||||
<a href="market/list">市场</a>
|
||||
</li>
|
||||
<li class="has-dropdown">
|
||||
<a href="https://hertzbeat.apache.org/zh-cn/" target="_blank">社区</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript:">about</a>
|
||||
</li>
|
||||
<li class="has-dropdown">
|
||||
<a href="javascript:" target="_blank">其他</a>
|
||||
<ul class="submenu tp-submenu">
|
||||
<li><a href="javascript:" target="_blank">博客</a></li>
|
||||
<li><a href="javascript:" target="_blank">xxx</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-2 col-lg-6 col-md-6 col-sm-6 col-6">
|
||||
<div class="tp-header__right-box d-flex align-items-center justify-content-end">
|
||||
<ul class="d-none d-sm-block">
|
||||
<li>
|
||||
<div class="tp-header__icon-box">
|
||||
<a href="user-center/assets" *ngIf="isLogin">
|
||||
<span class="p-relative">
|
||||
<span class="material-symbols-outlined" style="color: #000000">person</span>
|
||||
</span>
|
||||
</a>
|
||||
<a href="user-center/star" *ngIf="isLogin">
|
||||
<span class="p-relative">
|
||||
<span class="material-symbols-outlined" style="color: #000000">star</span>
|
||||
</span>
|
||||
</a>
|
||||
<a href="javascript:">
|
||||
<span class="p-relative">
|
||||
<span class="material-symbols-outlined" style="color: #000000">translate</span>
|
||||
</span>
|
||||
</a>
|
||||
<a href="/home-page" *ngIf="isLogin" (click)="logout()">
|
||||
<span class="p-relative">
|
||||
<span class="material-symbols-outlined" style="color: #000000">logout</span>
|
||||
</span>
|
||||
</a>
|
||||
<a href="/login" *ngIf="!isLogin">
|
||||
<span class="p-relative">
|
||||
<span class="material-symbols-outlined" style="color: #000000">login</span>
|
||||
</span>
|
||||
</a>
|
||||
<a href="/sign-up" *ngIf="!isLogin">
|
||||
<span class="p-relative">
|
||||
<span class="material-symbols-outlined" style="color: #000000">person_add</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<router-outlet></router-outlet>
|
||||
<footer>
|
||||
<div class="tp-footer__area p-relative grey-bg pb-5" style="padding-top: 45px;">
|
||||
<div class="container">
|
||||
<div class="row" style="width: 1400px;">
|
||||
<div class="col-xl-4 col-lg-6 col-md-6 mb-5 wow tpfadeUp" data-wow-duration=".9s" data-wow-delay=".3s">
|
||||
<div class="tp-footer__widget z-index footer-col-1">
|
||||
<div class="tp-footer__logo">
|
||||
<a href="home-page">
|
||||
<img src="../../../assets/svg/brand.svg" alt="">
|
||||
</a>
|
||||
</div>
|
||||
<div class="tp-footer__text">
|
||||
<p>开源实时观测系统</p>
|
||||
</div>
|
||||
<div class="tp-footer__contact-list">
|
||||
<div class="tp-footer__contact-item pb-5 d-flex about-items-center">
|
||||
<div class="tp-footer__icon">
|
||||
<img src="assets/svg/github.svg" alt="">
|
||||
</div>
|
||||
<div class="tp-footer__text">
|
||||
<a href="https://github.com/apache/hertzbeat"> Github </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-footer__contact-item d-flex about-items-center">
|
||||
<div class="tp-footer__icon">
|
||||
<span>
|
||||
<img src="assets/svg/email.svg" alt="">
|
||||
</span>
|
||||
</div>
|
||||
<div class="tp-footer__text">
|
||||
<a href="邮箱地址"> 邮箱@163.com </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-6 col-md-6 mb-5 wow tpfadeUp" data-wow-duration=".9s" data-wow-delay=".5s">
|
||||
<div class="tp-footer__widget footer-col-2">
|
||||
<h4 class="tp-footer__widget-title">导航</h4>
|
||||
<div class="tp-footer__list">
|
||||
<ul>
|
||||
<li><a href="page-home">首页</a></li>
|
||||
<li><a href="#">社区</a></li>
|
||||
<li><a href="#">市场</a></li>
|
||||
<li><a href="#">About</a></li>
|
||||
<li><a href="#">其他</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-6 col-md-6 mb-5 wow tpfadeUp" data-wow-duration=".9s" data-wow-delay=".7s">
|
||||
<div class="tp-footer__widget footer-col-3">
|
||||
<h4 class="tp-footer__widget-title">相关资源</h4>
|
||||
<div class="tp-footer__list">
|
||||
<ul>
|
||||
<li><a href="#">GitHub 仓库</a></li>
|
||||
<li><a href="#">团队</a></li>
|
||||
<li><a href="#">博客</a></li>
|
||||
<li><a href="#">其他资源</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-copyright__area grey-bg tp-copyright__border">
|
||||
<div class="container">
|
||||
<div class="row" style="width: 1350px;">
|
||||
<div class="col-xl-12 wow tpfadeUp" data-wow-duration=".9s" data-wow-delay=".3s">
|
||||
<div
|
||||
class="tp-copyright__wrapper d-flex align-items-center justify-content-sm-between justify-content-center">
|
||||
<div class="tp-copyright__text text-center">
|
||||
<span
|
||||
>Apache HertzBeat is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache
|
||||
Incubator. Incubation is required of all newly accepted projects until a further review indicates that the
|
||||
infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful
|
||||
ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it
|
||||
does indicate that the project has yet to be fully endorsed by the ASF.</span
|
||||
>
|
||||
<br/>
|
||||
<HR style="FILTER: alpha(opacity=100,finishopacity=0,style=3)" width="100%" color="#987cb9"
|
||||
SIZE="3">
|
||||
<span
|
||||
>Copyright © 2026 The Apache Software Foundation. Apache HertzBeat, HertzBeat, and its feather logo are trademarks of
|
||||
The Apache Software Foundation.</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {LayoutDefaultOptions} from '@delon/theme/layout-default';
|
||||
import {RouterOutlet} from "@angular/router";
|
||||
import {NzImageDirective} from "ng-zorro-antd/image";
|
||||
import {TemplateService} from "../../service/template.service";
|
||||
import {NzMessageService} from "ng-zorro-antd/message";
|
||||
import {NgIf} from "@angular/common";
|
||||
import {LocalStorageService} from "../../service/local-storage.service";
|
||||
import {DataService} from "../../service/data.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-market',
|
||||
templateUrl: 'market.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterOutlet,
|
||||
NzImageDirective,
|
||||
NgIf
|
||||
]
|
||||
})
|
||||
export class LayoutMarketComponent implements OnInit{
|
||||
options: LayoutDefaultOptions = {
|
||||
logoExpanded: `./assets/brand_white.svg`,
|
||||
logoCollapsed: `./assets/logo.svg`
|
||||
};
|
||||
constructor(private templateService: TemplateService,
|
||||
private msg: NzMessageService,
|
||||
private localStorageService: LocalStorageService,
|
||||
private dataService: DataService
|
||||
) {}
|
||||
|
||||
count=0;
|
||||
isLogin:boolean = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dataService.isLoginMsg.subscribe(isLogin => this.isLogin = isLogin)
|
||||
const userInfo = this.localStorageService.getData('userInfo');
|
||||
if(userInfo!=null){
|
||||
this.isLogin=true
|
||||
}
|
||||
|
||||
this.templateService.getTemplateCount(0,0).subscribe(message=>{
|
||||
if (message.code == 0) {
|
||||
this.count=message.data;
|
||||
}else{
|
||||
this.msg.error(message.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
logout():void{
|
||||
this.localStorageService.removeData('userInfo');
|
||||
this.localStorageService.removeData('userId');
|
||||
this.localStorageService.removeData('Authorization');
|
||||
this.localStorageService.removeData('refresh-token');
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export class Message<T> {
|
||||
data!: T;
|
||||
msg!: string;
|
||||
code: number = 0;
|
||||
}
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<main>
|
||||
<div class="tp-hero__area z-index">
|
||||
<div class="tp-hero__bg tp-hero__height p-relative fix"
|
||||
style="background-image: url('../../../assets/svg/home-page-bg.svg')">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-xl-6 col-lg-6">
|
||||
<div class="tp-hero__left-box z-index">
|
||||
<div class="tp-hero__section-box">
|
||||
<span class="tp-hero-subtitle wow" data-wow-duration=".9s" data-wow-delay=".3s">HertzBeat</span>
|
||||
<h3 class="tp-hero-title wow" data-wow-duration=".9s" data-wow-delay=".5s">
|
||||
<span class="p-relative"
|
||||
>监控模版市场
|
||||
<span class="tp-slider-title-shape">
|
||||
<img src="assets/svg/title-line.svg" alt="">
|
||||
</span>
|
||||
</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="tp-hero__left-text wow tpfadeUp" data-wow-duration=".9s" data-wow-delay=".7s">
|
||||
<p>开源实时观测系统 <br />快来上传、浏览、下载模版吧!</p>
|
||||
<a class="tp-main-btn" href="market/list"
|
||||
>开始浏览
|
||||
<i>
|
||||
<svg width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17.6742 4.74002C17.3484 4.25133 16.8597 3.92554 16.2896 3.76264C15.0679 3.5183 13.9276 4.25133 13.6018 5.3916L12.8688 7.99794L5.78281 1.07486C4.96833 0.260384 3.66516 0.260384 2.93213 1.07486L2.85068 1.15631C2.60633 1.40065 2.52489 1.645 2.44344 1.97079C1.8733 1.88934 1.22172 2.13369 0.81448 2.54093C-0.081448 3.27396 -0.162896 4.57712 0.570136 5.3916L0.651584 5.47305L1.14027 6.04319C0.977376 6.12463 0.81448 6.20608 0.651584 6.36898C0.244344 6.77622 0 7.26491 0 7.83504C0 8.40518 0.244344 8.89386 0.570136 9.38255C5.04977 13.9436 6.67873 15.4097 7.08597 15.7355C7.9819 16.4685 9.36652 16.9572 10.6697 16.9572C11.4842 16.9572 12.2172 16.7943 12.9502 16.3056C14.3348 15.3282 15.4751 14.0251 16.0452 12.8034C16.2896 12.3961 16.6968 11.1744 17.9186 6.36898C18.0814 5.79884 18 5.22871 17.6742 4.74002ZM14.4163 12.2332C14.0091 13.2106 13.0317 14.2694 11.8914 15.0025C11.0769 15.5726 9.12217 15.2468 8.1448 14.4323C7.819 14.1065 6.19005 12.7219 1.79186 8.16083C1.71041 8.07938 1.62896 7.99794 1.62896 7.83504C1.62896 7.75359 1.71041 7.5907 1.79186 7.50925C1.95475 7.26491 2.28054 7.26491 2.52489 7.50925L5.04977 10.0341C5.21267 10.197 5.45701 10.2785 5.61991 10.2785H5.70136C5.86425 10.2785 6.1086 10.197 6.27149 9.95269C6.59728 9.62689 6.59728 9.13821 6.27149 8.81242L1.79186 4.25133C1.62896 4.08844 1.62896 3.84409 1.79186 3.76264C2.0362 3.5183 2.36199 3.5183 2.60633 3.76264L4.80543 5.88029L7.00453 8.07938C7.16742 8.24228 7.41176 8.32373 7.65611 8.32373C7.90045 8.32373 8.06335 8.24228 8.22624 8.07938C8.55204 7.75359 8.55204 7.26491 8.22624 6.93911L4.0724 2.86672C3.9095 2.70382 3.9095 2.37803 4.0724 2.13369C4.23529 1.97079 4.47964 1.97079 4.64253 2.13369L12.7059 10.0341C12.8688 10.197 13.0317 10.2785 13.276 10.2785C13.5204 10.2785 13.7647 10.197 13.8462 10.1156C14.0091 9.95269 14.009 9.87124 14.0905 9.70834V9.62689L15.1493 5.79884C15.2308 5.47305 15.5566 5.31016 15.8824 5.3916C16.0452 5.3916 16.1267 5.47305 16.2081 5.63595C16.2896 5.79884 16.2896 5.88029 16.2896 6.04319C15.1493 10.3599 14.6606 11.826 14.4163 12.2332ZM8.06335 1.56355C8.30769 1.645 8.47059 1.80789 8.71493 1.88934C8.95928 1.97079 9.12217 2.13369 9.36652 2.29658C9.69231 2.54093 10.0995 2.86672 10.4253 3.19251C10.7511 3.5183 11.0769 3.84409 11.3213 4.25133C11.4842 4.41423 11.7285 4.57712 11.9729 4.57712C12.1357 4.57712 12.2986 4.49568 12.3801 4.41423C12.7873 4.16988 12.8688 3.6812 12.6244 3.27396C12.2986 2.78527 11.9729 2.37803 11.5656 1.97079C11.1584 1.56355 10.7511 1.23776 10.2624 0.911967C10.0181 0.749072 9.77376 0.667624 9.52941 0.504728C9.20362 0.341832 8.95928 0.178936 8.71493 0.0974882C8.30769 -0.146856 7.819 0.0974882 7.65611 0.504728C7.41176 0.911967 7.65611 1.40065 8.06335 1.56355ZM4.96833 14.7581C4.72398 14.6767 4.47964 14.5138 4.31674 14.4323C4.0724 14.2694 3.9095 14.188 3.66516 14.0251C3.25792 13.6993 2.93213 13.3735 2.60633 13.0477C2.28054 12.7219 2.0362 12.3147 1.79186 11.9074C1.54751 11.5816 1.05882 11.4187 0.651584 11.6631C0.325792 11.9074 0.162896 12.3961 0.40724 12.8034C0.733032 13.2921 1.05882 13.7807 1.46606 14.188C1.8733 14.5952 2.28054 15.0025 2.76923 15.3282L3.50226 15.8169C3.50226 15.8169 3.99095 16.0613 4.23529 16.2242C4.31674 16.3056 4.47964 16.3056 4.56109 16.3056C4.88688 16.3056 5.13122 16.1427 5.37557 15.8169C5.53846 15.4097 5.37557 14.921 4.96833 14.7581Z"
|
||||
fill="url(#paint0_linear_106_218)"
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_106_2188" x1="0" y1="8.47848" x2="18" y2="8.47848" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#EE0979" />
|
||||
<stop offset="1" stop-color="#FF6A00" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-6 col-lg-6">
|
||||
<div class="tp-hero__thumb-box p-relative text-center text-lg-end">
|
||||
<div class="image-container">
|
||||
<img class="img1" src="../../../assets/svg/brand.svg" alt="">
|
||||
<img class="img2" src="../../../assets/svg/circle.svg" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-feature__area p-relative">
|
||||
<div class="container">
|
||||
<div class="tp-feature__border">
|
||||
<div class="row">
|
||||
<div class="col-xl-4 col-lg-6 col-md-6 mb-30" data-wow-duration=".9s" data-wow-delay=".3s">
|
||||
<div class="tp-feature__item feature-col-1 d-flex align-items-center">
|
||||
<div class="tp-feature__icon">
|
||||
<span>
|
||||
<img src="assets/svg/home-1.svg" alt="">
|
||||
</span>
|
||||
</div>
|
||||
<div class="tp-feature__content">
|
||||
<h4 class="tp-feature__title">开箱即用</h4>
|
||||
<p
|
||||
>集监控-告警-通知为一体,支持应用服务,Web,数据库,缓存,操作系统,中间件,大数据,云原生,网络等监控阈值告警;
|
||||
易用友好,无需Agent,全WEB页面操作</p
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-6 col-md-6 mb-30 wow tpfadeUp" data-wow-duration=".9s" data-wow-delay=".5s">
|
||||
<div class="tp-feature__item feature-col-2 d-flex align-items-center">
|
||||
<div class="tp-feature__icon">
|
||||
<span>
|
||||
<img src="assets/svg/home-2.svg" alt="">
|
||||
</span>
|
||||
</div>
|
||||
<div class="tp-feature__content">
|
||||
<h4 class="tp-feature__title">高性能与自定义</h4>
|
||||
<p
|
||||
>将 Http,Jmx,Ssh,Snmp,Jdbc 等协议规范可配置模版化,只需在线配置YML就可自定义监控指标; 灵活的告警阈值规则,消息及时送达</p
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-6 col-md-6 mb-30 wow tpfadeUp" data-wow-duration=".9s" data-wow-delay=".7s">
|
||||
<div class="tp-feature__item feature-col-3 border-none d-flex align-items-center">
|
||||
<div class="tp-feature__icon">
|
||||
<span>
|
||||
<img src="assets/svg/home-3.svg" alt="">
|
||||
</span>
|
||||
</div>
|
||||
<div class="tp-feature__content">
|
||||
<h4 class="tp-feature__title">拥抱开源</h4>
|
||||
<p>Apache HertzBeat 的单机集群版全开源,基于 Apache2.0 License; 欢迎任何对此有兴趣的同学参与其中</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
.image-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.img1, .img2 {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.img2 {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
|
||||
import {window} from "rxjs";
|
||||
|
||||
@Component({
|
||||
selector: 'home-page',
|
||||
templateUrl: './home-page.component.html',
|
||||
styleUrls: ['./home-page.component.less'],
|
||||
standalone: true,
|
||||
providers: [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class HomePageComponent implements OnInit,OnDestroy {
|
||||
constructor(
|
||||
fb: FormBuilder,
|
||||
) {
|
||||
this.form = fb.group({
|
||||
userName: [null, [Validators.required]],
|
||||
password: [null, [Validators.required]],
|
||||
mobile: [null, [Validators.required, Validators.pattern(/^1\d{10}$/)]],
|
||||
captcha: [null, [Validators.required]],
|
||||
remember: [true]
|
||||
});
|
||||
}
|
||||
|
||||
count=0;
|
||||
|
||||
form: FormGroup;
|
||||
error = '';
|
||||
type = 0;
|
||||
loading = false;
|
||||
|
||||
interval$: any;
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.interval$) {
|
||||
clearInterval(this.interval$);
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly window = window;
|
||||
}
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<main>
|
||||
<div class="tp-register__area pt-xxl-4 pb-xxl-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-xl-6">
|
||||
<div class="tp-register__form-box">
|
||||
<div class="tp-register__form-title text-center mb-5">
|
||||
<h6>邮箱登录</h6>
|
||||
<!-- <span>邮箱登录 <br>-->
|
||||
<!-- & become our partner</span>-->
|
||||
</div>
|
||||
<form>
|
||||
<div class="row">
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-register__input-box">
|
||||
<label for="email">Email 地址</label>
|
||||
<input id="email" type="email" placeholder="邮箱地址" name="identifier" [(ngModel)]="loginForm.identifier">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-register__input-box">
|
||||
<label for="password">密码</label>
|
||||
<input id="password" type="password" placeholder="密码" name="credential" [(ngModel)]="loginForm.credential">
|
||||
<a href="" class="tp-register__input-text">忘记密码?</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-contact-4__comment-agree label-2 pt-5 pb-5">
|
||||
<div class="form-check-box">
|
||||
<input class="form-check-input" type="checkbox" value="" id="flexCheckDefault">
|
||||
<label class="form-check-label text-theme" for="flexCheckDefault">
|
||||
我同意 xxx & <span class="red">xxx</span> 和 xxx
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-contact-4__btn">
|
||||
<button type="button" class="btn-no-icon w-100" (click)="submitLogin()">登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, Injector, OnDestroy, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormsModule} from '@angular/forms';
|
||||
import {AuthService, LoginDTO} from "../../service/auth.service";
|
||||
import {LocalStorageService} from "../../service/local-storage.service";
|
||||
import {NzMessageService} from "ng-zorro-antd/message";
|
||||
import {Router} from "@angular/router";
|
||||
import {NzButtonComponent} from "ng-zorro-antd/button";
|
||||
import {DataService} from "../../service/data.service";
|
||||
|
||||
@Component({
|
||||
selector: 'login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.less'],
|
||||
standalone: true,
|
||||
providers: [],
|
||||
imports: [
|
||||
NzButtonComponent,
|
||||
FormsModule
|
||||
],
|
||||
// changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class LoginComponent implements OnInit,OnDestroy {
|
||||
constructor(
|
||||
fb: FormBuilder,
|
||||
private authService: AuthService,
|
||||
private localStorageService: LocalStorageService,
|
||||
private msg: NzMessageService,
|
||||
private injector: Injector,
|
||||
private dataService: DataService,
|
||||
) {}
|
||||
|
||||
loginForm: LoginDTO={
|
||||
type:1,
|
||||
identifier:'',
|
||||
credential:'',
|
||||
};
|
||||
|
||||
submitLogin():void{
|
||||
console.log(this.loginForm)
|
||||
this.authService.tryLogin(this.loginForm).subscribe(response => {
|
||||
if(response.code == 0) {
|
||||
console.log(response);
|
||||
this.localStorageService.storageAuthorizationToken(response.data.token);
|
||||
this.localStorageService.storageRefreshToken(response.data.refreshToken);
|
||||
this.msg.success('登录成功');
|
||||
this.localStorageService.putData('userInfo',this.loginForm.identifier);
|
||||
this.localStorageService.putData('userId',response.data.id);
|
||||
this.dataService.sendLoginMsg(true);
|
||||
window.history.back();
|
||||
}else{
|
||||
this.msg.error('登录失败:'+response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { TemplateDetailComponent } from './template-detail/template-detail.component';
|
||||
import { TemplateListComponent } from './template-list/template-list.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TemplateListComponent },
|
||||
{ path: 'list', component: TemplateListComponent },
|
||||
{ path: 'detail', component: TemplateDetailComponent },
|
||||
{ path: '**', component: TemplateListComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class MarketRoutingModule {}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {ClipboardModule} from '@angular/cdk/clipboard';
|
||||
import {NgModule, Type} from '@angular/core';
|
||||
import {NzBreadCrumbModule} from 'ng-zorro-antd/breadcrumb';
|
||||
import {NzLayoutModule} from 'ng-zorro-antd/layout';
|
||||
import {NzRadioModule} from 'ng-zorro-antd/radio';
|
||||
import {NzSpaceModule} from 'ng-zorro-antd/space';
|
||||
import {NzSwitchModule} from 'ng-zorro-antd/switch';
|
||||
|
||||
import {MarketRoutingModule} from './market-routing.module';
|
||||
import {TemplateDetailComponent} from './template-detail/template-detail.component';
|
||||
import {TemplateListComponent} from './template-list/template-list.component';
|
||||
import {NzInputDirective, NzInputGroupComponent} from "ng-zorro-antd/input";
|
||||
import {NzOptionComponent, NzSelectModule} from "ng-zorro-antd/select";
|
||||
import {NzButtonComponent} from "ng-zorro-antd/button";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {NzPaginationComponent} from "ng-zorro-antd/pagination";
|
||||
import {NzCheckboxComponent, NzCheckboxGroupComponent} from "ng-zorro-antd/checkbox";
|
||||
import {NzIconDirective} from "ng-zorro-antd/icon";
|
||||
import {NzTooltipDirective} from "ng-zorro-antd/tooltip";
|
||||
import {NzCardComponent, NzCardMetaComponent} from "ng-zorro-antd/card";
|
||||
import {NzAvatarComponent} from "ng-zorro-antd/avatar";
|
||||
|
||||
const COMPONENTS: Array<Type<void>> = [TemplateListComponent, TemplateDetailComponent, TemplateListComponent];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
MarketRoutingModule,
|
||||
NzBreadCrumbModule,
|
||||
NzSwitchModule,
|
||||
NzRadioModule,
|
||||
NzLayoutModule,
|
||||
NzSpaceModule,
|
||||
ClipboardModule,
|
||||
NzInputGroupComponent,
|
||||
NzOptionComponent,
|
||||
NzButtonComponent,
|
||||
NzInputDirective,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
NzSelectModule,
|
||||
NzPaginationComponent,
|
||||
NzCheckboxComponent,
|
||||
NzCheckboxGroupComponent,
|
||||
NzIconDirective,
|
||||
NzTooltipDirective,
|
||||
NzCardComponent,
|
||||
NzCardMetaComponent,
|
||||
NzAvatarComponent
|
||||
],
|
||||
declarations: COMPONENTS,
|
||||
exports:[RouterModule]
|
||||
})
|
||||
export class MarketModule {}
|
||||
-277
@@ -1,277 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<main>
|
||||
<div
|
||||
class="tp-breadcrumb__area fix tp-breadcrumb-height"
|
||||
style="background-image: url('../../../../assets/svg/breadcrumb.svg');height: 250px"
|
||||
>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="tp-breadcrumb__content text-center z-index-5">
|
||||
<div class="tp-breadcrumb__list">
|
||||
<span><a href="index.html">Apache </a></span>
|
||||
<span class="dvdr">.</span>
|
||||
<span>HertzBeat</span>
|
||||
</div>
|
||||
<h3 class="tp-breadcrumb__title"
|
||||
><span class="p-relative z-index-5">
|
||||
模版
|
||||
<span class="tp-title-shape">
|
||||
<img src="assets/svg/title-line.svg" alt="">
|
||||
</span>
|
||||
</span>
|
||||
详情
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tp-product-details-area pt-xxl-4">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xl-6 col-lg-6" style="display: grid; place-items: center;height: 400px">
|
||||
<div class="tp-shop-details__wrapper">
|
||||
<div class="tp-shop-details__tab-content-box">
|
||||
<div class="tab-content" id="nav-tabContent" style="display: grid; place-items: center;height: 400px">
|
||||
<img src="assets/svg/{{templateInfo.categoryId}}-img.svg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6 col-lg-6" style="height: 400px">
|
||||
<div class="tp-shop-details__right-warp">
|
||||
<h3 class="tp-shop-details__title-sm">{{ (templateInfo!=null)?templateInfo.name:'xxx' }}</h3>
|
||||
<div class="tp-fea-product__star">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<span nz-icon nzType="star" nzTheme="outline"></span>
|
||||
<span class="review-text"> {{ templateInfo.star }}</span>
|
||||
</div> <div class="col-3">
|
||||
<span nz-icon nzType="eye" nzTheme="outline"></span>
|
||||
<span class="review-text"> 200</span>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<span nz-icon nzType="download" nzTheme="outline"></span>
|
||||
<span class="review-text"> {{ templateInfo.download>=1000?((templateInfo.download/1000).toFixed(2)+'k'):templateInfo.download }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-shop-details__product-info">
|
||||
<ul>
|
||||
<li><span>类别 : </span> {{ categoryStr }}</li>
|
||||
<li><span>标签 : </span> MySQL</li>
|
||||
<li><span>最新版本 : </span> {{ latestVersion?latestVersion.version:'xxx' }}</li>
|
||||
<li><span>最后更新时间 : </span> {{ templateInfo.updateTime }}</li>
|
||||
</ul></div>
|
||||
<div class="tp-shop-details__quantity-wrap d-flex align-items-center">
|
||||
<div class="tp-shop-details__btn me-4">
|
||||
<a class="btn-icon" href="javascript:" (click)="downloadTemplateNow()">
|
||||
<span class="material-symbols-outlined">download</span>下载
|
||||
</a>
|
||||
</div>
|
||||
<div class="tp-shop-details__btn me-4">
|
||||
<a class="btn-icon" href="javascript:" (click)="starTemplate(templateInfo.id)" *ngIf="!isStarNow">
|
||||
<span class="material-symbols-outlined">star</span>
|
||||
收藏</a>
|
||||
<a class="btn-icon" href="javascript:" (click)="cancelStarTemplate(templateInfo.id)" *ngIf="isStarNow">
|
||||
<span class="material-symbols-outlined">star</span>取消收藏</a>
|
||||
</div>
|
||||
<div class="tp-shop-details__btn me-4">
|
||||
<a class="btn-icon" href="javascript:" (click)="shareVersionNow(latestVersion.id)">
|
||||
<span class="material-symbols-outlined">share</span>分享</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="productdetails-tabs mb-5">
|
||||
<div class="row">
|
||||
<div class="col-xl-12 col-lg-12 col-12">
|
||||
<div class="product-additional-tab">
|
||||
<div class="pro-details-nav mb-4">
|
||||
<ul class="nav nav-tabs pro-details-nav-btn" id="myTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
class="nav-links"
|
||||
[ngClass]="showPage==1?'active':''"
|
||||
id="home-tab-1"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#home-1"
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-controls="home-1"
|
||||
aria-selected="true"
|
||||
(click)="showPage = 1"
|
||||
><span>详情</span></button
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
[ngClass]="showPage==2?'active':''"
|
||||
class="nav-links"
|
||||
id="information-tab"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#additional-information"
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-controls="additional-information"
|
||||
aria-selected="false"
|
||||
(click)="showPage = 2"
|
||||
><span>历史版本</span></button
|
||||
>
|
||||
</li>
|
||||
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
[ngClass]="showPage==3?'active':''"
|
||||
class="nav-links"
|
||||
id="size-chart-tab"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#chart"
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-controls="chart"
|
||||
aria-selected="false"
|
||||
(click)="showPage = 3"
|
||||
><span>FAQ</span></button
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content tp-content-tab" id="myTabContent-2">
|
||||
<div [hidden]="!(showPage == 1)" id="home-1" role="tabpanel" aria-labelledby="home-tab-1">
|
||||
<div class="product-details-list-box">
|
||||
<span> 概要信息 : </span>
|
||||
<p class="mb-30">{{ templateInfo.description }}</p>
|
||||
<!-- <p class="pb-55">。。。。。</p>-->
|
||||
</div>
|
||||
<div class="product-details-list-box">
|
||||
<span> 详细信息 : </span>
|
||||
<!-- <p class="mb-30">{{ templateInfo.description }}</p>-->
|
||||
<p class="pb-5">。。。。。</p>
|
||||
</div>
|
||||
<div class="product-details-list-box" style="width: 100%;">
|
||||
<span> 其他信息 : </span>
|
||||
<ul style="width: 100%;">
|
||||
<li>
|
||||
<span>
|
||||
<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M15.794 2.17595C14.426 3.42395 13.094 4.87595 11.798 6.53195C10.67 7.95995 9.656 9.42395 8.756 10.924C7.94 12.268 7.346 13.42 6.974 14.38C6.962 14.416 6.938 14.446 6.902 14.47C6.866 14.506 6.824 14.524 6.776 14.524C6.764 14.536 6.752 14.542 6.74 14.542C6.656 14.542 6.596 14.518 6.56 14.47L0.134 7.93595C0.122 7.92395 0.278 7.76795 0.602 7.46795C0.926 7.15595 1.244 6.87395 1.556 6.62195C1.904 6.33395 2.09 6.20195 2.114 6.22595L5.642 8.99795C6.674 7.78595 7.832 6.58595 9.116 5.39795C11.048 3.62195 13.04 2.10995 15.092 0.861953C15.128 0.861953 15.266 1.02995 15.506 1.36595L15.866 1.88795C15.878 1.93595 15.878 1.98995 15.866 2.04995C15.854 2.09795 15.83 2.13995 15.794 2.17595Z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</span>
|
||||
<p class="mb-30">{{ templateInfo.description }}</p>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M15.794 2.17595C14.426 3.42395 13.094 4.87595 11.798 6.53195C10.67 7.95995 9.656 9.42395 8.756 10.924C7.94 12.268 7.346 13.42 6.974 14.38C6.962 14.416 6.938 14.446 6.902 14.47C6.866 14.506 6.824 14.524 6.776 14.524C6.764 14.536 6.752 14.542 6.74 14.542C6.656 14.542 6.596 14.518 6.56 14.47L0.134 7.93595C0.122 7.92395 0.278 7.76795 0.602 7.46795C0.926 7.15595 1.244 6.87395 1.556 6.62195C1.904 6.33395 2.09 6.20195 2.114 6.22595L5.642 8.99795C6.674 7.78595 7.832 6.58595 9.116 5.39795C11.048 3.62195 13.04 2.10995 15.092 0.861953C15.128 0.861953 15.266 1.02995 15.506 1.36595L15.866 1.88795C15.878 1.93595 15.878 1.98995 15.866 2.04995C15.854 2.09795 15.83 2.13995 15.794 2.17595Z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</span>
|
||||
<p class="mb-30">{{ templateInfo.description }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div [hidden]="!(showPage == 2)" id="additional-information" role="tabpanel" aria-labelledby="information-tab">
|
||||
<div class="container">
|
||||
<div class="product__details-info table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="add-info">版本号</td>
|
||||
<td class="add-info-list">概要</td>
|
||||
<td class="add-info-list">更新时间</td>
|
||||
<td class="add-info-list">下载量</td>
|
||||
<td class="add-info-list">下载</td>
|
||||
<td class="add-info-list">分享链接</td>
|
||||
</tr>
|
||||
<tr *ngFor="let item of versionList; let i = index">
|
||||
<td class="add-info">{{ item.version }}</td>
|
||||
<td class="add-info-list"> {{ item.description }}</td>
|
||||
<td class="add-info-list"> {{ item.createTime }}</td>
|
||||
<td class="add-info-list"> {{ item.download>=1000?((item.download/1000).toFixed(2)+'k'):item.download }}</td>
|
||||
<td class="add-info-list">
|
||||
<a href="javascript:" (click)="downloadVersion(item.version,item.id)"> <span class="material-symbols-outlined">download</span></a
|
||||
></td>
|
||||
<td class="add-info-list">
|
||||
<a href="javascript:" (click)="shareVersionNow(item.id)"> <span class="material-symbols-outlined">share</span></a
|
||||
></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<nz-pagination [nzPageIndex]="pageIndex+1" [nzTotal]="totalElements" nzShowSizeChanger
|
||||
[(nzPageSize)]="pageSize" (nzPageSizeChange)="pageSizeChange($event)" (nzPageIndexChange)="pageIndexChange($event)"
|
||||
[nzPageSizeOptions]=pageSizeOptions ></nz-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div [hidden]="!(showPage == 3)" id="chart" role="tabpanel" aria-labelledby="size-chart-tab">
|
||||
<div class="tp-service-details-faq tp-faq-inner__customize">
|
||||
<div class="tp-custom-accordion">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-items tp-faq-active">
|
||||
<h2 class="accordion-header" id="headingOne">
|
||||
<button
|
||||
class="accordion-buttons"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseOne"
|
||||
aria-expanded="true"
|
||||
aria-controls="collapseOne"
|
||||
>
|
||||
这个模版怎么用?
|
||||
</button>
|
||||
</h2>
|
||||
<div
|
||||
id="collapseOne"
|
||||
class="accordion-collapse collapse show"
|
||||
aria-labelledby="headingOne"
|
||||
data-bs-parent="#accordionExample"
|
||||
>
|
||||
<div class="accordion-body"> 就这么用 </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-210
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {saveAs} from 'file-saver';
|
||||
import {NzMessageService} from 'ng-zorro-antd/message';
|
||||
|
||||
import {TemplateService} from '../../../service/template.service';
|
||||
import {window} from "rxjs";
|
||||
import {LocalStorageService} from "../../../service/local-storage.service";
|
||||
import {StarService} from "../../../service/star.service";
|
||||
import {VersionService} from "../../../service/version.service";
|
||||
|
||||
@Component({
|
||||
selector: 'market',
|
||||
templateUrl: './template-detail.component.html',
|
||||
styleUrls: ['./template-detail.component.less']
|
||||
})
|
||||
export class TemplateDetailComponent implements OnInit, OnDestroy {
|
||||
constructor(private templateService: TemplateService,
|
||||
private msg: NzMessageService,
|
||||
private localStorageService: LocalStorageService,
|
||||
private starService: StarService,
|
||||
private versionService: VersionService,) {}
|
||||
|
||||
userId:number = 0;
|
||||
|
||||
templateInfo :any = null;
|
||||
categoryList: any[] = [];
|
||||
latestVersion :any = null;
|
||||
versionList: any[] = [];
|
||||
|
||||
totalElements = 10;
|
||||
totalPages = 1;
|
||||
pageIndex=0;
|
||||
pageSize = 2;
|
||||
numberOfPages = 1;
|
||||
newPageIndex=this.pageIndex;
|
||||
newPageSize = this.pageSize;
|
||||
pageSizeOptions:number[]=[2,5,10,20];
|
||||
|
||||
categoryStr='';
|
||||
|
||||
isStarNow:boolean = false;
|
||||
|
||||
showPage = 1;
|
||||
|
||||
downloadTemplateNow(): void {
|
||||
this.templateService.downloadLatestTemplate(this.templateInfo.user, this.templateInfo.id, this.templateInfo.latest).subscribe(blob => {
|
||||
saveAs(blob, `${this.templateInfo.name}-${this.latestVersion.version}.yml`);
|
||||
this.localStorageService.removeData('nowTemplate');
|
||||
this.templateInfo.download++;
|
||||
for (let item of this.versionList) {
|
||||
if(item.id==this.templateInfo.latest) {
|
||||
item.download++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo));
|
||||
});
|
||||
}
|
||||
|
||||
downloadVersion(version:string, versionId:number): void {
|
||||
this.templateService.downloadTemplate(this.templateInfo.user, this.templateInfo.id,version, versionId).subscribe(blob => {
|
||||
saveAs(blob, `${this.templateInfo.name}-${version}.yml`);
|
||||
for (let item of this.versionList) {
|
||||
if(item.id==versionId) {
|
||||
item.download++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.localStorageService.removeData('nowTemplate');
|
||||
this.templateInfo.download++;
|
||||
this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo));
|
||||
});
|
||||
}
|
||||
|
||||
shareVersionNow(versionId:number): void {
|
||||
this.versionService.shareVersion(versionId).subscribe(message=>{
|
||||
if(message.code==0){
|
||||
this.msg.success('已复制分享链接,快去发送给对方吧!');
|
||||
const selBox = document.createElement('textarea');
|
||||
selBox.style.position = 'fixed';
|
||||
selBox.style.left = '0';
|
||||
selBox.style.top = '0';
|
||||
selBox.style.opacity = '0';
|
||||
selBox.value = message.msg;
|
||||
document.body.appendChild(selBox);
|
||||
selBox.focus();
|
||||
selBox.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(selBox);
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
const user=this.localStorageService.getData("userId");
|
||||
if(user==null) this.userId=0;
|
||||
else this.userId=parseInt(user);
|
||||
|
||||
this.templateInfo=JSON.parse(<string>this.localStorageService.getData('nowTemplate'));
|
||||
if(this.userId!=0){
|
||||
this.starService.assertTemplateStarByUser(this.userId,this.templateInfo.id).subscribe(response => {
|
||||
if(response.code == 0) {
|
||||
this.isStarNow=response.data
|
||||
}else{
|
||||
this.msg.error('是否收藏判断失败'+response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
this.versionService.getVersion(this.templateInfo.latest).subscribe(response => {
|
||||
if(response.code == 0) {
|
||||
this.latestVersion=response.data;
|
||||
console.log(this.latestVersion);
|
||||
}else {
|
||||
this.msg.error('版本信息获取失败'+response.msg)
|
||||
}
|
||||
})
|
||||
this.categoryList=JSON.parse(<string>this.localStorageService.getData('categoryList'));
|
||||
console.log(this.templateInfo);
|
||||
console.log(this.categoryList);
|
||||
for (const item of this.categoryList) {
|
||||
if(item.value==this.templateInfo.categoryId){
|
||||
this.categoryStr=item.label;
|
||||
}
|
||||
}
|
||||
this.getVersions();
|
||||
}
|
||||
|
||||
pageIndexChange(newIndex:number){
|
||||
this.newPageIndex=newIndex-1;
|
||||
console.log("newPageIndex",this.newPageIndex,"newPageSize",this.newPageSize);
|
||||
this.getVersions()
|
||||
}
|
||||
|
||||
pageSizeChange(newSize:number){
|
||||
this.newPageSize=newSize;
|
||||
console.log("newSize",newSize,"newPageIndex",this.newPageIndex);
|
||||
this.getVersions()
|
||||
}
|
||||
|
||||
getVersions(){
|
||||
this.versionService.getVersionPage(this.templateInfo.id,0,this.newPageIndex,this.newPageSize).subscribe(response => {
|
||||
if(response.code == 0) {
|
||||
this.versionList=response.data.content;
|
||||
this.totalElements=response.data.totalElements;
|
||||
this.totalPages=response.data.totalPages;
|
||||
this.pageIndex=response.data.pageable.pageNumber;
|
||||
this.pageSize=response.data.pageable.pageSize;
|
||||
this.numberOfPages=response.data.numberOfElements;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
starTemplate(id:number){
|
||||
const formData = new FormData();
|
||||
formData.append('user', this.userId.toString());
|
||||
formData.append('template', id.toString());
|
||||
this.starService.starTemplate(formData)
|
||||
.subscribe(message=>{
|
||||
if (message.code == 0) {
|
||||
this.msg.success(message.msg);
|
||||
this.isStarNow=true;
|
||||
this.templateInfo.star++;
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
cancelStarTemplate(id:number){
|
||||
const formData = new FormData();
|
||||
formData.append('templateId', id.toString());
|
||||
this.starService.cancelStarTemplate(this.userId,formData)
|
||||
.subscribe(message=>{
|
||||
if (message.code == 0) {
|
||||
this.msg.success(message.msg);
|
||||
this.isStarNow=false;
|
||||
this.templateInfo.star--;
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.localStorageService.removeData('nowTemplate');
|
||||
}
|
||||
|
||||
protected readonly window = window;
|
||||
}
|
||||
-229
@@ -1,229 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<main>
|
||||
<div
|
||||
class="tp-breadcrumb__area fix tp-breadcrumb-height"
|
||||
style="background-image: url('../../../../assets/svg/breadcrumb.svg');height: 250px"
|
||||
>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="tp-breadcrumb__content text-center z-index-5">
|
||||
<div class="tp-breadcrumb__list">
|
||||
<span><a href="../../../../index.html">Apache </a></span>
|
||||
<span class="dvdr">.</span>
|
||||
<span> HertzBeat</span>
|
||||
</div>
|
||||
<h3 class="tp-breadcrumb__title"
|
||||
><span class="p-relative z-index-5">
|
||||
监 控 模 版
|
||||
<span class="tp-title-shape">
|
||||
<img src="assets/svg/title-line.svg">
|
||||
</span>
|
||||
</span>
|
||||
市 场
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tp-product__area pt-xxl-4 pb-xxl-5">
|
||||
<div class="container">
|
||||
<div class="tp-product__top-area pb-5">
|
||||
<div class="row d-flex justify-content-end">
|
||||
<div class="col-xl-4 col-lg-4 mb-5">
|
||||
<div class="tp-product__filter">
|
||||
<nz-select nzShowSearch nzAllowClear nzPlaceHolder="选择排序方法" nzSize="large"
|
||||
[(ngModel)]="orderOption" (ngModelChange)="orderOptionChange($event)">
|
||||
<nz-option nzLabel="最早创建" nzValue=1></nz-option>
|
||||
<nz-option nzLabel="最近创建" nzValue=2></nz-option>
|
||||
<nz-option nzLabel="最早更新" nzValue=3></nz-option>
|
||||
<nz-option nzLabel="最近更新" nzValue=4></nz-option>
|
||||
<nz-option nzLabel="最少下载" nzValue=5></nz-option>
|
||||
<nz-option nzLabel="最多下载" nzValue=6></nz-option>
|
||||
<nz-option nzLabel="最少收藏" nzValue=7></nz-option>
|
||||
<nz-option nzLabel="最多收藏" nzValue=8></nz-option>
|
||||
</nz-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-4 mb-5">
|
||||
<div class="tp-product__input">
|
||||
<nz-input-group nzSearch nzSize="large" [nzAddOnAfter]="suffixButton">
|
||||
<input type="text" nz-input placeholder="关键字搜索" [(ngModel)]="nameLike"/>
|
||||
</nz-input-group>
|
||||
<ng-template #suffixButton>
|
||||
<button nz-button nzType="primary" nzSize="large" nzSearch (click)="getTemplatePageByOption()">
|
||||
<span class="material-symbols-outlined">search</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xl-3 col-lg-4">
|
||||
<div class="tp-shop-sidebar me-4">
|
||||
<!-- categories -->
|
||||
<div class="tp-shop-widget mb-3">
|
||||
<h3 class="tp-shop-widget-title">
|
||||
模版类别
|
||||
</h3>
|
||||
<div style="border-bottom: 1px solid rgb(233, 233, 233);"></div>
|
||||
<div class="tp-shop-widget-content mt-4">
|
||||
<div class="tp-shop-widget-categories">
|
||||
<label
|
||||
nz-checkbox
|
||||
[(ngModel)]="allChecked"
|
||||
(ngModelChange)="updateAllChecked()"
|
||||
[nzIndeterminate]="indeterminate">
|
||||
全选
|
||||
</label>
|
||||
<nz-checkbox-group [(ngModel)]="categoryList" (ngModelChange)="updateSingleChecked()"></nz-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-shop-widget mb-4">
|
||||
<h3 class="tp-shop-widget-title">标签</h3>
|
||||
<div style="border-bottom: 1px solid rgb(233, 233, 233);"></div>
|
||||
<div class="tp-shop-widget-tag-box mt-4">
|
||||
<div class="tp-shop-widget-tag" (click)="tagChange()">
|
||||
<span>Docker</span>
|
||||
<span>Linux</span>
|
||||
<span>K8S</span>
|
||||
<span>SpringBoot2</span>
|
||||
<span>SpringBoot3</span>
|
||||
<span>Web</span>
|
||||
<span>Windows</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-9 col-lg-8" style="position: relative;">
|
||||
<div class="container">
|
||||
<div class="row gy-0 gx-3">
|
||||
<div class="col-xl-4 col-md-6 mb-0" *ngFor="let item of templateList; let i = index">
|
||||
<div class="tp-fea-product__item tp-fea-product__item-2">
|
||||
<nz-card style="width: 300px;margin-top: 16px" [nzLoading]="loading" [nzActions]="[actionSetting, actionEdit, actionEllipsis]">
|
||||
<nz-card-meta
|
||||
[nzAvatar]="avatarTemplate"
|
||||
[nzTitle]=item.name
|
||||
[nzDescription]=item.description
|
||||
></nz-card-meta>
|
||||
</nz-card>
|
||||
<ng-template #avatarTemplate>
|
||||
<nz-avatar nzSrc="assets/svg/{{item.categoryId}}-img.svg"></nz-avatar>
|
||||
</ng-template>
|
||||
<ng-template #actionSetting>
|
||||
<div style=" display:inline-flex;align-items: center; color: rgba(18,8,24,0.92)">
|
||||
<span nz-icon nzType="star" nzTheme="outline" style="color: #b02a37"></span> {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }}
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #actionEdit>
|
||||
<div style=" display:inline-flex;align-items: center; color: rgba(18,8,24,0.92)">
|
||||
<span nz-icon nzType="eye" nzTheme="outline" style="color: #b02a37"></span> {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }}
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #actionEllipsis>
|
||||
<div style=" display:inline-flex;align-items: center; color: rgba(18,8,24,0.92)">
|
||||
<span nz-icon nzType="download" nzTheme="outline" style="color: #b02a37"></span> {{ item.download>=1000?((item.download/1000).toFixed(2)+'k'):item.download }}
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="template_card__icon-box">
|
||||
<a href="market/detail" onclick="event.preventDefault()" (click)="downloadLatestTemplate(item.id,item.user,item.latest,item.name)"
|
||||
nzTooltipTitle="下载最新版本" nzTooltipPlacement="bottom" nz-tooltip>
|
||||
<svg
|
||||
t="1720551677718"
|
||||
class="icon"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="1510"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<path
|
||||
d="M511.985404 988.20397L354.645856 830.863205l31.692198-31.692197 125.64735 125.646134 125.647351-125.646134 31.693414 31.692197z"
|
||||
fill="currentcolor"
|
||||
p-id="1511"
|
||||
></path>
|
||||
<path d="M489.574876 549.16438h44.821057v390.984362h-44.821057z" fill="currentcolor" p-id="1512"></path>
|
||||
<path
|
||||
d="M802.862512 498.506247a292.347627 292.347627 0 0 0 3.606362-45.781943c0-160.264776-129.920251-290.18381-290.183811-290.183811-156.325145 0-283.755607 123.617328-289.927168 278.428166-98.420231 18.360213-172.926572 104.690313-172.926573 208.435553 0 117.112497 94.937933 212.051646 212.051646 212.051646l0.254209-0.002433v0.002433h50.690974v-44.821058H265.760287v-0.003649c-0.09244 0-0.184879 0.003649-0.278535 0.003649-44.669019 0-86.664586-17.394462-118.249748-48.98084-31.585162-31.585162-48.980841-73.580729-48.980841-118.249748s17.394462-86.664586 48.980841-118.249748c22.566216-22.566216 50.447712-37.88322 80.820212-44.794298a168.56853 168.56853 0 0 1 37.429536-4.186542c2.410728 0 4.811726 0.060816 7.205426 0.161769a249.539565 249.539565 0 0 1-1.764867-29.609873c0-5.121885 0.173932-10.217012 0.484091-15.286596 3.651365-59.787763 28.659934-115.491154 71.381639-158.211643 46.342662-46.342662 107.959757-71.865731 173.498239-71.86573 65.539698 0 127.155576 25.521852 173.498238 71.86573 46.342662 46.342662 71.865731 107.959757 71.865731 173.498239 0 16.313162-1.583637 32.383062-4.674283 48.035767a242.757415 242.757415 0 0 1-12.339474 42.018677h43.569473v0.029192c0.211638-0.001216 0.420844-0.013379 0.632482-0.01338 1.11779 0 2.233147 0.014596 3.346071 0.041355 35.320453 0.841687 68.400461 14.992248 93.471062 40.062849 25.861203 25.861203 40.102987 60.24388 40.102987 96.817133 0 36.573253-14.241785 70.95593-40.102987 96.817133-25.861203 25.861203-60.245096 40.102987-96.817133 40.102987l-0.063248-0.001216v0.001216h-72.483617v44.821057h76.492577v-0.049868c98.550376-2.099353 177.796681-82.63738 177.796682-181.691309-0.002433-95.656772-73.899403-174.050444-167.718329-181.210866z"
|
||||
fill="currentcolor"
|
||||
p-id="1513"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="market/detail" (click)="pickTemplate(item.id)" nzTooltipTitle="详情" nzTooltipPlacement="bottom" nz-tooltip>
|
||||
<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8.79673 4.85355L12.0361 1.70712V3C12.0361 3.27614 12.2666 3.49999 12.5509 3.49999C12.8352 3.49999 13.0656 3.27614 13.0656 3V0.500039C13.0656 0.483562 13.0648 0.467086 13.0631 0.450656C13.0623 0.44325 13.0609 0.436078 13.0598 0.428789C13.0585 0.419953 13.0575 0.411094 13.0557 0.402305C13.054 0.393914 13.0516 0.385781 13.0495 0.377555C13.0475 0.369984 13.0458 0.362367 13.0434 0.354867C13.0409 0.346781 13.0378 0.338977 13.0349 0.331078C13.0321 0.323602 13.0296 0.316055 13.0264 0.308672C13.0233 0.301289 13.0196 0.294234 13.0161 0.287039C13.0124 0.279445 13.0089 0.271781 13.0048 0.264328C13.001 0.257437 12.9967 0.250875 12.9926 0.244172C12.9881 0.236883 12.9838 0.2295 12.9789 0.222375C12.9739 0.214969 12.9682 0.208008 12.9627 0.200883C12.9581 0.194953 12.9539 0.188859 12.949 0.18307C12.9383 0.170437 12.927 0.158273 12.9151 0.146719C12.9151 0.146625 12.915 0.146531 12.9149 0.146437C12.9148 0.146344 12.9147 0.146297 12.9146 0.146203C12.9027 0.134648 12.8902 0.123703 12.8772 0.11332C12.8712 0.108562 12.8649 0.104437 12.8588 0.0999844C12.8515 0.0946641 12.8443 0.0891562 12.8367 0.0842109C12.8294 0.0794531 12.8218 0.0753281 12.8142 0.0709688C12.8073 0.0669609 12.8006 0.0627656 12.7935 0.0590625C12.7858 0.0550781 12.778 0.0517031 12.7701 0.0481172C12.7627 0.0447187 12.7554 0.0411328 12.7479 0.0380625C12.7403 0.0350156 12.7325 0.0325313 12.7248 0.0298594C12.7166 0.0270234 12.7086 0.024 12.7003 0.0215625C12.6926 0.0192891 12.6847 0.017625 12.6769 0.0157266C12.6685 0.0136406 12.6601 0.0113438 12.6515 0.00967969C12.6424 0.00794531 12.6333 0.00689062 12.6242 0.005625C12.6167 0.00459375 12.6093 0.0031875 12.6017 0.00246094C12.5848 0.000867187 12.5678 0 12.5509 0H9.97704C9.69274 0 9.46228 0.223852 9.46228 0.499992C9.46228 0.776133 9.69274 0.999984 9.97704 0.999984H11.3081L8.06874 4.14645C7.86771 4.3417 7.86771 4.6583 8.06874 4.85355C8.26976 5.04881 8.59571 5.04881 8.79673 4.85355Z"
|
||||
fill="currentcolor"
|
||||
/>
|
||||
<path
|
||||
d="M4.97985 7.14644L1.74048 10.2929V9C1.74048 8.72386 1.51002 8.50001 1.22572 8.50001C0.941401 8.50001 0.710938 8.72386 0.710938 9V11.5C0.710938 11.5165 0.71183 11.5329 0.713495 11.5493C0.714243 11.5567 0.715667 11.5639 0.716753 11.5712C0.718056 11.58 0.719117 11.5889 0.720927 11.5977C0.72264 11.6061 0.725005 11.6142 0.727153 11.6224C0.729107 11.63 0.73082 11.6376 0.733161 11.6451C0.73567 11.6532 0.738783 11.661 0.741703 11.6689C0.744478 11.6764 0.747011 11.6839 0.750148 11.6913C0.753285 11.6987 0.757001 11.7057 0.7605 11.7129C0.764192 11.7205 0.767667 11.7282 0.771769 11.7356C0.775581 11.7425 0.7799 11.7491 0.784027 11.7558C0.788515 11.7631 0.792761 11.7705 0.79766 11.7776C0.802751 11.785 0.808422 11.7919 0.813899 11.7991C0.818484 11.805 0.822731 11.8111 0.827629 11.8169C0.838318 11.8296 0.849587 11.8417 0.861483 11.8533C0.86158 11.8534 0.861628 11.8535 0.861724 11.8535C0.861821 11.8536 0.861917 11.8537 0.862014 11.8538C0.87391 11.8653 0.886433 11.8763 0.899439 11.8867C0.905399 11.8914 0.911673 11.8955 0.917778 11.9C0.925113 11.9053 0.93228 11.9108 0.939905 11.9158C0.947216 11.9205 0.954817 11.9246 0.962345 11.929C0.969246 11.933 0.975979 11.9372 0.983097 11.9409C0.99077 11.9449 0.998661 11.9483 1.00648 11.9519C1.01389 11.9553 1.02117 11.9588 1.02875 11.9619C1.03635 11.9649 1.0441 11.9674 1.05182 11.9701C1.05995 11.9729 1.06799 11.976 1.07631 11.9784C1.08403 11.9807 1.09187 11.9823 1.09967 11.9842C1.10814 11.9863 1.11651 11.9886 1.12515 11.9903C1.1342 11.992 1.14332 11.9931 1.15242 11.9943C1.15992 11.9954 1.16733 11.9968 1.17493 11.9975C1.19182 11.9991 1.20876 12 1.2257 12H1.22572H3.79955C4.08384 12 4.3143 11.7761 4.3143 11.5C4.3143 11.2238 4.08384 11 3.79955 11H2.46848L5.70785 7.85355C5.90887 7.65829 5.90887 7.3417 5.70785 7.14644C5.50682 6.95119 5.18088 6.95119 4.97985 7.14644Z"
|
||||
fill="currentcolor"
|
||||
/>
|
||||
<path
|
||||
d="M12.9628 11.799C12.9682 11.7919 12.9739 11.785 12.9789 11.7776C12.9839 11.7705 12.9881 11.7631 12.9926 11.7558C12.9967 11.7491 13.001 11.7426 13.0048 11.7357C13.0089 11.7282 13.0124 11.7206 13.0161 11.7129C13.0196 11.7058 13.0233 11.6987 13.0264 11.6913C13.0296 11.684 13.0321 11.6764 13.0349 11.6689C13.0378 11.661 13.0409 11.6532 13.0434 11.6452C13.0458 11.6377 13.0475 11.63 13.0494 11.6225C13.0516 11.6142 13.0539 11.6061 13.0557 11.5977C13.0574 11.589 13.0585 11.5801 13.0598 11.5713C13.0609 11.564 13.0623 11.5568 13.0631 11.5494C13.0648 11.533 13.0656 11.5165 13.0656 11.5V9C13.0656 8.72386 12.8352 8.50001 12.5509 8.50001C12.2666 8.50001 12.0361 8.72386 12.0361 9V10.2929L8.79673 7.14644C8.59571 6.95119 8.26976 6.95119 8.06874 7.14644C7.86771 7.3417 7.86771 7.65829 8.06874 7.85355L11.3081 11H9.97704C9.69274 11 9.46228 11.2238 9.46228 11.5C9.46228 11.7761 9.69274 12 9.97704 12H12.5509C12.5678 12 12.5848 11.9991 12.6017 11.9975C12.6093 11.9968 12.6167 11.9954 12.6242 11.9943C12.6333 11.9931 12.6424 11.9921 12.6515 11.9903C12.6601 11.9886 12.6684 11.9863 12.6769 11.9842C12.6847 11.9823 12.6926 11.9807 12.7003 11.9784C12.7086 11.976 12.7166 11.973 12.7247 11.9701C12.7325 11.9674 12.7402 11.965 12.7478 11.9619C12.7554 11.9589 12.7627 11.9553 12.7701 11.9519C12.7779 11.9483 12.7858 11.9449 12.7935 11.9409C12.8006 11.9372 12.8073 11.933 12.8142 11.9291C12.8217 11.9247 12.8293 11.9205 12.8367 11.9158C12.8443 11.9108 12.8514 11.9054 12.8587 11.9001C12.8648 11.8956 12.8711 11.8914 12.8771 11.8867C12.89 11.8764 12.9025 11.8655 12.9143 11.8541C12.9145 11.8539 12.9147 11.8537 12.9148 11.8536C12.915 11.8534 12.9152 11.8532 12.9153 11.853C12.9271 11.8415 12.9383 11.8295 12.9489 11.8169C12.9539 11.8111 12.9581 11.805 12.9628 11.799Z"
|
||||
fill="currentcolor"
|
||||
/>
|
||||
<path
|
||||
d="M2.46848 1.00001H3.79954C4.08384 1.00001 4.3143 0.776156 4.3143 0.500016C4.3143 0.223852 4.08384 0 3.79954 0H1.2257H1.22567C1.20873 0 1.19177 0.000867188 1.1749 0.00248437C1.16728 0.00321094 1.1599 0.00459375 1.15239 0.00564844C1.14329 0.00691406 1.13417 0.00794531 1.12512 0.00967969C1.11649 0.0113438 1.10811 0.0136406 1.09964 0.0157266C1.09185 0.017625 1.08401 0.0192891 1.07629 0.0215625C1.06796 0.024 1.05993 0.0270469 1.05179 0.0298828C1.0441 0.0325781 1.03633 0.0350391 1.02873 0.0380859C1.02113 0.0411563 1.01381 0.0447422 1.00641 0.0481641C0.998612 0.0517266 0.990722 0.0551016 0.983073 0.0590859C0.975954 0.0627891 0.969198 0.0670078 0.962273 0.0710156C0.954793 0.0753516 0.947192 0.0794531 0.939881 0.0842109C0.932231 0.0891797 0.925041 0.0947109 0.917681 0.100055C0.9116 0.104484 0.905351 0.108586 0.899439 0.11332C0.87321 0.134227 0.849129 0.157617 0.827605 0.183094C0.822731 0.188836 0.818508 0.194906 0.813947 0.200836C0.808446 0.207984 0.802751 0.214969 0.797636 0.222398C0.792737 0.2295 0.788515 0.236859 0.784026 0.244148C0.7799 0.250852 0.775557 0.257437 0.771744 0.264352C0.767642 0.271781 0.764192 0.279422 0.7605 0.287016C0.757001 0.294211 0.753285 0.301312 0.750124 0.308695C0.746987 0.316078 0.744454 0.323602 0.741679 0.331102C0.738759 0.339 0.735646 0.346805 0.733113 0.354891C0.730772 0.362391 0.729059 0.370008 0.727104 0.377578C0.724957 0.385805 0.722592 0.393937 0.720879 0.402328C0.719093 0.411117 0.718032 0.419977 0.716729 0.428813C0.715667 0.436102 0.714219 0.443297 0.713471 0.45068C0.71183 0.467063 0.710938 0.483516 0.710938 0.499992V3C0.710938 3.27614 0.941401 3.49999 1.2257 3.49999C1.50999 3.49999 1.74046 3.27614 1.74046 3V1.70712L4.97983 4.85355C5.18085 5.04881 5.5068 5.04881 5.70782 4.85355C5.90885 4.6583 5.90885 4.3417 5.70782 4.14645L2.46848 1.00001Z"
|
||||
fill="currentcolor"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="javascript:" (click)="starTemplate(item.id)" *ngIf="!item.starByNowUser" nzTooltipTitle="收藏" nzTooltipPlacement="bottom" nz-tooltip>
|
||||
<svg width="16" height="13" viewBox="0 0 16 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M13.6048 1.52734C12.0189 0.1875 9.5853 0.378906 8.0814 1.9375C6.55015 0.378906 4.11655 0.1875 2.53062 1.52734C0.479836 3.25 0.780617 6.06641 2.25718 7.57031L7.04234 12.4648C7.31577 12.7383 7.67124 12.9023 8.0814 12.9023C8.46421 12.9023 8.81968 12.7383 9.09312 12.4648L13.9056 7.57031C15.3548 6.06641 15.6556 3.25 13.6048 1.52734ZM12.9486 6.64062L8.16343 11.5352C8.10874 11.5898 8.05405 11.5898 7.97202 11.5352L3.18687 6.64062C2.17515 5.62891 1.98374 3.71484 3.37827 2.53906C4.44468 1.63672 6.0853 1.77344 7.12437 2.8125L8.0814 3.79688L9.03843 2.8125C10.0501 1.77344 11.6908 1.63672 12.7572 2.51172C14.1517 3.71484 13.9603 5.62891 12.9486 6.64062Z"
|
||||
fill="currentcolor"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="javascript:" (click)="cancelStarTemplate(item.id)" *ngIf="item.starByNowUser" nzTooltipTitle="取消收藏" nzTooltipPlacement="bottom" nz-tooltip>
|
||||
<svg width="16" height="13" viewBox="0 0 16 13" style="fill: #b02a37" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M13.6048 1.52734C12.0189 0.1875 9.5853 0.378906 8.0814 1.9375C6.55015 0.378906 4.11655 0.1875 2.53062 1.52734C0.479836 3.25 0.780617 6.06641 2.25718 7.57031L7.04234 12.4648C7.31577 12.7383 7.67124 12.9023 8.0814 12.9023C8.46421 12.9023 8.81968 12.7383 9.09312 12.4648L13.9056 7.57031C15.3548 6.06641 15.6556 3.25 13.6048 1.52734ZM12.9486 6.64062L8.16343 11.5352C8.10874 11.5898 8.05405 11.5898 7.97202 11.5352L3.18687 6.64062C2.17515 5.62891 1.98374 3.71484 3.37827 2.53906C4.44468 1.63672 6.0853 1.77344 7.12437 2.8125L8.0814 3.79688L9.03843 2.8125C10.0501 1.77344 11.6908 1.63672 12.7572 2.51172C14.1517 3.71484 13.9603 5.62891 12.9486 6.64062Z"
|
||||
style="fill: #b02a37"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container bottom-0">
|
||||
<div class="d-flex justify-content-center">
|
||||
<nz-pagination [nzPageIndex]="pageIndex+1" [nzTotal]="totalElements" nzShowSizeChanger
|
||||
[(nzPageSize)]="pageSize" (nzPageIndexChange)="pageIndexChange($event)"
|
||||
(nzPageSizeChange)="pageSizeChange($event)" [nzPageSizeOptions]=pageSizeOptions></nz-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
nz-select {
|
||||
width: 352px;
|
||||
//height: 60px;
|
||||
}
|
||||
|
||||
.material-symbols-outlined {
|
||||
font-variation-settings:
|
||||
'FILL' 0,
|
||||
'wght' 400,
|
||||
'GRAD' 0,
|
||||
'opsz' 18
|
||||
}
|
||||
|
||||
second-container {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/deep/ .ant-checkbox-group, .ant-collapse {
|
||||
padding: 0;
|
||||
line-height: 1.5715;
|
||||
font-size: 17px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
box-sizing: border-box;
|
||||
font-variant: tabular-nums;
|
||||
font-feature-settings: 'tnum';
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/deep/ .ant-checkbox-wrapper {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
line-height: unset;
|
||||
cursor: pointer;
|
||||
font-size: 17px;
|
||||
font-family: "Gill Sans", sans-serif;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
-270
@@ -1,270 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {NzMessageService} from 'ng-zorro-antd/message';
|
||||
|
||||
import {TemplateService, TemplateVO} from '../../../service/template.service';
|
||||
import {CategoryService} from "../../../service/category.service";
|
||||
import {StarService} from "../../../service/star.service";
|
||||
import {LocalStorageService} from "../../../service/local-storage.service";
|
||||
import {saveAs} from "file-saver";
|
||||
|
||||
declare global {
|
||||
interface Window { URL: any; }
|
||||
}
|
||||
|
||||
window.URL = window.URL || {};
|
||||
|
||||
@Component({
|
||||
selector: 'market',
|
||||
templateUrl: './template-list.component.html',
|
||||
styleUrls: ['./template-list.component.less']
|
||||
})
|
||||
export class TemplateListComponent implements OnInit, OnDestroy {
|
||||
constructor(private templateService: TemplateService,
|
||||
private msg: NzMessageService,
|
||||
private categoryService: CategoryService,
|
||||
private starService: StarService,
|
||||
private localStorageService: LocalStorageService,) {}
|
||||
|
||||
templateList: TemplateVO[] = [];
|
||||
userId:number=0;
|
||||
|
||||
totalElements = 1;
|
||||
totalPages = 1;
|
||||
pageIndex=0;
|
||||
pageSize = 9;
|
||||
numberOfPages = 1;
|
||||
newPageIndex= this.pageIndex;
|
||||
newPageSize = this.pageSize;
|
||||
pageSizeOptions:number[]=[9,18,27];
|
||||
|
||||
nameLike='';
|
||||
type = 0;
|
||||
|
||||
allChecked = false;
|
||||
indeterminate = true;
|
||||
checkCategory:number[] = [1];
|
||||
categoryList = [
|
||||
{ label: '数据库监控模版', value: 1, checked: true },
|
||||
{ label: '应用服务监控模版', value: 2, checked: false },
|
||||
];
|
||||
|
||||
orderOption = 1;
|
||||
|
||||
loading = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.templateList=[];
|
||||
this.categoryService.clearCategoryList();
|
||||
this.categoryService.getAllCategoryByIsDel(0).subscribe(message => {
|
||||
// console.log('返回结果',message);
|
||||
if (message.code == 0) {
|
||||
this.categoryService.addCategoryList(message.data)
|
||||
this.categoryList=[];
|
||||
this.allChecked=true;
|
||||
this.indeterminate=false;
|
||||
this.categoryService.getCategoryList().forEach(item=>{
|
||||
this.checkCategory.push(item.id);
|
||||
this.categoryList.push({label: item.description, value: item.id, checked:true});
|
||||
})
|
||||
this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList));
|
||||
}else{
|
||||
this.msg.error('类别请求失败:'+message.msg);
|
||||
}
|
||||
})
|
||||
|
||||
const user=this.localStorageService.getData("userId");
|
||||
if(user==null) this.userId=0;
|
||||
else this.userId=parseInt(user);
|
||||
|
||||
this.templateService.getTemplatePage(0, this.userId,0,9).subscribe(message => {
|
||||
if (message.code == 0) {
|
||||
this.templateList.push(...message.data.content);
|
||||
console.log(this.templateList);
|
||||
this.totalElements=message.data.totalElements;
|
||||
this.totalPages=message.data.totalPages;
|
||||
this.pageIndex=message.data.pageable.pageNumber;
|
||||
this.pageSize=message.data.pageable.pageSize;
|
||||
this.numberOfPages=message.data.numberOfElements;
|
||||
// this.msg.success('查询成功');
|
||||
this.templateService.setTemplateSubject(this.templateList);
|
||||
} else {
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
orderOptionChange(orderValue:number) {
|
||||
this.msg.warning('排序功能开发中!');
|
||||
console.log(orderValue);
|
||||
}
|
||||
|
||||
tagChange(){
|
||||
this.msg.warning('标签功能开发中!');
|
||||
}
|
||||
|
||||
pageIndexChange(newIndex:number){
|
||||
this.newPageIndex=newIndex-1;
|
||||
// console.log("newPageIndex",this.newPageIndex,"newPageSize",this.newPageSize);
|
||||
this.getTemplatePageByOption()
|
||||
}
|
||||
|
||||
pageSizeChange(newSize:number){
|
||||
this.newPageSize=newSize;
|
||||
// console.log("newSize",newSize,"newPageIndex",this.newPageIndex);
|
||||
this.getTemplatePageByOption()
|
||||
}
|
||||
|
||||
getTemplatePageByOption(){
|
||||
this.templateService.getTemplatePageByOption(this.userId,this.allChecked,this.checkCategory,this.nameLike,this.orderOption,0,this.newPageIndex,this.newPageSize)
|
||||
.subscribe(message => {
|
||||
if (message.code == 0) {
|
||||
this.templateList=[];
|
||||
this.templateList.push(...message.data.content);
|
||||
this.totalElements=message.data.totalElements;
|
||||
this.totalPages=message.data.totalPages;
|
||||
this.pageIndex=message.data.pageable.pageNumber;
|
||||
this.pageSize=message.data.pageable.pageSize;
|
||||
this.numberOfPages=message.data.numberOfElements;
|
||||
// this.msg.success('查询成功');
|
||||
this.templateService.setTemplateSubject(this.templateList);
|
||||
console.log(this.templateList)
|
||||
console.log(message)
|
||||
} else {
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
updateAllChecked(): void {
|
||||
this.checkCategory=[];
|
||||
this.indeterminate = false;
|
||||
if (this.allChecked) {
|
||||
this.categoryList = this.categoryList.map(item => ({
|
||||
...item,
|
||||
checked: true
|
||||
}));
|
||||
} else {
|
||||
this.categoryList = this.categoryList.map(item => ({
|
||||
...item,
|
||||
checked: false
|
||||
}));
|
||||
}
|
||||
this.categoryList.forEach(item => {
|
||||
if (item.checked) {
|
||||
this.checkCategory.push(item.value);
|
||||
}
|
||||
})
|
||||
if(this.checkCategory.length!=0) this.getTemplatePageByOption();
|
||||
}
|
||||
|
||||
updateSingleChecked(): void {
|
||||
this.checkCategory=[];
|
||||
if (this.categoryList.every(item => !item.checked)) {
|
||||
this.allChecked = false;
|
||||
this.indeterminate = false;
|
||||
} else if (this.categoryList.every(item => item.checked)) {
|
||||
this.allChecked = true;
|
||||
this.indeterminate = false;
|
||||
} else {
|
||||
this.allChecked = false;
|
||||
this.indeterminate = true;
|
||||
}
|
||||
this.categoryList.forEach(item => {
|
||||
if (item.checked) {
|
||||
this.checkCategory.push(item.value);
|
||||
}
|
||||
})
|
||||
this.getTemplatePageByOption();
|
||||
}
|
||||
|
||||
downloadLatestTemplate(id:number,user:number,latest:number,name:string){
|
||||
this.templateService.downloadLatestTemplate(user,id,latest)
|
||||
.subscribe((blob:Blob)=>{
|
||||
saveAs(blob, `${name}-latest.yml`);
|
||||
for (let templateVO of this.templateList) {
|
||||
if(templateVO.id==id) {
|
||||
templateVO.download++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.error('下载文件时发生错误:', error);
|
||||
});
|
||||
}
|
||||
|
||||
pickTemplate(id:number){
|
||||
this.templateService.setNowTemplate(id);
|
||||
let nowTemplate = this.templateService.getNowTemplate();
|
||||
localStorage.setItem('nowTemplate', JSON.stringify(nowTemplate));
|
||||
// console.log(this.templateService.getNowTemplate());
|
||||
}
|
||||
|
||||
starTemplate(id:number){
|
||||
const formData = new FormData();
|
||||
formData.append('user', this.userId.toString());
|
||||
formData.append('template', id.toString());
|
||||
this.starService.starTemplate(formData)
|
||||
.subscribe(message=>{
|
||||
if (message.code == 0) {
|
||||
for (let templateVO of this.templateList) {
|
||||
if(templateVO.id==id) {
|
||||
templateVO.starByNowUser=true;
|
||||
templateVO.star++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.msg.success(message.msg);
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
cancelStarTemplate(id:number){
|
||||
const formData = new FormData();
|
||||
formData.append('templateId', id.toString());
|
||||
this.starService.cancelStarTemplate(this.userId,formData)
|
||||
.subscribe(message=>{
|
||||
if (message.code == 0) {
|
||||
this.msg.success(message.msg);
|
||||
for (let templateVO of this.templateList) {
|
||||
if(templateVO.id==id) {
|
||||
templateVO.starByNowUser=false;
|
||||
templateVO.star--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.templateList=[];
|
||||
this.categoryList=[];
|
||||
this.templateService.clearTemplateSubject();
|
||||
this.categoryService.clearCategoryList();
|
||||
}
|
||||
protected readonly event = event;
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Routes} from '@angular/router';
|
||||
import {LayoutMarketComponent} from '../layout/market/market.component';
|
||||
import {HomePageComponent} from './home-page/home-page.component';
|
||||
import {LoginComponent} from './login/login.component';
|
||||
import {SignUpComponent} from "./sign-up/sign-up.component";
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: LayoutMarketComponent,
|
||||
children: [
|
||||
{ path: '', redirectTo: 'home-page', pathMatch: 'full' },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: 'sign-up', component: SignUpComponent },
|
||||
{ path: 'home-page', component: HomePageComponent },
|
||||
{ path: 'market', loadChildren: () => import('./market/market.module').then(m => m.MarketModule) },
|
||||
{ path: 'user-center', loadChildren: () => import('./user-center/user-center.module').then(m => m.UserCenterModule) }
|
||||
]
|
||||
},
|
||||
{ path: '**', redirectTo: 'exception/404' }
|
||||
];
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {NgModule, Type} from '@angular/core';
|
||||
import {NzCollapseModule} from 'ng-zorro-antd/collapse';
|
||||
import {NzDividerModule} from 'ng-zorro-antd/divider';
|
||||
import {NzListModule} from 'ng-zorro-antd/list';
|
||||
import {NzTagModule} from 'ng-zorro-antd/tag';
|
||||
import {NzTimelineModule} from 'ng-zorro-antd/timeline';
|
||||
|
||||
import {LayoutModule} from '../layout/layout.module';
|
||||
import {HomePageComponent} from './home-page/home-page.component';
|
||||
import {LoginComponent} from './login/login.component';
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {NzMessageModule} from "ng-zorro-antd/message";
|
||||
import {BrowserModule} from "@angular/platform-browser";
|
||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {SignUpComponent} from "./sign-up/sign-up.component";
|
||||
|
||||
const COMPONENTS: Array<Type<void>> = [
|
||||
HomePageComponent,LoginComponent,SignUpComponent
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
NzTagModule,
|
||||
NzTimelineModule,
|
||||
NzDividerModule,
|
||||
LayoutModule,
|
||||
NzCollapseModule,
|
||||
NzListModule,
|
||||
RouterModule,
|
||||
COMPONENTS,
|
||||
NzMessageModule,
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule
|
||||
],
|
||||
exports:[RouterModule]
|
||||
})
|
||||
export class RoutesModule {}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<main>
|
||||
<div class="tp-register__area pt-xxl-4 pb-xxl-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-xl-6">
|
||||
<div class="tp-register__form-box">
|
||||
<div class="tp-register__form-title text-center mb-5">
|
||||
<h6>注册</h6>
|
||||
</div>
|
||||
<form>
|
||||
<div class="row">
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-register__input-box">
|
||||
<label for="sign-up-name">用户名</label>
|
||||
<input id="sign-up-name" type="text" placeholder="用户名" autocomplete="off" name="name" [(ngModel)]="SignUpForm.name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-register__input-box">
|
||||
<label for="sign-up-email">Email 地址</label>
|
||||
<input id="sign-up-email" type="email" placeholder="邮箱地址" autocomplete="off" name="email" [(ngModel)]="SignUpForm.email">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-register__input-box">
|
||||
<label for="sign-up-password">密码</label>
|
||||
<input id="sign-up-password" type="password" placeholder="密码" autocomplete="off" name="password" [(ngModel)]="SignUpForm.password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-register__input-box">
|
||||
<label for="sign-up-passwordOk">确认密码</label>
|
||||
<input id="sign-up-passwordOk" type="password" placeholder="密码" autocomplete="off" name="passwordOk" [(ngModel)]="passwordOk">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-12">
|
||||
<div class="tp-contact-4__comment-agree label-2 pt-5 pb-5">
|
||||
<div class="form-check-box">
|
||||
<input class="form-check-input" type="checkbox" value="" id="flexCheckDefault">
|
||||
<label class="form-check-label text-theme" for="flexCheckDefault">
|
||||
我同意 xxx & <span class="red">xxx</span> 和 xxx
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-contact-4__btn">
|
||||
<button type="button" class="btn-no-icon w-100" (click)="submitSignUp()">去注册</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, Injector, OnDestroy, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormsModule} from '@angular/forms';
|
||||
import {AuthService, LoginDTO, SignUpDTO} from "../../service/auth.service";
|
||||
import {LocalStorageService} from "../../service/local-storage.service";
|
||||
import {NzMessageService} from "ng-zorro-antd/message";
|
||||
import {Router} from "@angular/router";
|
||||
import {NzButtonComponent} from "ng-zorro-antd/button";
|
||||
import {DataService} from "../../service/data.service";
|
||||
|
||||
@Component({
|
||||
selector: 'login',
|
||||
templateUrl: './sign-up.component.html',
|
||||
styleUrls: ['./sign-up.component.less'],
|
||||
standalone: true,
|
||||
providers: [],
|
||||
imports: [
|
||||
NzButtonComponent,
|
||||
FormsModule
|
||||
],
|
||||
// changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class SignUpComponent implements OnInit,OnDestroy {
|
||||
constructor(
|
||||
fb: FormBuilder,
|
||||
private authService: AuthService,
|
||||
private localStorageService: LocalStorageService,
|
||||
private msg: NzMessageService,
|
||||
private injector: Injector,
|
||||
private dataService: DataService,
|
||||
) {}
|
||||
|
||||
SignUpForm: SignUpDTO={
|
||||
name:'',
|
||||
email:'',
|
||||
password:'',
|
||||
};
|
||||
|
||||
passwordOk:string='';
|
||||
|
||||
submitSignUp():void{
|
||||
// console.log(this.SignUpForm)
|
||||
if(this.passwordOk!=this.SignUpForm.password) this.msg.error('密码不一致');
|
||||
if(this.SignUpForm.email==null||this.SignUpForm.name==null||this.SignUpForm.password==null) this.msg.error('信息不全');
|
||||
this.authService.register(this.SignUpForm).subscribe(response => {
|
||||
console.log(response);
|
||||
if(response.code == 0) {
|
||||
this.msg.success('注册成功');
|
||||
// window.history.back();
|
||||
}else{
|
||||
this.msg.error('注册失败:'+response.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
}
|
||||
}
|
||||
-349
File diff suppressed because one or more lines are too long
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-302
@@ -1,302 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {saveAs} from 'file-saver';
|
||||
import {NzMessageService} from 'ng-zorro-antd/message';
|
||||
|
||||
import {TemplateService} from '../../../service/template.service';
|
||||
import {finalize, Observable, Subscription, window} from "rxjs";
|
||||
import {LocalStorageService} from "../../../service/local-storage.service";
|
||||
import {CategoryService} from "../../../service/category.service";
|
||||
import {VersionService} from "../../../service/version.service";
|
||||
import {NzUploadChangeParam, NzUploadFile} from "ng-zorro-antd/upload";
|
||||
|
||||
interface TemplateInfo {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
descriptionVersion: string;
|
||||
latest: number;
|
||||
versions: string[];
|
||||
currentVersion: string;
|
||||
user: string;
|
||||
userId: number;
|
||||
category: string;
|
||||
categoryId: number;
|
||||
download: number;
|
||||
star:number;
|
||||
create_time: string;
|
||||
update_time: string;
|
||||
off_shelf: number;
|
||||
is_del: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'market',
|
||||
templateUrl: './assets-detail.component.html',
|
||||
styleUrls: ['./assets-detail.component.less']
|
||||
})
|
||||
export class AssetsDetailComponent implements OnInit, OnDestroy {
|
||||
constructor(private templateService: TemplateService,
|
||||
private msg: NzMessageService,
|
||||
private localStorageService: LocalStorageService,
|
||||
private categoryService: CategoryService,
|
||||
private versionService: VersionService,) {}
|
||||
|
||||
userId:number=0;
|
||||
|
||||
templateInfo :any = null;
|
||||
categoryList: any[] = [];
|
||||
latestVersion :any = null;
|
||||
versionList: any[] = [];
|
||||
|
||||
totalElements = 10;
|
||||
totalPages = 1;
|
||||
pageIndex=0;
|
||||
pageSize = 2;
|
||||
numberOfPages = 1;
|
||||
newPageIndex=this.pageIndex;
|
||||
newPageSize = this.pageSize;
|
||||
pageSizeOptions:number[]=[2,5,10,20];
|
||||
|
||||
categoryStr='';
|
||||
|
||||
showPage = 1;
|
||||
|
||||
visible = false;
|
||||
|
||||
error = 'success';
|
||||
type = 0;
|
||||
loading = false;
|
||||
|
||||
count = 0;
|
||||
interval$: any;
|
||||
|
||||
fileList: NzUploadFile[] = [];
|
||||
file: any[] = [];
|
||||
|
||||
newTemplateInfo = {
|
||||
id: 0,
|
||||
name: '',
|
||||
description: '模版描述',
|
||||
descriptionVersion: '版本描述',
|
||||
latest: 0,
|
||||
currentVersion: 'v1.0.0',
|
||||
user: 'user',
|
||||
userId: 1,
|
||||
category: '',
|
||||
categoryId: 0,
|
||||
download: 0,
|
||||
star:0,
|
||||
create_time: '2024',
|
||||
update_time: '2024',
|
||||
off_shelf: 0,
|
||||
is_del: 0
|
||||
} as TemplateInfo;
|
||||
|
||||
open(): void {
|
||||
this.visible = true;
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
handleChange(info: NzUploadChangeParam) {
|
||||
if (info.file.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
|
||||
const isLt4M = info.file.size! / 1024 / 1024 < 4;
|
||||
if (!isLt4M) {
|
||||
// this.message.error('Message.File.SizeFile');
|
||||
console.log('error:文件超过4M');
|
||||
}
|
||||
// this.file = this.file.concat(info.file);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
this.file.pop();
|
||||
// this.msg.success(`${info.file.name} file uploaded successfully`);
|
||||
} else if (info.file.status === 'error') {
|
||||
// this.msg.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
}
|
||||
|
||||
beforeUpload = (file: any) => {
|
||||
while (this.file.length > 0) {
|
||||
this.file.pop();
|
||||
}
|
||||
console.log('beforeUpload', file);
|
||||
this.file.push(file);
|
||||
console.log('afterUpload', this.file);
|
||||
return false;
|
||||
};
|
||||
|
||||
getCategoryStr(value:number):string{
|
||||
for (const item of this.categoryList) {
|
||||
if(item.value==value){
|
||||
return item.label;
|
||||
}
|
||||
}
|
||||
return ' '
|
||||
}
|
||||
|
||||
updateTemplate(): void {
|
||||
if(this.file.length==0){
|
||||
this.msg.error("文件为空");
|
||||
return;
|
||||
}
|
||||
const formData = new FormData();
|
||||
if (this.file.length > 0) {
|
||||
formData.append('file', this.file[0]);
|
||||
this.newTemplateInfo.id=this.templateInfo.id;
|
||||
this.newTemplateInfo.name=this.templateInfo.name;
|
||||
this.newTemplateInfo.description=this.templateInfo.description;
|
||||
this.newTemplateInfo.userId=this.templateInfo.user;
|
||||
this.newTemplateInfo.categoryId=this.templateInfo.categoryId;
|
||||
this.newTemplateInfo.category=this.getCategoryStr(this.newTemplateInfo.categoryId)
|
||||
formData.append('templateDto', JSON.stringify(this.newTemplateInfo));
|
||||
const uploadTemplateRes$ = this.templateService
|
||||
.upload(formData)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
uploadTemplateRes$.unsubscribe();
|
||||
// this.tableLoading = false;
|
||||
})
|
||||
)
|
||||
.subscribe(
|
||||
message => {
|
||||
console.log('message', message);
|
||||
if (message.code === 0) {
|
||||
// this.notifySvc.success(this.i18nSvc.fanyi('common.notify.edit-success'), '');
|
||||
this.msg.success(`模版文件上传成功`);
|
||||
this.getVersions();
|
||||
this.close();
|
||||
} else {
|
||||
this.msg.error(`模版上传失败:${message.msg}`);
|
||||
// this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), message.msg);
|
||||
}
|
||||
// this.loadAlertConvergeTable();
|
||||
// this.tableLoading = false;
|
||||
},
|
||||
error => {
|
||||
console.log('err', error);
|
||||
// this.tableLoading = false;
|
||||
// this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), error.msg);
|
||||
this.msg.error(`模版上传失败`, error.msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
downloadTemplateNow(): void {
|
||||
this.templateService.downloadLatestTemplate(this.templateInfo.user, this.templateInfo.id, this.templateInfo.latest).subscribe(blob => {
|
||||
saveAs(blob, `${this.templateInfo.name}-${this.latestVersion.version}.yml`);
|
||||
this.localStorageService.removeData('nowTemplate');
|
||||
this.templateInfo.download++;
|
||||
this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo));
|
||||
});
|
||||
}
|
||||
|
||||
downloadVersion(version:string, versionId:number): void {
|
||||
this.templateService.downloadTemplate(this.templateInfo.user, this.templateInfo.id,version, versionId).subscribe(blob => {
|
||||
saveAs(blob, `${this.templateInfo.name}-${version}.yml`);
|
||||
this.localStorageService.removeData('nowTemplate');
|
||||
this.templateInfo.download++;
|
||||
this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo));
|
||||
});
|
||||
}
|
||||
|
||||
shareVersionNow(versionId:number): void {
|
||||
this.versionService.shareVersion(versionId).subscribe(message=>{
|
||||
if(message.code==0){
|
||||
this.msg.success('已复制分享链接,快去发送给对方吧!');
|
||||
const selBox = document.createElement('textarea');
|
||||
selBox.style.position = 'fixed';
|
||||
selBox.style.left = '0';
|
||||
selBox.style.top = '0';
|
||||
selBox.style.opacity = '0';
|
||||
selBox.value = message.msg;
|
||||
document.body.appendChild(selBox);
|
||||
selBox.focus();
|
||||
selBox.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(selBox);
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
const user=this.localStorageService.getData("userId");
|
||||
if(user==null) this.userId=0;
|
||||
else this.userId=parseInt(user);
|
||||
|
||||
this.templateInfo=JSON.parse(<string>this.localStorageService.getData('nowTemplate'));
|
||||
this.versionService.getVersion(this.templateInfo.latest).subscribe(response => {
|
||||
if(response.code == 0) {
|
||||
this.latestVersion=response.data;
|
||||
console.log(this.latestVersion);
|
||||
}else {
|
||||
this.msg.error('版本信息获取失败'+response.msg)
|
||||
}
|
||||
})
|
||||
this.categoryList=JSON.parse(<string>this.localStorageService.getData('categoryList'));
|
||||
// console.log(this.templateInfo);
|
||||
// console.log(this.categoryList);
|
||||
for (const item of this.categoryList) {
|
||||
if(item.value==this.templateInfo.categoryId){
|
||||
this.categoryStr=item.label;
|
||||
}
|
||||
}
|
||||
this.getVersions();
|
||||
}
|
||||
|
||||
pageIndexChange(newIndex:number){
|
||||
this.newPageIndex=newIndex-1;
|
||||
console.log("newPageIndex",this.newPageIndex,"newPageSize",this.newPageSize);
|
||||
this.getVersions()
|
||||
}
|
||||
|
||||
pageSizeChange(newSize:number){
|
||||
this.newPageSize=newSize;
|
||||
console.log("newSize",newSize,"newPageIndex",this.newPageIndex);
|
||||
this.getVersions()
|
||||
}
|
||||
|
||||
getVersions(){
|
||||
this.versionService.getVersionPage(this.templateInfo.id,0,this.newPageIndex,this.newPageSize).subscribe(response => {
|
||||
if(response.code == 0) {
|
||||
this.versionList=response.data.content;
|
||||
this.totalElements=response.data.totalElements;
|
||||
this.totalPages=response.data.totalPages;
|
||||
this.pageIndex=response.data.pageable.pageNumber;
|
||||
this.pageSize=response.data.pageable.pageSize;
|
||||
this.numberOfPages=response.data.numberOfElements;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.localStorageService.removeData('nowTemplate');
|
||||
}
|
||||
|
||||
protected readonly window = window;
|
||||
}
|
||||
-192
File diff suppressed because one or more lines are too long
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-231
@@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {FormBuilder} from '@angular/forms';
|
||||
import {NzMessageService} from 'ng-zorro-antd/message';
|
||||
import {NzUploadChangeParam, NzUploadFile} from 'ng-zorro-antd/upload';
|
||||
import {finalize, window} from 'rxjs';
|
||||
|
||||
import {TemplateService} from '../../../service/template.service';
|
||||
|
||||
import {CategoryService} from "../../../service/category.service";
|
||||
import {LocalStorageService} from "../../../service/local-storage.service";
|
||||
import {saveAs} from "file-saver";
|
||||
|
||||
interface TemplateInfo {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
descriptionVersion: string;
|
||||
latest: number;
|
||||
versions: string[];
|
||||
currentVersion: string;
|
||||
user: string;
|
||||
userId: number;
|
||||
category: string;
|
||||
categoryId: number;
|
||||
download: number;
|
||||
star:number,
|
||||
create_time: string;
|
||||
update_time: string;
|
||||
off_shelf: number;
|
||||
is_del: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'user-upload',
|
||||
templateUrl: './user-assets.component.html',
|
||||
styleUrls: ['./user-assets.component.less'],
|
||||
})
|
||||
export class UserAssetsComponent implements OnInit,OnDestroy {
|
||||
constructor(fb: FormBuilder,
|
||||
private templateService: TemplateService,
|
||||
private msg: NzMessageService,
|
||||
private categoryService: CategoryService,
|
||||
private localStorageService: LocalStorageService,) {}
|
||||
|
||||
userId:number=0;
|
||||
|
||||
templateList: any[] = [];
|
||||
|
||||
totalElements = 1;
|
||||
totalPages = 1;
|
||||
pageIndex=0;
|
||||
pageSize = 9;
|
||||
numberOfPages = 1;
|
||||
newPageIndex=this.pageIndex;
|
||||
newPageSize = this.pageSize;
|
||||
pageSizeOptions:number[]=[9,18,27];
|
||||
|
||||
nameLike='';
|
||||
type = 0;
|
||||
|
||||
allChecked = false;
|
||||
indeterminate = true;
|
||||
checkCategory:number[] = [1];
|
||||
categoryList = [
|
||||
{ label: '数据库监控模版', value: 1, checked: true },
|
||||
{ label: '应用服务监控模版', value: 2, checked: false },
|
||||
];
|
||||
|
||||
orderOption = 1;
|
||||
|
||||
loading = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
const user=this.localStorageService.getData("userId");
|
||||
if(user==null) this.userId=0;
|
||||
else this.userId=parseInt(user);
|
||||
|
||||
// this.templateList=[];
|
||||
this.categoryService.clearCategoryList();
|
||||
this.categoryService.getAllCategoryByIsDel(0).subscribe(message => {
|
||||
console.log('返回结果',message);
|
||||
if (message.code == 0) {
|
||||
this.categoryService.addCategoryList(message.data)
|
||||
this.categoryList=[];
|
||||
this.allChecked=true;
|
||||
this.indeterminate=false;
|
||||
this.categoryService.getCategoryList().forEach(item=>{
|
||||
this.checkCategory.push(item.id);
|
||||
this.categoryList.push({label: item.description, value: item.id, checked:true});
|
||||
})
|
||||
this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList));
|
||||
}else{
|
||||
this.msg.error('类别请求失败:'+message.msg);
|
||||
}
|
||||
})
|
||||
|
||||
this.templateService.getTemplatePageByUser(this.userId,0,this.pageSize).subscribe(message => {
|
||||
if (message.code == 0) {
|
||||
this.templateList.push(...message.data.content);
|
||||
this.totalElements=message.data.totalElements;
|
||||
this.totalPages=message.data.totalPages;
|
||||
this.pageIndex=message.data.pageable.pageNumber;
|
||||
this.pageSize=message.data.pageable.pageSize;
|
||||
this.numberOfPages=message.data.numberOfElements;
|
||||
this.msg.success('查询成功');
|
||||
this.templateService.setTemplateSubject(this.templateList);
|
||||
} else {
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
orderOptionChange(orderValue:number) {
|
||||
//
|
||||
console.log(orderValue);
|
||||
}
|
||||
|
||||
pageIndexChange(newIndex:number){
|
||||
this.newPageIndex=newIndex-1;
|
||||
this.getTemplatePageByOption()
|
||||
}
|
||||
|
||||
pageSizeChange(newSize:number){
|
||||
this.newPageSize=newSize;
|
||||
this.getTemplatePageByOption()
|
||||
}
|
||||
|
||||
getTemplatePageByOption(){
|
||||
this.templateService.getTemplatePageByOption(this.userId,this.allChecked,this.checkCategory,this.nameLike,this.orderOption,0,this.newPageIndex,this.newPageSize)
|
||||
.subscribe(message => {
|
||||
if (message.code == 0) {
|
||||
this.templateList=[];
|
||||
this.templateList.push(...message.data.content);
|
||||
this.totalElements=message.data.totalElements;
|
||||
this.totalPages=message.data.totalPages;
|
||||
this.pageIndex=message.data.pageable.pageNumber;
|
||||
this.pageSize=message.data.pageable.pageSize;
|
||||
this.numberOfPages=message.data.numberOfElements;
|
||||
this.msg.success('查询成功');
|
||||
this.templateService.setTemplateSubject(this.templateList);
|
||||
} else {
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
updateAllChecked(): void {
|
||||
this.checkCategory=[];
|
||||
this.indeterminate = false;
|
||||
if (this.allChecked) {
|
||||
this.categoryList = this.categoryList.map(item => ({
|
||||
...item,
|
||||
checked: true
|
||||
}));
|
||||
} else {
|
||||
this.categoryList = this.categoryList.map(item => ({
|
||||
...item,
|
||||
checked: false
|
||||
}));
|
||||
}
|
||||
this.categoryList.forEach(item => {
|
||||
if (item.checked) {
|
||||
this.checkCategory.push(item.value);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
updateSingleChecked(): void {
|
||||
this.checkCategory=[];
|
||||
if (this.categoryList.every(item => !item.checked)) {
|
||||
this.allChecked = false;
|
||||
this.indeterminate = false;
|
||||
} else if (this.categoryList.every(item => item.checked)) {
|
||||
this.allChecked = true;
|
||||
this.indeterminate = false;
|
||||
} else {
|
||||
this.allChecked = false;
|
||||
this.indeterminate = true;
|
||||
}
|
||||
this.categoryList.forEach(item => {
|
||||
if (item.checked) {
|
||||
this.checkCategory.push(item.value);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
downloadLatestTemplate(id:number,user:number,latest:number,name:string){
|
||||
this.templateService.downloadLatestTemplate(user,id,latest)
|
||||
.subscribe((blob:Blob)=>{
|
||||
saveAs(blob, `${name}-latest.yml`);
|
||||
},
|
||||
error => {
|
||||
console.error('下载文件时发生错误:', error);
|
||||
});
|
||||
}
|
||||
|
||||
pickTemplate(id:number){
|
||||
this.templateService.setNowTemplate(id);
|
||||
let nowTemplate = this.templateService.getNowTemplate();
|
||||
localStorage.setItem('nowTemplate', JSON.stringify(nowTemplate));
|
||||
// console.log(this.templateService.getNowTemplate());
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.templateList=[];
|
||||
this.categoryList=[];
|
||||
this.templateService.clearTemplateSubject();
|
||||
this.categoryService.clearCategoryList();
|
||||
}
|
||||
|
||||
protected readonly window = window;
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { UserUploadComponent } from './user-upload/user-upload.component';
|
||||
import {UserAssetsComponent} from "./user-assets/user-assets.component";
|
||||
import {AssetsDetailComponent} from "./assets-detail/assets-detail.component";
|
||||
import {UserStarComponent} from "./user-star/user-star.component";
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: UserUploadComponent },
|
||||
{ path: 'upload', component: UserUploadComponent },
|
||||
{ path: 'assets', component: UserAssetsComponent },
|
||||
{ path: 'detail', component: AssetsDetailComponent },
|
||||
{ path: 'star', component: UserStarComponent },
|
||||
{ path: '**', component: UserUploadComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class UserCenterRoutingModule {}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {NgModule, Type} from '@angular/core';
|
||||
import {NzDividerModule} from 'ng-zorro-antd/divider';
|
||||
import {NzUploadModule} from 'ng-zorro-antd/upload';
|
||||
|
||||
import {UserCenterRoutingModule} from './user-center-routing.module';
|
||||
import {UserUploadComponent} from './user-upload/user-upload.component';
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select";
|
||||
import {NzAutosizeDirective, NzInputDirective, NzInputGroupComponent} from "ng-zorro-antd/input";
|
||||
import {NzFormControlComponent, NzFormDirective, NzFormItemComponent, NzFormLabelComponent} from "ng-zorro-antd/form";
|
||||
import {NzColDirective, NzRowDirective} from "ng-zorro-antd/grid";
|
||||
import {NzDatePickerComponent} from "ng-zorro-antd/date-picker";
|
||||
import {NzTimePickerComponent} from "ng-zorro-antd/time-picker";
|
||||
import {NzInputNumberComponent} from "ng-zorro-antd/input-number";
|
||||
import {NzIconDirective} from "ng-zorro-antd/icon";
|
||||
import {UserAssetsComponent} from "./user-assets/user-assets.component";
|
||||
import {NzPaginationComponent} from "ng-zorro-antd/pagination";
|
||||
import {AssetsDetailComponent} from "./assets-detail/assets-detail.component";
|
||||
import {NzDrawerComponent, NzDrawerContentDirective} from "ng-zorro-antd/drawer";
|
||||
import {NzButtonComponent} from "ng-zorro-antd/button";
|
||||
import {UserStarComponent} from "./user-star/user-star.component";
|
||||
import {NzTooltipDirective} from "ng-zorro-antd/tooltip";
|
||||
import {NzAvatarComponent} from "ng-zorro-antd/avatar";
|
||||
import {NzCardComponent, NzCardMetaComponent} from "ng-zorro-antd/card";
|
||||
|
||||
const COMPONENTS: Array<Type<void>> = [UserUploadComponent, UserAssetsComponent,AssetsDetailComponent,UserStarComponent];
|
||||
|
||||
@NgModule({
|
||||
|
||||
imports: [
|
||||
UserCenterRoutingModule,
|
||||
NzDividerModule,
|
||||
NzUploadModule,
|
||||
FormsModule,
|
||||
CommonModule,
|
||||
NzOptionComponent,
|
||||
NzSelectComponent,
|
||||
NzAutosizeDirective,
|
||||
NzInputDirective,
|
||||
NzFormItemComponent,
|
||||
NzFormLabelComponent,
|
||||
NzFormControlComponent,
|
||||
NzColDirective,
|
||||
NzDatePickerComponent,
|
||||
NzTimePickerComponent,
|
||||
NzInputNumberComponent,
|
||||
NzFormDirective,
|
||||
NzIconDirective,
|
||||
NzPaginationComponent,
|
||||
NzDrawerComponent,
|
||||
NzButtonComponent,
|
||||
NzInputGroupComponent,
|
||||
NzRowDirective,
|
||||
NzDrawerContentDirective,
|
||||
NzTooltipDirective,
|
||||
NzAvatarComponent,
|
||||
NzCardComponent,
|
||||
NzCardMetaComponent,
|
||||
],
|
||||
declarations: COMPONENTS,
|
||||
providers:[...COMPONENTS],
|
||||
})
|
||||
export class UserCenterModule {}
|
||||
-208
File diff suppressed because one or more lines are too long
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-226
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {FormBuilder} from '@angular/forms';
|
||||
import {NzMessageService} from 'ng-zorro-antd/message';
|
||||
|
||||
import {TemplateService, TemplateVO} from '../../../service/template.service';
|
||||
|
||||
import {CategoryService} from "../../../service/category.service";
|
||||
import {StarService} from "../../../service/star.service";
|
||||
import {LocalStorageService} from "../../../service/local-storage.service";
|
||||
import {saveAs} from "file-saver";
|
||||
|
||||
// interface TemplateInfo {
|
||||
// id: number;
|
||||
// name: string;
|
||||
// description: string;
|
||||
// descriptionVersion: string;
|
||||
// latest: number;
|
||||
// versions: string[];
|
||||
// currentVersion: string;
|
||||
// user: string;
|
||||
// userId: number;
|
||||
// category: string;
|
||||
// categoryId: number;
|
||||
// download: number;
|
||||
// star:number,
|
||||
// create_time: string;
|
||||
// update_time: string;
|
||||
// off_shelf: number;
|
||||
// is_del: number;
|
||||
// }
|
||||
|
||||
@Component({
|
||||
selector: 'user-upload',
|
||||
templateUrl: './user-star.component.html',
|
||||
styleUrls: ['./user-star.component.less'],
|
||||
})
|
||||
export class UserStarComponent implements OnInit,OnDestroy {
|
||||
constructor(fb: FormBuilder,
|
||||
private templateService: TemplateService,
|
||||
private msg: NzMessageService,
|
||||
private categoryService: CategoryService,
|
||||
private starService: StarService,
|
||||
private localStorageService: LocalStorageService,) {}
|
||||
|
||||
userId:number=0;
|
||||
|
||||
templateList: TemplateVO[] = [];
|
||||
|
||||
totalElements = 1;
|
||||
totalPages = 1;
|
||||
pageIndex=0;
|
||||
pageSize = 9;
|
||||
numberOfPages = 1;
|
||||
newPageIndex=this.pageIndex;
|
||||
newPageSize = this.pageSize;
|
||||
pageSizeOptions:number[]=[9,18,27];
|
||||
|
||||
nameLike='';
|
||||
type = 0;
|
||||
|
||||
allChecked = false;
|
||||
indeterminate = true;
|
||||
checkCategory:number[] = [1];
|
||||
categoryList = [
|
||||
{ label: '数据库监控模版', value: 1, checked: true },
|
||||
{ label: '应用服务监控模版', value: 2, checked: false },
|
||||
];
|
||||
|
||||
orderOption = 1;
|
||||
|
||||
loading = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.templateList=[]
|
||||
const user=this.localStorageService.getData("userId");
|
||||
if(user==null) this.userId=0;
|
||||
else this.userId=parseInt(user);
|
||||
|
||||
this.categoryService.clearCategoryList();
|
||||
this.categoryService.getAllCategoryByIsDel(0).subscribe(message => {
|
||||
console.log('返回结果',message);
|
||||
if (message.code == 0) {
|
||||
this.categoryService.addCategoryList(message.data)
|
||||
this.categoryList=[];
|
||||
this.allChecked=true;
|
||||
this.indeterminate=false;
|
||||
this.categoryService.getCategoryList().forEach(item=>{
|
||||
this.checkCategory.push(item.id);
|
||||
this.categoryList.push({label: item.description, value: item.id, checked:true});
|
||||
})
|
||||
this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList));
|
||||
}else{
|
||||
this.msg.error('类别请求失败:'+message.msg);
|
||||
}
|
||||
})
|
||||
|
||||
this.starService.getTemplatePageByUserStar(this.userId,0,9).subscribe(message => {
|
||||
if (message.code == 0) {
|
||||
this.templateList=message.data.content;
|
||||
// this.templateList.push(...message.data.content);
|
||||
this.totalElements=message.data.totalElements;
|
||||
this.totalPages=message.data.totalPages;
|
||||
this.pageIndex=message.data.pageable.pageNumber;
|
||||
this.pageSize=message.data.pageable.pageSize;
|
||||
this.numberOfPages=message.data.numberOfElements;
|
||||
this.msg.success('查询成功');
|
||||
this.templateService.setTemplateSubject(this.templateList);
|
||||
} else {
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pageIndexChange(newIndex:number){
|
||||
this.newPageIndex=newIndex-1;
|
||||
this.getTemplatePageByOption()
|
||||
}
|
||||
|
||||
pageSizeChange(newSize:number){
|
||||
this.newPageSize=newSize;
|
||||
this.getTemplatePageByOption()
|
||||
}
|
||||
|
||||
getTemplatePageByOption(){
|
||||
this.templateService.getTemplatePageByOption(this.userId,this.allChecked,this.checkCategory,this.nameLike,this.orderOption,0,this.newPageIndex,this.newPageSize)
|
||||
.subscribe(message => {
|
||||
if (message.code == 0) {
|
||||
this.templateList=[];
|
||||
this.templateList.push(...message.data.content);
|
||||
this.totalElements=message.data.totalElements;
|
||||
this.totalPages=message.data.totalPages;
|
||||
this.pageIndex=message.data.pageable.pageNumber;
|
||||
this.pageSize=message.data.pageable.pageSize;
|
||||
this.numberOfPages=message.data.numberOfElements;
|
||||
this.msg.success('查询成功');
|
||||
this.templateService.setTemplateSubject(this.templateList);
|
||||
} else {
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
downloadLatestTemplate(id:number,user:number,latest:number,name:string){
|
||||
this.templateService.downloadLatestTemplate(user,id,latest)
|
||||
.subscribe((blob:Blob)=>{
|
||||
saveAs(blob, `${name}-latest.yml`);
|
||||
},
|
||||
error => {
|
||||
console.error('下载文件时发生错误:', error);
|
||||
});
|
||||
}
|
||||
|
||||
pickTemplate(id:number){
|
||||
this.templateService.setNowTemplate(id);
|
||||
let nowTemplate = this.templateService.getNowTemplate();
|
||||
localStorage.setItem('nowTemplate', JSON.stringify(nowTemplate));
|
||||
// console.log(this.templateService.getNowTemplate());
|
||||
}
|
||||
|
||||
starTemplate(id:number){
|
||||
const formData = new FormData();
|
||||
formData.append('user', this.userId.toString());
|
||||
formData.append('template', id.toString());
|
||||
this.starService.starTemplate(formData)
|
||||
.subscribe(message=>{
|
||||
if (message.code == 0) {
|
||||
for (let templateVO of this.templateList) {
|
||||
if(templateVO.id==id) {
|
||||
templateVO.starByNowUser=true;
|
||||
templateVO.star++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.msg.success(message.msg);
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
cancelStarTemplate(id:number){
|
||||
const formData = new FormData();
|
||||
formData.append('templateId', id.toString());
|
||||
this.starService.cancelStarTemplate(1,formData)
|
||||
.subscribe(message=>{
|
||||
if (message.code == 0) {
|
||||
this.msg.success(message.msg);
|
||||
for (let templateVO of this.templateList) {
|
||||
if(templateVO.id==id) {
|
||||
templateVO.starByNowUser=false;
|
||||
templateVO.star--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.msg.error(message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.templateList=[];
|
||||
this.categoryList=[];
|
||||
this.templateService.clearTemplateSubject();
|
||||
this.categoryService.clearCategoryList();
|
||||
}
|
||||
}
|
||||
-169
@@ -1,169 +0,0 @@
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<main>
|
||||
<div
|
||||
class="tp-breadcrumb__area fix tp-breadcrumb-height"
|
||||
style="background-image: url('../../../../assets/svg/breadcrumb.svg');height: 250px"
|
||||
>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="tp-breadcrumb__content text-center z-index-5">
|
||||
<div class="tp-breadcrumb__list">
|
||||
<span><a href="#">Apache </a></span>
|
||||
<span class="dvdr">.</span>
|
||||
<span>HertzBeat</span>
|
||||
</div>
|
||||
<h3 class="tp-breadcrumb__title"
|
||||
><span class="p-relative z-index-5">
|
||||
个人
|
||||
<span class="tp-title-shape">
|
||||
<img src="assets/svg/title-line.svg">
|
||||
</span>
|
||||
</span>
|
||||
中心
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tp-service-details-area pt-xxl-4 pb-xxl-5">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-2">
|
||||
<div class="tp-service-widget">
|
||||
<div class="tp-service-widget-item mb-4">
|
||||
<div class="tp-service-widget-tab">
|
||||
<ul>
|
||||
<li
|
||||
><a href="javascript:">总览 <i class="fa-regular fa-arrow-right-long"></i></a
|
||||
></li>
|
||||
<li
|
||||
><a href="/user-center/assets">资产 <i class="fa-regular fa-arrow-right-long"></i></a
|
||||
></li>
|
||||
<li
|
||||
><a href="/user-center/star">收藏 <i class="fa-regular fa-arrow-right-long"></i></a
|
||||
></li>
|
||||
<li
|
||||
><a class="active" href="javascript:">上传 <i class="fa-regular fa-arrow-right-long"></i></a
|
||||
></li>
|
||||
<li
|
||||
><a href="javascript:">通知 <i class="fa-regular fa-arrow-right-long"></i></a
|
||||
></li>
|
||||
<li
|
||||
><a href="javascript:">设置 <i class="fa-regular fa-arrow-right-long"></i></a
|
||||
></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-10">
|
||||
<div class="tp-service-contact-form"
|
||||
style="background-image: url('../../../../assets/svg/upload-bg.svg')">
|
||||
<h6>新建模版</h6>
|
||||
<span>按照规定格式上传自定义模版吧!</span>
|
||||
<form nz-form>
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="2">模版名称</nz-form-label>
|
||||
<nz-form-control
|
||||
[nzValidateStatus]="error"
|
||||
[nzSpan]="24"
|
||||
nzErrorTip="不能具备特殊字符"
|
||||
>
|
||||
<input nz-input [(ngModel)]="templateInfo.name" name="name" />
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="2">模版类别</nz-form-label>
|
||||
<nz-form-control [nzValidateStatus]="error" [nzSpan]="24">
|
||||
<nz-select nzShowSearch nzAllowClear nzPlaceHolder="请选择模版类别"
|
||||
nzSize="large" [(ngModel)]="templateInfo.categoryId" name="categorySelect">
|
||||
<nz-option *ngFor="let temp of categoryList" [nzLabel]="temp.label" [nzValue]=temp.value></nz-option>
|
||||
</nz-select>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="2">模版标签</nz-form-label>
|
||||
<nz-form-control
|
||||
[nzSpan]="24"
|
||||
[nzValidateStatus]="error"
|
||||
>
|
||||
<input nz-input disabled [ngModel]="'该功能开发中'" name="tag" />
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="2">首版版本号</nz-form-label>
|
||||
<nz-form-control [nzSpan]="24" [nzValidateStatus]="error">
|
||||
<input nz-input [(ngModel)]="templateInfo.currentVersion" name="currentVersion" />
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="2">模版描述</nz-form-label>
|
||||
<nz-form-control
|
||||
[nzSpan]="24"
|
||||
>
|
||||
<textarea nz-input placeholder="请对该模版进行简单描述" [nzAutosize]="{ minRows: 3, maxRows: 5 }"
|
||||
[(ngModel)]="templateInfo.description" name="description"></textarea>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="2">首版描述</nz-form-label>
|
||||
<nz-form-control
|
||||
[nzSpan]="24"
|
||||
>
|
||||
<textarea nz-input placeholder="请对该模版进行简单描述" [nzAutosize]="{ minRows: 3, maxRows: 5 }"
|
||||
[(ngModel)]="templateInfo.descriptionVersion" name="descriptionVersion"></textarea>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-label [nzSpan]="2">首版文件</nz-form-label>
|
||||
<nz-form-control [nzSpan]="48">
|
||||
<nz-upload
|
||||
nzType="drag"
|
||||
nzAccept=".yml"
|
||||
[nzAction]="'template/localFileUpload'"
|
||||
[nzLimit]="1"
|
||||
[nzMultiple]="true"
|
||||
[(nzFileList)]="fileList"
|
||||
(nzChange)="handleChange($event)"
|
||||
[nzBeforeUpload]="beforeUpload"
|
||||
[nzShowUploadList]="true"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<span nz-icon nzType="inbox"></span>
|
||||
</p>
|
||||
<p class="ant-upload-text">点击该区域上传文件</p>
|
||||
</nz-upload>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<div class="tp-service-contact-btn mt-4 z-index-5">
|
||||
<button type="button" class="tp-main-btn w-100" (click)="uploadTemplate()">上传</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-211
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {FormBuilder} from '@angular/forms';
|
||||
import {NzMessageService} from 'ng-zorro-antd/message';
|
||||
import {NzUploadChangeParam, NzUploadFile} from 'ng-zorro-antd/upload';
|
||||
import {finalize, window} from 'rxjs';
|
||||
|
||||
import {TemplateService} from '../../../service/template.service';
|
||||
|
||||
import {CategoryService} from "../../../service/category.service";
|
||||
import {LocalStorageService} from "../../../service/local-storage.service";
|
||||
|
||||
interface TemplateInfo {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
descriptionVersion: string;
|
||||
latest: number;
|
||||
versions: string[];
|
||||
currentVersion: string;
|
||||
user: string;
|
||||
userId: number;
|
||||
category: string;
|
||||
categoryId: number;
|
||||
download: number;
|
||||
star:number,
|
||||
create_time: string;
|
||||
update_time: string;
|
||||
off_shelf: number;
|
||||
is_del: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'user-upload',
|
||||
templateUrl: './user-upload.component.html',
|
||||
styleUrls: ['./user-upload.component.less'],
|
||||
})
|
||||
export class UserUploadComponent implements OnInit,OnDestroy {
|
||||
constructor(fb: FormBuilder,
|
||||
private templateService: TemplateService,
|
||||
private msg: NzMessageService,
|
||||
private categoryService: CategoryService,
|
||||
private localStorageService: LocalStorageService,) {}
|
||||
|
||||
userId:number=0;
|
||||
|
||||
error = 'success';
|
||||
type = 0;
|
||||
loading = false;
|
||||
|
||||
count = 0;
|
||||
interval$: any;
|
||||
|
||||
fileList: NzUploadFile[] = [];
|
||||
file: any[] = [];
|
||||
uniqueFile:any=null;
|
||||
|
||||
templateInfo = {
|
||||
id: 0,
|
||||
name: '',
|
||||
description: '模版描述',
|
||||
descriptionVersion: '首版描述',
|
||||
latest: 0,
|
||||
currentVersion: 'v1.0.0',
|
||||
user: 'user',
|
||||
userId: 1,
|
||||
category: '',
|
||||
categoryId: 0,
|
||||
download: 0,
|
||||
star:0,
|
||||
create_time: '2024',
|
||||
update_time: '2024',
|
||||
off_shelf: 0,
|
||||
is_del: 0
|
||||
} as TemplateInfo;
|
||||
|
||||
categoryList = [
|
||||
{ label: '数据库监控模版', value: 1, checked: true },
|
||||
{ label: '应用服务监控模版', value: 2, checked: false },
|
||||
];
|
||||
|
||||
ngOnInit(): void {
|
||||
const user=this.localStorageService.getData("userId");
|
||||
const userName=this.localStorageService.getData("userInfo");
|
||||
if(user==null) this.userId=0;
|
||||
else this.userId=parseInt(user);
|
||||
this.templateInfo.userId=this.userId;
|
||||
this.templateInfo.user=userName==null?'user':userName;
|
||||
|
||||
this.categoryList=[];
|
||||
this.categoryService.clearCategoryList();
|
||||
this.categoryService.getAllCategoryByIsDel(0).subscribe(message => {
|
||||
if (message.code == 0) {
|
||||
for (const item of message.data) {
|
||||
this.categoryList.push({label: item.description, value: item.id, checked:true});
|
||||
}
|
||||
this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList));
|
||||
}else{
|
||||
this.msg.error('类别请求失败:'+message.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getCategoryStr(value:number):string{
|
||||
for (const item of this.categoryList) {
|
||||
if(item.value==value){
|
||||
return item.label;
|
||||
}
|
||||
}
|
||||
return ' '
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.interval$) {
|
||||
clearInterval(this.interval$);
|
||||
}
|
||||
}
|
||||
|
||||
handleChange(info: NzUploadChangeParam) {
|
||||
if (info.file.status !== 'uploading') {
|
||||
const isLt4M = info.file.size! / 1024 / 1024 < 4;
|
||||
if (!isLt4M) {
|
||||
// this.message.error('Message.File.SizeFile');
|
||||
console.log('error:文件超过4M');
|
||||
}
|
||||
// this.file = this.file.concat(info.file);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
this.file.pop();
|
||||
this.fileList.reverse()
|
||||
if(this.fileList.length > 1) {
|
||||
this.fileList.pop()
|
||||
}
|
||||
// this.msg.success(`${info.file.name} file uploaded successfully`);
|
||||
} else if (info.file.status === 'error') {
|
||||
this.fileList=[];
|
||||
// this.msg.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
}
|
||||
|
||||
beforeUpload = (file: any) => {
|
||||
this.file.push(file);
|
||||
this.uniqueFile=file;
|
||||
this.fileList=[]
|
||||
return true;
|
||||
};
|
||||
|
||||
uploadTemplate(): void {
|
||||
console.log('ss',this.file, this.fileList);
|
||||
console.log(this.uniqueFile)
|
||||
if(this.uniqueFile==null){
|
||||
this.msg.error("文件为空");
|
||||
return;
|
||||
}
|
||||
const formData = new FormData();
|
||||
if (this.uniqueFile != null) {
|
||||
formData.append('file', this.uniqueFile);
|
||||
this.templateInfo.category=this.getCategoryStr(this.templateInfo.categoryId)
|
||||
formData.append('templateDto', JSON.stringify(this.templateInfo));
|
||||
const uploadTemplateRes$ = this.templateService
|
||||
.upload(formData)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
uploadTemplateRes$.unsubscribe();
|
||||
// this.tableLoading = false;
|
||||
})
|
||||
)
|
||||
.subscribe(
|
||||
message => {
|
||||
console.log('message', message);
|
||||
if (message.code === 0) {
|
||||
// this.notifySvc.success(this.i18nSvc.fanyi('common.notify.edit-success'), '');
|
||||
this.msg.success(`模版文件上传成功`);
|
||||
this.fileList=[]
|
||||
} else {
|
||||
this.msg.error(`模版上传失败:${message.msg}`);
|
||||
// this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), message.msg);
|
||||
}
|
||||
// this.loadAlertConvergeTable();
|
||||
// this.tableLoading = false;
|
||||
},
|
||||
error => {
|
||||
console.log('err', error);
|
||||
// this.tableLoading = false;
|
||||
// this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), error.msg);
|
||||
this.msg.error(`模版上传失败`, error.msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly window = window;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
|
||||
import {Message} from '../pojo/Message';
|
||||
|
||||
const auth_login_uri = '/auth/login';
|
||||
const auth_refresh_uri = '/auth/refresh';
|
||||
const auth_register_uri = '/auth/register';
|
||||
|
||||
export interface LoginDTO {
|
||||
type:number,
|
||||
identifier:string,
|
||||
credential:string,
|
||||
}
|
||||
|
||||
export interface SignUpDTO {
|
||||
name:string,
|
||||
email:string,
|
||||
password:string,
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
public tryLogin(data: LoginDTO): Observable<Message<any>> {
|
||||
return this.http.post<Message<any>>(auth_login_uri,data);
|
||||
}
|
||||
|
||||
public register(data:SignUpDTO): Observable<Message<any>> {
|
||||
return this.http.post<Message<any>>(auth_register_uri,data);
|
||||
}
|
||||
|
||||
public refreshToken(refreshToken: string): Observable<Message<any>> {
|
||||
return this.http.post<Message<any>>(auth_refresh_uri, {"token":refreshToken});
|
||||
}
|
||||
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||
import {Injectable, Optional} from '@angular/core';
|
||||
import {BehaviorSubject, Observable} from 'rxjs';
|
||||
|
||||
import {Message} from '../pojo/Message';
|
||||
|
||||
const category_uri = '/category/all';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CategoryService {
|
||||
constructor(@Optional() private http: HttpClient) {}
|
||||
|
||||
private categorySubject = new BehaviorSubject<any[]>([]);
|
||||
|
||||
addCategoryList(arr: any[]) {
|
||||
const currentData = this.categorySubject.getValue();
|
||||
this.categorySubject.next([...currentData, ...arr]);
|
||||
}
|
||||
|
||||
clearCategoryList() {
|
||||
this.categorySubject.next([]);
|
||||
}
|
||||
|
||||
getCategoryList() {
|
||||
return this.categorySubject.getValue();
|
||||
}
|
||||
|
||||
public getAllCategoryByIsDel(isDel: number): Observable<Message<any>> {
|
||||
if(this.http==null){
|
||||
console.log('http注册失败,为null')
|
||||
}
|
||||
return this.http.get<Message<any>>(category_uri+'/'+isDel,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class DataService {
|
||||
|
||||
private isLoginMessageSource = new BehaviorSubject(false);
|
||||
isLoginMsg = this.isLoginMessageSource.asObservable();
|
||||
|
||||
constructor() { }
|
||||
|
||||
sendLoginMsg(message: boolean) {
|
||||
this.isLoginMessageSource.next(message)
|
||||
}
|
||||
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
const AuthorizationConst = 'Authorization';
|
||||
const RefreshTokenConst = 'refresh-token';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LocalStorageService {
|
||||
constructor() {}
|
||||
|
||||
public putData(key: string, value: string) {
|
||||
localStorage.setItem(key, value);
|
||||
}
|
||||
|
||||
public removeData(key: string) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
|
||||
public getData(key: string): string | null {
|
||||
const data = localStorage.getItem(key);
|
||||
return data === null ? null : data;
|
||||
}
|
||||
|
||||
public getAuthorizationToken(): string | null {
|
||||
return this.getData(AuthorizationConst);
|
||||
}
|
||||
|
||||
public getRefreshToken(): string | null {
|
||||
return this.getData(RefreshTokenConst);
|
||||
}
|
||||
|
||||
public storageRefreshToken(token: string) {
|
||||
return this.putData(RefreshTokenConst, token);
|
||||
}
|
||||
|
||||
public storageAuthorizationToken(token: string) {
|
||||
return this.putData(AuthorizationConst, token);
|
||||
}
|
||||
|
||||
public hasAuthorizationToken() {
|
||||
return localStorage.getItem(AuthorizationConst) != null;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||
import {Injectable, Optional} from '@angular/core';
|
||||
import {BehaviorSubject, Observable} from 'rxjs';
|
||||
|
||||
import {Message} from '../pojo/Message';
|
||||
|
||||
const template_star_uri = '/template/star';
|
||||
const star_page_user_uri='/star/page/user';
|
||||
const star_user_uri='/star';
|
||||
const star_isStar_uri='/star/isStar';
|
||||
const star_cancel_uri='/star/cancel';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class StarService {
|
||||
constructor(@Optional() private http: HttpClient) {}
|
||||
|
||||
public getTemplatePageByUserStar(userId: number, page:number, size:number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(star_page_user_uri+'/'+userId+'?page='+page+'&size='+size);
|
||||
}
|
||||
|
||||
public getTemplateIdsByUser(userId: number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(star_user_uri+'/'+userId);
|
||||
}
|
||||
|
||||
public assertTemplateStarByUser(userId: number,template:number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(star_isStar_uri+'/'+userId+'/'+template);
|
||||
}
|
||||
|
||||
public cancelStarTemplate(userId: number, data:FormData): Observable<Message<any>> {
|
||||
return this.http.post<Message<any>>(star_cancel_uri+'/'+userId,data);
|
||||
}
|
||||
|
||||
public starTemplate(data:FormData): Observable<Message<any>> {
|
||||
return this.http.post<Message<any>>(template_star_uri,data);
|
||||
}
|
||||
|
||||
}
|
||||
-166
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||
import {Injectable, Optional} from '@angular/core';
|
||||
import {BehaviorSubject, Observable} from 'rxjs';
|
||||
|
||||
import {Message} from '../pojo/Message';
|
||||
|
||||
export interface TemplateVO {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
latest: number;
|
||||
user: number;
|
||||
categoryId: number;
|
||||
tag:number;
|
||||
download: number;
|
||||
star:number,
|
||||
create_time: string;
|
||||
update_time: string;
|
||||
off_shelf: number;
|
||||
isDel: number;
|
||||
starByNowUser:boolean;
|
||||
}
|
||||
|
||||
const template_count_uri = '/template/count';
|
||||
const template_upload_uri = '/template/upload';
|
||||
const template_page_uri = '/template/page';
|
||||
const template_page_name_uri='/template/page/name';
|
||||
const template_page_option_uri='/template/page/option';
|
||||
const template_page_order_uri='/template/page/order';
|
||||
const template_page_user_uri='/template/page/user';
|
||||
const template_download_uri = '/template/download/';
|
||||
const template_download_latest_uri = '/template/download/latest/';
|
||||
const template_page_category_uri = '/template/page/category';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TemplateService {
|
||||
constructor(@Optional() private http: HttpClient) {}
|
||||
|
||||
private templateSubject = new BehaviorSubject<any[]>([]);
|
||||
private nowTemplateSubject=new BehaviorSubject<any>('');
|
||||
|
||||
setNowTemplate(id:number){
|
||||
console.log(this.getTemplateById(id));
|
||||
this.nowTemplateSubject.next(this.getTemplateById(id));
|
||||
}
|
||||
|
||||
getNowTemplate(){
|
||||
return this.nowTemplateSubject.value;
|
||||
}
|
||||
|
||||
setTemplateSubject(item: any[]) {
|
||||
this.clearTemplateSubject();
|
||||
this.templateSubject.next([...item]);
|
||||
}
|
||||
|
||||
clearTemplateSubject(){
|
||||
this.templateSubject.next([]);
|
||||
}
|
||||
|
||||
getTemplateById(id:number) {
|
||||
for (const item of this.templateSubject.getValue()) {
|
||||
if (item.id === id) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public upload(data: FormData): Observable<Message<any>> {
|
||||
return this.http.post<Message<any>>(template_upload_uri, data);
|
||||
}
|
||||
|
||||
public getTemplatePage(isDel: number, userId:number, page:number, size:number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(template_page_uri+'/'+isDel+'/'+userId+'?page='+page+'&size='+size,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
|
||||
public getTemplatePageByUser(userId: number, page:number, size:number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(template_page_user_uri+'/'+userId+'?page='+page+'&size='+size,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
|
||||
public getTemplatePageByOption(userId:number, allCategory:boolean,category: number[],nameLike:string,orderOption:number,
|
||||
isDel: number, page:number, size:number): Observable<Message<any>> {
|
||||
var categoryStr='';
|
||||
for (const id of category) {
|
||||
categoryStr+=id+'_';
|
||||
}
|
||||
categoryStr=categoryStr.substring(0,categoryStr.length-1);
|
||||
if(page<0){
|
||||
page=0;
|
||||
}
|
||||
if(nameLike!=''){
|
||||
if(allCategory){
|
||||
return this.http.get<Message<any>>(template_page_name_uri+'/'+nameLike+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'&category='+category,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
else if(!allCategory){
|
||||
return this.http.get<Message<any>>(template_page_option_uri+'/'+nameLike+'/'+categoryStr+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'&category='+category,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
else{
|
||||
return this.http.get<Message<any>>(template_page_option_uri+'/'+nameLike+'/'+categoryStr+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'&category='+category,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(allCategory){
|
||||
return this.http.get<Message<any>>(
|
||||
template_page_order_uri+'/'+orderOption+'/'+isDel+'/'+userId+'?page='+page+'&size='+size+'',
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
else if(!allCategory&&category.length>0){
|
||||
return this.http.get<Message<any>>(
|
||||
template_page_category_uri+'/'+categoryStr+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'',
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
else{
|
||||
return this.http.get<Message<any>>(
|
||||
template_page_category_uri+'/'+'_'+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'',
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getTemplateCount(isDel:number, offshelf:number): Observable<any> {
|
||||
return this.http.get<Message<number>>(`${template_count_uri}/${isDel}/${offshelf}`);
|
||||
}
|
||||
|
||||
public downloadTemplate(ownerId: number, templateId: number, version: string, versionId:number): Observable<any> {
|
||||
const httpOptions: Object = {
|
||||
responseType: 'blob'
|
||||
};
|
||||
return this.http.get<Blob>(`${template_download_uri + ownerId}/${templateId}/${version}/${versionId}`,
|
||||
httpOptions);
|
||||
}
|
||||
|
||||
public downloadLatestTemplate(user: number, templateId: number, latest: number): Observable<any> {
|
||||
const httpOptions: Object = {
|
||||
responseType: 'blob'
|
||||
};
|
||||
return this.http.get<Blob>(`${template_download_latest_uri + user}/${templateId}/${latest}`, httpOptions);
|
||||
}
|
||||
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||
import {Injectable, Optional} from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
|
||||
import {Message} from '../pojo/Message';
|
||||
|
||||
const template_upload_uri = '/template/upload';
|
||||
const version_page_uri = '/version/page';
|
||||
const version_get_uri = '/version/get';
|
||||
const share_uri='/share/getShareURL';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class VersionService {
|
||||
constructor(@Optional() private http: HttpClient) {}
|
||||
|
||||
public upload(data: FormData): Observable<Message<any>> {
|
||||
return this.http.post<Message<any>>(template_upload_uri, data);
|
||||
}
|
||||
|
||||
public getVersion(id: number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(version_get_uri+'/'+id);
|
||||
}
|
||||
|
||||
public getVersionPage(templateId :number, isDel: number, page:number, size:number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(version_page_uri+'/'+templateId+'/'+isDel+'?page='+page+'&size='+size,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
|
||||
public shareVersion(versionId:number): Observable<Message<any>> {
|
||||
return this.http.get<Message<any>>(share_uri+'/'+versionId,
|
||||
{headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export const CONSTANTS = {
|
||||
VERSION: 'v1.6.0'
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 6.1 KiB |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1730129285495" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15074" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M614.318657 0H411.286337L309.924677 176.10441l101.36166 176.10341H614.319657L715.679318 176.10441z m-34.811883 292.312021H445.688222L378.830446 176.10441l66.857776-116.208611h133.819552l66.856776 116.208611z m340.023861 207.537305H716.704314l-101.25966 175.899411 101.25966 176.308409h200.26733l76.174744-127.879572 27.746907-48.429837z m22.422925 193.714351l-58.769803 98.49467H751.209199l-66.755777-116.30961 66.755777-116.209611h133.819551l67.164776 116.209611z m-564.148111 30.715897l27.542908-48.531837-101.259661-176.001411H101.261376L0.001715 675.747737l101.259661 176.10441h200.267329z m-242.039189 67.779773L69.008484 675.747737l66.755776-116.207611H269.380813l66.857776 116.207611-10.238966 17.71294-58.666803 98.49567zM615.136655 802.297313a18.121939 18.121939 0 0 0-21.296929-8.599972 282.790053 282.790053 0 0 1-84.263718 12.592958 287.295038 287.295038 0 0 1-83.034722-12.081959 18.121939 18.121939 0 0 0-10.238965 34.709883 322.720919 322.720919 0 0 0 93.683686 13.821954 317.396937 317.396937 0 0 0 95.116681-14.436951 18.224939 18.224939 0 0 0 10.033967-26.517912z m106.788642 149.1765a18.429938 18.429938 0 0 0-24.469918-6.654978 435.550541 435.550541 0 0 1-376.576739 0 17.81494 17.81494 0 0 0-24.981916 6.347979v0.716998a17.81494 17.81494 0 0 0 6.347979 24.059919l6.449978 3.173989a472.921416 472.921416 0 0 0 399.305662 1.330996l7.780974-3.582988a18.633938 18.633938 0 0 0 6.14398-25.391915z m-0.921997-672.061749a18.224939 18.224939 0 0 0 2.96999 22.421925 289.957029 289.957029 0 0 1 81.089728 146.821508 18.121939 18.121939 0 1 0 35.424882-7.371975 324.256914 324.256914 0 0 0-33.06989-88.972702 320.365927 320.365927 0 0 0-58.462804-76.687743 18.121939 18.121939 0 0 0-27.951906 3.788987z m79.144735-165.968444a18.429938 18.429938 0 0 0 5.93798 24.572918 437.700534 437.700534 0 0 1 181.223393 331.013891 18.01994 18.01994 0 0 0 17.712941 18.941936h0.819997a17.91794 17.91794 0 0 0 18.019939-16.995943v-7.167976a476.095405 476.095405 0 0 0-192.077356-352.20782c-2.251992-1.739994-4.504985-3.275989-6.859977-4.913983a18.224939 18.224939 0 0 0-24.776917 6.756977zM199.245048 460.738457a18.224939 18.224939 0 0 0 15.766947-15.971947 289.44503 289.44503 0 0 1 66.653777-153.579485 18.326939 18.326939 0 0 0 1.023996-22.319926 18.01994 18.01994 0 0 0-28.360905-1.330995 327.635903 327.635903 0 0 0-49.554834 80.57773 321.389923 321.389923 0 0 0-24.879917 93.170688 17.91794 17.91794 0 0 0 19.350936 19.453935zM22.42464 499.028328a18.633938 18.633938 0 0 0 15.869947-19.657934 437.598534 437.598534 0 0 1 151.223493-346.26884 18.01994 18.01994 0 0 0 4.197986-25.596914v-0.716998a17.81494 17.81494 0 0 0-24.572918-3.787987l-5.527981 4.606985A476.300405 476.300405 0 0 0 1.844709 474.76441v8.599971a17.91794 17.91794 0 0 0 20.579931 15.664947z" fill="#0091FF" p-id="15075"></path></svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1730129120871" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="26355" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M734.55 958.642c-8.92 7.075-17.596 9.65-26.331 11.97-29.26 7.77-59.262 11.006-89.31 12.8-36.894 2.206-73.877 3.857-110.828 3.979-52.548 0.17-105.076-2.068-157.183-9.542-14.54-2.086-28.854-5.96-43.121-9.608-4.68-1.197-8.879-4.263-13.297-6.475l0.039-1.995c3.269-1.666 6.37-3.934 9.835-4.896 16.514-4.584 33.14-8.764 49.7-13.183 7.797-2.081 15.703-3.917 23.272-6.657 25.706-9.31 39.178-28.68 42.117-55.065 2.053-18.432 2.273-37.082 2.939-55.647 0.411-11.5 0.098-11.51-11.558-11.51-90.01 0.001-180.022 0.052-270.033-0.041-18.044-0.02-35.893-1.801-53.185-7.532-29.098-9.648-45.89-30.241-51.496-59.69-2.778-14.601-4.365-29.664-4.388-44.522-0.286-187.912-0.218-375.824-0.137-563.736 0.008-18.217 1.314-36.326 7.147-53.849 9.396-28.227 29.064-45.242 57.587-51.658 12.126-2.726 24.786-3.095 37.214-4.443 2.199-0.24 4.446-0.03 6.671-0.035 214.147-0.446 428.294-0.992 642.441-1.25 40.394-0.05 80.81 0.43 121.176 1.863 23.697 0.84 45.85 7.633 63.176 25.38 14.369 14.717 21.044 33.029 23.097 52.888 1.697 16.415 2.284 33.009 2.297 49.525 0.153 174.359 0.161 348.718 0.006 523.077-0.02 20.964 0.83 41.966-3.716 62.8-8.5 38.966-33.794 63.296-73.402 68.702-11.179 1.525-22.541 2.39-33.82 2.414-89.202 0.191-178.404 0.169-267.607-0.034-6.032-0.016-8.468 1.756-9.785 7.641-3.78 16.865-6.653 33.743-4.377 51.067 3.798 28.888 20.722 47.906 45.959 60.541 20.776 10.405 43.144 15.928 65.582 21.219l23.32 5.502zM903.574 636.58v-6.17c0-169.508-0.033-339.016 0.136-508.523 0.006-6.19-2.18-7.162-7.686-7.16-255.679 0.124-511.356 0.108-767.034 0.11-8.224 0-8.23 0.007-8.23 8.19l-0.002 506.703v6.85h782.816z" p-id="26356" fill="#1296db"></path><path d="M265.493 387.607c0.792-32.67 8.11-63.154 27.95-89.562 24.382-32.451 57.926-47.38 97.853-49.024 26.832-1.106 52.396 3.726 75.453 18.203 29.132 18.291 45.493 45.49 52.192 78.518 7.359 36.294 5.524 72.107-10.345 106.174-17.094 36.695-45.623 59.478-85.428 67.648-31.731 6.51-62.44 3.522-91.246-11.82-35.49-18.903-55.009-49.605-62.67-88.307-2.066-10.45-2.548-21.212-3.76-31.83z m198.846-1.825c0.346-16.533-1.834-32.656-8.117-48.05-9.59-23.498-26.106-38.864-51.97-41.687-27.17-2.966-49.449 6.956-63.405 30.469-21.474 36.18-21.773 74.334-4.228 112.011 11.557 24.814 33.178 35.697 60.083 35.383 27.186-0.32 47.046-12.97 58.422-37.905 7.259-15.904 9.636-32.84 9.215-50.221z m152.31-70.271c12.084 22.908 27.609 41.113 51.98 51.006 13.38 5.433 26.174 12.685 38.442 20.378 10.524 6.6 18.518 16.18 24.053 27.564 6.253 12.863 7.644 26.488 2.277 39.455-13.172 31.815-34.913 55.935-69.363 64.046-16.035 3.776-33.31 2.902-50.026 2.964-11.23 0.041-22.724-0.835-33.644-3.309-19.672-4.449-28.233-18.613-25.024-38.58 2.26-14.065 2.33-13.767 16.273-11.287 20.268 3.605 40.586 7.066 61.002 9.652 16.137 2.045 28.356-5.98 38.17-18.087 4.694-5.79 3.007-11.746-0.115-17.563-8.191-15.263-20.959-25.334-36.455-32.465-13.568-6.244-27.41-12.067-40.371-19.414-17.24-9.776-30.599-23.801-35.318-43.601-9.413-39.495 4.868-80.21 56.205-90.848 14.941-3.097 30.414-4.097 45.705-4.903 13.47-0.707 27.12-0.728 40.517 0.63 16.615 1.683 25.14 12.239 24.663 28.85-0.178 6.187-0.032 13.702-3.342 18.15-4.127 5.548-11.303 0.123-17.097-0.602-10.013-1.254-19.918-3.349-29.92-4.728-11.81-1.63-22.964 0.737-33.187 6.873-8.626 5.18-17.095 10.621-25.426 15.819z" p-id="26357" fill="#1296db"></path></svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1730128991635" class="icon" viewBox="0 0 1042 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19230" xmlns:xlink="http://www.w3.org/1999/xlink" width="203.515625" height="200"><path d="M271.725714 0L18.285714 146.322286v292.662857l253.44 146.322286 253.44-146.322286V146.322286z" fill="#FFA552" p-id="19231"></path><path d="M778.605714 0L525.165714 146.322286v292.662857l253.44 146.322286 253.476572-146.322286V146.322286z" fill="#C3C5C6" p-id="19232"></path><path d="M271.725714 584.905143v292.662857l253.44 146.322286 253.44-146.322286V584.905143l-253.44-146.340572z" fill="#FA6400" p-id="19233"></path><path d="M778.276571 584.685714L525.165714 730.806857 272.091429 584.685714V292.461714l253.074285-146.139428 253.110857 146.139428z" fill="#181818" p-id="19234"></path><path d="M488.594286 501.924571a73.142857 73.142857 0 1 0 73.142857-126.72 73.142857 73.142857 0 0 0-73.142857 126.72M235.154286 229.302857a73.142857 73.142857 0 0 1 73.142857 126.665143 73.142857 73.142857 0 0 1-73.142857-126.665143m616.612571 63.323429a73.142857 73.142857 0 1 1-146.285714 0 73.142857 73.142857 0 0 1 146.285714 0m-363.154286 501.906285a73.142857 73.142857 0 0 0 73.142858-126.646857 73.142857 73.142857 0 0 0-73.142858 126.646857" fill="#FFFFFF" p-id="19235"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user