feat: add SharePanel component for social sharing with QR code support
Some checks failed
docker-images / resolve-build-targets (push) Successful in 7s
ui-regression / playwright-regression (push) Failing after 13m47s
docker-images / build-and-push (push) Failing after 7s
docker-images / submit-indexnow (push) Has been skipped

- Implemented SharePanel component in `SharePanel.astro` for sharing content on social media platforms.
- Integrated QR code generation for WeChat sharing using the `qrcode` library.
- Added localization support for English and Chinese languages.
- Created utility functions in `seo.ts` for building article summaries and FAQs.
- Introduced API routes for serving IndexNow key and generating full LLM catalog and summaries.
- Enhanced SEO capabilities with structured data for articles and pages.
This commit is contained in:
2026-04-02 14:15:21 +08:00
parent a516be2e91
commit 3628a46ed1
53 changed files with 4390 additions and 91 deletions

View File

@@ -157,6 +157,8 @@ pub struct SiteSettingsPayload {
pub seo_default_og_image: Option<String>,
#[serde(default, alias = "seoDefaultTwitterHandle")]
pub seo_default_twitter_handle: Option<String>,
#[serde(default, alias = "seoWechatShareQrEnabled")]
pub seo_wechat_share_qr_enabled: Option<bool>,
#[serde(default, alias = "notificationWebhookUrl")]
pub notification_webhook_url: Option<String>,
#[serde(default, alias = "notificationChannelType")]
@@ -212,6 +214,7 @@ pub struct PublicSiteSettingsResponse {
pub subscription_popup_delay_seconds: i32,
pub seo_default_og_image: Option<String>,
pub seo_default_twitter_handle: Option<String>,
pub seo_wechat_share_qr_enabled: bool,
}
#[derive(Clone, Debug, Serialize)]
@@ -693,6 +696,9 @@ impl SiteSettingsPayload {
item.seo_default_twitter_handle =
normalize_optional_string(Some(seo_default_twitter_handle));
}
if let Some(seo_wechat_share_qr_enabled) = self.seo_wechat_share_qr_enabled {
item.seo_wechat_share_qr_enabled = Some(seo_wechat_share_qr_enabled);
}
if let Some(notification_webhook_url) = self.notification_webhook_url {
item.notification_webhook_url =
normalize_optional_string(Some(notification_webhook_url));
@@ -848,6 +854,7 @@ fn default_payload() -> SiteSettingsPayload {
media_r2_secret_access_key: None,
seo_default_og_image: None,
seo_default_twitter_handle: None,
seo_wechat_share_qr_enabled: Some(false),
notification_webhook_url: None,
notification_channel_type: Some("webhook".to_string()),
notification_comment_enabled: Some(false),
@@ -945,6 +952,7 @@ fn public_response(model: Model) -> PublicSiteSettingsResponse {
.unwrap_or_else(default_subscription_popup_delay_seconds),
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),
}
}