优化 UI 组件和提示信息格式

在 `MarkdownWpfRenderer.cs` 中,修改 `RenderHtmlBlock` 方法以支持 `<think>` 标签,返回包含进度条的 `Expander` 控件或直接返回文本块。更新 `PromptUtil.cs` 中的 `UsePrompt` 方法,增加当前时间和用户提问的 Excel 列信息格式。

在 `App.xaml` 中移除 `ThemeDictionary` 的 `ColorMode` 属性,简化主题定义。重构 `AiMessageControll.xaml` 的 UI,使用 `DockPanel` 和 `ButtonGroup`,并增加分隔线。

在 `ImportExcelPage.xaml` 中添加上下文菜单,调整 `TabControl` 和 `DataGrid` 属性以支持虚拟化,重构参数配置 UI,使用 `hc:Card` 和 `DockPanel` 结构。

在 `ImportExcelPage.xaml.cs` 中添加按钮点击事件处理程序以切换配置显示状态。在 `ImportViewModel.cs` 中更新 AI 消息处理逻辑,使用新提示格式,并添加 `_showConfig` 属性及其文档注释。
This commit is contained in:
Ling 2025-03-05 23:14:54 +08:00
commit 6d5b4a33b9
7 changed files with 219 additions and 140 deletions

View File

@ -379,19 +379,22 @@ public class MarkdownWpfRenderer
if (text.StartsWith("<think>")) if (text.StartsWith("<think>"))
{ {
text = text.Replace("<think>", "").Replace("</think>", ""); text = text.Replace("<think>", "").Replace("</think>", "");
}
var htmlText = new SelectableTextBlock(); var htmlText = new SelectableTextBlock();
htmlText.Text = text; htmlText.Text = text;
var expander = new Expander(); var expander = new Expander();
var header = new StackPanel(); var header = new StackPanel();
header.Orientation = Orientation.Horizontal; header.Children.Add(new ProgressBar() { IsIndeterminate = true, Width = 30 });
header.HorizontalAlignment = HorizontalAlignment.Center;
header.Children.Add(new TextBlock() { Text="思考内容",Margin = new Thickness(0,0,5,0) });
//header.Children.Add(new ProgressBar() { IsIndeterminate = true,Width = 30,Height= 5 });
expander.Header = header; expander.Header = header;
expander.IsExpanded = false;
expander.Content = htmlText; expander.Content = htmlText;
return expander; return expander;
}
else
{
var htmlText = new SelectableTextBlock();
htmlText.Text = text;
return htmlText;
}
} }
public FrameworkElement RenderMathBlock(MathBlock mathBlock, CancellationToken cancellationToken) public FrameworkElement RenderMathBlock(MathBlock mathBlock, CancellationToken cancellationToken)

View File

@ -11,24 +11,47 @@ class PromptUtil
public static string UsePrompt(string msg,string excelPrompt) public static string UsePrompt(string msg,string excelPrompt)
{ {
return $@" return $@"
Excel和WPS公式大师Excel与WPS公式相关的问题 Excel公式大师Excel公式相关的问题
<current_time>
{DateTime.Now}
</current_time>
excel文件列信息为
<excel_columns>
{excelPrompt}
</excel_columns>
<question>
{msg}
</question>
1. 1.
2. 2.
3. 12Excel公式 3. 12Excel公式
4. 4.
5. 使 5. 使
6. 使<think>使</think> 6. 使
7. 使
```Excel_{{}} ```Excel_{{}}
=SUM(A1:A100) =SUM(A1:A100)
```
{DateTime.Now}
excel文件列信息为{excelPrompt}
{msg}
"; ";
} }
} }

View File

@ -12,7 +12,7 @@
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" /> <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" /> <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
<mu:ControlsDictionary /> <mu:ControlsDictionary />
<mu:ThemeDictionary ColorMode="Light" /> <mu:ThemeDictionary />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>

View File

@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:local="clr-namespace:ExcelHelper.Views.Components" xmlns:local="clr-namespace:ExcelHelper.Views.Components"
xmlns:local1="clr-namespace:ExcelHelper.Converter" xmlns:local1="clr-namespace:ExcelHelper.Converter"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -87,6 +88,15 @@
</TabItem> </TabItem>
</TabControl> </TabControl>
<DockPanel>
<hc:ButtonGroup Margin="5,0">
<Button
Height="20"
hc:IconElement.Geometry="{StaticResource WindowRestoreGeometry}"
Background="Transparent"
FontSize="10"
Foreground="#99000000" />
</hc:ButtonGroup>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal"> <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<TextBlock <TextBlock
Margin="0,5,5,0" Margin="0,5,5,0"
@ -99,6 +109,13 @@
Foreground="#99000000" Foreground="#99000000"
Text="{Binding Timestamp, StringFormat='{}{0:HH:mm}'}" /> Text="{Binding Timestamp, StringFormat='{}{0:HH:mm}'}" />
</StackPanel> </StackPanel>
</DockPanel>
<hc:Divider
Height="10"
Margin="0,3"
LineStroke="#000"
LineStrokeThickness="2"
Visibility="{Binding IsUser, Converter={StaticResource Boolean2VisibilityReConverter}}" />
</StackPanel> </StackPanel>
</Border> </Border>
</DataTemplate> </DataTemplate>
@ -107,46 +124,53 @@
</ScrollViewer> </ScrollViewer>
<!-- 输入区 --> <!-- 输入区 -->
<Grid Grid.Row="1" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border <Border
Grid.Column="0" Grid.Row="1"
BorderBrush="#CCCCCC" Margin="8"
BorderThickness="1" Padding="5"
CornerRadius="5"> Background="Transparent"
BorderBrush="#000"
BorderThickness="2"
CornerRadius="3">
<StackPanel Grid.Row="1" Background="White">
<TextBox <TextBox
x:Name="MessageInput" x:Name="MessageInput"
MinHeight="40" MinHeight="40"
MaxHeight="120" MaxHeight="120"
Padding="8" Padding="8"
AcceptsReturn="True" AcceptsReturn="True"
Background="Transparent"
BorderThickness="0" BorderThickness="0"
IsEnabled="{Binding IsWaiting, Converter={StaticResource InverseBoolConverter}, UpdateSourceTrigger=PropertyChanged, ElementName=userControl}" IsEnabled="{Binding IsWaiting, Converter={StaticResource InverseBoolConverter}, UpdateSourceTrigger=PropertyChanged, ElementName=userControl}"
KeyDown="MessageInput_KeyDown" KeyDown="MessageInput_KeyDown"
Text="{Binding CurrentMessage, UpdateSourceTrigger=PropertyChanged, ElementName=userControl}" Text="{Binding CurrentMessage, UpdateSourceTrigger=PropertyChanged, ElementName=userControl}"
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</Border> <DockPanel>
<hc:ComboBox Height="30" SelectedIndex="1">
<ComboBoxItem Content="DeepSeek-V3" />
<ComboBoxItem Content="DeepSeek-V3" />
<ComboBoxItem Content="DeepSeek-V3" />
</hc:ComboBox>
<Button <Button
Grid.Column="1" Height="30"
Height="40" Margin="5"
Margin="5,0,0,0"
Padding="15,0" Padding="15,0"
HorizontalAlignment="Right"
Background="#000" Background="#000"
BorderBrush="Transparent" BorderBrush="Transparent"
BorderThickness="0" BorderThickness="0"
Click="SendButton_Click" Click="SendButton_Click"
Content="发送" Content="发送"
Foreground="White" Foreground="White"
IsEnabled="{Binding IsWaiting, Converter={StaticResource InverseBoolConverter}, UpdateSourceTrigger=PropertyChanged, ElementName=userControl}" /> IsEnabled="{Binding IsWaiting, Converter={StaticResource InverseBoolConverter}, UpdateSourceTrigger=PropertyChanged, ElementName=userControl}" />
</Grid>
</DockPanel>
</StackPanel>
</Border>
<!-- 等待指示器 --> <!-- 等待指示器 -->
<Border <Border
Grid.Row="1" Grid.Row="1"

View File

@ -46,6 +46,10 @@
</Grid> </Grid>
</DataTemplate> </DataTemplate>
<ContextMenu x:Key="DataGridContextMenu">
<MenuItem Header="问这一行数据" />
<MenuItem Header="问这一行数据" />
</ContextMenu>
</Page.Resources> </Page.Resources>
<Grid <Grid
AllowDrop="True" AllowDrop="True"
@ -82,22 +86,25 @@
Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}" /> Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}" />
<hc:TabControl <hc:TabControl
Grid.Column="0" Grid.Column="0"
Grid.ColumnSpan="2"
Margin="5,5,7,5" Margin="5,5,7,5"
ShowCloseButton="False" ShowCloseButton="False"
ShowContextMenu="False"> ShowContextMenu="False">
<hc:TabItem Header="预览"> <hc:TabItem Header="预览">
<DataGrid <DataGrid
x:Name="ExcelDataPreviewGrid" x:Name="ExcelDataPreviewGrid"
hc:DataGridAttach.CanUnselectAllWithBlankArea="True"
hc:DataGridAttach.ShowRowNumber="True"
hc:DataGridAttach.ShowSelectAllButton="True"
AutoGenerateColumns="False" AutoGenerateColumns="False"
ContextMenu="{StaticResource DataGridContextMenu}"
EnableColumnVirtualization="True" EnableColumnVirtualization="True"
EnableRowVirtualization="True" EnableRowVirtualization="True"
IsReadOnly="True" IsReadOnly="True"
ItemsSource="{Binding ExcelData, IsAsync=True}" ItemsSource="{Binding ExcelData, IsAsync=True}"
RowHeight="NaN" RowHeight="NaN"
ScrollViewer.CanContentScroll="True" ScrollViewer.CanContentScroll="True"
VirtualizingPanel.IsContainerVirtualizable="True" VirtualizingPanel.ScrollUnit="Pixel" />
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling" />
</hc:TabItem> </hc:TabItem>
<hc:TabItem Header="Columns2Prompt"> <hc:TabItem Header="Columns2Prompt">
@ -126,38 +133,38 @@
</Grid> </Grid>
</hc:TabItem> </hc:TabItem>
</hc:TabControl> </hc:TabControl>
<GridSplitter
Grid.Column="0"
Width="2"
Margin="0,5" />
<hc:Card <hc:Card
x:Name="ConfigCard"
Grid.Column="1" Grid.Column="1"
Width="Auto" Width="Auto"
Height="Auto"
Margin="5" Margin="5"
HorizontalAlignment="Stretch"> HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Opacity="0.95">
<hc:Card.Header> <hc:Card.Header>
<hc:SimpleStackPanel <DockPanel Margin="5">
Margin="5"
HorizontalAlignment="Center"
Orientation="Horizontal">
<TextBlock <TextBlock
Margin="5,0" Margin="5,0"
HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="参数配置" /> Text="参数配置" />
<Button <Button
VerticalAlignment="Center" HorizontalAlignment="Right"
Command="{Binding ReLoadExcelCommand}" Click="Button_Click_1"
Content="重新读取Excel" Content=""
Style="{StaticResource ButtonPrimary}" /> DockPanel.Dock="Left" />
</hc:SimpleStackPanel> </DockPanel>
</hc:Card.Header> </hc:Card.Header>
<hc:TransitioningContentControl TransitionMode="Bottom2Top" Visibility="{Binding ShowConfig, Converter={StaticResource BooleanToVisibilityConverter}}">
<hc:SimpleStackPanel SnapsToDevicePixels="True"> <hc:SimpleStackPanel SnapsToDevicePixels="True">
<hc:SimpleStackPanel.Resources> <hc:SimpleStackPanel.Resources>
<Style TargetType="{x:Type hc:SimpleStackPanel}"> <Style TargetType="{x:Type hc:SimpleStackPanel}">
<Setter Property="Margin" Value="5,5" /> <Setter Property="Margin" Value="5,5" />
</Style> </Style>
</hc:SimpleStackPanel.Resources> </hc:SimpleStackPanel.Resources>
<hc:SimpleStackPanel Orientation="Horizontal"> <hc:SimpleStackPanel Orientation="Horizontal">
<Label Content="指定的Sheet" /> <Label Content="指定的Sheet" />
<hc:ComboBox <hc:ComboBox
@ -206,12 +213,22 @@
ItemsSource="{Binding ExcelFiles}" ItemsSource="{Binding ExcelFiles}"
SelectedValue="{Binding CurrentFilePath}" /> SelectedValue="{Binding CurrentFilePath}" />
</hc:SimpleStackPanel> </hc:SimpleStackPanel>
<hc:SimpleStackPanel IsEnabled="False" Orientation="Horizontal"> <hc:SimpleStackPanel
IsEnabled="False"
Orientation="Horizontal"
ToolTip="暂不支持加密的Excel">
<Label Content="Excel密码" /> <Label Content="Excel密码" />
<PasswordBox MinWidth="60" utils:PasswordBoxHelper.Password="{Binding ExcelPassword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <PasswordBox MinWidth="60" utils:PasswordBoxHelper.Password="{Binding ExcelPassword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="?" ToolTip="未加密留空多个Excel如果不同密码请分批次导入" /> <Button Content="?" ToolTip="未加密留空多个Excel如果不同密码请分批次导入" />
</hc:SimpleStackPanel> </hc:SimpleStackPanel>
<Button
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding ReLoadExcelCommand}"
Content="重新读取Excel"
Style="{StaticResource ButtonPrimary}" />
</hc:SimpleStackPanel> </hc:SimpleStackPanel>
</hc:TransitioningContentControl>
</hc:Card> </hc:Card>
<hc:Card Grid.Column="2"> <hc:Card Grid.Column="2">
<!-- Fix: Added Mode=OneWay --> <!-- Fix: Added Mode=OneWay -->

View File

@ -117,4 +117,9 @@ public partial class ImportExcelPage : Page, IView, IRecipient<UpdateDataGridCol
// 标记事件已处理,防止冒泡 // 标记事件已处理,防止冒泡
e.Handled = true; e.Handled = true;
} }
private void Button_Click_1(object sender, System.Windows.RoutedEventArgs e)
{
ViewModel.ShowConfig = !ViewModel.ShowConfig;
}
} }

View File

@ -321,8 +321,9 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
}; };
Messages.Add(aiChat); Messages.Add(aiChat);
var promptedMsg = PromptUtil.UsePrompt(message,ExcelPromptString);
#if DEBUG #if DEBUG
var results = TEST_AI_CONTENT.Split('\n'); var results = promptedMsg.Split('\n');
foreach(var result in results) foreach(var result in results)
{ {
aiChat.Content += result; aiChat.Content += result;
@ -330,7 +331,6 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
await Task.Delay(5); await Task.Delay(5);
} }
#else #else
var promptedMsg = PromptUtil.UsePrompt(message,ExcelPromptString);
history.Add(new Microsoft.Extensions.AI.ChatMessage history.Add(new Microsoft.Extensions.AI.ChatMessage
{ {
Role = Microsoft.Extensions.AI.ChatRole.User, Role = Microsoft.Extensions.AI.ChatRole.User,
@ -449,6 +449,13 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
[ObservableProperty] [ObservableProperty]
private string _dbType; private string _dbType;
/// <summary>
/// 是否显示配置信息
/// </summary>
[ObservableProperty]
private bool _showConfig = false;
/// <summary> /// <summary>
/// 加密连接 /// 加密连接
/// </summary> /// </summary>