mirror of https://github.com/halo-dev/halo
commit
640fa13171
|
@ -1,15 +1,15 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '2.1.3.RELEASE'
|
||||
id "io.freefair.lombok" version "3.6.6"
|
||||
// id 'war'
|
||||
id 'java'
|
||||
id 'war'
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
group = 'run.halo.app'
|
||||
archivesBaseName = 'halo'
|
||||
version = '1.0.1'
|
||||
version = '1.0.2'
|
||||
sourceCompatibility = '1.8'
|
||||
description = 'Halo, personal blog system developed in Java.'
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ import java.io.IOException;
|
|||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.HALO_ADMIN_RELATIVE_PATH;
|
||||
|
||||
/**
|
||||
* Mvc configuration.
|
||||
*
|
||||
|
@ -88,12 +90,10 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
|
|||
.addResourceLocations("classpath:/admin/");
|
||||
registry.addResourceHandler("/upload/**")
|
||||
.addResourceLocations(workDir + "upload/");
|
||||
registry.addResourceHandler("/favicon.ico")
|
||||
.addResourceLocations("classpath:/static/halo-admin/images/favicon.ico");
|
||||
registry.addResourceHandler("/backup/**")
|
||||
.addResourceLocations(workDir + "backup/");
|
||||
registry.addResourceHandler("/admin/**")
|
||||
.addResourceLocations(workDir + "templates/admin/")
|
||||
.addResourceLocations(workDir + HALO_ADMIN_RELATIVE_PATH)
|
||||
.addResourceLocations("classpath:/admin/");
|
||||
|
||||
if (!haloProperties.isDocDisabled()) {
|
||||
|
@ -122,7 +122,7 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
|
|||
configurer.setDefaultEncoding("UTF-8");
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("auto_import","/common/macro/common_macro.ftl as common");
|
||||
properties.setProperty("auto_import", "/common/macro/common_macro.ftl as common");
|
||||
|
||||
configurer.setFreemarkerSettings(properties);
|
||||
|
||||
|
|
|
@ -67,4 +67,10 @@ public class AdminController {
|
|||
return adminService.refreshToken(refreshToken);
|
||||
}
|
||||
|
||||
@PutMapping("halo-admin")
|
||||
@ApiOperation("Updates halo-admin manually")
|
||||
public void updateAdmin() {
|
||||
adminService.updateAdminAssets();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -82,6 +82,20 @@ public class HaloConst {
|
|||
*/
|
||||
public static String USER_SESSION_KEY = "user_session";
|
||||
|
||||
/**
|
||||
* Github Api url for halo-admin release.
|
||||
*/
|
||||
public final static String HALO_ADMIN_RELEASES_LATEST = "https://api.github.com/repos/halo-dev/halo-admin/releases/latest";
|
||||
|
||||
/**
|
||||
* Halo admin version regex.
|
||||
*/
|
||||
public final static String HALO_ADMIN_VERSION_REGEX = "halo-admin-\\d+\\.\\d+(\\.\\d+)?(-\\S*)?\\.zip";
|
||||
|
||||
public final static String HALO_ADMIN_RELATIVE_PATH = "templates/admin/";
|
||||
|
||||
public final static String HALO_ADMIN_RELATIVE_BACKUP_PATH = "templates/admin-backup/";
|
||||
|
||||
static {
|
||||
// Set version
|
||||
HALO_VERSION = HaloConst.class.getPackage().getImplementationVersion();
|
||||
|
|
|
@ -64,4 +64,9 @@ public interface AdminService {
|
|||
*/
|
||||
@NonNull
|
||||
AuthToken refreshToken(@NonNull String refreshToken);
|
||||
|
||||
/**
|
||||
* Updates halo admin assets.
|
||||
*/
|
||||
void updateAdminAssets();
|
||||
}
|
||||
|
|
|
@ -182,7 +182,6 @@ public interface BasePostService<POST extends BasePost> extends CrudService<POST
|
|||
@Transactional
|
||||
void increaseLike(@NonNull Integer postId);
|
||||
|
||||
|
||||
/**
|
||||
* Creates or updates by post.
|
||||
*
|
||||
|
|
|
@ -2,15 +2,17 @@ package run.halo.app.service.impl;
|
|||
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import run.halo.app.cache.StringCacheStore;
|
||||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.exception.BadRequestException;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
import run.halo.app.exception.ServiceException;
|
||||
import run.halo.app.model.dto.EnvironmentDTO;
|
||||
import run.halo.app.model.dto.StatisticDTO;
|
||||
import run.halo.app.model.entity.User;
|
||||
|
@ -24,11 +26,20 @@ import run.halo.app.security.context.SecurityContextHolder;
|
|||
import run.halo.app.security.token.AuthToken;
|
||||
import run.halo.app.security.util.SecurityUtils;
|
||||
import run.halo.app.service.*;
|
||||
import run.halo.app.utils.FileUtils;
|
||||
import run.halo.app.utils.HaloUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.*;
|
||||
|
||||
/**
|
||||
* Admin service implementation.
|
||||
|
@ -61,7 +72,9 @@ public class AdminServiceImpl implements AdminService {
|
|||
|
||||
private final StringCacheStore cacheStore;
|
||||
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
private final HaloProperties haloProperties;
|
||||
|
||||
private final String driverClassName;
|
||||
|
||||
|
@ -77,7 +90,8 @@ public class AdminServiceImpl implements AdminService {
|
|||
UserService userService,
|
||||
LinkService linkService,
|
||||
StringCacheStore cacheStore,
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
RestTemplate restTemplate,
|
||||
HaloProperties haloProperties,
|
||||
@Value("${spring.datasource.driver-class-name}") String driverClassName,
|
||||
@Value("${spring.profiles.active:prod}") String mode) {
|
||||
this.postService = postService;
|
||||
|
@ -90,7 +104,8 @@ public class AdminServiceImpl implements AdminService {
|
|||
this.userService = userService;
|
||||
this.linkService = linkService;
|
||||
this.cacheStore = cacheStore;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.restTemplate = restTemplate;
|
||||
this.haloProperties = haloProperties;
|
||||
this.driverClassName = driverClassName;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
@ -220,6 +235,101 @@ public class AdminServiceImpl implements AdminService {
|
|||
return buildAuthToken(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void updateAdminAssets() {
|
||||
// Request github api
|
||||
ResponseEntity<Map> responseEntity = restTemplate.getForEntity(HaloConst.HALO_ADMIN_RELEASES_LATEST, Map.class);
|
||||
|
||||
if (responseEntity == null ||
|
||||
responseEntity.getStatusCode().isError() ||
|
||||
responseEntity.getBody() == null) {
|
||||
log.debug("Failed to request remote url: [{}]", HALO_ADMIN_RELEASES_LATEST);
|
||||
throw new ServiceException("系统无法访问到 Github 的 API").setErrorData(HALO_ADMIN_RELEASES_LATEST);
|
||||
}
|
||||
|
||||
Object assetsObject = responseEntity.getBody().get("assets");
|
||||
|
||||
if (assetsObject instanceof List) {
|
||||
try {
|
||||
List assets = (List) assetsObject;
|
||||
Map assetMap = (Map) assets.stream()
|
||||
.filter(assetPredicate())
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new ServiceException("Halo admin 最新版暂无资源文件,请稍后再试"));
|
||||
|
||||
Object browserDownloadUrl = assetMap.getOrDefault("browser_download_url", "");
|
||||
// Download the assets
|
||||
ResponseEntity<byte[]> downloadResponseEntity = restTemplate.getForEntity(browserDownloadUrl.toString(), byte[].class);
|
||||
|
||||
if (downloadResponseEntity == null ||
|
||||
downloadResponseEntity.getStatusCode().isError() ||
|
||||
downloadResponseEntity.getBody() == null) {
|
||||
throw new ServiceException("Failed to request remote url: " + browserDownloadUrl.toString()).setErrorData(browserDownloadUrl.toString());
|
||||
}
|
||||
|
||||
String adminTargetName = haloProperties.getWorkDir() + HALO_ADMIN_RELATIVE_PATH;
|
||||
|
||||
Path adminPath = Paths.get(adminTargetName);
|
||||
Path adminBackupPath = Paths.get(haloProperties.getWorkDir(), HALO_ADMIN_RELATIVE_BACKUP_PATH);
|
||||
|
||||
backupAndClearAdminAssetsIfPresent(adminPath, adminBackupPath);
|
||||
|
||||
// Create temp folder
|
||||
Path assetTempPath = FileUtils.createTempDirectory()
|
||||
.resolve(assetMap.getOrDefault("name", "halo-admin-latest.zip").toString());
|
||||
|
||||
// Unzip
|
||||
FileUtils.unzip(downloadResponseEntity.getBody(), assetTempPath);
|
||||
|
||||
// Copy it to template/admin folder
|
||||
FileUtils.copyFolder(FileUtils.tryToSkipZipParentFolder(assetTempPath), adminPath);
|
||||
} catch (Throwable t) {
|
||||
log.error("Failed to update halo admin", t);
|
||||
throw new ServiceException("更新 Halo admin 失败");
|
||||
}
|
||||
} else {
|
||||
throw new ServiceException("Github API 返回内容有误").setErrorData(assetsObject);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@SuppressWarnings("unchecked")
|
||||
private Predicate<Object> assetPredicate() {
|
||||
return asset -> {
|
||||
if (!(asset instanceof Map)) {
|
||||
return false;
|
||||
}
|
||||
Map aAssetMap = (Map) asset;
|
||||
// Get content-type
|
||||
String contentType = aAssetMap.getOrDefault("content_type", "").toString();
|
||||
|
||||
Object name = aAssetMap.getOrDefault("name", "");
|
||||
return name.toString().matches(HALO_ADMIN_VERSION_REGEX) && contentType.equalsIgnoreCase("application/zip");
|
||||
};
|
||||
}
|
||||
|
||||
private void backupAndClearAdminAssetsIfPresent(@NonNull Path sourcePath, @NonNull Path backupPath) throws IOException {
|
||||
Assert.notNull(sourcePath, "Source path must not be null");
|
||||
Assert.notNull(backupPath, "Backup path must not be null");
|
||||
|
||||
if (!FileUtils.isEmpty(sourcePath)) {
|
||||
// Clone this assets
|
||||
Path adminPathBackup = Paths.get(haloProperties.getWorkDir(), HALO_ADMIN_RELATIVE_BACKUP_PATH);
|
||||
|
||||
// Delete backup
|
||||
FileUtils.deleteFolder(backupPath);
|
||||
|
||||
// Copy older assets into backup
|
||||
FileUtils.copyFolder(sourcePath, backupPath);
|
||||
|
||||
// Delete older assets
|
||||
FileUtils.deleteFolder(sourcePath);
|
||||
} else {
|
||||
FileUtils.createIfAbsent(sourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds authentication token.
|
||||
*
|
||||
|
|
|
@ -5,7 +5,6 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.PullResult;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.transport.RemoteConfig;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
|
@ -34,10 +33,9 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.service.ThemeService;
|
||||
import run.halo.app.utils.FileUtils;
|
||||
import run.halo.app.utils.FilenameUtils;
|
||||
import run.halo.app.utils.GitUtils;
|
||||
import run.halo.app.utils.HaloUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -46,6 +44,7 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.DEFAULT_THEME_ID;
|
||||
|
@ -127,15 +126,17 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
|
||||
Optional<ThemeProperty[]> themePropertiesOptional = cacheStore.getAny(THEMES_CACHE_KEY, ThemeProperty[].class);
|
||||
|
||||
try {
|
||||
if (themePropertiesOptional.isPresent()) {
|
||||
// Convert to theme properties
|
||||
ThemeProperty[] themeProperties = themePropertiesOptional.get();
|
||||
return new HashSet<>(Arrays.asList(themeProperties));
|
||||
}
|
||||
if (themePropertiesOptional.isPresent()) {
|
||||
// Convert to theme properties
|
||||
ThemeProperty[] themeProperties = themePropertiesOptional.get();
|
||||
return new HashSet<>(Arrays.asList(themeProperties));
|
||||
}
|
||||
|
||||
try (Stream<Path> pathStream = Files.list(getBasePath())) {
|
||||
|
||||
// List and filter sub folders
|
||||
List<Path> themePaths = Files.list(getBasePath()).filter(path -> Files.isDirectory(path)).collect(Collectors.toList());
|
||||
List<Path> themePaths = pathStream.filter(path -> Files.isDirectory(path))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(themePaths)) {
|
||||
return Collections.emptySet();
|
||||
|
@ -172,9 +173,8 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
// Get the theme path
|
||||
Path themePath = Paths.get(getThemeOfNonNullBy(themeId).getThemePath());
|
||||
|
||||
try {
|
||||
return Files.list(themePath)
|
||||
.filter(path -> StringUtils.startsWithIgnoreCase(path.getFileName().toString(), CUSTOM_SHEET_PREFIX))
|
||||
try (Stream<Path> pathStream = Files.list(themePath)) {
|
||||
return pathStream.filter(path -> StringUtils.startsWithIgnoreCase(path.getFileName().toString(), CUSTOM_SHEET_PREFIX))
|
||||
.map(path -> {
|
||||
// Remove prefix
|
||||
String customTemplate = StringUtils.removeStartIgnoreCase(path.getFileName().toString(), CUSTOM_SHEET_PREFIX);
|
||||
|
@ -253,8 +253,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
|
||||
try {
|
||||
// Delete the folder
|
||||
FileUtils.del(Paths.get(themeProperty.getThemePath()));
|
||||
|
||||
FileUtils.deleteFolder(Paths.get(themeProperty.getThemePath()));
|
||||
// Delete theme cache
|
||||
eventPublisher.publishEvent(new ThemeUpdatedEvent(this));
|
||||
} catch (Exception e) {
|
||||
|
@ -377,7 +376,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
|
||||
try {
|
||||
// Create temp directory
|
||||
tempPath = createTempPath();
|
||||
tempPath = FileUtils.createTempDirectory();
|
||||
String basename = FilenameUtils.getBasename(file.getOriginalFilename());
|
||||
Path themeTempPath = tempPath.resolve(basename);
|
||||
|
||||
|
@ -391,7 +390,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
FileUtils.unzip(zis, themeTempPath);
|
||||
|
||||
// Go to the base folder and add the theme into system
|
||||
return add(FileUtils.skipZipParentFolder(themeTempPath));
|
||||
return add(FileUtils.tryToSkipZipParentFolder(themeTempPath));
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("上传主题失败: " + file.getOriginalFilename(), e);
|
||||
} finally {
|
||||
|
@ -408,7 +407,10 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
Assert.isTrue(Files.isDirectory(themeTmpPath), "Theme temporary path must be a directory");
|
||||
|
||||
log.debug("Children path of [{}]:", themeTmpPath);
|
||||
Files.list(themeTmpPath).forEach(path -> log.debug(path.toString()));
|
||||
|
||||
try (Stream<Path> pathStream = Files.list(themeTmpPath)) {
|
||||
pathStream.forEach(path -> log.debug(path.toString()));
|
||||
}
|
||||
|
||||
// Check property config
|
||||
ThemeProperty tmpThemeProperty = getProperty(themeTmpPath);
|
||||
|
@ -443,7 +445,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
|
||||
try {
|
||||
// Create temp path
|
||||
tmpPath = createTempPath();
|
||||
tmpPath = FileUtils.createTempDirectory();
|
||||
// Create temp path
|
||||
Path themeTmpPath = tmpPath.resolve(HaloUtils.randomUUIDWithoutDash());
|
||||
|
||||
|
@ -451,7 +453,8 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
downloadZipAndUnzip(uri, themeTmpPath);
|
||||
} else {
|
||||
uri = StringUtils.appendIfMissingIgnoreCase(uri, ".git", ".git");
|
||||
cloneFromGit(uri, themeTmpPath);
|
||||
// Clone from git
|
||||
GitUtils.cloneFromGit(uri, themeTmpPath);
|
||||
}
|
||||
|
||||
return add(themeTmpPath);
|
||||
|
@ -491,83 +494,56 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
String branch = StringUtils.isBlank(themeProperty.getBranch()) ?
|
||||
DEFAULT_REMOTE_BRANCH : themeProperty.getBranch();
|
||||
|
||||
File themeFolder = Paths.get(themeProperty.getThemePath()).toFile();
|
||||
// Open the theme path
|
||||
Git git;
|
||||
Git git = null;
|
||||
|
||||
try {
|
||||
git = Git.open(themeFolder);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
// Repository is not initialized
|
||||
git = Git.init().setDirectory(themeFolder).call();
|
||||
}
|
||||
|
||||
// Force to set remote name
|
||||
git.remoteRemove().setRemoteName(THEME_PROVIDER_REMOTE_NAME).call();
|
||||
RemoteConfig remoteConfig = git.remoteAdd()
|
||||
.setName(THEME_PROVIDER_REMOTE_NAME)
|
||||
.setUri(new URIish(themeProperty.getRepo()))
|
||||
.call();
|
||||
|
||||
// Add all changes
|
||||
git.add()
|
||||
.addFilepattern(".")
|
||||
.call();
|
||||
// Commit the changes
|
||||
git.commit().setMessage("Commit by halo automatically").call();
|
||||
|
||||
// Check out to specified branch
|
||||
if (!StringUtils.equalsIgnoreCase(branch, git.getRepository().getBranch())) {
|
||||
boolean present = git.branchList()
|
||||
.call()
|
||||
.stream()
|
||||
.map(Ref::getName)
|
||||
.anyMatch(name -> StringUtils.equalsIgnoreCase(name, branch));
|
||||
|
||||
git.checkout()
|
||||
.setCreateBranch(true)
|
||||
.setForced(!present)
|
||||
.setName(branch)
|
||||
git = GitUtils.openOrInit(Paths.get(themeProperty.getThemePath()));
|
||||
// Force to set remote name
|
||||
git.remoteRemove().setRemoteName(THEME_PROVIDER_REMOTE_NAME).call();
|
||||
RemoteConfig remoteConfig = git.remoteAdd()
|
||||
.setName(THEME_PROVIDER_REMOTE_NAME)
|
||||
.setUri(new URIish(themeProperty.getRepo()))
|
||||
.call();
|
||||
|
||||
// Add all changes
|
||||
git.add()
|
||||
.addFilepattern(".")
|
||||
.call();
|
||||
// Commit the changes
|
||||
git.commit().setMessage("Commit by halo automatically").call();
|
||||
|
||||
// Check out to specified branch
|
||||
if (!StringUtils.equalsIgnoreCase(branch, git.getRepository().getBranch())) {
|
||||
boolean present = git.branchList()
|
||||
.call()
|
||||
.stream()
|
||||
.map(Ref::getName)
|
||||
.anyMatch(name -> StringUtils.equalsIgnoreCase(name, branch));
|
||||
|
||||
git.checkout()
|
||||
.setCreateBranch(true)
|
||||
.setForced(!present)
|
||||
.setName(branch)
|
||||
.call();
|
||||
}
|
||||
|
||||
// Pull with rebasing
|
||||
PullResult pullResult = git.pull()
|
||||
.setRemote(remoteConfig.getName())
|
||||
.setRemoteBranchName(branch)
|
||||
.setRebase(true)
|
||||
.call();
|
||||
|
||||
if (!pullResult.isSuccessful()) {
|
||||
log.debug("Rebase result: [{}]", pullResult.getRebaseResult());
|
||||
log.debug("Merge result: [{}]", pullResult.getMergeResult());
|
||||
|
||||
throw new ThemeUpdateException("拉取失败!您与主题作者可能同时更改了同一个文件");
|
||||
}
|
||||
} finally {
|
||||
GitUtils.closeQuietly(git);
|
||||
}
|
||||
|
||||
// Pull with rebasing
|
||||
PullResult pullResult = git.pull()
|
||||
.setRemote(remoteConfig.getName())
|
||||
.setRemoteBranchName(branch)
|
||||
.setRebase(true)
|
||||
.call();
|
||||
|
||||
if (!pullResult.isSuccessful()) {
|
||||
log.debug("Rebase result: [{}]", pullResult.getRebaseResult());
|
||||
log.debug("Merge result: [{}]", pullResult.getMergeResult());
|
||||
|
||||
throw new ThemeUpdateException("拉取失败!您与主题作者可能同时更改了同一个文件");
|
||||
}
|
||||
// Close git
|
||||
git.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones theme from git.
|
||||
*
|
||||
* @param gitUrl git url must not be blank
|
||||
* @param targetPath target path must not be null
|
||||
* @throws GitAPIException throws when clone error
|
||||
*/
|
||||
private void cloneFromGit(@NonNull String gitUrl, @NonNull Path targetPath) throws GitAPIException {
|
||||
Assert.hasText(gitUrl, "Git url must not be blank");
|
||||
Assert.notNull(targetPath, "Target path must not be null");
|
||||
|
||||
log.debug("Cloning git repo [{}] to [{}]", gitUrl, targetPath);
|
||||
|
||||
// Clone it
|
||||
Git.cloneRepository()
|
||||
.setURI(gitUrl)
|
||||
.setDirectory(targetPath.toFile())
|
||||
.call();
|
||||
|
||||
log.debug("Cloned git repo [{}]", gitUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -592,22 +568,8 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
|
||||
log.debug("Downloaded [{}]", zipUrl);
|
||||
|
||||
// New zip input stream
|
||||
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(downloadResponse.getBody()));
|
||||
|
||||
// Unzip it
|
||||
FileUtils.unzip(zis, targetPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates temporary path.
|
||||
*
|
||||
* @return temporary path
|
||||
* @throws IOException if an I/O error occurs or the temporary-file directory does not exist
|
||||
*/
|
||||
@NonNull
|
||||
private Path createTempPath() throws IOException {
|
||||
return Files.createTempDirectory("halo");
|
||||
FileUtils.unzip(downloadResponse.getBody(), targetPath);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -625,10 +587,10 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
try (Stream<Path> pathStream = Files.list(topPath)) {
|
||||
List<ThemeFile> themeFiles = new LinkedList<>();
|
||||
|
||||
Files.list(topPath).forEach(path -> {
|
||||
pathStream.forEach(path -> {
|
||||
// Build theme file
|
||||
ThemeFile themeFile = new ThemeFile();
|
||||
themeFile.setName(path.getFileName().toString());
|
||||
|
@ -787,12 +749,13 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
private Optional<String> getScreenshotsFileName(@NonNull Path themePath) throws IOException {
|
||||
Assert.notNull(themePath, "Theme path must not be null");
|
||||
|
||||
return Files.list(themePath)
|
||||
.filter(path -> Files.isRegularFile(path)
|
||||
&& Files.isReadable(path)
|
||||
&& FilenameUtils.getBasename(path.toString()).equalsIgnoreCase(THEME_SCREENSHOTS_NAME))
|
||||
.findFirst()
|
||||
.map(path -> path.getFileName().toString());
|
||||
try (Stream<Path> pathStream = Files.list(themePath)) {
|
||||
return pathStream.filter(path -> Files.isRegularFile(path)
|
||||
&& Files.isReadable(path)
|
||||
&& FilenameUtils.getBasename(path.toString()).equalsIgnoreCase(THEME_SCREENSHOTS_NAME))
|
||||
.findFirst()
|
||||
.map(path -> path.getFileName().toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
package run.halo.app.utils;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import run.halo.app.exception.ForbiddenException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
|
@ -67,18 +66,30 @@ public class FileUtils {
|
|||
public static void deleteFolder(@NonNull Path deletingPath) throws IOException {
|
||||
Assert.notNull(deletingPath, "Deleting path must not be null");
|
||||
|
||||
log.debug("Deleting [{}]", deletingPath);
|
||||
log.info("Deleting [{}]", deletingPath);
|
||||
|
||||
Files.walk(deletingPath)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
// Delete folder recursively
|
||||
org.eclipse.jgit.util.FileUtils.delete(deletingPath.toFile(),
|
||||
org.eclipse.jgit.util.FileUtils.RECURSIVE | org.eclipse.jgit.util.FileUtils.RETRY);
|
||||
|
||||
log.debug("Deleted [{}] successfully", deletingPath);
|
||||
// try (Stream<Path> pathStream = Files.walk(deletingPath)) {
|
||||
// pathStream.sorted(Comparator.reverseOrder())
|
||||
// .peek(path -> log.debug("Try to delete [{}]", path.toString()))
|
||||
// .forEach(path -> {
|
||||
// try {
|
||||
// Files.delete(path);
|
||||
// log.debug("Deleted [{}] successfully", path.toString());
|
||||
// } catch (IOException e) {
|
||||
// throw new ServiceException("Failed to delete " + path.toString(), e).setErrorData(deletingPath.toString());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
log.info("Deleted [{}] successfully", deletingPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip content to the target path.
|
||||
* Unzips content to the target path.
|
||||
*
|
||||
* @param zis zip input stream must not be null
|
||||
* @param targetPath target path must not be null and not empty
|
||||
|
@ -115,23 +126,40 @@ public class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skips zip parent folder. (Go into base folder)
|
||||
* Unzips content to the target path.
|
||||
*
|
||||
* @param bytes zip bytes array must not be null
|
||||
* @param targetPath target path must not be null and not empty
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void unzip(@NonNull byte[] bytes, @NonNull Path targetPath) throws IOException {
|
||||
Assert.notNull(bytes, "Zip bytes must not be null");
|
||||
|
||||
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes));
|
||||
unzip(zis, targetPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to skip zip parent folder. (Go into base folder)
|
||||
*
|
||||
* @param unzippedPath unzipped path must not be null
|
||||
* @return path containing base files
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Path skipZipParentFolder(@NonNull Path unzippedPath) throws IOException {
|
||||
public static Path tryToSkipZipParentFolder(@NonNull Path unzippedPath) throws IOException {
|
||||
Assert.notNull(unzippedPath, "Unzipped folder must not be null");
|
||||
|
||||
List<Path> childrenPath = Files.list(unzippedPath).collect(Collectors.toList());
|
||||
// TODO May cause a latent problem.
|
||||
try (Stream<Path> pathStream = Files.list(unzippedPath)) {
|
||||
List<Path> childrenPath = pathStream.collect(Collectors.toList());
|
||||
|
||||
if (childrenPath.size() == 1 && Files.isDirectory(childrenPath.get(0))) {
|
||||
return childrenPath.get(0);
|
||||
if (childrenPath.size() == 1 && Files.isDirectory(childrenPath.get(0))) {
|
||||
return childrenPath.get(0);
|
||||
}
|
||||
return unzippedPath;
|
||||
}
|
||||
|
||||
return unzippedPath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,7 +189,13 @@ public class FileUtils {
|
|||
public static boolean isEmpty(@NonNull Path path) throws IOException {
|
||||
Assert.notNull(path, "Path must not be null");
|
||||
|
||||
return Files.list(path).count() == 0;
|
||||
if (!Files.isDirectory(path) || Files.notExists(path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try (Stream<Path> pathStream = Files.list(path)) {
|
||||
return pathStream.count() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,43 +295,15 @@ public class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除文件或者文件夹
|
||||
* Creates temp directory.
|
||||
*
|
||||
* @param path path
|
||||
* @return boolean
|
||||
* @throws IORuntimeException IORuntimeException
|
||||
* @return temp directory path
|
||||
* @throws IOException if an I/O error occurs or the temporary-file directory does not exist
|
||||
*/
|
||||
public static boolean del(Path path) throws IORuntimeException {
|
||||
if (Files.notExists(path)) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
if (Files.isDirectory(path)) {
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
|
||||
if (e == null) {
|
||||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Files.delete(path);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
return true;
|
||||
@NonNull
|
||||
public static Path createTempDirectory() throws IOException {
|
||||
return Files.createTempDirectory("halo");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package run.halo.app.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.storage.file.WindowCacheConfig;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Git utilities.
|
||||
*
|
||||
* @author johnniang
|
||||
* @date 19-6-12
|
||||
*/
|
||||
@Slf4j
|
||||
public class GitUtils {
|
||||
|
||||
private GitUtils() {
|
||||
// Config packed git MMAP
|
||||
WindowCacheConfig config = new WindowCacheConfig();
|
||||
config.setPackedGitMMAP(false);
|
||||
config.install();
|
||||
}
|
||||
|
||||
public static void cloneFromGit(@NonNull String repoUrl, @NonNull Path targetPath) throws GitAPIException {
|
||||
Assert.hasText(repoUrl, "Repository remote url must not be blank");
|
||||
Assert.notNull(targetPath, "Target path must not be null");
|
||||
|
||||
log.debug("Trying to clone git repo [{}] to [{}]", repoUrl, targetPath);
|
||||
|
||||
// Use try-with-resource-statement
|
||||
Git git = null;
|
||||
try {
|
||||
git = Git.cloneRepository()
|
||||
.setURI(repoUrl)
|
||||
.setDirectory(targetPath.toFile())
|
||||
.call();
|
||||
log.debug("Cloned git repo [{}] successfully", repoUrl);
|
||||
} finally {
|
||||
closeQuietly(git);
|
||||
}
|
||||
}
|
||||
|
||||
public static Git openOrInit(Path repoPath) throws IOException, GitAPIException {
|
||||
Git git;
|
||||
|
||||
try {
|
||||
git = Git.open(repoPath.toFile());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
log.warn("Git repository may not exist, we will try to initialize an empty repository", e);
|
||||
git = Git.init().setDirectory(repoPath.toFile()).call();
|
||||
}
|
||||
|
||||
return git;
|
||||
}
|
||||
|
||||
public static void closeQuietly(Git git) {
|
||||
if (git != null) {
|
||||
git.getRepository().close();
|
||||
git.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@ import org.springframework.util.Assert;
|
|||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
.attach-detail-img img{width:100%}.ant-divider-horizontal[data-v-b694bf52]{margin:24px 0 12px 0}.search-box[data-v-b694bf52]{padding-bottom:12px}.attach-thumb[data-v-b694bf52]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.attach-thumb img[data-v-b694bf52]{width:100%;height:100%;position:absolute;top:0;left:0}.ant-card-meta[data-v-b694bf52]{padding:.8rem}.attach-detail-img img[data-v-b694bf52]{width:100%}.table-operator[data-v-b694bf52]{margin-bottom:0}
|
|
@ -0,0 +1 @@
|
|||
.category-tree[data-v-0f333a36]{margin-top:1rem}
|
|
@ -0,0 +1 @@
|
|||
.attach-detail-img img{width:100%}.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}@-webkit-keyframes scaleDraw-data-v-0ce6900e{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(1.3);transform:scale(1.3)}50%{-webkit-transform:scale(1);transform:scale(1)}75%{-webkit-transform:scale(1.3);transform:scale(1.3)}}@keyframes scaleDraw-data-v-0ce6900e{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(1.3);transform:scale(1.3)}50%{-webkit-transform:scale(1);transform:scale(1)}75%{-webkit-transform:scale(1.3);transform:scale(1.3)}}.upload-button[data-v-0ce6900e]{-webkit-animation:scaleDraw-data-v-0ce6900e 4s ease-in-out infinite;position:fixed;bottom:30px;right:30px}.theme-thumb[data-v-0ce6900e]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.theme-thumb img[data-v-0ce6900e]{width:100%;height:100%;position:absolute;top:0;left:0}
|
|
@ -0,0 +1 @@
|
|||
.height-100[data-v-1ac0b863]{height:100vh}.install-action[data-v-1ac0b863]{margin-top:1rem}.previus-button[data-v-1ac0b863]{margin-right:1rem}.install-card[data-v-1ac0b863]{-webkit-box-shadow:0 10px 20px 0 hsla(0,0%,92.5%,.86);box-shadow:0 10px 20px 0 hsla(0,0%,92.5%,.86)}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
.environment-info ul,ul{margin:0;padding:0;list-style:none}.environment-info a{margin-right:10px}
|
|
@ -1 +0,0 @@
|
|||
ul{margin:0;padding:0;list-style:none}
|
|
@ -1 +0,0 @@
|
|||
.height-100[data-v-f2997e68]{height:100vh}.install-action[data-v-f2997e68]{margin-top:1rem}.previus-button[data-v-f2997e68]{margin-right:1rem}.install-card[data-v-f2997e68]{-webkit-box-shadow:0 10px 20px 0 hsla(0,0%,92.5%,.86);box-shadow:0 10px 20px 0 hsla(0,0%,92.5%,.86)}
|
|
@ -0,0 +1 @@
|
|||
.v-note-wrapper[data-v-6778754a]{z-index:1000;min-height:580px}.sheet-thum .img[data-v-6778754a]{width:100%;cursor:pointer;border-radius:4px}.sheet-thum .sheet-thum-remove[data-v-6778754a]{margin-top:16px}
|
|
@ -1 +0,0 @@
|
|||
.category-tree[data-v-77634e76]{margin-top:1rem}
|
|
@ -1 +0,0 @@
|
|||
.v-note-wrapper[data-v-5a42b07f]{z-index:1000;min-height:580px}.sheet-thum .img[data-v-5a42b07f]{width:100%;cursor:pointer;border-radius:4px}.sheet-thum .sheet-thum-remove[data-v-5a42b07f]{margin-top:16px}
|
|
@ -0,0 +1 @@
|
|||
.attach-detail-img img{width:100%}.ant-divider-horizontal[data-v-18d41aa9]{margin:24px 0 12px 0}.search-box[data-v-18d41aa9]{padding-bottom:12px}.attach-thumb[data-v-18d41aa9]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.attach-thumb img[data-v-18d41aa9]{width:100%;height:100%;position:absolute;top:0;left:0}.ant-card-meta[data-v-18d41aa9]{padding:.8rem}.attach-detail-img img[data-v-18d41aa9]{width:100%}.table-operator[data-v-18d41aa9]{margin-bottom:0}
|
|
@ -0,0 +1 @@
|
|||
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}.ant-divider-horizontal[data-v-4bf43659]{margin:24px 0 12px 0}.search-box[data-v-4bf43659]{padding-bottom:12px}.photo-thumb[data-v-4bf43659]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.photo-thumb img[data-v-4bf43659]{width:100%;height:100%;position:absolute;top:0;left:0}.ant-card-meta[data-v-4bf43659]{padding:.8rem}.photo-detail-img img[data-v-4bf43659]{width:100%}.table-operator[data-v-4bf43659]{margin-bottom:0}
|
|
@ -1 +0,0 @@
|
|||
.attach-detail-img img{width:100%}.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}.upload-button[data-v-40d5a5ae]{position:fixed;bottom:30px;right:30px}.theme-thumb[data-v-40d5a5ae]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.theme-thumb img[data-v-40d5a5ae]{width:100%;height:100%;position:absolute;top:0;left:0}
|
|
@ -1 +0,0 @@
|
|||
.analysis-card-container[data-v-4cadd8f2]{position:relative;overflow:hidden;width:100%}.analysis-card-container .meta[data-v-4cadd8f2]{position:relative;overflow:hidden;width:100%;color:rgba(0,0,0,.45);font-size:14px;line-height:22px}.analysis-card-container .meta .analysis-card-action[data-v-4cadd8f2]{cursor:pointer;position:absolute;top:0;right:0}.number[data-v-4cadd8f2]{overflow:hidden;text-overflow:ellipsis;word-break:break-all;white-space:nowrap;color:#000;margin-top:4px;margin-bottom:0;font-size:32px;line-height:38px;height:38px}
|
|
@ -1 +0,0 @@
|
|||
.v-note-wrapper[data-v-669770a4]{z-index:1000;min-height:580px}.post-thum .img[data-v-669770a4]{width:100%;cursor:pointer;border-radius:4px}.post-thum .post-thum-remove[data-v-669770a4]{margin-top:16px}
|
|
@ -0,0 +1 @@
|
|||
.analysis-card-container[data-v-698a5e37]{position:relative;overflow:hidden;width:100%}.analysis-card-container .meta[data-v-698a5e37]{position:relative;overflow:hidden;width:100%;color:rgba(0,0,0,.45);font-size:14px;line-height:22px}.analysis-card-container .meta .analysis-card-action[data-v-698a5e37]{cursor:pointer;position:absolute;top:0;right:0}.number[data-v-698a5e37]{overflow:hidden;text-overflow:ellipsis;word-break:break-all;white-space:nowrap;color:#000;margin-top:4px;margin-bottom:0;font-size:32px;line-height:38px;height:38px}
|
|
@ -1 +0,0 @@
|
|||
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}.ant-divider-horizontal[data-v-2a97a053]{margin:24px 0 12px 0}.search-box[data-v-2a97a053]{padding-bottom:12px}.photo-thumb[data-v-2a97a053]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.photo-thumb img[data-v-2a97a053]{width:100%;height:100%;position:absolute;top:0;left:0}.ant-card-meta[data-v-2a97a053]{padding:.8rem}.photo-detail-img img[data-v-2a97a053]{width:100%}.table-operator[data-v-2a97a053]{margin-bottom:0}
|
|
@ -1 +1 @@
|
|||
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}.page-header-wrapper-grid-content-main[data-v-0c60a972]{width:100%;height:100%;min-height:100%;-webkit-transition:.3s;transition:.3s}.page-header-wrapper-grid-content-main .profile-center-avatarHolder[data-v-0c60a972]{text-align:center;margin-bottom:24px}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar[data-v-0c60a972]{margin:0 auto;width:104px;height:104px;margin-bottom:20px;border-radius:50%;overflow:hidden;cursor:pointer}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar img[data-v-0c60a972]{height:100%;width:100%}.page-header-wrapper-grid-content-main .profile-center-avatarHolder .username[data-v-0c60a972]{color:rgba(0,0,0,.85);font-size:20px;line-height:28px;font-weight:500;margin-bottom:4px}.page-header-wrapper-grid-content-main .profile-center-detail p[data-v-0c60a972]{margin-bottom:8px;padding-left:26px;position:relative}.page-header-wrapper-grid-content-main .profile-center-detail i[data-v-0c60a972]{position:absolute;height:14px;width:14px;left:0;top:4px}
|
||||
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}.page-header-wrapper-grid-content-main[data-v-69ef61d6]{width:100%;height:100%;min-height:100%;-webkit-transition:.3s;transition:.3s}.page-header-wrapper-grid-content-main .profile-center-avatarHolder[data-v-69ef61d6]{text-align:center;margin-bottom:24px}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar[data-v-69ef61d6]{margin:0 auto;width:104px;height:104px;margin-bottom:20px;border-radius:50%;overflow:hidden;cursor:pointer}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar img[data-v-69ef61d6]{height:100%;width:100%}.page-header-wrapper-grid-content-main .profile-center-avatarHolder .username[data-v-69ef61d6]{color:rgba(0,0,0,.85);font-size:20px;line-height:28px;font-weight:500;margin-bottom:4px}.page-header-wrapper-grid-content-main .profile-center-detail p[data-v-69ef61d6]{margin-bottom:8px;padding-left:26px;position:relative}.page-header-wrapper-grid-content-main .profile-center-detail i[data-v-69ef61d6]{position:absolute;height:14px;width:14px;left:0;top:4px}
|
|
@ -0,0 +1 @@
|
|||
.v-note-wrapper[data-v-348cd59e]{z-index:1000;min-height:580px}.post-thum .img[data-v-348cd59e]{width:100%;cursor:pointer;border-radius:4px}.post-thum .post-thum-remove[data-v-348cd59e]{margin-top:16px}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
.exception[data-v-230942b4]{min-height:500px;height:80%;-webkit-box-align:center;-ms-flex-align:center;align-items:center;text-align:center;margin-top:150px}.exception .img[data-v-230942b4]{display:inline-block;padding-right:52px;zoom:1}.exception .img img[data-v-230942b4]{height:360px;max-width:430px}.exception .content[data-v-230942b4]{display:inline-block;-webkit-box-flex:1;-ms-flex:auto;flex:auto}.exception .content h1[data-v-230942b4]{color:#434e59;font-size:72px;font-weight:600;line-height:72px;margin-bottom:24px}.exception .content .desc[data-v-230942b4]{color:rgba(0,0,0,.45);font-size:20px;line-height:28px;margin-bottom:16px}.mobile .exception[data-v-230942b4]{margin-top:30px}.mobile .exception .img[data-v-230942b4]{padding-right:unset}.mobile .exception .img img[data-v-230942b4]{height:40%;max-width:80%}
|
|
@ -1 +0,0 @@
|
|||
.exception[data-v-729a8fea]{min-height:500px;height:80%;-webkit-box-align:center;-ms-flex-align:center;align-items:center;text-align:center;margin-top:150px}.exception .img[data-v-729a8fea]{display:inline-block;padding-right:52px;zoom:1}.exception .img img[data-v-729a8fea]{height:360px;max-width:430px}.exception .content[data-v-729a8fea]{display:inline-block;-webkit-box-flex:1;-ms-flex:auto;flex:auto}.exception .content h1[data-v-729a8fea]{color:#434e59;font-size:72px;font-weight:600;line-height:72px;margin-bottom:24px}.exception .content .desc[data-v-729a8fea]{color:rgba(0,0,0,.45);font-size:20px;line-height:28px;margin-bottom:16px}.mobile .exception[data-v-729a8fea]{margin-top:30px}.mobile .exception .img[data-v-729a8fea]{padding-right:unset}.mobile .exception .img img[data-v-729a8fea]{height:40%;max-width:80%}
|
|
@ -1 +1 @@
|
|||
<!DOCTYPE html><html lang=zh-cmn-Hans><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta name=robots content=noindex,nofllow><meta name=generator content=Halo><link rel=icon href=/logo.png><title>Halo Dashboard</title><link href=/css/chunk-009936c1.f3153164.css rel=prefetch><link href=/css/chunk-0aa79c38.26a33a1b.css rel=prefetch><link href=/css/chunk-1be69b35.b6783003.css rel=prefetch><link href=/css/chunk-2ca3170e.61a5a976.css rel=prefetch><link href=/css/chunk-37d95348.909d3d1b.css rel=prefetch><link href=/css/chunk-436563a2.cb1e7f15.css rel=prefetch><link href=/css/chunk-46d7532c.94c6eb30.css rel=prefetch><link href=/css/chunk-4851a43a.210847fe.css rel=prefetch><link href=/css/chunk-6e38bcf5.2ee2b33a.css rel=prefetch><link href=/css/chunk-70b33d4d.701a4459.css rel=prefetch><link href=/css/chunk-75c7eed4.7cf84e9e.css rel=prefetch><link href=/css/chunk-9449c032.dafef2de.css rel=prefetch><link href=/css/chunk-9cb97d52.046bf41d.css rel=prefetch><link href=/css/chunk-bb4f0d4a.c1990d7c.css rel=prefetch><link href=/css/fail.e9c3e2d8.css rel=prefetch><link href=/js/chunk-009936c1.cde57fa8.js rel=prefetch><link href=/js/chunk-0aa79c38.2659df6e.js rel=prefetch><link href=/js/chunk-0ba750a2.02c8e842.js rel=prefetch><link href=/js/chunk-142c8832.8aceee71.js rel=prefetch><link href=/js/chunk-1be69b35.4a496da5.js rel=prefetch><link href=/js/chunk-2ca3170e.258d6e52.js rel=prefetch><link href=/js/chunk-2d0b64bf.25665dba.js rel=prefetch><link href=/js/chunk-2d0d65a2.1c8f2476.js rel=prefetch><link href=/js/chunk-2d21a35c.2fc10284.js rel=prefetch><link href=/js/chunk-2d228d13.dd7018e7.js rel=prefetch><link href=/js/chunk-37d95348.9ac04f40.js rel=prefetch><link href=/js/chunk-436563a2.89c8f183.js rel=prefetch><link href=/js/chunk-46d7532c.7500e276.js rel=prefetch><link href=/js/chunk-4851a43a.e3ce92c4.js rel=prefetch><link href=/js/chunk-5bf599cc.fc6c7d8c.js rel=prefetch><link href=/js/chunk-6e38bcf5.7b552106.js rel=prefetch><link href=/js/chunk-70b33d4d.f5bbad6f.js rel=prefetch><link href=/js/chunk-75c7eed4.cee58ce6.js rel=prefetch><link href=/js/chunk-87e2df70.f4b6bdc6.js rel=prefetch><link href=/js/chunk-9449c032.0036f54b.js rel=prefetch><link href=/js/chunk-9cb97d52.abfd8c14.js rel=prefetch><link href=/js/chunk-bb4f0d4a.3b7dfaaa.js rel=prefetch><link href=/js/fail.8a6d08f5.js rel=prefetch><link href=/css/app.d748d7bc.css rel=preload as=style><link href=/css/chunk-vendors.278be955.css rel=preload as=style><link href=/js/app.1842d5e6.js rel=preload as=script><link href=/js/chunk-vendors.811663b9.js rel=preload as=script><link href=/css/chunk-vendors.278be955.css rel=stylesheet><link href=/css/app.d748d7bc.css rel=stylesheet></head><body><noscript><strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.811663b9.js></script><script src=/js/app.1842d5e6.js></script></body></html>
|
||||
<!DOCTYPE html><html lang=zh-cmn-Hans><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta name=robots content=noindex,nofllow><meta name=generator content=Halo><link rel=icon href=/logo.png><title>Halo Dashboard</title><link href=/css/chunk-0337f7a6.4c6b622f.css rel=prefetch><link href=/css/chunk-1079f749.94b473ad.css rel=prefetch><link href=/css/chunk-14e0b302.32f796a8.css rel=prefetch><link href=/css/chunk-161dc990.5ac5144c.css rel=prefetch><link href=/css/chunk-1be69b35.43c1fc12.css rel=prefetch><link href=/css/chunk-31c8ea42.4a090118.css rel=prefetch><link href=/css/chunk-5000e55c.7fb9bc61.css rel=prefetch><link href=/css/chunk-6d8b31f6.ad8d17b2.css rel=prefetch><link href=/css/chunk-81d936d8.05888d95.css rel=prefetch><link href=/css/chunk-b2d0b040.389eca76.css rel=prefetch><link href=/css/chunk-bb4f0d4a.c1990d7c.css rel=prefetch><link href=/css/chunk-bfd5bbcc.6a83ae7d.css rel=prefetch><link href=/css/chunk-c0a1d3c4.09186be6.css rel=prefetch><link href=/css/chunk-cec31564.6f053d75.css rel=prefetch><link href=/css/fail.809a6bc5.css rel=prefetch><link href=/js/chunk-0337f7a6.11326d77.js rel=prefetch><link href=/js/chunk-0ba750a2.b786c9db.js rel=prefetch><link href=/js/chunk-1079f749.ec67c7db.js rel=prefetch><link href=/js/chunk-142c8832.0f8270b3.js rel=prefetch><link href=/js/chunk-14e0b302.a86d1254.js rel=prefetch><link href=/js/chunk-161dc990.5de9313f.js rel=prefetch><link href=/js/chunk-1be69b35.81559bfc.js rel=prefetch><link href=/js/chunk-2d0b64bf.61d5d7c3.js rel=prefetch><link href=/js/chunk-2d0d65a2.2249765a.js rel=prefetch><link href=/js/chunk-2d21a35c.eda7a11a.js rel=prefetch><link href=/js/chunk-2d228d13.85b46532.js rel=prefetch><link href=/js/chunk-31c8ea42.0b2feab9.js rel=prefetch><link href=/js/chunk-5000e55c.3bd9ce3a.js rel=prefetch><link href=/js/chunk-5bf599cc.ac9398f3.js rel=prefetch><link href=/js/chunk-6d8b31f6.b64e5366.js rel=prefetch><link href=/js/chunk-81d936d8.5c1d2539.js rel=prefetch><link href=/js/chunk-87e2df70.0ada7d4e.js rel=prefetch><link href=/js/chunk-b2d0b040.b0d70d07.js rel=prefetch><link href=/js/chunk-bb4f0d4a.048dc3a4.js rel=prefetch><link href=/js/chunk-bfd5bbcc.d2ca1e80.js rel=prefetch><link href=/js/chunk-c0a1d3c4.41d0d3f8.js rel=prefetch><link href=/js/chunk-cec31564.cfe3fd85.js rel=prefetch><link href=/js/fail.61f30b0f.js rel=prefetch><link href=/css/app.f8b02c30.css rel=preload as=style><link href=/css/chunk-vendors.ee4e8dbf.css rel=preload as=style><link href=/js/app.845922f6.js rel=preload as=script><link href=/js/chunk-vendors.2f7bce79.js rel=preload as=script><link href=/css/chunk-vendors.ee4e8dbf.css rel=stylesheet><link href=/css/app.f8b02c30.css rel=stylesheet></head><body><noscript><strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.2f7bce79.js></script><script src=/js/app.845922f6.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-1be69b35"],{"031c":function(t,a,e){},2967:function(t,a,e){"use strict";e.r(a);var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"page-header-index-wide"},[e("a-row",[e("a-col",{attrs:{span:24}},[e("a-card",{attrs:{bordered:!1}},[e("a-list",{attrs:{itemLayout:"horizontal"}},[e("a-list-item",[e("a-list-item-meta",[e("h3",{attrs:{slot:"title"},slot:"title"},[t._v("\n 环境信息\n ")]),e("template",{slot:"description"},[e("ul",[e("li",[t._v("版本:"+t._s(t.environments.version))]),e("li",[t._v("数据库:"+t._s(t.environments.database))]),e("li",[t._v("启动时间:"+t._s(t._f("moment")(t.environments.startTime)))])]),e("a",{attrs:{href:"https://github.com/halo-dev",target:"_blank"}},[t._v("开源地址\n "),e("a-icon",{attrs:{type:"link"}})],1),t._v(" \n "),e("a",{attrs:{href:"https://halo.run/docs",target:"_blank"}},[t._v("用户文档\n "),e("a-icon",{attrs:{type:"link"}})],1),t._v(" \n "),e("a",{attrs:{href:"https://bbs.halo.run",target:"_blank"}},[t._v("在线社区\n "),e("a-icon",{attrs:{type:"link"}})],1),t._v(" \n ")])],2)],1),e("a-list-item",[e("a-list-item-meta",[e("h3",{attrs:{slot:"title"},slot:"title"},[t._v("\n 开发者\n ")]),e("template",{slot:"description"},t._l(t.developers,function(t,a){return e("a-tooltip",{key:a,attrs:{placement:"top",title:t.name}},[e("a-avatar",{style:{marginRight:"10px"},attrs:{size:"large",src:t.avatar}})],1)}),1)],2)],1),e("a-list-item",[e("a-list-item-meta",[e("h3",{attrs:{slot:"title"},slot:"title"},[t._v("\n 时间轴\n ")]),e("template",{slot:"description"},[e("a-timeline",[e("a-timeline-item",[t._v("...")]),t._l(t.steps,function(a,n){return e("a-timeline-item",{key:n},[t._v(t._s(a.date)+" "+t._s(a.content))])})],2)],1)],2)],1)],1)],1)],1)],1)],1)},i=[],s=e("50fc"),r={data:function(){return{environments:{},developers:[{name:"Ryan Wang",avatar:"//cn.gravatar.com/avatar/7cc7f29278071bd4dce995612d428834?s=256&d=mm",website:"https://ryanc.cc",github:"https://github.com/ruibaby"},{name:"John Niang",avatar:"//cn.gravatar.com/avatar/1dcf60ef27363dae539385d5bae9b2bd?s=256&d=mm",website:"https://johnniang.me",github:"https://github.com/johnniang"},{name:"Aquan",avatar:"//cn.gravatar.com/avatar/3958035fa354403fa9ca3fca36b08068?s=256&d=mm",website:"https://blog.eunji.cn",github:"https://github.com/aquanlerou"},{name:"appdev",avatar:"//cn.gravatar.com/avatar/08cf681fb7c6ad1b4fe70a8269c2103c?s=256&d=mm",website:"https://www.apkdv.com",github:"https://github.com/appdev"}],steps:[{date:"2019-06-01",content:"1.0 正式版发布"},{date:"2019-05-03",content:"Star 数达到 3300"},{date:"2019-01-30",content:"John Niang 加入开发"},{date:"2018-10-18",content:"构建镜像到 Docker hub"},{date:"2018-09-22",content:"Star 数达到 800"},{date:"2018-05-02",content:"第一条 Issue"},{date:"2018-05-01",content:"Star 数达到 100"},{date:"2018-04-29",content:"第一个 Pull request"},{date:"2018-04-28",content:"正式开源"},{date:"2018-03-21",content:"确定命名为 Halo,并上传到 Github"}]}},created:function(){this.getEnvironments()},methods:{getEnvironments:function(){var t=this;s["a"].environments().then(function(a){t.environments=a.data.data})}}},o=r,c=(e("5ea2"),e("17cc")),l=Object(c["a"])(o,n,i,!1,null,null,null);a["default"]=l.exports},"5ea2":function(t,a,e){"use strict";var n=e("031c"),i=e.n(n);i.a}}]);
|
|
@ -0,0 +1 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-1be69b35"],{"031c":function(t,a,e){},2967:function(t,a,e){"use strict";e.r(a);var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"page-header-index-wide"},[e("a-row",[e("a-col",{attrs:{span:24}},[e("a-card",{attrs:{bordered:!1}},[e("a-card",{staticClass:"environment-info",attrs:{title:"环境信息",bordered:!1}},[e("a-popconfirm",{attrs:{slot:"extra",placement:"left",okText:"确定",cancelText:"取消"},on:{confirm:t.confirmUpdate},slot:"extra"},[e("template",{slot:"title"},[e("p",[t._v("确定更新 "),e("b",[t._v("Halo admin")]),t._v(" 吗?")])]),e("a-icon",{attrs:{slot:"icon",type:"cloud-download"},slot:"icon"}),e("a-button",{attrs:{loading:t.updating,type:"dashed",shape:"circle",icon:"cloud-download"}})],2),e("ul",[e("li",[t._v("Server 版本:"+t._s(t.environments.version))]),e("li",[t._v("Admin 版本:"+t._s(t.adminVersion))]),e("li",[t._v("数据库:"+t._s(t.environments.database))]),e("li",[t._v("运行模式:"+t._s(t.environments.mode))]),e("li",[t._v("启动时间:"+t._s(t._f("moment")(t.environments.startTime)))])]),e("a",{attrs:{href:"https://github.com/halo-dev",target:"_blank"}},[t._v("开源地址\n "),e("a-icon",{attrs:{type:"link"}})],1),e("a",{attrs:{href:"https://halo.run/docs",target:"_blank"}},[t._v("用户文档\n "),e("a-icon",{attrs:{type:"link"}})],1),e("a",{attrs:{href:"https://bbs.halo.run",target:"_blank"}},[t._v("在线社区\n "),e("a-icon",{attrs:{type:"link"}})],1)],1),e("a-card",{attrs:{title:"开发者",bordered:!1}},t._l(t.developers,function(t,a){return e("a",{key:a,attrs:{href:t.github,target:"_blank"}},[e("a-tooltip",{attrs:{placement:"top",title:t.name}},[e("a-avatar",{style:{marginRight:"10px"},attrs:{size:"large",src:t.avatar}})],1)],1)}),0),e("a-card",{attrs:{title:"时间轴",bordered:!1}},[e("a-timeline",[e("a-timeline-item",[t._v("...")]),t._l(t.steps,function(a,n){return e("a-timeline-item",{key:n},[t._v(t._s(a.date)+" "+t._s(a.content))])})],2)],1)],1)],1)],1)],1)},i=[],r=e("50fc"),o={data:function(){return{adminVersion:this.VERSION,environments:{},developers:[{name:"Ryan Wang",avatar:"//cn.gravatar.com/avatar/7cc7f29278071bd4dce995612d428834?s=256&d=mm",website:"https://ryanc.cc",github:"https://github.com/ruibaby"},{name:"John Niang",avatar:"//cn.gravatar.com/avatar/1dcf60ef27363dae539385d5bae9b2bd?s=256&d=mm",website:"https://johnniang.me",github:"https://github.com/johnniang"},{name:"Aquan",avatar:"//cn.gravatar.com/avatar/3958035fa354403fa9ca3fca36b08068?s=256&d=mm",website:"https://blog.eunji.cn",github:"https://github.com/aquanlerou"},{name:"appdev",avatar:"//cn.gravatar.com/avatar/08cf681fb7c6ad1b4fe70a8269c2103c?s=256&d=mm",website:"https://www.apkdv.com",github:"https://github.com/appdev"}],steps:[{date:"2019-06-01",content:"1.0 正式版发布"},{date:"2019-05-03",content:"Star 数达到 3300"},{date:"2019-01-30",content:"John Niang 加入开发"},{date:"2018-10-18",content:"构建镜像到 Docker hub"},{date:"2018-09-22",content:"Star 数达到 800"},{date:"2018-05-02",content:"第一条 Issue"},{date:"2018-05-01",content:"Star 数达到 100"},{date:"2018-04-29",content:"第一个 Pull request"},{date:"2018-04-28",content:"正式开源"},{date:"2018-03-21",content:"确定命名为 Halo,并上传到 Github"}],updating:!1}},created:function(){this.getEnvironments()},computed:{updateText:function(){return this.updating?"更新中...":"更新"}},methods:{getEnvironments:function(){var t=this;r["a"].environments().then(function(a){t.environments=a.data.data})},confirmUpdate:function(){var t=this;this.updating=!0,r["a"].updateAdminAssets().then(function(a){t.$notification.success({message:"更新成功",description:"请刷新后体验最新版本!"})}).finally(function(){t.updating=!1})}}},s=o,c=(e("5ea2"),e("17cc")),d=Object(c["a"])(s,n,i,!1,null,null,null);a["default"]=d.exports},"5ea2":function(t,a,e){"use strict";var n=e("031c"),i=e.n(n);i.a}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d21a35c"],{bb17:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"page-header-index-wide"},[n("a-row",{attrs:{gutter:12}},[n("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:10,lg:10,md:10,sm:24,xs:24}},[n("a-card",{attrs:{title:t.title}},[n("a-form",{attrs:{layout:"horizontal"}},[n("a-form-item",{attrs:{label:"网站名称:"}},[n("a-input",{model:{value:t.link.name,callback:function(e){t.$set(t.link,"name",e)},expression:"link.name"}})],1),n("a-form-item",{attrs:{label:"网站地址:",help:"* 需要加上 http://"}},[n("a-input",{model:{value:t.link.url,callback:function(e){t.$set(t.link,"url",e)},expression:"link.url"}})],1),n("a-form-item",{attrs:{label:"Logo:"}},[n("a-input",{model:{value:t.link.logo,callback:function(e){t.$set(t.link,"logo",e)},expression:"link.logo"}})],1),n("a-form-item",{attrs:{label:"分组:",help:"* 非必填"}},[n("a-input",{model:{value:t.link.team,callback:function(e){t.$set(t.link,"team",e)},expression:"link.team"}})],1),n("a-form-item",{attrs:{label:"描述:"}},[n("a-input",{attrs:{type:"textarea",autosize:{minRows:5}},model:{value:t.link.description,callback:function(e){t.$set(t.link,"description",e)},expression:"link.description"}})],1),n("a-form-item",["create"===t.formType?n("a-button",{attrs:{type:"primary"},on:{click:t.handleSaveClick}},[t._v("保存")]):n("a-button-group",[n("a-button",{attrs:{type:"primary"},on:{click:t.handleSaveClick}},[t._v("更新")]),"update"===t.formType?n("a-button",{attrs:{type:"dashed"},on:{click:t.handleAddLink}},[t._v("返回添加")]):t._e()],1)],1)],1)],1)],1),n("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:14,lg:14,md:14,sm:24,xs:24}},[n("a-card",{attrs:{title:"所有友情链接"}},[n("a-table",{attrs:{columns:t.columns,dataSource:t.links,loading:t.loading,rowKey:function(t){return t.id}},scopedSlots:t._u([{key:"url",fn:function(e){return[n("a",{attrs:{target:"_blank",href:e}},[t._v(t._s(e))])]}},{key:"name",fn:function(e){return n("ellipsis",{attrs:{length:15,tooltip:""}},[t._v(t._s(e))])}},{key:"action",fn:function(e,a){return n("span",{},[n("a",{attrs:{href:"javascript:;"},on:{click:function(e){return t.handleEditLink(a.id)}}},[t._v("编辑")]),n("a-divider",{attrs:{type:"vertical"}}),n("a-popconfirm",{attrs:{title:"你确定要删除【"+a.name+"】链接?",okText:"确定",cancelText:"取消"},on:{confirm:function(e){return t.handleDeleteLink(a.id)}}},[n("a",{attrs:{href:"javascript:;"}},[t._v("删除")])])],1)}}])})],1)],1)],1)],1)},i=[],l=(n("69a3"),n("9efd")),o="/api/admin/links",c={listAll:function(){return Object(l["a"])({url:"".concat(o),method:"get"})},create:function(t){return Object(l["a"])({url:o,data:t,method:"post"})},get:function(t){return Object(l["a"])({url:"".concat(o,"/").concat(t),method:"get"})},update:function(t,e){return Object(l["a"])({url:"".concat(o,"/").concat(t),data:e,method:"put"})},delete:function(t){return Object(l["a"])({url:"".concat(o,"/").concat(t),method:"delete"})}},r=c,s=[{title:"名称",dataIndex:"name",scopedSlots:{customRender:"name"}},{title:"网址",dataIndex:"url",scopedSlots:{customRender:"url"}},{title:"分组",dataIndex:"team"},{title:"操作",key:"action",scopedSlots:{customRender:"action"}}],d={data:function(){return{formType:"create",data:[],loading:!1,columns:s,links:[],link:{}}},computed:{title:function(){return this.link.id?"修改友情链接":"添加友情链接"}},created:function(){this.loadLinks()},methods:{loadLinks:function(){var t=this;this.loading=!0,r.listAll().then(function(e){t.links=e.data.data,t.loading=!1})},handleSaveClick:function(){this.createOrUpdateLink()},handleAddLink:function(){this.formType="create",this.link={}},handleEditLink:function(t){var e=this;r.get(t).then(function(t){e.link=t.data.data,e.formType="update"})},handleDeleteLink:function(t){var e=this;r.delete(t).then(function(t){e.$message.success("删除成功!"),e.loadLinks()})},createOrUpdateLink:function(){var t=this;this.link.id?r.update(this.link.id,this.link).then(function(e){t.$message.success("更新成功!"),t.loadLinks()}):r.create(this.link).then(function(e){t.$message.success("保存成功!"),t.loadLinks()}),this.handleAddLink()}}},u=d,m=n("17cc"),k=Object(m["a"])(u,a,i,!1,null,"243cf1cf",null);e["default"]=k.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d21a35c"],{bb17:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"page-header-index-wide"},[n("a-row",{attrs:{gutter:12}},[n("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:10,lg:10,md:10,sm:24,xs:24}},[n("a-card",{attrs:{title:t.title}},[n("a-form",{attrs:{layout:"horizontal"}},[n("a-form-item",{attrs:{label:"网站名称:"}},[n("a-input",{model:{value:t.link.name,callback:function(e){t.$set(t.link,"name",e)},expression:"link.name"}})],1),n("a-form-item",{attrs:{label:"网站地址:",help:"* 需要加上 http://"}},[n("a-input",{model:{value:t.link.url,callback:function(e){t.$set(t.link,"url",e)},expression:"link.url"}})],1),n("a-form-item",{attrs:{label:"Logo:"}},[n("a-input",{model:{value:t.link.logo,callback:function(e){t.$set(t.link,"logo",e)},expression:"link.logo"}})],1),n("a-form-item",{attrs:{label:"分组:",help:"* 非必填"}},[n("a-input",{model:{value:t.link.team,callback:function(e){t.$set(t.link,"team",e)},expression:"link.team"}})],1),n("a-form-item",{attrs:{label:"描述:"}},[n("a-input",{attrs:{type:"textarea",autosize:{minRows:5}},model:{value:t.link.description,callback:function(e){t.$set(t.link,"description",e)},expression:"link.description"}})],1),n("a-form-item",["create"===t.formType?n("a-button",{attrs:{type:"primary"},on:{click:t.handleSaveClick}},[t._v("保存")]):n("a-button-group",[n("a-button",{attrs:{type:"primary"},on:{click:t.handleSaveClick}},[t._v("更新")]),"update"===t.formType?n("a-button",{attrs:{type:"dashed"},on:{click:t.handleAddLink}},[t._v("返回添加")]):t._e()],1)],1)],1)],1)],1),n("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:14,lg:14,md:14,sm:24,xs:24}},[n("a-card",{attrs:{title:"所有友情链接"}},[n("a-table",{attrs:{columns:t.columns,dataSource:t.links,loading:t.loading,rowKey:function(t){return t.id}},scopedSlots:t._u([{key:"url",fn:function(e){return[n("a",{attrs:{target:"_blank",href:e}},[t._v(t._s(e))])]}},{key:"name",fn:function(e){return n("ellipsis",{attrs:{length:15,tooltip:""}},[t._v(t._s(e))])}},{key:"action",fn:function(e,a){return n("span",{},[n("a",{attrs:{href:"javascript:;"},on:{click:function(e){return t.handleEditLink(a.id)}}},[t._v("编辑")]),n("a-divider",{attrs:{type:"vertical"}}),n("a-popconfirm",{attrs:{title:"你确定要删除【"+a.name+"】链接?",okText:"确定",cancelText:"取消"},on:{confirm:function(e){return t.handleDeleteLink(a.id)}}},[n("a",{attrs:{href:"javascript:;"}},[t._v("删除")])])],1)}}])})],1)],1)],1)],1)},i=[],l=(n("69a3"),n("9efd")),o="/api/admin/links",r={listAll:function(){return Object(l["a"])({url:"".concat(o),method:"get"})},create:function(t){return Object(l["a"])({url:o,data:t,method:"post"})},get:function(t){return Object(l["a"])({url:"".concat(o,"/").concat(t),method:"get"})},update:function(t,e){return Object(l["a"])({url:"".concat(o,"/").concat(t),data:e,method:"put"})},delete:function(t){return Object(l["a"])({url:"".concat(o,"/").concat(t),method:"delete"})}},c=r,s=[{title:"名称",dataIndex:"name",scopedSlots:{customRender:"name"}},{title:"网址",dataIndex:"url",scopedSlots:{customRender:"url"}},{title:"分组",dataIndex:"team"},{title:"操作",key:"action",scopedSlots:{customRender:"action"}}],d={data:function(){return{formType:"create",data:[],loading:!1,columns:s,links:[],link:{}}},computed:{title:function(){return this.link.id?"修改友情链接":"添加友情链接"}},created:function(){this.loadLinks()},methods:{loadLinks:function(){var t=this;this.loading=!0,c.listAll().then(function(e){t.links=e.data.data,t.loading=!1})},handleSaveClick:function(){this.createOrUpdateLink()},handleAddLink:function(){this.formType="create",this.link={}},handleEditLink:function(t){var e=this;c.get(t).then(function(t){e.link=t.data.data,e.formType="update"})},handleDeleteLink:function(t){var e=this;c.delete(t).then(function(t){e.$message.success("删除成功!"),e.loadLinks()})},createOrUpdateLink:function(){var t=this;this.link.id?c.update(this.link.id,this.link).then(function(e){t.$message.success("更新成功!"),t.loadLinks()}):c.create(this.link).then(function(e){t.$message.success("保存成功!"),t.loadLinks()}),this.handleAddLink()}}},u=d,m=n("17cc"),k=Object(m["a"])(u,a,i,!1,null,"56d4c6ed",null);e["default"]=k.exports}}]);
|
|
@ -1 +1 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d228d13"],{db98:function(a,t,o){"use strict";o.r(t);var e=function(){var a=this,t=a.$createElement,o=a._self._c||t;return o("div",{staticClass:"page-header-index-wide"},[o("div",{staticClass:"card-content"},[o("a-row",{attrs:{gutter:12}},[o("a-col",{attrs:{xl:6,lg:6,md:12,sm:24,xs:24}},[o("a-card",{attrs:{title:"Markdown 文章导入",bordered:!1,bodyStyle:{padding:"16px"}}},[o("p",[a._v("支持 Hexo/Jekyll 文章导入并解析元数据")]),o("a-button",{staticStyle:{float:"right"},attrs:{type:"primary"},on:{click:a.handleImportMarkdown}},[a._v("导入")])],1)],1)],1),o("a-modal",{attrs:{title:"Markdown 文章导入",footer:null},model:{value:a.markdownUpload,callback:function(t){a.markdownUpload=t},expression:"markdownUpload"}},[o("upload",{attrs:{name:"files",multiple:"",accept:"text/markdown",uploadHandler:a.uploadHandler},on:{change:a.handleChange}},[o("p",{staticClass:"ant-upload-drag-icon"},[o("a-icon",{attrs:{type:"inbox"}})],1),o("p",{staticClass:"ant-upload-text"},[a._v("拖拽或点击选择 Markdown 文件到此处")]),o("p",{staticClass:"ant-upload-hint"},[a._v("支持多个文件同时上传")])])],1)],1)])},n=[],d=(o("7364"),o("9efd")),r="/api/admin/backups",l={importMarkdown:function(a,t,o){return Object(d["a"])({url:"".concat(r,"/import/markdowns"),timeout:864e4,data:a,onUploadProgress:t,cancelToken:o,method:"post"})}},s=l,i={data:function(){return{markdownUpload:!1,uploadHandler:s.importMarkdown}},methods:{handleImportMarkdown:function(){this.markdownUpload=!0},handleChange:function(a){var t=a.file.status;"uploading"!==t&&console.log(a.file,a.fileList),"done"===t?this.$message.success("".concat(a.file.name," 导入成功!")):"error"===t&&this.$message.error("".concat(a.file.name," 导入失败!"))}}},c=i,p=o("17cc"),u=Object(p["a"])(c,e,n,!1,null,"5fc42ae9",null);t["default"]=u.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d228d13"],{db98:function(a,t,o){"use strict";o.r(t);var e=function(){var a=this,t=a.$createElement,o=a._self._c||t;return o("div",{staticClass:"page-header-index-wide"},[o("div",{staticClass:"card-content"},[o("a-row",{attrs:{gutter:12}},[o("a-col",{attrs:{xl:6,lg:6,md:12,sm:24,xs:24}},[o("a-card",{attrs:{title:"Markdown 文章导入",bordered:!1,bodyStyle:{padding:"16px"}}},[o("p",[a._v("支持 Hexo/Jekyll 文章导入并解析元数据")]),o("a-button",{staticStyle:{float:"right"},attrs:{type:"primary"},on:{click:a.handleImportMarkdown}},[a._v("导入")])],1)],1)],1),o("a-modal",{attrs:{title:"Markdown 文章导入",footer:null},model:{value:a.markdownUpload,callback:function(t){a.markdownUpload=t},expression:"markdownUpload"}},[o("upload",{attrs:{name:"files",multiple:"",accept:"text/markdown",uploadHandler:a.uploadHandler},on:{change:a.handleChange}},[o("p",{staticClass:"ant-upload-drag-icon"},[o("a-icon",{attrs:{type:"inbox"}})],1),o("p",{staticClass:"ant-upload-text"},[a._v("拖拽或点击选择 Markdown 文件到此处")]),o("p",{staticClass:"ant-upload-hint"},[a._v("支持多个文件同时上传")])])],1)],1)])},n=[],d=(o("7364"),o("9efd")),r="/api/admin/backups",l={importMarkdown:function(a,t,o){return Object(d["a"])({url:"".concat(r,"/import/markdowns"),timeout:864e4,data:a,onUploadProgress:t,cancelToken:o,method:"post"})}},s=l,i={data:function(){return{markdownUpload:!1,uploadHandler:s.importMarkdown}},methods:{handleImportMarkdown:function(){this.markdownUpload=!0},handleChange:function(a){var t=a.file.status;"uploading"!==t&&console.log(a.file,a.fileList),"done"===t?this.$message.success("".concat(a.file.name," 导入成功!")):"error"===t&&this.$message.error("".concat(a.file.name," 导入失败!"))}}},c=i,p=o("17cc"),u=Object(p["a"])(c,e,n,!1,null,"8dab78e6",null);t["default"]=u.exports}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-9449c032"],{9231:function(a,e,t){"use strict";var s=t("ea0a"),n=t.n(s);n.a},ac2a5:function(a,e,t){"use strict";t.r(e);var s=function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("div",{staticClass:"container"},[a._m(0),t("div",{staticClass:"loginBody animated"},[t("a-form",{attrs:{layout:"vertical"},nativeOn:{keyup:function(e){return!e.type.indexOf("key")&&a._k(e.keyCode,"enter",13,e.key,"Enter")?null:a.handleLogin(e)}}},[t("a-form-item",{staticClass:"animated fadeInUp",style:{"animation-delay":"0.1s"}},[t("a-input",{attrs:{placeholder:"用户名/邮箱"},model:{value:a.username,callback:function(e){a.username=e},expression:"username"}},[t("a-icon",{staticStyle:{color:"rgba(0,0,0,.25)"},attrs:{slot:"prefix",type:"user"},slot:"prefix"})],1)],1),t("a-form-item",{staticClass:"animated fadeInUp",style:{"animation-delay":"0.2s"}},[t("a-input",{attrs:{type:"password",placeholder:"密码"},model:{value:a.password,callback:function(e){a.password=e},expression:"password"}},[t("a-icon",{staticStyle:{color:"rgba(0,0,0,.25)"},attrs:{slot:"prefix",type:"lock"},slot:"prefix"})],1)],1),t("a-row",[t("a-button",{staticClass:"animated fadeInUp",style:{"animation-delay":"0.3s"},attrs:{type:"primary",block:!0},on:{click:a.handleLogin}},[a._v("登录")])],1)],1)],1)])},n=[function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("div",{staticClass:"loginLogo animated fadeInUp"},[t("span",[a._v("Halo")])])}],i=(t("34a3"),t("e20c")),r=t("591a"),o={data:function(){return{username:null,password:null}},methods:Object(i["a"])({},Object(r["b"])(["login","loadUser"]),{handleLogin:function(){var a=this;this.username?this.password?this.login({username:this.username,password:this.password}).then(function(e){a.loginSuccess()}):this.$message.warn("密码不能为空!"):this.$message.warn("用户名不能为空!")},loginSuccess:function(){this.loadUser(),this.$route.query.redirect?this.$router.replace(this.$route.query.redirect):this.$router.replace({name:"Dashboard"})}})},l=o,c=(t("9231"),t("17cc")),u=Object(c["a"])(l,s,n,!1,null,null,null);e["default"]=u.exports},ea0a:function(a,e,t){}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-cec31564"],{9231:function(e,a,t){"use strict";var s=t("ea0a"),n=t.n(s);n.a},ac2a:function(e,a,t){"use strict";t.r(a);var s=function(){var e=this,a=e.$createElement,t=e._self._c||a;return t("div",{staticClass:"container"},[e._m(0),t("div",{staticClass:"loginBody animated"},[t("a-form",{attrs:{layout:"vertical"},nativeOn:{keyup:function(a){return!a.type.indexOf("key")&&e._k(a.keyCode,"enter",13,a.key,"Enter")?null:e.handleLogin(a)}}},[t("a-form-item",{staticClass:"animated fadeInUp",style:{"animation-delay":"0.1s"}},[t("a-input",{attrs:{placeholder:"用户名/邮箱"},model:{value:e.username,callback:function(a){e.username=a},expression:"username"}},[t("a-icon",{staticStyle:{color:"rgba(0,0,0,.25)"},attrs:{slot:"prefix",type:"user"},slot:"prefix"})],1)],1),t("a-form-item",{staticClass:"animated fadeInUp",style:{"animation-delay":"0.2s"}},[t("a-input",{attrs:{type:"password",placeholder:"密码"},model:{value:e.password,callback:function(a){e.password=a},expression:"password"}},[t("a-icon",{staticStyle:{color:"rgba(0,0,0,.25)"},attrs:{slot:"prefix",type:"lock"},slot:"prefix"})],1)],1),t("a-row",[t("a-button",{staticClass:"animated fadeInUp",style:{"animation-delay":"0.3s"},attrs:{type:"primary",block:!0},on:{click:e.handleLogin}},[e._v("登录")])],1)],1)],1)])},n=[function(){var e=this,a=e.$createElement,t=e._self._c||a;return t("div",{staticClass:"loginLogo animated fadeInUp"},[t("span",[e._v("Halo")])])}],i=(t("34a3"),t("e20c")),r=t("591a"),o={data:function(){return{username:null,password:null}},methods:Object(i["a"])({},Object(r["b"])(["login","loadUser"]),{handleLogin:function(){var e=this;this.username?this.password?this.login({username:this.username,password:this.password}).then(function(a){e.loginSuccess()}):this.$message.warn("密码不能为空!"):this.$message.warn("用户名不能为空!")},loginSuccess:function(){this.loadUser(),this.$route.query.redirect?this.$router.replace(this.$route.query.redirect):this.$router.replace({name:"Dashboard"})}})},l=o,c=(t("9231"),t("17cc")),u=Object(c["a"])(l,s,n,!1,null,null,null);a["default"]=u.exports},ea0a:function(e,a,t){}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["fail"],{5517:function(t,e,s){"use strict";var c=s("92530"),n=s.n(c);n.a},92530:function(t,e,s){},cc89:function(t,e,s){"use strict";s.r(e);var c=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("exception-page",{attrs:{type:"404"}})},n=[],a=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"exception"},[s("div",{staticClass:"img"},[s("img",{attrs:{src:t.config[t.type].img}})]),s("div",{staticClass:"content"},[s("h1",[t._v(t._s(t.config[t.type].title))]),s("div",{staticClass:"desc"},[t._v(t._s(t.config[t.type].desc))]),s("div",{staticClass:"action"},[s("a-button",{attrs:{type:"primary"},on:{click:t.handleToHome}},[t._v("返回首页")])],1)])])},i=[],o={404:{img:"https://gw.alipayobjects.com/zos/rmsportal/KpnpchXsobRgLElEozzI.svg",title:"404",desc:"抱歉,你访问的页面不存在"},500:{img:"https://gw.alipayobjects.com/zos/rmsportal/RVRUAYdCGeYNBWoKiIwB.svg",title:"500",desc:"抱歉,服务器出错了"}},p=o,r={name:"Exception",props:{type:{type:String,default:"404"}},data:function(){return{config:p}},methods:{handleToHome:function(){this.$router.push({name:"Dashboard"})}}},l=r,u=(s("5517"),s("17cc")),d=Object(u["a"])(l,a,i,!1,null,"729a8fea",null),f=d.exports,m={components:{ExceptionPage:f}},g=m,v=Object(u["a"])(g,c,n,!1,null,"388fe08d",null);e["default"]=v.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["fail"],{"01a4":function(t,e,s){},2254:function(t,e,s){"use strict";var a=s("01a4"),c=s.n(a);c.a},cc89:function(t,e,s){"use strict";s.r(e);var a=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("exception-page",{attrs:{type:"404"}})},c=[],n=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"exception"},[s("div",{staticClass:"img"},[s("img",{attrs:{src:t.config[t.type].img}})]),s("div",{staticClass:"content"},[s("h1",[t._v(t._s(t.config[t.type].title))]),s("div",{staticClass:"desc"},[t._v(t._s(t.config[t.type].desc))]),s("div",{staticClass:"action"},[s("a-button",{attrs:{type:"primary"},on:{click:t.handleToHome}},[t._v("返回首页")])],1)])])},i=[],o={404:{img:"https://gw.alipayobjects.com/zos/rmsportal/KpnpchXsobRgLElEozzI.svg",title:"404",desc:"抱歉,你访问的页面不存在"},500:{img:"https://gw.alipayobjects.com/zos/rmsportal/RVRUAYdCGeYNBWoKiIwB.svg",title:"500",desc:"抱歉,服务器出错了"}},p=o,r={name:"Exception",props:{type:{type:String,default:"404"}},data:function(){return{config:p}},methods:{handleToHome:function(){this.$router.push({name:"Dashboard"})}}},l=r,u=(s("2254"),s("17cc")),d=Object(u["a"])(l,n,i,!1,null,"230942b4",null),m=d.exports,g={components:{ExceptionPage:m}},f=g,v=Object(u["a"])(f,a,c,!1,null,"e319b3a6",null);e["default"]=v.exports}}]);
|
|
@ -8,6 +8,7 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
|
@ -27,26 +28,29 @@ public class FileUtilsTest {
|
|||
// Create test folders
|
||||
Files.createDirectories(testPath);
|
||||
|
||||
System.out.println("Walk path list");
|
||||
List<Path> walkList = Files.walk(tempDirectory).collect(Collectors.toList());
|
||||
walkList.forEach(System.out::println);
|
||||
Assert.assertThat(walkList.size(), equalTo(4));
|
||||
try (Stream<Path> pathStream = Files.walk(tempDirectory)) {
|
||||
List<Path> walkList = pathStream.collect(Collectors.toList());
|
||||
walkList.forEach(System.out::println);
|
||||
Assert.assertThat(walkList.size(), equalTo(4));
|
||||
}
|
||||
|
||||
try (Stream<Path> pathStream = Files.walk(tempDirectory, 1)) {
|
||||
List<Path> walkList = pathStream.collect(Collectors.toList());
|
||||
walkList.forEach(System.out::println);
|
||||
Assert.assertThat(walkList.size(), equalTo(2));
|
||||
}
|
||||
|
||||
System.out.println("Walk 1 deep path list");
|
||||
List<Path> walk1DeepList = Files.walk(tempDirectory, 1).collect(Collectors.toList());
|
||||
walk1DeepList.forEach(System.out::println);
|
||||
Assert.assertThat(walk1DeepList.size(), equalTo(2));
|
||||
try (Stream<Path> pathStream = Files.list(tempDirectory)) {
|
||||
List<Path> walkList = pathStream.collect(Collectors.toList());
|
||||
walkList.forEach(System.out::println);
|
||||
Assert.assertThat(walkList.size(), equalTo(1));
|
||||
}
|
||||
|
||||
System.out.println("List path list");
|
||||
List<Path> listList = Files.list(tempDirectory).collect(Collectors.toList());
|
||||
listList.forEach(System.out::println);
|
||||
Assert.assertThat(listList.size(), equalTo(1));
|
||||
|
||||
System.out.println("List test path list");
|
||||
List<Path> testPathList = Files.list(testPath).collect(Collectors.toList());
|
||||
testPathList.forEach(System.out::println);
|
||||
Assert.assertThat(testPathList.size(), equalTo(0));
|
||||
try (Stream<Path> pathStream = Files.list(testPath)) {
|
||||
List<Path> walkList = pathStream.collect(Collectors.toList());
|
||||
walkList.forEach(System.out::println);
|
||||
Assert.assertThat(walkList.size(), equalTo(0));
|
||||
}
|
||||
|
||||
// Delete it
|
||||
FileUtils.deleteFolder(tempDirectory);
|
||||
|
|
|
@ -41,9 +41,10 @@ public class GithubTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getLatestReleaseTest() throws Throwable {
|
||||
ResponseEntity<Map> responseEntity = restTemplate.getForEntity(API_URL, Map.class);
|
||||
System.out.println("Reponse: " + responseEntity);
|
||||
System.out.println("Response: " + responseEntity);
|
||||
Object assetsObject = responseEntity.getBody().get("assets");
|
||||
System.out.println("Assets class: " + assetsObject.getClass());
|
||||
System.out.println("Assets: " + assetsObject);
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package run.halo.app.utils;
|
||||
|
||||
import com.sun.nio.zipfs.JarFileSystemProvider;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.*;
|
||||
import java.util.Collections;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Path test.
|
||||
|
@ -25,18 +24,4 @@ public class PathTest {
|
|||
|
||||
System.out.println("Path: " + path.toString());
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void getPathOfJarFileSuccessfully() throws URISyntaxException, IOException {
|
||||
// String file = "jar:file:/path/to/jar/xxx.jar!/BOOT-INF/classes!/templates/themes";
|
||||
// URI uri = new URI(file);
|
||||
// FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap());
|
||||
// Path path = fileSystem.getPath("/BOOT-INF/classes/templates/themes");
|
||||
//
|
||||
// System.out.println("Path: " + path.toString());
|
||||
//
|
||||
// Files.walk(path, 1).forEach(p -> {
|
||||
// System.out.println(p.toString());
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package run.halo.app.utils;
|
||||
|
||||
import io.micrometer.core.annotation.TimedSet;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
|
Loading…
Reference in New Issue