From af2e7b4f2f8389a714bb8e802eb9c90160551750 Mon Sep 17 00:00:00 2001 From: lincube Date: Tue, 24 Mar 2026 09:33:56 +0800 Subject: [PATCH] 0.7.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 橘鸦新闻 --- LanMountainDesktop/Assets/bilibili.svg | 1 + LanMountainDesktop/Assets/juya_avatar.jpg | Bin 0 -> 65386 bytes LanMountainDesktop/Assets/wechat.svg | 1 + .../ComponentSystem/BuiltInComponentIds.cs | 1 + .../ComponentSystem/ComponentRegistry.cs | 10 + .../Views/Components/DailyNewsView.axaml | 105 +++ .../Views/Components/DailyNewsView.axaml.cs | 526 ++++++++++++ .../DesktopComponentRuntimeRegistry.cs | 4 + .../Views/Components/JuyaNewsWidget.axaml | 104 +++ .../Views/Components/JuyaNewsWidget.axaml.cs | 756 ++++++++++++++++++ README.md | 152 +++- docs/JUYA_NEWS_DESIGN.md | 556 +++++++++++++ docs/PRODUCT.md | 2 +- 13 files changed, 2181 insertions(+), 37 deletions(-) create mode 100644 LanMountainDesktop/Assets/bilibili.svg create mode 100644 LanMountainDesktop/Assets/juya_avatar.jpg create mode 100644 LanMountainDesktop/Assets/wechat.svg create mode 100644 LanMountainDesktop/Views/Components/DailyNewsView.axaml create mode 100644 LanMountainDesktop/Views/Components/DailyNewsView.axaml.cs create mode 100644 LanMountainDesktop/Views/Components/JuyaNewsWidget.axaml create mode 100644 LanMountainDesktop/Views/Components/JuyaNewsWidget.axaml.cs create mode 100644 docs/JUYA_NEWS_DESIGN.md diff --git a/LanMountainDesktop/Assets/bilibili.svg b/LanMountainDesktop/Assets/bilibili.svg new file mode 100644 index 0000000..6c114c7 --- /dev/null +++ b/LanMountainDesktop/Assets/bilibili.svg @@ -0,0 +1 @@ +Bilibili \ No newline at end of file diff --git a/LanMountainDesktop/Assets/juya_avatar.jpg b/LanMountainDesktop/Assets/juya_avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da95680ef466c5ca63201334861d1eb9a04237d4 GIT binary patch literal 65386 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 literal 0 HcmV?d00001 diff --git a/LanMountainDesktop/Assets/wechat.svg b/LanMountainDesktop/Assets/wechat.svg new file mode 100644 index 0000000..c3eb6c4 --- /dev/null +++ b/LanMountainDesktop/Assets/wechat.svg @@ -0,0 +1 @@ +WeChat \ No newline at end of file diff --git a/LanMountainDesktop/ComponentSystem/BuiltInComponentIds.cs b/LanMountainDesktop/ComponentSystem/BuiltInComponentIds.cs index 825c60f..dbc10d8 100644 --- a/LanMountainDesktop/ComponentSystem/BuiltInComponentIds.cs +++ b/LanMountainDesktop/ComponentSystem/BuiltInComponentIds.cs @@ -33,6 +33,7 @@ public static class BuiltInComponentIds public const string DesktopDailyWord2x2 = "DesktopDailyWord2x2"; public const string DesktopCnrDailyNews = "DesktopCnrDailyNews"; public const string DesktopIfengNews = "DesktopIfengNews"; + public const string DesktopJuyaNews = "DesktopJuyaNews"; public const string DesktopBilibiliHotSearch = "DesktopBilibiliHotSearch"; public const string DesktopBaiduHotSearch = "DesktopBaiduHotSearch"; public const string DesktopStcn24Forum = "DesktopStcn24Forum"; diff --git a/LanMountainDesktop/ComponentSystem/ComponentRegistry.cs b/LanMountainDesktop/ComponentSystem/ComponentRegistry.cs index 52c9c02..b06c996 100644 --- a/LanMountainDesktop/ComponentSystem/ComponentRegistry.cs +++ b/LanMountainDesktop/ComponentSystem/ComponentRegistry.cs @@ -261,6 +261,16 @@ public sealed class ComponentRegistry MinHeightCells: 4, AllowStatusBarPlacement: false, AllowDesktopPlacement: true), + new DesktopComponentDefinition( + BuiltInComponentIds.DesktopJuyaNews, + "橘鸦早报", + "News", + "Info", + MinWidthCells: 4, + MinHeightCells: 4, + AllowStatusBarPlacement: false, + AllowDesktopPlacement: true, + ResizeMode: DesktopComponentResizeMode.Free), new DesktopComponentDefinition( BuiltInComponentIds.DesktopBilibiliHotSearch, "Bilibili Hot Search", diff --git a/LanMountainDesktop/Views/Components/DailyNewsView.axaml b/LanMountainDesktop/Views/Components/DailyNewsView.axaml new file mode 100644 index 0000000..9fccee7 --- /dev/null +++ b/LanMountainDesktop/Views/Components/DailyNewsView.axaml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LanMountainDesktop/Views/Components/JuyaNewsWidget.axaml.cs b/LanMountainDesktop/Views/Components/JuyaNewsWidget.axaml.cs new file mode 100644 index 0000000..328066b --- /dev/null +++ b/LanMountainDesktop/Views/Components/JuyaNewsWidget.axaml.cs @@ -0,0 +1,756 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Linq; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Media; +using Avalonia.Media.Imaging; +using Avalonia.Styling; +using Avalonia.Threading; +using LanMountainDesktop.Models; +using LanMountainDesktop.Services; + +namespace LanMountainDesktop.Views.Components; + +public partial class JuyaNewsWidget : UserControl, IDesktopComponentWidget +{ + private static readonly FontFamily MiSansFontFamily = new("MiSans VF, avares://LanMountainDesktop/Assets/Fonts#MiSans"); + private static readonly HttpClient HttpClient = new() + { + Timeout = TimeSpan.FromSeconds(15) + }; + + private const string RssUrl = "https://imjuya.github.io/juya-ai-daily/rss.xml"; + private const double BaseCellSize = 48d; + private const int BaseWidthCells = 4; + private const int BaseHeightCells = 4; + private const int InitialLoadDays = 3; + private const int LoadMoreDays = 3; + private const int MaxCachedDays = 30; + + private readonly Dictionary _cachedNews = new(); + private readonly List _loadedDates = new(); + private readonly List _dailyViews = new(); + + private double _currentCellSize = BaseCellSize; + private bool _isAttached; + private bool _isLoading; + private bool _isNightVisual; + private DateTime _earliestLoadedDate = DateTime.Today; + + public JuyaNewsWidget() + { + InitializeComponent(); + + BrandTextBlock.FontFamily = MiSansFontFamily; + LoadingTextBlock.FontFamily = MiSansFontFamily; + StatusTextBlock.FontFamily = MiSansFontFamily; + + AttachedToVisualTree += OnAttachedToVisualTree; + DetachedFromVisualTree += OnDetachedFromVisualTree; + SizeChanged += OnSizeChanged; + ActualThemeVariantChanged += OnActualThemeVariantChanged; + + ApplyCellSize(_currentCellSize); + ApplyLoadingState(); + } + + public void ApplyCellSize(double cellSize) + { + _currentCellSize = Math.Max(1, cellSize); + UpdateAdaptiveLayout(); + } + + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) + { + _isAttached = true; + _ = LoadInitialNewsAsync(); + } + + private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) + { + _isAttached = false; + } + + private void OnSizeChanged(object? sender, SizeChangedEventArgs e) + { + ApplyCellSize(_currentCellSize); + } + + private void OnActualThemeVariantChanged(object? sender, EventArgs e) + { + _isNightVisual = ResolveNightMode(); + UpdateAdaptiveLayout(); + } + + private bool ResolveNightMode() + { + if (ActualThemeVariant == ThemeVariant.Dark) + { + return true; + } + + if (ActualThemeVariant == ThemeVariant.Light) + { + return false; + } + + if (this.TryFindResource("AdaptiveSurfaceBaseBrush", out var value) && + value is ISolidColorBrush brush) + { + return CalculateRelativeLuminance(brush.Color) < 0.45; + } + + return true; + } + + private static double CalculateRelativeLuminance(Color color) + { + static double ToLinear(double channel) + { + return channel <= 0.03928 + ? channel / 12.92 + : Math.Pow((channel + 0.055) / 1.055, 2.4); + } + + var r = ToLinear(color.R / 255d); + var g = ToLinear(color.G / 255d); + var b = ToLinear(color.B / 255d); + return 0.2126 * r + 0.7152 * g + 0.0722 * b; + } + + private void ApplyNightModeVisual() + { + // 卡片背景 + CardBorder.Background = new SolidColorBrush(_isNightVisual ? Color.Parse("#2d2a2a") : Color.Parse("#fefefe")); + + // 品牌标题 + BrandTextBlock.Foreground = new SolidColorBrush(_isNightVisual ? Color.Parse("#d4736a") : Color.Parse("#bb5649")); + + // 刷新按钮 + RefreshButton.BorderBrush = new SolidColorBrush(_isNightVisual ? Color.Parse("#d4736a") : Color.Parse("#bb5649")); + RefreshButton.Foreground = new SolidColorBrush(_isNightVisual ? Color.Parse("#d4736a") : Color.Parse("#bb5649")); + + // 头像背景 + AvatarBorder.Background = new SolidColorBrush(_isNightVisual ? Color.Parse("#3d3a3a") : Color.Parse("#f8f5ec")); + + // 状态文字 + StatusTextBlock.Foreground = new SolidColorBrush(_isNightVisual ? Color.Parse("#9a9590") : Color.Parse("#757575")); + LoadingTextBlock.Foreground = new SolidColorBrush(_isNightVisual ? Color.Parse("#9a9590") : Color.Parse("#757575")); + + // 更新所有日期视图的样式 + foreach (var view in _dailyViews) + { + view.ApplyNightMode(_isNightVisual); + } + } + + private async Task LoadInitialNewsAsync() + { + if (!_isAttached || _isLoading) + { + return; + } + + _isLoading = true; + LoadingTextBlock.IsVisible = true; + StatusTextBlock.IsVisible = false; + + try + { + // 解析RSS获取所有新闻 + var allNews = await FetchJuyaNewsAsync(); + + if (!_isAttached) + { + return; + } + + // 缓存新闻数据 + foreach (var news in allNews) + { + _cachedNews[news.Date.Date] = news; + } + + // 加载最近几天的新闻 + var today = DateTime.Today; + var datesToLoad = Enumerable.Range(0, InitialLoadDays) + .Select(i => today.AddDays(-i)) + .Where(d => _cachedNews.ContainsKey(d)) + .OrderByDescending(d => d) + .ToList(); + + await Dispatcher.UIThread.InvokeAsync(() => + { + if (!_isAttached) return; + + NewsStackPanel.Children.Clear(); + _dailyViews.Clear(); + _loadedDates.Clear(); + + foreach (var date in datesToLoad) + { + AddDailyNewsToView(_cachedNews[date]); + _loadedDates.Add(date); + } + + if (_loadedDates.Any()) + { + _earliestLoadedDate = _loadedDates.Min(); + } + + LoadingTextBlock.IsVisible = false; + StatusTextBlock.IsVisible = false; + UpdateAdaptiveLayout(); + }); + } + catch + { + await Dispatcher.UIThread.InvokeAsync(() => + { + if (!_isAttached) return; + StatusTextBlock.Text = "加载失败"; + StatusTextBlock.IsVisible = true; + LoadingTextBlock.IsVisible = false; + }); + } + finally + { + _isLoading = false; + } + } + + private async Task> FetchJuyaNewsAsync() + { + var result = new List(); + + try + { + // 使用字节数组获取内容,确保正确解码 UTF-8 + var response = await HttpClient.GetByteArrayAsync(RssUrl); + var rssContent = System.Text.Encoding.UTF8.GetString(response); + var doc = XDocument.Parse(rssContent); + + var contentNs = XNamespace.Get("http://purl.org/rss/1.0/modules/content/"); + + var items = doc.Descendants("item"); + + foreach (var item in items) + { + var title = item.Element("title")?.Value ?? ""; + var link = item.Element("link")?.Value ?? ""; + var pubDate = item.Element("pubDate")?.Value ?? ""; + var contentEncoded = item.Element(contentNs + "encoded")?.Value ?? ""; + + // 解析日期 + if (!DateTime.TryParse(pubDate, out var date)) + { + date = DateTime.Today; + } + + // 提取封面图URL + var coverImageUrl = ExtractCoverImageUrl(contentEncoded); + + // 提取视频链接 + var (bilibiliUrl, youtubeUrl) = ExtractVideoUrls(contentEncoded); + + // 解析概览(简短列表) + var overviewCategories = ParseOverview(contentEncoded); + + // 解析详细内容 + var detailedNews = ParseDetailedNews(contentEncoded); + + var news = new JuyaDailyNews( + Date: date, + Title: title, + CoverImageUrl: coverImageUrl, + IssueUrl: link, + BilibiliUrl: bilibiliUrl, + YoutubeUrl: youtubeUrl, + OverviewCategories: overviewCategories, + DetailedNews: detailedNews, + FetchedAt: DateTimeOffset.Now + ); + + result.Add(news); + } + } + catch + { + // 返回空列表 + } + + return result.OrderByDescending(n => n.Date).ToList(); + } + + private static string ExtractCoverImageUrl(string content) + { + if (string.IsNullOrWhiteSpace(content)) + { + return ""; + } + + var match = Regex.Match(content, @"]+src=[""']([^""']+)[""']", RegexOptions.IgnoreCase); + return match.Success ? match.Groups[1].Value : ""; + } + + private static (string bilibili, string youtube) ExtractVideoUrls(string content) + { + if (string.IsNullOrWhiteSpace(content)) + { + return ("", ""); + } + + string bilibiliUrl = ""; + string youtubeUrl = ""; + + var bilibiliMatch = Regex.Match(content, @"]+href=[""'](https?://(?:www\.)?bilibili\.com/[^""']+)[""'][^>]*>", RegexOptions.IgnoreCase); + if (bilibiliMatch.Success) + { + bilibiliUrl = bilibiliMatch.Groups[1].Value; + } + + var youtubeMatch = Regex.Match(content, @"]+href=[""'](https?://(?:www\.)?(?:youtube\.com|youtu\.be)/[^""']+)[""'][^>]*>", RegexOptions.IgnoreCase); + if (youtubeMatch.Success) + { + youtubeUrl = youtubeMatch.Groups[1].Value; + } + + return (bilibiliUrl, youtubeUrl); + } + + private static List ParseOverview(string content) + { + var categories = new List(); + + if (string.IsNullOrWhiteSpace(content)) + { + return categories; + } + + var categoryIcons = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + ["要闻"] = "📌", + ["开发生态"] = "💻", + ["产品应用"] = "📱", + ["产品发布"] = "🚀", + ["模型发布"] = "🤖", + ["行业动态"] = "📈", + ["技术与洞察"] = "🔍", + ["学术研究"] = "📚", + ["研究"] = "🔬", + ["开源"] = "🔓", + ["投资"] = "💰", + ["融资"] = "💵", + ["商业"] = "💼", + ["市场"] = "📊", + ["AI绘画"] = "🎨", + ["设计"] = "✏️", + ["创意"] = "💡", + ["前瞻与传闻"] = "🔮", + ["趋势"] = "📉", + ["预测"] = "🔭", + ["政策"] = "📋", + ["法规"] = "⚖️", + ["监管"] = "🛡️", + ["硬件"] = "🔧", + ["芯片"] = "🖥️", + ["基础设施"] = "🏗️", + ["其他"] = "•", + ["要点"] = "📋", + ["摘要"] = "📝" + }; + + var overviewMatch = Regex.Match(content, @"

\s*概览\s*

(.*?)(?:
|$)", RegexOptions.Singleline | RegexOptions.IgnoreCase); + + if (!overviewMatch.Success) + { + return categories; + } + + var overviewContent = overviewMatch.Groups[1].Value; + + var h3Matches = Regex.Matches(overviewContent, @"

([^<]+)

\s*
    (.*?)
", RegexOptions.Singleline | RegexOptions.IgnoreCase); + + foreach (Match match in h3Matches) + { + var categoryName = match.Groups[1].Value.Trim(); + var listContent = match.Groups[2].Value; + + var icon = categoryIcons.GetValueOrDefault(categoryName, "•"); + + var items = new List(); + var itemMatches = Regex.Matches(listContent, @"
  • (.*?)
  • ", RegexOptions.Singleline | RegexOptions.IgnoreCase); + + foreach (Match itemMatch in itemMatches) + { + var itemText = itemMatch.Groups[1].Value; + + string itemTitle; + string itemUrl; + int? number = null; + + var linkMatch = Regex.Match(itemText, @"]+href=[""']([^""']+)[""'][^>]*>(.*?)
    ", RegexOptions.Singleline | RegexOptions.IgnoreCase); + + if (linkMatch.Success) + { + itemUrl = linkMatch.Groups[1].Value; + var linkText = Regex.Replace(linkMatch.Groups[2].Value, @"<[^>]+>", "").Trim(); + + var beforeLink = itemText.Substring(0, itemText.IndexOf("]+>", "").Trim(); + + if (string.IsNullOrWhiteSpace(itemTitle)) + { + itemTitle = linkText; + } + } + else + { + itemTitle = Regex.Replace(itemText, @"<[^>]+>", "").Trim(); + itemUrl = ""; + } + + var numberMatch = Regex.Match(itemText, @"\s*#(\d+)\s*|#(\d+)"); + if (numberMatch.Success) + { + number = int.Parse(numberMatch.Groups[1].Success ? numberMatch.Groups[1].Value : numberMatch.Groups[2].Value); + } + + itemTitle = Regex.Replace(itemTitle, @"^\s*#\d+\s*", "").Trim(); + itemTitle = Regex.Replace(itemTitle, @"[→↗\s]+$", "").Trim(); + + if (!string.IsNullOrWhiteSpace(itemTitle) && itemTitle.Length > 1) + { + items.Add(new JuyaOverviewItem(itemTitle, itemUrl, number)); + } + } + + if (items.Any()) + { + categories.Add(new JuyaOverviewCategory(categoryName, icon, items)); + } + } + + return categories; + } + + private static List ParseDetailedNews(string content) + { + var newsItems = new List(); + + if (string.IsNullOrWhiteSpace(content)) + { + return newsItems; + } + + var detailedMatch = Regex.Match(content, @"
    (.*)$", RegexOptions.Singleline | RegexOptions.IgnoreCase); + if (!detailedMatch.Success) + { + return newsItems; + } + + var detailedContent = detailedMatch.Groups[1].Value; + + var newsMatches = Regex.Matches(detailedContent, @"

    (.*?)

    (.*?)(?=

    |
    |$)", RegexOptions.Singleline | RegexOptions.IgnoreCase); + + foreach (Match match in newsMatches) + { + var headerContent = match.Groups[1].Value; + var bodyContent = match.Groups[2].Value; + + var numberMatch = Regex.Match(headerContent, @"\s*#(\d+)\s*"); + if (!numberMatch.Success) + { + numberMatch = Regex.Match(headerContent, @"#(\d+)"); + } + + int? number = numberMatch.Success ? int.Parse(numberMatch.Groups[1].Value) : null; + + string title; + var linkMatch = Regex.Match(headerContent, @"]*>(.*?)", RegexOptions.Singleline | RegexOptions.IgnoreCase); + if (linkMatch.Success) + { + title = Regex.Replace(linkMatch.Groups[1].Value, @"<[^>]+>", "").Trim(); + } + else + { + title = Regex.Replace(headerContent, @".*?", "", RegexOptions.Singleline | RegexOptions.IgnoreCase); + title = Regex.Replace(title, @"<[^>]+>", "").Trim(); + title = Regex.Replace(title, @"#\d+", "").Trim(); + } + + var bodyText = ExtractBodyText(bodyContent); + + var relatedLinks = new List(); + var linkMatches = Regex.Matches(bodyContent, @"]+href=[""']([^""']+)[""'][^>]*>", RegexOptions.IgnoreCase); + foreach (Match linkMatch2 in linkMatches) + { + var url = linkMatch2.Groups[1].Value; + if (!string.IsNullOrWhiteSpace(url) && !relatedLinks.Contains(url)) + { + relatedLinks.Add(url); + } + } + + if (!string.IsNullOrWhiteSpace(title) && !string.IsNullOrWhiteSpace(bodyText)) + { + newsItems.Add(new JuyaDetailedNewsItem(title, number ?? 0, bodyText, relatedLinks)); + } + } + + return newsItems; + } + + private static string ExtractBodyText(string htmlContent) + { + if (string.IsNullOrWhiteSpace(htmlContent)) + { + return ""; + } + + // 提取 blockquote 内容 + var blockquoteMatch = Regex.Match(htmlContent, @"
    (.*?)
    ", RegexOptions.Singleline | RegexOptions.IgnoreCase); + if (blockquoteMatch.Success) + { + var text = blockquoteMatch.Groups[1].Value; + // 移除

    标签但保留内容 + text = Regex.Replace(text, @"

    (.*?)

    ", "$1\n\n", RegexOptions.Singleline | RegexOptions.IgnoreCase); + // 移除其他 HTML 标签 + text = Regex.Replace(text, @"<[^>]+>", ""); + // 清理多余空白 + text = Regex.Replace(text, @"\n{3,}", "\n\n"); + return text.Trim(); + } + + // 如果没有 blockquote,提取所有

    标签内容 + var paragraphs = Regex.Matches(htmlContent, @"

    (.*?)

    ", RegexOptions.Singleline | RegexOptions.IgnoreCase); + if (paragraphs.Count > 0) + { + var text = string.Join("\n\n", paragraphs.Cast().Select(m => + Regex.Replace(m.Groups[1].Value, @"<[^>]+>", "").Trim())); + return text.Trim(); + } + + // 最后尝试直接移除所有 HTML 标签 + return Regex.Replace(htmlContent, @"<[^>]+>", "").Trim(); + } + + private void AddDailyNewsToView(JuyaDailyNews news) + { + var view = new DailyNewsView(news, _isNightVisual); + view.CoverImageClicked += (s, e) => TryOpenUrl(news.IssueUrl); + view.NewsItemClicked += (s, url) => TryOpenUrl(url); + NewsStackPanel.Children.Add(view); + _dailyViews.Add(view); + } + + private async void OnScrollChanged(object? sender, ScrollChangedEventArgs e) + { + if (_isLoading || !_isAttached) + { + return; + } + + var scrollViewer = (ScrollViewer)sender!; + + var offset = scrollViewer.Offset; + var extent = scrollViewer.Extent; + var viewport = scrollViewer.Viewport; + + if (offset.Y >= extent.Height - viewport.Height - 200) + { + await LoadMoreNewsAsync(); + } + } + + private async Task LoadMoreNewsAsync() + { + if (_isLoading || !_isAttached) + { + return; + } + + var nextDates = Enumerable.Range(1, LoadMoreDays) + .Select(i => _earliestLoadedDate.AddDays(-i)) + .Where(d => _cachedNews.ContainsKey(d) && !_loadedDates.Contains(d)) + .ToList(); + + if (!nextDates.Any()) + { + return; + } + + _isLoading = true; + LoadingTextBlock.IsVisible = true; + + try + { + await Dispatcher.UIThread.InvokeAsync(() => + { + if (!_isAttached) return; + + foreach (var date in nextDates.OrderByDescending(d => d)) + { + AddDailyNewsToView(_cachedNews[date]); + _loadedDates.Add(date); + } + + _earliestLoadedDate = _loadedDates.Min(); + LoadingTextBlock.IsVisible = false; + UpdateAdaptiveLayout(); + }); + } + finally + { + _isLoading = false; + } + } + + private async void OnRefreshButtonClick(object? sender, RoutedEventArgs e) + { + e.Handled = true; + + if (_isLoading) + { + return; + } + + _cachedNews.Clear(); + _loadedDates.Clear(); + _dailyViews.Clear(); + NewsStackPanel.Children.Clear(); + _earliestLoadedDate = DateTime.Today; + + await LoadInitialNewsAsync(); + } + + private void TryOpenUrl(string? url) + { + if (string.IsNullOrWhiteSpace(url)) + { + return; + } + + try + { + var startInfo = new ProcessStartInfo + { + FileName = url, + UseShellExecute = true + }; + Process.Start(startInfo); + } + catch + { + // 忽略错误 + } + } + + private void ApplyLoadingState() + { + StatusTextBlock.Text = "加载中..."; + StatusTextBlock.IsVisible = true; + } + + private void UpdateAdaptiveLayout() + { + var scale = ResolveScale(); + var softScale = Math.Clamp(scale, 0.80, 1.32); + var totalWidth = Bounds.Width > 1 ? Bounds.Width : _currentCellSize * BaseWidthCells; + var totalHeight = Bounds.Height > 1 ? Bounds.Height : _currentCellSize * BaseHeightCells; + + var unifiedMainRectangle = ResolveUnifiedMainRectangle(); + RootBorder.CornerRadius = unifiedMainRectangle; + CardBorder.CornerRadius = unifiedMainRectangle; + + var horizontalPadding = Math.Clamp(16 * softScale, 10, 24); + var verticalPadding = Math.Clamp(14 * softScale, 8, 20); + CardBorder.Padding = new Thickness(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding); + + var headerHeight = Math.Clamp(40 * softScale, 28, 56); + HeaderGrid.Height = headerHeight; + + BrandTextBlock.FontSize = Math.Clamp(20 * softScale, 14, 26); + + var avatarSize = Math.Clamp(36 * softScale, 24, 48); + AvatarBorder.Width = avatarSize; + AvatarBorder.Height = avatarSize; + AvatarBorder.CornerRadius = new CornerRadius(avatarSize / 2); + + var buttonFontSize = Math.Clamp(13 * softScale, 10, 16); + RefreshButton.FontSize = buttonFontSize; + RefreshButton.Padding = new Thickness( + Math.Clamp(8 * softScale, 6, 12), + Math.Clamp(4 * softScale, 2, 6) + ); + + StatusTextBlock.FontSize = Math.Clamp(16 * softScale, 12, 22); + LoadingTextBlock.FontSize = Math.Clamp(14 * softScale, 11, 18); + + foreach (var view in _dailyViews) + { + view.UpdateLayout(softScale, totalWidth - horizontalPadding * 2); + } + + ApplyNightModeVisual(); + } + + private double ResolveScale() + { + var expectedWidth = _currentCellSize * BaseWidthCells; + var expectedHeight = _currentCellSize * BaseHeightCells; + if (expectedWidth <= 0 || expectedHeight <= 0) + { + return 1d; + } + + var actualWidth = Bounds.Width > 1 ? Bounds.Width : expectedWidth; + var actualHeight = Bounds.Height > 1 ? Bounds.Height : expectedHeight; + var scaleX = actualWidth / expectedWidth; + var scaleY = actualHeight / expectedHeight; + return Math.Clamp(Math.Min(scaleX, scaleY), 0.72, 2.4); + } + + private CornerRadius ResolveUnifiedMainRectangle() => new(ResolveUnifiedMainRadiusValue()); + + private static double ResolveUnifiedMainRadiusValue() => + HostAppearanceThemeProvider.GetOrCreate().GetCurrent().CornerRadiusTokens.Lg.TopLeft; +} + +// 数据模型 +public sealed record JuyaDailyNews( + DateTime Date, + string Title, + string CoverImageUrl, + string IssueUrl, + string BilibiliUrl, + string YoutubeUrl, + IReadOnlyList OverviewCategories, + IReadOnlyList DetailedNews, + DateTimeOffset FetchedAt); + +public sealed record JuyaOverviewCategory( + string Name, + string Icon, + IReadOnlyList Items); + +public sealed record JuyaOverviewItem( + string Title, + string Url, + int? Number); + +public sealed record JuyaDetailedNewsItem( + string Title, + int Number, + string BodyText, + IReadOnlyList RelatedLinks); diff --git a/README.md b/README.md index 89d8176..47ff11b 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,133 @@ -# LanMountainDesktop +# 阑山桌面 / LanMountainDesktop -`LanMountainDesktop` is the authoritative host repository for the desktop app and the host-side Plugin SDK. +> 你的桌面,不止一面 -## Repository Ownership +[![.NET 10](https://img.shields.io/badge/.NET-10-512BD4)](https://dotnet.microsoft.com/) +[![Avalonia UI](https://img.shields.io/badge/Avalonia%20UI-11.2-blue)](https://avaloniaui.net/) +[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) -This repository owns: +> [!IMPORTANT] +> **温馨提示**:本项目有部分成分由**氛围编程 (Vibe Coding)** 方式编写。 +> +> 如果您对此类项目有固有的排斥感,请无视此项目,谢谢。 -- `LanMountainDesktop/`: desktop host app and plugin runtime -- `LanMountainDesktop.PluginSdk/`: canonical plugin API baseline (`4.0.0`) -- `LanMountainDesktop.Shared.Contracts/`: shared host/plugin contract types -- `LanMountainDesktop.Appearance/`: host appearance and radius token generation -- `LanMountainDesktop.Settings.Core/`: host settings primitives -- `LanMountainDesktop.Tests/`: host and SDK tests +## 简介 -This repository does not own: +**阑山桌面**是一个跨平台桌面环境增强工具,面向需要高频查看信息、追求桌面效率与个性化体验的用户。 -- plugin market metadata or developer portal content -- official sample plugin release source -- independent ecosystem documentation hub +基于 Avalonia UI 和 .NET 10 构建,支持 Windows、Linux、macOS 三大平台。 -## Ecosystem Boundaries +![Platform](https://img.shields.io/badge/Windows-✓-0078D4) +![Platform](https://img.shields.io/badge/Linux-✓-FCC624?logo=linux&logoColor=black) +![Platform](https://img.shields.io/badge/macOS-✓-000000?logo=apple) -- Host and SDK source of truth: `LanMountainDesktop` (this repo) -- Plugin market and developer materials: standalone `LanAirApp` repo -- Official sample plugin source of truth: standalone `LanMountainDesktop.SamplePlugin` repo -- `ClassIsland`: reference-only project, not part of build or release flow +## 核心特性 -## Plugin SDK v4 Baseline +### 📊 信息聚合 +- 课程表、日历、天气、新闻、热搜 +- 所有信息一目了然,无需频繁切换窗口 -- API baseline: `4.0.0` -- Manifest file: `plugin.json` -- Package extension: `.laapp` -- Entry model: `Initialize(HostBuilderContext, IServiceCollection)` -- Appearance model: `IPluginAppearanceContext`, `PluginAppearanceSnapshot`, `PluginCornerRadiusTokens`, `PluginCornerRadiusPreset` -- Component registration model: `AddPluginDesktopComponent(PluginDesktopComponentOptions options)` +### 🎯 效率工具 +- 自习环境监测、计时器、知识卡片 +- 最近文档、浏览器快捷入口 +- 常用工具组件一键触达 -## Plugin Package Surfaces +### 🎨 个性化桌面 +- 自由布局,随心所欲摆放组件 +- 多页桌面,工作学习场景分离 +- 主题切换、玻璃效果、圆角风格 -- `LanMountainDesktop.PluginSdk`: official plugin SDK package (includes `buildTransitive` default `.laapp` packaging targets) -- `LanMountainDesktop.Shared.Contracts`: shared contract package for host/plugin boundaries -- `LanMountainDesktop.PluginTemplate`: official `dotnet new` template package (`shortName`: `lmd-plugin`) +### 🔌 插件生态 +- 通过 `.laapp` 插件扩展功能 +- 官方 Plugin SDK 支持自定义组件 +- 设置页、组件、集成功能一站式接入 -Use `scripts/Pack-PluginPackages.ps1` to generate local-feed packages for CI or workspace integration tests. +## 为谁而设计 -## Workspace Market Resolution +| 用户类型 | 典型场景 | +|---------|---------| +| 🎓 学生用户 | 课程表、自习监测、计时、天气和日常信息聚合 | +| 💼 办公用户 | 日历、资讯、最近文档、常用工具入口 | +| 🎨 效率爱好者 | 自由布局、主题切换、插件扩展 | +| 🇨🇳 中文用户 | 本地化界面、农历和节假日等本地语境支持 | -For local market debugging, the host resolves workspace files from the sibling repository path (`..\\LanAirApp`) instead of reading the in-repo mirror folder. +## 快速开始 + +### 环境要求 +- .NET SDK 10 + +### 构建与运行 + +```bash +# 还原依赖 +dotnet restore + +# 构建项目 +dotnet build LanMountainDesktop.slnx -c Debug + +# 运行桌面宿主 +dotnet run --project LanMountainDesktop/LanMountainDesktop.csproj +``` + +### 运行测试 + +```bash +dotnet test LanMountainDesktop.slnx -c Debug +``` + +## 插件开发 + +阑山桌面支持通过 Plugin SDK 开发自定义插件: + +```bash +# 安装插件模板 +dotnet new install LanMountainDesktop.PluginTemplate + +# 创建新插件 +dotnet new lmd-plugin -n MyPlugin +``` + +- **Plugin SDK**: `LanMountainDesktop.PluginSdk` (API 4.0.0) +- **共享契约**: `LanMountainDesktop.Shared.Contracts` +- **迁移指南**: [PLUGIN_SDK_V4_MIGRATION.md](docs/PLUGIN_SDK_V4_MIGRATION.md) + +## 项目结构 + +``` +LanMountainDesktop/ +├── LanMountainDesktop/ # 桌面宿主应用 +├── LanMountainDesktop.PluginSdk/ # 官方插件 SDK +├── LanMountainDesktop.Shared.Contracts/ # 宿主与插件共享契约 +├── LanMountainDesktop.Appearance/ # 主题与外观基础设施 +├── LanMountainDesktop.Settings.Core/# 设置持久化基础设施 +└── LanMountainDesktop.Tests/ # 测试项目 +``` + +## 生态边界 + +| 项目 | 职责 | +|-----|------| +| **本仓库** | 桌面宿主、插件运行时、Plugin SDK、共享契约 | +| [LanAirApp](https://github.com/yourorg/LanAirApp) | 插件市场元数据、开发者生态材料 | +| [LanMountainDesktop.SamplePlugin](https://github.com/yourorg/LanMountainDesktop.SamplePlugin) | 官方示例插件 | + +## 文档索引 + +- [产品定位](docs/PRODUCT.md) - 产品愿景与目标用户 +- [架构说明](docs/ARCHITECTURE.md) - 仓库结构与运行时主线 +- [开发指南](docs/DEVELOPMENT.md) - 构建、测试、调试 +- [视觉规范](docs/VISUAL_SPEC.md) - 主题、颜色、玻璃层级 +- [圆角规范](docs/CORNER_RADIUS_SPEC.md) - 圆角层级与动态规则 +- [贡献指南](docs/CONTRIBUTING.md) - PR、spec、文档协作规则 + +## 技术栈 + +- **UI 框架**: [Avalonia UI](https://avaloniaui.net/) +- **开发平台**: [.NET 10](https://dotnet.microsoft.com/) +- **支持平台**: Windows 10+, Linux, macOS + +## 许可证 + +[MIT](LICENSE) -See: -- `docs/ECOSYSTEM_BOUNDARIES.md` -- `docs/PLUGIN_SDK_V4_MIGRATION.md` diff --git a/docs/JUYA_NEWS_DESIGN.md b/docs/JUYA_NEWS_DESIGN.md new file mode 100644 index 0000000..a0b0b7d --- /dev/null +++ b/docs/JUYA_NEWS_DESIGN.md @@ -0,0 +1,556 @@ +# 橘鸦新闻组件 UI 设计文档 + +## 1. 数据源分析 + +### RSS 结构 +```xml + + 2026-03-23 + https://imjuya.github.io/juya-ai-daily/issue-37/ + AI 早报 2026-03-23 视频版... + + +

    AI 早报 2026-03-23

    +

    视频版: B站链接 | YouTube链接

    +

    要闻

    +
      +
    • 微信正式推出ClawBot插件... #1
    • +
    +

    开发者

    +
      +
    • Claude Code 测试新功能... #2
    • +
    + ...更多分类 + ]]> +
    + Mon, 23 Mar 2026 00:34:38 +0000 +
    +``` + +### 推送时间规律 +- **推送时间**: 每天凌晨 00:30 - 02:00 (UTC+0) +- **北京时间**: 每天上午 08:30 - 10:00 +- **历史数据**: RSS包含约30天的历史数据(从2026-02-18开始) +- **更新频率**: 每日一期,一期多条新闻 + +### 内容结构 +每期早报包含: +1. **封面图片** - 每日独特的封面图 +2. **视频版链接** - B站和YouTube双平台 +3. **要闻** - 2-3条重要新闻 +4. **开发者** - 技术相关动态 +5. **产品发布** - 新产品/功能 +6. **模型发布** - AI模型更新 +7. **其他分类** - 投资、开源、研究等 + +--- + +## 2. 设计理念 + +### 品牌调性 +- **橘鸦官网风格**: 柔和、温暖、阅读友好 +- **主色调**: 砖红色/陶土色 (#bb5649) - 来自官网 +- **背景色**: 米白色/奶油色 (#fefefe, #f8f5ec) - 柔和不刺眼 +- **文字色**: 深灰蓝 (#34495e) - 温和专业 +- **视觉风格**: 简洁优雅、阅读舒适、温暖亲切 + +### 设计关键词 +- 柔和温暖 +- 阅读友好 +- 优雅简洁 +- 舒适护眼 +- **垂直连续滚动** ← 核心交互 + +--- + +## 3. 色彩方案 (参考橘鸦官网) + +### 官网色彩提取 +``` +官网主色 (砖红/陶土): #bb5649 +官网文字: #34495e +官网背景: #fefefe +官网次要背景: #f8f5ec (米黄/奶油) +官网引用块背景: rgba(192,91,77,.05) +官网引用块边框: rgba(192,91,77,.3) +官网链接悬停: #bb5649 +官网元信息: #757575 +``` + +### 日间模式 (Light Mode) - 柔和风格 +| 元素 | 颜色 | 用途 | +|-----|------|------| +| 卡片背景 | #fefefe | 主卡片底色 (官网背景色) | +| 卡片边框 | #e6e6e6 | 细微边框 | +| 品牌标题 | #bb5649 | "橘鸦" 文字 (官网主色) | +| 日期标题 | #bb5649 | 日期大标题 | +| 新闻标题 | #34495e | 新闻条目文字 | +| 分类标签 | #bb5649 | 要闻/开发者等 | +| 时间戳 | #757575 | 发布时间 | +| 悬停背景 | rgba(192,91,77,.05) | 条目悬停效果 | +| 分隔线 | #e6e6e6 | 日期分隔 | +| 加载提示 | #757575 | 加载更多提示 | + +### 夜间模式 (Dark Mode) - 柔和暗色 +| 元素 | 颜色 | 用途 | +|-----|------|------| +| 卡片背景 | #2d2a2a | 深暖灰 | +| 卡片边框 | #3d3a3a | 细微边框 | +| 品牌标题 | #d4736a | 柔和砖红 | +| 日期标题 | #d4736a | 日期大标题 | +| 新闻标题 | #e8e4e0 | 新闻条目文字 | +| 分类标签 | #d4736a | 要闻/开发者等 | +| 时间戳 | #9a9590 | 次要信息 | +| 悬停背景 | rgba(212,115,106,.1) | 条目悬停效果 | +| 分隔线 | #3d3a3a | 日期分隔 | +| 加载提示 | #9a9590 | 加载更多提示 | + +--- + +## 4. 布局设计 + +### 组件尺寸 +- **默认尺寸**: 4格宽 x 4格高 +- **最小尺寸**: 4格宽 x 4格高 +- **滚动方向**: 垂直滚动 + +### 垂直连续滚动布局 + +``` +┌─────────────────────────────────────────┐ +│ 🧱 橘鸦 · AI早报 [🔗 官网] │ ← Header (固定或随滚动) +├─────────────────────────────────────────┤ +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ 📰 封面图 2026-03-23 │ │ ← 今天的新闻 +│ │ │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ # 2026年3月23日 星期一 │ ← 日期大标题 +│ │ +│ ## 📌 要闻 │ +│ • 微信正式推出ClawBot插件... │ +│ • OpenAI发布GPT-5.4预览版... │ +│ │ +│ ## 💻 开发者 │ +│ • Claude Code测试新功能... │ +│ • 阶跃星辰推出StepPlan... │ +│ │ +│ 📺 视频版: B站 | YouTube │ +│ │ +│ ───────────────────────────────────── │ ← 日期分隔线 +│ │ +│ ┌───────────────────────────────────┐ │ +│ │ 📰 封面图 2026-03-22 │ │ ← 昨天的新闻 +│ │ │ │ (往下滑动显示) +│ └───────────────────────────────────┘ │ +│ │ +│ # 2026年3月22日 星期日 │ +│ │ +│ ## 📌 要闻 │ +│ • OpenAI发布GPT-5.4... │ +│ • Google推出新功能... │ +│ │ +│ ## 💻 开发者 │ +│ • Anthropic更新Claude... │ +│ │ +│ 📺 视频版: B站 | YouTube │ +│ │ +│ ───────────────────────────────────── │ +│ │ +│ ┌───────────────────────────────────┐ │ ← 前天的新闻 +│ │ 📰 封面图 2026-03-21 │ │ (继续往下滑动) +│ │ │ │ +│ └───────────────────────────────────┘ │ +│ │ +│ # 2026年3月21日 星期六 │ +│ │ +│ ... │ +│ │ +│ ───────────────────────────────────── │ +│ │ +│ 正在加载更多... ↓ │ ← 加载提示 +│ │ +└─────────────────────────────────────────┘ +``` + +### 日期分隔设计 +``` +┌─────────────────────────────────────────┐ +│ │ +│ ─────────── 3月22日 星期日 ─────────── │ ← 日期分隔条 +│ │ +│ [昨天的新闻内容] │ +│ │ +└─────────────────────────────────────────┘ +``` + +### 单期新闻结构 +``` +┌─────────────────────────────────────────┐ +│ │ +│ [封面图 - 16:9 比例] │ +│ │ +│ # 2026年3月23日 星期一 │ ← 日期大标题 +│ │ +│ ## 📌 要闻 │ ← 分类标题 +│ • 新闻条目1 │ +│ • 新闻条目2 │ +│ │ +│ ## 💻 开发者 │ +│ • 新闻条目3 │ +│ • 新闻条目4 │ +│ │ +│ ## 🚀 产品发布 │ +│ • 新闻条目5 │ +│ │ +│ 📺 视频版: [B站] [YouTube] │ ← 视频链接 +│ │ +└─────────────────────────────────────────┘ +``` + +--- + +## 5. 字体规范 + +### 字体族 +```xml +FontFamily="MiSans VF, avares://LanMountainDesktop/Assets/Fonts#MiSans" +``` + +### 字号规范 + +| 元素 | 字号 | 字重 | 说明 | +|-----|------|------|------| +| 品牌标题 | 20px | SemiBold | 顶部固定标题 | +| 日期大标题 | 22px | Bold | 每期日期 | +| 分类标题 | 16px | SemiBold | 要闻/开发者等 | +| 新闻条目 | 14px | Regular | 主要阅读内容 | +| 视频链接 | 13px | Regular | 底部视频入口 | +| 加载提示 | 13px | Regular | 加载更多 | + +--- + +## 6. 核心交互: 垂直连续滚动 + +### 滚动行为 +``` +用户往下滑动 + ↓ +显示今天的新闻内容 + ↓ +继续往下滑动 + ↓ +显示日期分隔线 + ↓ +显示昨天的新闻内容 + ↓ +继续往下滑动 + ↓ +显示前天的新闻内容 + ↓ +... + ↓ +到达已加载内容的底部 + ↓ +显示"正在加载更多..." + ↓ +自动加载更早的新闻 +``` + +### 加载策略 +```csharp +// 初始加载: 最近3天的新闻 +// 滚动到底部: 自动加载接下来3天 +// 最大加载: 30天历史数据 +// 内存管理: 只保留可视区域 ±3 天的数据 +``` + +### 滚动位置记忆 +```csharp +// 记录用户当前滚动位置 +// 切换主题/刷新时不重置位置 +// 下次打开组件时恢复到上次位置 +``` + +--- + +## 7. 交互设计 + +### 悬停效果 +``` +新闻条目悬停: +- 背景色: 透明 → rgba(192,91,77,.05) +- 过渡时间: 200ms +- 光标: Hand cursor +``` + +### 点击效果 +``` +新闻条目点击: +- 打开浏览器跳转原文链接 +- 轻微缩放: scale(0.98) +- 过渡时间: 100ms +``` + +### 封面图点击 +``` +封面图点击: +- 打开当期官网页面 +- 轻微放大效果 +``` + +### 日期标题点击 +``` +日期标题点击: +- 展开/收起该期新闻 +- 箭头图标旋转动画 +``` + +--- + +## 8. 动画效果 + +### 滚动动画 +``` +内容跟随滚动: +- 自然滚动,无额外动画 +- 保持流畅 60fps +``` + +### 加载动画 +``` +新内容加载: +- 淡入: opacity 0 → 1 (300ms) +- 缓动: ease-out +``` + +### 日期分隔线动画 +``` +日期分隔线进入视口: +- 轻微放大: scale(0.95) → scale(1) +- 透明度: 0.5 → 1 +- 时长: 200ms +``` + +--- + +## 9. 响应式适配 + +### 缩放规则 +```csharp +scale = Math.Clamp(currentCellSize / 48, 0.56, 2.0) + +字体缩放: baseFontSize * scale +间距缩放: baseSpacing * scale +``` + +### 最小尺寸保障 +``` +最小字体: 11px +最小间距: 8px +最小触摸区域: 44px +``` + +--- + +## 10. 代码结构预览 + +### XAML 结构 +```xml + + + + + + + +