fix: исправлены роуты веб-сервера и обновлён Makefile

- Убран дублирующийся роут /favicon.ico
- Добавлен импорт ServeDir
- Makefile: поддержка ImageMagick 6 и 7
- Добавлена цель favicon
This commit is contained in:
2026-04-18 11:12:54 +03:00
parent 6a642beb5c
commit 4646dd2b70
8 changed files with 107 additions and 17 deletions

19
Cargo.lock generated
View File

@@ -33,6 +33,7 @@ dependencies = [
"tower", "tower",
"tower-http", "tower-http",
"urlencoding", "urlencoding",
"winres",
] ]
[[package]] [[package]]
@@ -1768,6 +1769,15 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "tower" name = "tower"
version = "0.5.3" version = "0.5.3"
@@ -2167,6 +2177,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winres"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
dependencies = [
"toml",
]
[[package]] [[package]]
name = "wit-bindgen" name = "wit-bindgen"
version = "0.51.0" version = "0.51.0"

View File

@@ -48,3 +48,9 @@ opt-level = "z"
lto = true lto = true
codegen-units = 1 codegen-units = 1
strip = true strip = true
[target.'cfg(windows)'.dependencies]
winres = "0.1"
[build-dependencies]
winres = "0.1"

BIN
assets/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

9
build.rs Normal file
View File

@@ -0,0 +1,9 @@
// build.rs
fn main() {
#[cfg(windows)]
{
let mut res = winres::WindowsResource::new();
res.set_icon("assets/logo.ico");
res.compile().unwrap();
}
}

View File

@@ -1,4 +1,4 @@
.PHONY: all clean build-mac build-windows build-linux build-linux-musl package help quick package-single .PHONY: all clean build-mac build-windows build-linux build-linux-musl package help quick package-single icons favicon
# Название проекта # Название проекта
PROJECT_NAME := ae_anons PROJECT_NAME := ae_anons
@@ -18,11 +18,14 @@ BLUE := \033[0;34m
CYAN := \033[0;36m CYAN := \033[0;36m
MAGENTA := \033[0;35m MAGENTA := \033[0;35m
BOLD := \033[1m BOLD := \033[1m
NC := \033[0m # No Color NC := \033[0m
# Файл для хранения времени сборки # Файл для хранения времени сборки
TIMING_FILE := .build_timing TIMING_FILE := .build_timing
# Определение команды ImageMagick (v6 = convert, v7 = magick)
IMAGEMAGICK := $(shell command -v magick 2>/dev/null || command -v convert 2>/dev/null || echo "false")
help: help:
@echo "$(BOLD)$(CYAN)AE Anons - Makefile команды$(NC)" @echo "$(BOLD)$(CYAN)AE Anons - Makefile команды$(NC)"
@echo "" @echo ""
@@ -41,6 +44,10 @@ help:
@echo " make package - Создать пакеты для всех платформ" @echo " make package - Создать пакеты для всех платформ"
@echo " make package-single - Создать пакет для текущей платформы" @echo " make package-single - Создать пакет для текущей платформы"
@echo "" @echo ""
@echo "$(GREEN)Иконки:$(NC)"
@echo " make icons - Создать все иконки (logo.ico, logo.icns, favicon.ico)"
@echo " make favicon - Создать только favicon.ico"
@echo ""
@echo "$(GREEN)Очистка:$(NC)" @echo "$(GREEN)Очистка:$(NC)"
@echo " make clean - Очистить все сборки" @echo " make clean - Очистить все сборки"
@echo " make clean-timing - Очистить файл с временами сборки" @echo " make clean-timing - Очистить файл с временами сборки"
@@ -49,14 +56,12 @@ help:
# ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ # ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ
# ============================================ # ============================================
# Копирование общих файлов в пакет
define copy_common_files define copy_common_files
@cp .env.example $(1)/ 2>/dev/null || true @cp .env.example $(1)/ 2>/dev/null || true
@cp README.md $(1)/ 2>/dev/null || true @cp README.md $(1)/ 2>/dev/null || true
@if [ -f LICENSE ]; then cp LICENSE $(1)/; else echo "$(YELLOW)⚠️ LICENSE не найден, пропускаем$(NC)"; fi @if [ -f LICENSE ]; then cp LICENSE $(1)/; else echo "$(YELLOW)⚠️ LICENSE не найден, пропускаем$(NC)"; fi
endef endef
# Функция для замера времени
define measure_time define measure_time
@start=$$(date +%s); \ @start=$$(date +%s); \
$(2); \ $(2); \
@@ -66,7 +71,6 @@ define measure_time
echo "$(GREEN)$(1) завершён за $$duration сек$(NC)" echo "$(GREEN)$(1) завершён за $$duration сек$(NC)"
endef endef
# Функция для вывода итоговой таблицы
define print_timing_summary define print_timing_summary
@echo "" @echo ""
@echo "$(BOLD)$(CYAN)═══════════════════════════════════════════════════════════════$(NC)" @echo "$(BOLD)$(CYAN)═══════════════════════════════════════════════════════════════$(NC)"
@@ -88,6 +92,43 @@ define print_timing_summary
@rm -f $(TIMING_FILE) @rm -f $(TIMING_FILE)
endef endef
# ============================================
# ИКОНКИ
# ============================================
icons: favicon
@echo "$(GREEN)Создание иконок для Windows и macOS...$(NC)"
@if [ "$(IMAGEMAGICK)" = "false" ]; then \
echo "$(RED)❌ ImageMagick не установлен. Установите: brew install imagemagick$(NC)"; \
exit 1; \
fi
# Windows .ico
@$(IMAGEMAGICK) assets/logo.png -define icon:auto-resize=256,128,64,48,32,16 assets/logo.ico
@echo "$(GREEN) ✓ assets/logo.ico$(NC)"
# macOS .icns
@mkdir -p assets/icon.iconset
@sips -z 16 16 assets/logo.png --out assets/icon.iconset/icon_16x16.png 2>/dev/null
@sips -z 32 32 assets/logo.png --out assets/icon.iconset/icon_16x16@2x.png 2>/dev/null
@sips -z 32 32 assets/logo.png --out assets/icon.iconset/icon_32x32.png 2>/dev/null
@sips -z 64 64 assets/logo.png --out assets/icon.iconset/icon_32x32@2x.png 2>/dev/null
@sips -z 128 128 assets/logo.png --out assets/icon.iconset/icon_128x128.png 2>/dev/null
@sips -z 256 256 assets/logo.png --out assets/icon.iconset/icon_128x128@2x.png 2>/dev/null
@sips -z 256 256 assets/logo.png --out assets/icon.iconset/icon_256x256.png 2>/dev/null
@sips -z 512 512 assets/logo.png --out assets/icon.iconset/icon_256x256@2x.png 2>/dev/null
@sips -z 512 512 assets/logo.png --out assets/icon.iconset/icon_512x512.png 2>/dev/null
@iconutil -c icns assets/icon.iconset -o assets/logo.icns 2>/dev/null
@rm -rf assets/icon.iconset
@echo "$(GREEN) ✓ assets/logo.icns$(NC)"
favicon:
@echo "$(GREEN)Создание favicon.ico...$(NC)"
@if [ "$(IMAGEMAGICK)" = "false" ]; then \
echo "$(RED)❌ ImageMagick не установлен. Установите: brew install imagemagick$(NC)"; \
exit 1; \
fi
@$(IMAGEMAGICK) assets/logo.png -define icon:auto-resize=48,32,16 src/static/favicon.ico
@echo "$(GREEN) ✓ src/static/favicon.ico$(NC)"
# ============================================ # ============================================
# ОПРЕДЕЛЕНИЕ ПЛАТФОРМЫ # ОПРЕДЕЛЕНИЕ ПЛАТФОРМЫ
# ============================================ # ============================================
@@ -113,7 +154,6 @@ endif
quick: detect-platform quick: detect-platform
# Быстрая сборка без упаковки (только бинарник)
quick-release: quick-release:
ifeq ($(UNAME_S),Darwin) ifeq ($(UNAME_S),Darwin)
@echo "$(GREEN)🍎 Сборка для macOS...$(NC)" @echo "$(GREEN)🍎 Сборка для macOS...$(NC)"

BIN
src/static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -4,12 +4,13 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AE Anons - Nexrender Job Manager</title> <title>AE Anons</title>
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/png" href="/favicon.ico"> <link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/favicon.ico"> <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/assets/logo.png">
<!-- CSS -->
<link rel="stylesheet" href="/static/fontawesome/all.min.css"> <link rel="stylesheet" href="/static/fontawesome/all.min.css">
<link rel="stylesheet" href="/static/style.css"> <link rel="stylesheet" href="/static/style.css">
</head> </head>
@@ -26,7 +27,7 @@
<i class="fas fa-bolt"></i> <i class="fas fa-bolt"></i>
</div> </div>
</div> </div>
<h1>AE Anons - Nexrender Job Manager</h1> <h1>AE Anons</h1>
</div> </div>
<div class="header-controls"> <div class="header-controls">
<button class="theme-toggle" onclick="toggleTheme()"> <button class="theme-toggle" onclick="toggleTheme()">

View File

@@ -89,13 +89,16 @@ pub async fn run_web_server(config: Config) -> anyhow::Result<()> {
.route("/favicon.ico", get(favicon)) .route("/favicon.ico", get(favicon))
.route("/static/style.css", get(style_css)) .route("/static/style.css", get(style_css))
.route("/static/fontawesome/all.min.css", get(fontawesome_css)) .route("/static/fontawesome/all.min.css", get(fontawesome_css))
.nest_service("/static/fontawesome/webfonts", ServeDir::new("src/static/fontawesome/webfonts"))
.route("/assets/logo.png", get(logo_png)) .route("/assets/logo.png", get(logo_png))
.route("/api/jobs", get(list_jobs)) .route("/api/jobs", get(list_jobs))
.route("/api/generate", post(generate_jobs)) .route("/api/generate", post(generate_jobs))
.route("/api/cleanup", post(cleanup_jobs)) .route("/api/cleanup", post(cleanup_jobs))
.route("/api/status", get(get_status)) .route("/api/status", get(get_status))
.route("/api/jobs/stop-all", post(stop_all_jobs)) .route("/api/jobs/stop-all", post(stop_all_jobs))
.nest_service(
"/static/fontawesome/webfonts",
ServeDir::new("src/static/fontawesome/webfonts"),
)
.layer(TraceLayer::new_for_http()) .layer(TraceLayer::new_for_http())
.with_state(state); .with_state(state);
@@ -112,19 +115,31 @@ async fn index_page() -> Html<&'static str> {
} }
async fn style_css() -> impl IntoResponse { async fn style_css() -> impl IntoResponse {
([(CONTENT_TYPE, "text/css")], include_str!("static/style.css")) (
[(CONTENT_TYPE, "text/css")],
include_str!("static/style.css"),
)
} }
async fn fontawesome_css() -> impl IntoResponse { async fn fontawesome_css() -> impl IntoResponse {
([(CONTENT_TYPE, "text/css")], include_str!("static/fontawesome/all.min.css")) (
[(CONTENT_TYPE, "text/css")],
include_str!("static/fontawesome/all.min.css"),
)
} }
async fn logo_png() -> impl IntoResponse { async fn logo_png() -> impl IntoResponse {
([(CONTENT_TYPE, "image/png")], include_bytes!("../assets/logo.png").as_slice()) (
[(CONTENT_TYPE, "image/png")],
include_bytes!("../assets/logo.png").as_slice(),
)
} }
async fn favicon() -> impl IntoResponse { async fn favicon() -> impl IntoResponse {
([(CONTENT_TYPE, "image/png")], include_bytes!("../assets/logo.png").as_slice()) (
[(CONTENT_TYPE, "image/x-icon")],
include_bytes!("static/favicon.ico").as_slice(),
)
} }
async fn list_jobs(State(state): State<AppState>) -> Result<Json<Vec<JobInfo>>, AppError> { async fn list_jobs(State(state): State<AppState>) -> Result<Json<Vec<JobInfo>>, AppError> {