feat: 历史界面美化 + 按应用分类
实现两个用户需求:消息内容完整显示、按 Gotify Application 分类。 新增: - Models/GotifyApplication.cs:对应 GET /application 返回字段(id/name/description/defaultPriority/createdAt/internal) - Services/ApplicationCache.cs:在内存里缓存 id→Application 映射,提供 GetName/Get 解析,Updated 事件触发 UI 刷新 - Services/GotifyApiService.GetApplicationsAsync:GET /application?limit=999 拉取应用列表 - Converters/ValueConverters.cs: - PriorityToBrushConverter:优先级 0/1-4/5-7/8+ 分别用浅灰/灰蓝/橙/红区分 - AppNameToBrushConverter:对应用名做 FNV-1a 32-bit hash → HSL 色相,让每个应用在历史里视觉上可区分 - GotifyMessage.AppName 字段(JsonIgnore),由 UI 在加入历史前从缓存查后填入 主窗重构(两栏布局): - 左侧历史列表:用 DataTemplate 自定义每行(优先级徽章 + 应用名彩色 + 标题 + 消息预览 TextWrapping+Trimming),不再用 GridView 单行 - 右侧详情面板:选中消息后显示完整内容(应用名大标题、描述、优先级+说明、时间、标题、App ID、消息正文、URL 链接) - 顶部状态条:状态点颜色(绿/橙/红/灰)+ 应用数显示(实时更新) - 新增按钮「刷新应用」,手动 GET /application,用于用户新建 Gotify app 后同步 - URL 链接(如果有)在详情面板显示,点击用默认浏览器打开 - SaveButton 在保存配置后自动重新拉应用列表+历史,不用重启 App.xaml.cs 改造:创建 ApplicationCache,启动时后台异步刷新一次,订阅 Updated 事件让 MainWindow 重新解析已加载消息的 AppName(因为消息先到,缓存可能后到) Color/Brush/MessageBox 在 WPF+WinForms 双开项目里撞名,ValueConverters 和 MainWindow.xaml.cs 都加 using alias 固定走 WPF。 实测:启动后 ApplicationCache refreshed count=5,WebSocket connected,历史拉了 50 条股票分析报告,通知正常弹。
This commit is contained in:
+314
-101
@@ -1,14 +1,92 @@
|
||||
<Window x:Class="WindowsGotify.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:WindowsGotify"
|
||||
Title="Windows Gotify"
|
||||
Width="780"
|
||||
Height="620"
|
||||
MinWidth="640"
|
||||
MinHeight="480"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
Width="1100"
|
||||
Height="720"
|
||||
MinWidth="900"
|
||||
MinHeight="560"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Background="#FAFAFA">
|
||||
|
||||
<Grid Margin="20">
|
||||
<Window.Resources>
|
||||
<!-- 优先级颜色 -->
|
||||
<local:PriorityToBrushConverter x:Key="PriorityToBrush"/>
|
||||
<local:AppNameToBrushConverter x:Key="AppNameToBrush"/>
|
||||
|
||||
<!-- 历史列表行模板 -->
|
||||
<DataTemplate x:Key="MessageRowTemplate">
|
||||
<Grid Margin="0,4" Height="Auto">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="44"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 左侧优先级徽章 -->
|
||||
<Border Grid.RowSpan="2"
|
||||
Grid.Column="0"
|
||||
Background="{Binding Priority, Converter={StaticResource PriorityToBrush}}"
|
||||
CornerRadius="4"
|
||||
Margin="0,2,8,2"
|
||||
Padding="4,2"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding PriorityDisplay}"
|
||||
Foreground="White"
|
||||
FontWeight="Bold"
|
||||
FontSize="11"
|
||||
HorizontalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<!-- 第一行:应用名 + 时间 -->
|
||||
<DockPanel Grid.Row="0" Grid.Column="1">
|
||||
<TextBlock DockPanel.Dock="Right"
|
||||
Text="{Binding DateDisplay}"
|
||||
Foreground="#888"
|
||||
FontSize="11"
|
||||
VerticalAlignment="Center"
|
||||
Margin="8,0,0,0" />
|
||||
<TextBlock Text="{Binding AppName}"
|
||||
FontWeight="Bold"
|
||||
FontSize="13"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{Binding AppName, Converter={StaticResource AppNameToBrush}}" />
|
||||
</DockPanel>
|
||||
|
||||
<!-- 第二行:标题(无则隐藏)+ 消息预览 -->
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" Margin="0,2,0,0">
|
||||
<TextBlock Text="{Binding TitleDisplay}"
|
||||
FontWeight="SemiBold"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Visibility="{Binding TitleDisplay, Converter={StaticResource PriorityToBrush}, ConverterParameter=hideIfEmpty}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding TitleDisplay}" Value="(无标题)">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding Message}"
|
||||
TextWrapping="Wrap"
|
||||
MaxHeight="44"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Foreground="#444"
|
||||
FontSize="12" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid Margin="16">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
@@ -17,109 +95,244 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 标题 -->
|
||||
<StackPanel Grid.Row="0">
|
||||
<!-- 头部标题 -->
|
||||
<StackPanel Grid.Row="0" Margin="0,0,0,12">
|
||||
<TextBlock Text="Windows Gotify"
|
||||
FontSize="26"
|
||||
FontWeight="Bold" />
|
||||
<TextBlock Text="Gotify → Windows 原生通知 · 应用内查看历史"
|
||||
Margin="0,2,0,14"
|
||||
Foreground="Gray" />
|
||||
FontSize="24"
|
||||
FontWeight="Bold"
|
||||
Foreground="#222" />
|
||||
<TextBlock Text="Gotify → Windows 原生通知 · 应用内按应用分类查看历史"
|
||||
Margin="0,2,0,0"
|
||||
Foreground="#888"
|
||||
FontSize="12" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- 设置区 -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Gotify URL" />
|
||||
<TextBox x:Name="UrlTextBox"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,4,12,12"
|
||||
Height="30" />
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Client Token" />
|
||||
<PasswordBox x:Name="TokenBox"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,4,0,12"
|
||||
Height="30" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.ColumnSpan="2"
|
||||
x:Name="StatusText"
|
||||
FontSize="14"
|
||||
Margin="0,0,0,4" />
|
||||
<TextBlock Grid.Row="3" Grid.ColumnSpan="2"
|
||||
Text="配置保存在 %LOCALAPPDATA%\WindowsGotify\config.json"
|
||||
Foreground="Gray"
|
||||
FontSize="11" />
|
||||
</Grid>
|
||||
|
||||
<!-- 历史区 -->
|
||||
<Border Grid.Row="3"
|
||||
BorderBrush="#DDD"
|
||||
<Border Grid.Row="1"
|
||||
Background="White"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Padding="0"
|
||||
Margin="0,12,0,0">
|
||||
<DockPanel>
|
||||
<Grid DockPanel.Dock="Top" Margin="10,8,10,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="历史消息(点击行可在浏览器打开链接,留空则只选中)"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="HistoryCountText"
|
||||
Grid.Column="1"
|
||||
Foreground="Gray"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
Padding="12"
|
||||
Margin="0,0,0,8">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ListView x:Name="HistoryList"
|
||||
BorderThickness="0"
|
||||
MouseDoubleClick="HistoryList_MouseDoubleClick">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="时间" Width="150" DisplayMemberBinding="{Binding DateDisplay}"/>
|
||||
<GridViewColumn Header="优先级" Width="60" DisplayMemberBinding="{Binding PriorityDisplay}"/>
|
||||
<GridViewColumn Header="标题" Width="120" DisplayMemberBinding="{Binding TitleDisplay}"/>
|
||||
<GridViewColumn Header="内容" Width="380" DisplayMemberBinding="{Binding Message}"/>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</DockPanel>
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="Gotify URL"
|
||||
FontSize="11"
|
||||
Foreground="#666" />
|
||||
<TextBox x:Name="UrlTextBox"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,2,12,0"
|
||||
Height="28"
|
||||
Padding="6,0"
|
||||
FontSize="12" />
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="1"
|
||||
Text="Client Token"
|
||||
FontSize="11"
|
||||
Foreground="#666" />
|
||||
<PasswordBox x:Name="TokenBox"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,2,0,0"
|
||||
Height="28"
|
||||
Padding="6,0"
|
||||
FontSize="12" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 按钮区 -->
|
||||
<StackPanel Grid.Row="4"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,12,0,0">
|
||||
<Button Content="刷新历史"
|
||||
Width="100"
|
||||
Height="34"
|
||||
Margin="0,0,8,0"
|
||||
Click="RefreshButton_Click" />
|
||||
<Button Content="测试通知"
|
||||
Width="100"
|
||||
Height="34"
|
||||
Margin="0,0,8,0"
|
||||
Click="TestButton_Click" />
|
||||
<Button Content="保存并重连"
|
||||
Width="120"
|
||||
Height="34"
|
||||
Click="SaveButton_Click" />
|
||||
</StackPanel>
|
||||
<!-- 状态 + 操作 -->
|
||||
<DockPanel Grid.Row="2" Margin="0,4,0,8">
|
||||
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Ellipse x:Name="StatusDot" Width="8" Height="8" Fill="#999" Margin="0,0,6,0"/>
|
||||
<TextBlock x:Name="StatusText"
|
||||
Text="状态:等待连接"
|
||||
FontSize="12"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="AppCountText"
|
||||
Text=" · 应用:?"
|
||||
FontSize="12"
|
||||
Foreground="#666"
|
||||
VerticalAlignment="Center"
|
||||
Margin="12,0,0,0" />
|
||||
</StackPanel>
|
||||
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="刷新应用"
|
||||
Width="86" Height="30" Margin="0,0,6,0"
|
||||
Click="RefreshAppsButton_Click" />
|
||||
<Button Content="刷新历史"
|
||||
Width="86" Height="30" Margin="0,0,6,0"
|
||||
Click="RefreshButton_Click" />
|
||||
<Button Content="测试通知"
|
||||
Width="86" Height="30" Margin="0,0,6,0"
|
||||
Click="TestButton_Click" />
|
||||
<Button Content="保存并重连"
|
||||
Width="100" Height="30"
|
||||
Background="#0078D4" Foreground="White" BorderThickness="0"
|
||||
Click="SaveButton_Click" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
|
||||
<!-- 主区域:历史(左) + 详情(右) -->
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" MinWidth="320"/>
|
||||
<ColumnDefinition Width="6"/>
|
||||
<ColumnDefinition Width="3*" MinWidth="380"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 历史列表 -->
|
||||
<Border Grid.Column="0"
|
||||
Background="White"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<DockPanel>
|
||||
<Border DockPanel.Dock="Top"
|
||||
Background="#F5F5F5"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="0,0,0,1"
|
||||
Padding="12,8">
|
||||
<DockPanel>
|
||||
<TextBlock Text="历史消息"
|
||||
FontWeight="Bold"
|
||||
FontSize="12"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="HistoryCountText"
|
||||
DockPanel.Dock="Right"
|
||||
Text="共 0 条"
|
||||
FontSize="11"
|
||||
Foreground="#888"
|
||||
VerticalAlignment="Center" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<ListView x:Name="HistoryList"
|
||||
BorderThickness="0"
|
||||
ItemTemplate="{StaticResource MessageRowTemplate}"
|
||||
SelectionChanged="HistoryList_SelectionChanged"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto">
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<Setter Property="Padding" Value="10,4"/>
|
||||
<Setter Property="BorderBrush" Value="#EEE"/>
|
||||
<Setter Property="BorderThickness" Value="0,0,0,1"/>
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
</ListView>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<GridSplitter Grid.Column="1"
|
||||
Width="6"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="Transparent" />
|
||||
|
||||
<!-- 详情面板 -->
|
||||
<Border Grid.Column="2"
|
||||
Background="White"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<Grid Margin="16">
|
||||
<TextBlock x:Name="DetailEmptyHint"
|
||||
Text="← 左侧选一条消息查看详情"
|
||||
Foreground="#AAA"
|
||||
FontSize="13"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
<StackPanel x:Name="DetailPanel" Visibility="Collapsed">
|
||||
<!-- 应用名(大标题,带颜色) -->
|
||||
<TextBlock x:Name="DetailAppName"
|
||||
FontSize="22"
|
||||
FontWeight="Bold"
|
||||
Margin="0,0,0,4" />
|
||||
<TextBlock x:Name="DetailAppDesc"
|
||||
Foreground="#888"
|
||||
FontSize="12"
|
||||
Margin="0,0,0,12"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<!-- 元数据行 -->
|
||||
<Border Background="#F5F5F5"
|
||||
CornerRadius="4"
|
||||
Padding="10,8"
|
||||
Margin="0,0,0,12">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="优先级" Foreground="#666" FontSize="11" Width="60"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" x:Name="DetailPriority" FontSize="12" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="时间" Foreground="#666" FontSize="11" Width="60"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" x:Name="DetailDate" FontSize="12" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="标题" Foreground="#666" FontSize="11" Width="60"/>
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" x:Name="DetailTitle" FontSize="12" TextWrapping="Wrap"/>
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="App ID" Foreground="#666" FontSize="11" Width="60"/>
|
||||
<TextBlock Grid.Row="6" Grid.Column="1" x:Name="DetailAppId" FontSize="12" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<TextBlock Text="消息正文" Foreground="#666" FontSize="11" Margin="0,0,0,4"/>
|
||||
<Border Background="#F5F5F5"
|
||||
CornerRadius="4"
|
||||
Padding="10,8"
|
||||
Margin="0,0,0,12">
|
||||
<TextBlock x:Name="DetailMessage"
|
||||
TextWrapping="Wrap"
|
||||
FontSize="13"
|
||||
LineHeight="20" />
|
||||
</Border>
|
||||
|
||||
<TextBlock x:Name="DetailUrlLabel"
|
||||
Text="点击链接"
|
||||
Foreground="#666"
|
||||
FontSize="11"
|
||||
Margin="0,0,0,4"
|
||||
Visibility="Collapsed" />
|
||||
<TextBlock x:Name="DetailUrl"
|
||||
Foreground="#0078D4"
|
||||
FontSize="12"
|
||||
TextDecorations="Underline"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonUp="DetailUrl_Click"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,12"
|
||||
Visibility="Collapsed" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- 底部提示 -->
|
||||
<TextBlock Grid.Row="4"
|
||||
Text="配置保存在 %LOCALAPPDATA%\WindowsGotify\config.json"
|
||||
Foreground="#999"
|
||||
FontSize="10"
|
||||
Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
Reference in New Issue
Block a user