feat: 添加站点设置中的 favicon URL 支持,更新相关接口和页面
All checks were successful
ui-regression / playwright-regression (push) Successful in 6m20s
docker-images / resolve-build-targets (push) Successful in 6s
docker-images / build-and-push (admin) (push) Successful in 25s
docker-images / build-and-push (backend) (push) Successful in 35s
docker-images / build-and-push (frontend) (push) Successful in 1m46s
docker-images / submit-indexnow (push) Successful in 15s
All checks were successful
ui-regression / playwright-regression (push) Successful in 6m20s
docker-images / resolve-build-targets (push) Successful in 6s
docker-images / build-and-push (admin) (push) Successful in 25s
docker-images / build-and-push (backend) (push) Successful in 35s
docker-images / build-and-push (frontend) (push) Successful in 1m46s
docker-images / submit-indexnow (push) Successful in 15s
This commit is contained in:
@@ -397,6 +397,14 @@ impl Hooks for App {
|
||||
Some(trimmed.to_string())
|
||||
}
|
||||
});
|
||||
let seo_favicon_url = settings["seo_favicon_url"].as_str().and_then(|value| {
|
||||
let trimmed = value.trim();
|
||||
if trimmed.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(trimmed.to_string())
|
||||
}
|
||||
});
|
||||
|
||||
let item = site_settings::ActiveModel {
|
||||
id: Set(settings["id"].as_i64().unwrap_or(1) as i32),
|
||||
@@ -441,6 +449,7 @@ impl Hooks for App {
|
||||
music_enabled: Set(music_enabled),
|
||||
maintenance_mode_enabled: Set(maintenance_mode_enabled),
|
||||
maintenance_access_code: Set(maintenance_access_code),
|
||||
seo_favicon_url: Set(seo_favicon_url),
|
||||
ai_enabled: Set(settings["ai_enabled"].as_bool()),
|
||||
paragraph_comments_enabled: Set(settings["paragraph_comments_enabled"]
|
||||
.as_bool()
|
||||
|
||||
@@ -213,6 +213,7 @@ pub struct AdminSiteSettingsResponse {
|
||||
pub media_r2_public_base_url: Option<String>,
|
||||
pub media_r2_access_key_id: Option<String>,
|
||||
pub media_r2_secret_access_key: Option<String>,
|
||||
pub seo_favicon_url: Option<String>,
|
||||
pub seo_default_og_image: Option<String>,
|
||||
pub seo_default_twitter_handle: Option<String>,
|
||||
pub seo_wechat_share_qr_enabled: bool,
|
||||
@@ -1068,6 +1069,7 @@ fn build_settings_response(
|
||||
media_r2_public_base_url: item.media_r2_public_base_url,
|
||||
media_r2_access_key_id: item.media_r2_access_key_id,
|
||||
media_r2_secret_access_key: item.media_r2_secret_access_key,
|
||||
seo_favicon_url: item.seo_favicon_url,
|
||||
seo_default_og_image: item.seo_default_og_image,
|
||||
seo_default_twitter_handle: item.seo_default_twitter_handle,
|
||||
seo_wechat_share_qr_enabled: item.seo_wechat_share_qr_enabled.unwrap_or(false),
|
||||
|
||||
@@ -160,6 +160,8 @@ pub struct SiteSettingsPayload {
|
||||
pub media_r2_access_key_id: Option<String>,
|
||||
#[serde(default, alias = "mediaR2SecretAccessKey")]
|
||||
pub media_r2_secret_access_key: Option<String>,
|
||||
#[serde(default, alias = "seoFaviconUrl")]
|
||||
pub seo_favicon_url: Option<String>,
|
||||
#[serde(default, alias = "seoDefaultOgImage")]
|
||||
pub seo_default_og_image: Option<String>,
|
||||
#[serde(default, alias = "seoDefaultTwitterHandle")]
|
||||
@@ -220,6 +222,7 @@ pub struct PublicSiteSettingsResponse {
|
||||
pub subscription_popup_title: String,
|
||||
pub subscription_popup_description: String,
|
||||
pub subscription_popup_delay_seconds: i32,
|
||||
pub seo_favicon_url: Option<String>,
|
||||
pub seo_default_og_image: Option<String>,
|
||||
pub seo_default_twitter_handle: Option<String>,
|
||||
pub seo_wechat_share_qr_enabled: bool,
|
||||
@@ -776,6 +779,9 @@ impl SiteSettingsPayload {
|
||||
item.media_r2_secret_access_key =
|
||||
normalize_optional_string(Some(media_r2_secret_access_key));
|
||||
}
|
||||
if let Some(seo_favicon_url) = self.seo_favicon_url {
|
||||
item.seo_favicon_url = normalize_optional_string(Some(seo_favicon_url));
|
||||
}
|
||||
if let Some(seo_default_og_image) = self.seo_default_og_image {
|
||||
item.seo_default_og_image = normalize_optional_string(Some(seo_default_og_image));
|
||||
}
|
||||
@@ -942,6 +948,7 @@ fn default_payload() -> SiteSettingsPayload {
|
||||
media_r2_public_base_url: None,
|
||||
media_r2_access_key_id: None,
|
||||
media_r2_secret_access_key: None,
|
||||
seo_favicon_url: None,
|
||||
seo_default_og_image: None,
|
||||
seo_default_twitter_handle: None,
|
||||
seo_wechat_share_qr_enabled: Some(false),
|
||||
@@ -1041,6 +1048,7 @@ fn public_response(model: Model) -> PublicSiteSettingsResponse {
|
||||
subscription_popup_delay_seconds: model
|
||||
.subscription_popup_delay_seconds
|
||||
.unwrap_or_else(default_subscription_popup_delay_seconds),
|
||||
seo_favicon_url: model.seo_favicon_url,
|
||||
seo_default_og_image: model.seo_default_og_image,
|
||||
seo_default_twitter_handle: model.seo_default_twitter_handle,
|
||||
seo_wechat_share_qr_enabled: model.seo_wechat_share_qr_enabled.unwrap_or(false),
|
||||
|
||||
@@ -60,3 +60,4 @@
|
||||
ai_system_prompt: "你是这个博客的站内 AI 助手。请优先依据检索到的站内内容回答问题,回答保持准确、简洁、清晰;如果上下文不足,请明确说明,不要编造。"
|
||||
ai_top_k: 4
|
||||
ai_chunk_size: 1200
|
||||
seo_favicon_url: null
|
||||
|
||||
@@ -111,6 +111,7 @@ async fn sync_site_settings(ctx: &AppContext, base: &Path) -> Result<()> {
|
||||
let music_enabled = seed["music_enabled"].as_bool().or(Some(true));
|
||||
let maintenance_mode_enabled = seed["maintenance_mode_enabled"].as_bool().or(Some(false));
|
||||
let maintenance_access_code = as_optional_string(&seed["maintenance_access_code"]);
|
||||
let seo_favicon_url = as_optional_string(&seed["seo_favicon_url"]);
|
||||
let comment_verification_mode = as_optional_string(&seed["comment_verification_mode"]);
|
||||
let subscription_verification_mode =
|
||||
as_optional_string(&seed["subscription_verification_mode"]);
|
||||
@@ -196,6 +197,9 @@ async fn sync_site_settings(ctx: &AppContext, base: &Path) -> Result<()> {
|
||||
if is_blank(&existing.maintenance_access_code) {
|
||||
model.maintenance_access_code = Set(maintenance_access_code.clone());
|
||||
}
|
||||
if is_blank(&existing.seo_favicon_url) {
|
||||
model.seo_favicon_url = Set(seo_favicon_url.clone());
|
||||
}
|
||||
if existing.ai_enabled.is_none() {
|
||||
model.ai_enabled = Set(seed["ai_enabled"].as_bool());
|
||||
}
|
||||
@@ -278,6 +282,7 @@ async fn sync_site_settings(ctx: &AppContext, base: &Path) -> Result<()> {
|
||||
music_enabled: Set(music_enabled),
|
||||
maintenance_mode_enabled: Set(maintenance_mode_enabled),
|
||||
maintenance_access_code: Set(maintenance_access_code),
|
||||
seo_favicon_url: Set(seo_favicon_url),
|
||||
ai_enabled: Set(seed["ai_enabled"].as_bool()),
|
||||
paragraph_comments_enabled: Set(seed["paragraph_comments_enabled"]
|
||||
.as_bool()
|
||||
|
||||
@@ -78,6 +78,8 @@ pub struct Model {
|
||||
#[sea_orm(column_type = "Text", nullable)]
|
||||
pub media_r2_secret_access_key: Option<String>,
|
||||
#[sea_orm(column_type = "Text", nullable)]
|
||||
pub seo_favicon_url: Option<String>,
|
||||
#[sea_orm(column_type = "Text", nullable)]
|
||||
pub seo_default_og_image: Option<String>,
|
||||
pub seo_default_twitter_handle: Option<String>,
|
||||
pub seo_wechat_share_qr_enabled: Option<bool>,
|
||||
|
||||
Reference in New Issue
Block a user