diff --git a/LinkToolAddin.csproj b/LinkToolAddin.csproj
index 0f3f990..bece90c 100644
--- a/LinkToolAddin.csproj
+++ b/LinkToolAddin.csproj
@@ -120,6 +120,26 @@
Always
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
diff --git a/common/LocalResource.cs b/common/LocalResource.cs
index fc1e719..4f4e53a 100644
--- a/common/LocalResource.cs
+++ b/common/LocalResource.cs
@@ -1,5 +1,7 @@
using System;
using System.IO;
+using System.Windows.Controls;
+using System.Windows.Media.Imaging;
namespace LinkToolAddin.common;
@@ -8,12 +10,6 @@ public class LocalResource
public static string ReadFileByResource(string resourceName)
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
-
- string[] resourceNames = assembly.GetManifestResourceNames();
- foreach (string name in resourceNames)
- {
- Console.WriteLine(name);
- }
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
@@ -28,4 +24,24 @@ public class LocalResource
}
}
}
+
+ public static BitmapImage ReadImageByResource(string resourceName)
+ {
+ var assembly = System.Reflection.Assembly.GetExecutingAssembly();
+ using (Stream stream = assembly.GetManifestResourceStream(resourceName))
+ {
+ if (stream == null)
+ {
+ Console.WriteLine("资源未找到,请检查资源名称是否正确。");
+ return null;
+ }
+
+ // 如果是 WPF,可以转换为 BitmapImage
+ BitmapImage bitmap = new BitmapImage();
+ bitmap.BeginInit();
+ bitmap.StreamSource = stream;
+ bitmap.EndInit();
+ return bitmap;
+ }
+ }
}
\ No newline at end of file
diff --git a/host/Gateway.cs b/host/Gateway.cs
index 2a789c5..78889e8 100644
--- a/host/Gateway.cs
+++ b/host/Gateway.cs
@@ -282,12 +282,28 @@ public class Gateway
{
//如果本次回复不包含任何工具的调用或提示词的调用,则不再请求
goOn = false;
+ MessageListItem endMessageListItem1 = new ChatMessageItem
+ {
+ type = MessageType.END_TAG,
+ content = "",
+ id = (timestamp+3).ToString(),
+ role = "assistant"
+ };
+ callback?.Invoke(endMessageListItem1);
break;
}
await foreach(LlmStreamChat llmStreamChat in bailian.SendChatStreamAsync(jsonContent))
{
if (!goOn)
{
+ MessageListItem endMessageListItem2 = new ChatMessageItem
+ {
+ type = MessageType.END_TAG,
+ content = "",
+ id = (timestamp+3).ToString(),
+ role = "assistant"
+ };
+ callback?.Invoke(endMessageListItem2);
break;
}
@@ -299,7 +315,7 @@ public class Gateway
content = llmStreamChat.Choices[0].Delta.ResoningContent,
role = "assistant",
type = MessageType.REASON_MESSAGE,
- id = (timestamp-1).ToString()
+ id = (timestamp+2).ToString()
};
Application.Current.Dispatcher.Invoke(() =>
{
@@ -352,6 +368,14 @@ public class Gateway
else
{
//包含工具调用请求的消息
+ XElement toolUse = XElement.Parse(matched);
+ string fullToolName = toolUse.Element("name")?.Value;
+ string toolArgs = toolUse.Element("arguments")?.Value;
+ Dictionary toolParams = JsonConvert.DeserializeObject>(toolArgs);
+ string serverName = fullToolName.Contains(":") ? fullToolName.Split(':')[0] : fullToolName;
+ string toolName = fullToolName.Contains(":") ? fullToolName.Split(':')[1] : fullToolName;
+ McpServer mcpServer = mcpServerList.GetServer(serverName);
+ //将工具调用请求添加至列表中待一次回答完整后再统一进行调用
MessageListItem chatMessageListItem = new ChatMessageItem()
{
content = remaining,
@@ -363,14 +387,21 @@ public class Gateway
{
callback?.Invoke(chatMessageListItem);
});
- XElement toolUse = XElement.Parse(matched);
- string fullToolName = toolUse.Element("name")?.Value;
- string toolArgs = toolUse.Element("arguments")?.Value;
- Dictionary toolParams = JsonConvert.DeserializeObject>(toolArgs);
- string serverName = fullToolName.Contains(":") ? fullToolName.Split(':')[0] : fullToolName;
- string toolName = fullToolName.Contains(":") ? fullToolName.Split(':')[1] : fullToolName;
- McpServer mcpServer = mcpServerList.GetServer(serverName);
- //将工具调用请求添加至列表中待一次回答完整后再统一进行调用
+ MessageListItem toolMessageListItem = new ToolMessageItem()
+ {
+ content = "",
+ result = "",
+ toolName = toolName,
+ toolParams = toolParams,
+ role = "user",
+ type = MessageType.TOOL_MESSAGE,
+ id = (timestamp+1).ToString(),
+ status = "loading"
+ };
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ callback?.Invoke(toolMessageListItem);
+ });
mcpToolRequests = new List();
McpToolRequest mcpToolRequest = new McpToolRequest()
{
@@ -415,7 +446,9 @@ public class Gateway
type = MessageType.TOOL_MESSAGE,
status = toolResponse.IsError ? "fail" : "success",
content = JsonConvert.SerializeObject(toolResponse),
- id = (timestamp + 1).ToString()
+ result = JsonConvert.SerializeObject(toolResponse),
+ id = (timestamp + 1).ToString(),
+ role = "user"
};
messages.Add(new Message
{
@@ -441,7 +474,9 @@ public class Gateway
type = MessageType.TOOL_MESSAGE,
status = toolResponse.IsError ? "fail" : "success",
content = JsonConvert.SerializeObject(toolResponse),
- id = (timestamp + 1).ToString()
+ result = JsonConvert.SerializeObject(toolResponse),
+ id = (timestamp + 1).ToString(),
+ role = "user"
};
messages.Add(new Message
{
@@ -486,7 +521,9 @@ public class Gateway
type = MessageType.TOOL_MESSAGE,
status = "fail",
content = JsonConvert.SerializeObject(innerResult),
- id = (timestamp + 1).ToString()
+ result = JsonConvert.SerializeObject(innerResult),
+ id = (timestamp + 1).ToString(),
+ role = "user"
};
messages.Add(new Message
{
@@ -507,7 +544,9 @@ public class Gateway
type = MessageType.TOOL_MESSAGE,
status = "success",
content = JsonConvert.SerializeObject(innerResult),
- id = (timestamp + 1).ToString()
+ result = JsonConvert.SerializeObject(innerResult),
+ id = (timestamp + 1).ToString(),
+ role = "user"
};
messages.Add(new Message
{
@@ -546,7 +585,8 @@ public class Gateway
type = MessageType.TOOL_MESSAGE,
status = "success",
content = "成功调用提示词:"+promptRequest.PromptName,
- id = (timestamp+1).ToString()
+ id = (timestamp+1).ToString(),
+ result = "成功调用提示词:"+promptRequest.PromptName
};
Application.Current.Dispatcher.Invoke(() =>
{
@@ -559,6 +599,14 @@ public class Gateway
log.Error(e.Message);
}
}
+ MessageListItem endMessageListItem = new ChatMessageItem
+ {
+ type = MessageType.END_TAG,
+ content = "",
+ id = (timestamp+3).ToString(),
+ role = "assistant"
+ };
+ callback?.Invoke(endMessageListItem);
}
}
diff --git a/resource/img/fold.png b/resource/img/fold.png
new file mode 100644
index 0000000..2690b19
Binary files /dev/null and b/resource/img/fold.png differ
diff --git a/resource/img/linktool.png b/resource/img/linktool.png
new file mode 100644
index 0000000..37264c2
Binary files /dev/null and b/resource/img/linktool.png differ
diff --git a/resource/img/tool.png b/resource/img/tool.png
new file mode 100644
index 0000000..09bee43
Binary files /dev/null and b/resource/img/tool.png differ
diff --git a/resource/img/unfold.png b/resource/img/unfold.png
new file mode 100644
index 0000000..749e87e
Binary files /dev/null and b/resource/img/unfold.png differ
diff --git a/resource/img/user.png b/resource/img/user.png
new file mode 100644
index 0000000..a992685
Binary files /dev/null and b/resource/img/user.png differ
diff --git a/ui/VersionButton.cs b/ui/VersionButton.cs
index 62e157d..bc4df57 100644
--- a/ui/VersionButton.cs
+++ b/ui/VersionButton.cs
@@ -22,7 +22,7 @@ namespace LinkToolAddin
{
internal class VersionButton : Button
{
- private string version = "0.1.0";
+ private string version = "0.1.1";
protected override void OnClick()
{
MessageBox.Show($"当前LinkTool版本为{version}", "版本信息");
diff --git a/ui/dockpane/DialogDockpane.xaml b/ui/dockpane/DialogDockpane.xaml
index 84e7de1..d232eaa 100644
--- a/ui/dockpane/DialogDockpane.xaml
+++ b/ui/dockpane/DialogDockpane.xaml
@@ -5,9 +5,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="clr-namespace:LinkToolAddin.ui.dockpane"
xmlns:extensions="clr-namespace:ArcGIS.Desktop.Extensions;assembly=ArcGIS.Desktop.Extensions"
- xmlns:controls="clr-namespace:ArcGIS.Desktop.Framework.Controls;assembly=ArcGIS.Desktop.Framework"
+ xmlns:controls="clr-namespace:ArcGIS.Desktop.Framework.Controls;assembly=ArcGIS.Desktop.Framework"
+ xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="d"
- d:DesignHeight="300" d:DesignWidth="300"
+ d:DesignHeight="650" d:DesignWidth="300"
d:DataContext="{Binding Path=ui.DialogDockpaneViewModel}">
@@ -16,13 +17,39 @@
-
+
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/dockpane/DialogDockpane.xaml.cs b/ui/dockpane/DialogDockpane.xaml.cs
index aa2ea7f..3e623ae 100644
--- a/ui/dockpane/DialogDockpane.xaml.cs
+++ b/ui/dockpane/DialogDockpane.xaml.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Net.Http;
@@ -12,10 +14,15 @@ using Microsoft.Extensions.Logging;
using System.Text.Json;
using System.Threading;
using System.Windows.Documents;
+using System.Windows.Media;
+using ArcGIS.Desktop.Core;
using ArcGIS.Desktop.Core.Geoprocessing;
using LinkToolAddin.client;
+using LinkToolAddin.common;
+using LinkToolAddin.host;
using LinkToolAddin.host.llm;
using LinkToolAddin.host.llm.entity;
+using LinkToolAddin.message;
using LinkToolAddin.resource;
using LinkToolAddin.server;
using log4net;
@@ -29,17 +36,26 @@ using Newtonsoft.Json;
namespace LinkToolAddin.ui.dockpane
{
+ public class ItemModel
+ {
+ public string Content { get; set; }
+ }
///
/// Interaction logic for DialogDockpaneView.xaml
///
public partial class DialogDockpaneView : UserControl
{
private static ILog log = LogManager.GetLogger(typeof(DialogDockpaneView));
-
+
+ private List idList = new List();
+ private ConcurrentDictionary messageDict = new ConcurrentDictionary();
+ private ConcurrentDictionary borderItemsDict = new ConcurrentDictionary();
+
public DialogDockpaneView()
{
InitLogger();
InitializeComponent();
+ DataContext = this;
}
private async void TestServer_OnClick(object sender, RoutedEventArgs e)
@@ -81,5 +97,396 @@ namespace LinkToolAddin.ui.dockpane
log.Info("Info 日志(控制台和文件可见)");
log.Error("Error 日志(严重问题)");
}
+
+ private void SendButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ string question = QuestionTextbox.Text;
+ string defaultGdbPath = Project.Current.DefaultGeodatabasePath;
+ string gdbPath = @"";
+ long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ MessageListItem userMsg = new ChatMessageItem()
+ {
+ content = question,
+ role = "user",
+ type = MessageType.CHAT_MESSAGE,
+ id = timestamp.ToString()
+ };
+ Border userMsgBoder = GetUserChatBorder(userMsg);
+ idList.Add(timestamp.ToString());
+ messageDict[timestamp.ToString()] = userMsg;
+ QuestionTextbox.Text = "";
+ borderItemsDict[timestamp.ToString()] = userMsgBoder;
+ ChatHistoryStackPanel.Children.Add(userMsgBoder);
+ Gateway.SendMessageStream(question,"qwen3-235b-a22b",defaultGdbPath,NewMessage_Recall);
+ }
+
+ public void NewMessage_Recall(MessageListItem msg)
+ {
+ string msgId = msg.id;
+ log.Info(msg.content);
+ double verticalOffset = ScrollViewer.VerticalOffset;
+ double viewportHeight = ScrollViewer.ViewportHeight;
+ double contentHeight = ChatHistoryStackPanel.ActualHeight;
+ double tolerance = 24;
+ if (!idList.Contains(msgId))
+ {
+ //不存在该消息,需添加到ListView中
+ if (msg.content == "")
+ {
+ return;
+ }
+ idList.Add(msgId);
+ messageDict[msgId] = msg;
+ if (msg.role == "user")
+ {
+ if (msg.type == MessageType.TOOL_MESSAGE)
+ {
+ Border border = GetToolChatBorder(msg);
+ borderItemsDict[msgId] = border;
+ ChatHistoryStackPanel.Children.Add(border);
+ StatusTextBlock.Text = "正在执行工具";
+ }else if (msg.type == MessageType.CHAT_MESSAGE)
+ {
+ Border border = GetUserChatBorder(msg);
+ borderItemsDict[msgId] = border;
+ ChatHistoryStackPanel.Children.Add(border);
+ StatusTextBlock.Text = "正在读取用户输入";
+ }
+ }
+ else if(msg.role == "assistant")
+ {
+ if (msg.type == MessageType.REASON_MESSAGE)
+ {
+ Border border = GetAiReasonBorder(msg);
+ borderItemsDict[msgId] = border;
+ ChatHistoryStackPanel.Children.Add(border);
+ StatusTextBlock.Text = "深度思考中";
+ }else if (msg.type == MessageType.CHAT_MESSAGE)
+ {
+ Border border = GetAiChatBorder(msg);
+ borderItemsDict[msgId] = border;
+ ChatHistoryStackPanel.Children.Add(border);
+ StatusTextBlock.Text = "回答生成中";
+ }else if (msg.type == MessageType.END_TAG)
+ {
+ StatusTextBlock.Text = "";
+ }
+ }
+ }
+ else
+ {
+ //已有该消息,只需要修改内容
+ messageDict[msgId] = msg;
+ if (msg.content == "")
+ {
+ ChatHistoryStackPanel.Children.Remove(borderItemsDict[msgId]);
+ borderItemsDict.TryRemove(msgId, out Border border);
+ messageDict.TryRemove(msgId, out MessageListItem tempMsg);
+ idList.Remove(msgId);
+ }
+ if (msg.role == "user")
+ {
+ if (msg.type == MessageType.TOOL_MESSAGE)
+ {
+ Border borderItem = borderItemsDict[msgId];
+ Grid grid = borderItem.Child as Grid;
+ TextBlock textBlock = grid.Children[1] as TextBlock;
+ textBlock.Text = (msg as ToolMessageItem).toolName;
+ StatusTextBlock.Text = "正在执行工具";
+ }else if (msg.type == MessageType.CHAT_MESSAGE)
+ {
+ Border borderItem = borderItemsDict[msgId];
+ Grid grid = borderItem.Child as Grid;
+ TextBox textBox = grid.Children[1] as TextBox;
+ textBox.Text = msg.content;
+ StatusTextBlock.Text = "正在读取用户输入";
+ }
+ }
+ else
+ {
+ if (msg.type == MessageType.REASON_MESSAGE)
+ {
+ Border borderItem = borderItemsDict[msgId];
+ Grid grid = borderItem.Child as Grid;
+ TextBox textBox = grid.Children[0] as TextBox;
+ textBox.Text = msg.content;
+ StatusTextBlock.Text = "深度思考中";
+ }else if (msg.type == MessageType.CHAT_MESSAGE)
+ {
+ Border borderItem = borderItemsDict[msgId];
+ Grid grid = borderItem.Child as Grid;
+ TextBox textBox = grid.Children[1] as TextBox;
+ textBox.Text = msg.content;
+ StatusTextBlock.Text = "回答生成中";
+ }else if (msg.type == MessageType.END_TAG)
+ {
+ StatusTextBlock.Text = "";
+ }
+ }
+ }
+ if (Math.Abs(verticalOffset + viewportHeight - contentHeight) < tolerance)
+ {
+ ScrollViewer.ScrollToBottom();
+ }
+ }
+
+ private Border GetAiChatBorder(MessageListItem msg)
+ {
+ Border border = new Border();
+ border.Margin = new Thickness(8, 12, 8, 12);
+ border.BorderThickness = new Thickness(0);
+ // border.Background = Brushes.DarkSeaGreen;
+ Grid grid = new Grid();
+ Image icon = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.linktool.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top
+ };
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(24, GridUnitType.Pixel)});
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(1, GridUnitType.Star)});
+ TextBox textBox = new TextBox();
+ grid.Children.Add(icon);
+ grid.Children.Add(textBox);
+ Grid.SetColumn(icon, 0);
+ Grid.SetColumn(textBox, 1);
+ textBox.IsReadOnly = true;
+ textBox.BorderThickness = new Thickness(0);
+ textBox.Background = Brushes.Transparent;
+ textBox.Text = msg.content;
+ textBox.TextWrapping = TextWrapping.Wrap;
+ border.Child = grid;
+ return border;
+ }
+
+ private Border GetAiReasonBorder(MessageListItem msg)
+ {
+ Border border = new Border();
+ border.Margin = new Thickness(8, 12, 8, 12);
+ border.BorderThickness = new Thickness(0);
+ // border.Background = Brushes.DarkSeaGreen;
+ Grid grid = new Grid();
+ Image icon = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.linktool.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top
+ };
+ Image fold = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.fold.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top
+ };
+ Image unfold = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.unfold.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top
+ };
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(24, GridUnitType.Pixel)});
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(1, GridUnitType.Star)});
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(16, GridUnitType.Pixel)});
+ TextBox textBox = new TextBox();
+ // grid.Children.Add(icon);
+ grid.Children.Add(textBox);
+ // Grid.SetColumn(icon, 0);
+ Grid.SetColumn(textBox, 1);
+ textBox.IsReadOnly = true;
+ textBox.Foreground = Brushes.Gray;
+ textBox.BorderThickness = new Thickness(2,0,0,0);
+ textBox.BorderBrush = Brushes.Gray;
+ textBox.Background = Brushes.Transparent;
+ textBox.Text = msg.content;
+ textBox.TextWrapping = TextWrapping.Wrap;
+ Button button = new Button();
+ StackPanel panel = new StackPanel();
+ panel.Orientation = Orientation.Horizontal;
+ panel.Children.Add(fold);
+ button.Content = panel;
+ button.BorderThickness = new Thickness(0);
+ button.Background = Brushes.Transparent;
+ button.Width = 16;
+ button.Height = 16;
+ button.Padding = new Thickness(0);
+ button.HorizontalAlignment = HorizontalAlignment.Center;
+ button.VerticalAlignment = VerticalAlignment.Top;
+ button.Tag = "fold";
+ button.Click += FoldButton_OnClick;
+ Grid.SetColumn(button, 2);
+ grid.Children.Add(button);
+ border.Child = grid;
+ return border;
+ }
+
+ private void FoldButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ Button button = sender as Button;
+ string tag = button.Tag.ToString();
+ if (tag == "fold")
+ {
+ button.Tag = "unfold";
+ Grid grid = button.Parent as Grid;
+ TextBox textBox = grid.Children[0] as TextBox;
+ textBox.Visibility = Visibility.Collapsed;
+ StackPanel stackPanel = button.Content as StackPanel;
+ Image unfold = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.unfold.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top
+ };
+ stackPanel.Children.Clear();
+ stackPanel.Children.Add(unfold);
+ }
+ else
+ {
+ button.Tag = "fold";
+ Image fold = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.fold.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top
+ };
+ Grid grid = button.Parent as Grid;
+ TextBox textBox = grid.Children[0] as TextBox;
+ textBox.Visibility = Visibility.Visible;
+ StackPanel stackPanel = button.Content as StackPanel;
+ stackPanel.Children.Clear();
+ stackPanel.Children.Add(fold);
+ }
+
+ }
+
+ private Border GetUserChatBorder(MessageListItem msg)
+ {
+ Border border = new Border();
+ border.Margin = new Thickness(8, 12, 8, 12);
+ border.BorderThickness = new Thickness(0);
+ // border.Background = Brushes.DarkSeaGreen;
+ Grid grid = new Grid();
+ Image icon = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.user.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top
+ };
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(1, GridUnitType.Star)});
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(24, GridUnitType.Pixel)});
+ TextBox textBox = new TextBox();
+ textBox.HorizontalAlignment = HorizontalAlignment.Right;
+ grid.Children.Add(icon);
+ grid.Children.Add(textBox);
+ Grid.SetColumn(icon, 1);
+ Grid.SetColumn(textBox, 0);
+ textBox.Background = Brushes.Transparent;
+ textBox.IsReadOnly = true;
+ textBox.BorderThickness = new Thickness(0);
+ textBox.Text = msg.content;
+ textBox.TextWrapping = TextWrapping.Wrap;
+ border.Child = grid;
+ return border;
+ }
+
+ private Border GetToolChatBorder(MessageListItem msg)
+ {
+ Border border = new Border();
+ border.Margin = new Thickness(24);
+ border.Padding = new Thickness(8);
+ border.BorderThickness = new Thickness(1);
+ border.BorderBrush = Brushes.Gray;
+ border.CornerRadius = new CornerRadius(3);
+ // border.Background = Brushes.DarkSeaGreen;
+ Grid grid = new Grid();
+ Image icon = new Image()
+ {
+ Source = LocalResource.ReadImageByResource("LinkToolAddin.resource.img.tool.png"),
+ Stretch = Stretch.Fill,
+ HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center
+ };
+ icon.Margin = new Thickness(0, 0, 8, 0);
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(24, GridUnitType.Pixel)});
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(1, GridUnitType.Star)});
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(36, GridUnitType.Pixel)});
+ grid.ColumnDefinitions.Add(new ColumnDefinition(){Width = new GridLength(36, GridUnitType.Pixel)});
+ TextBlock textBlock = new TextBlock();
+ ToolMessageItem toolMsg = msg as ToolMessageItem;
+ textBlock.Text = toolMsg.toolName + " | " + toolMsg.status;
+ textBlock.TextWrapping = TextWrapping.Wrap;
+ grid.Children.Add(icon);
+ grid.Children.Add(textBlock);
+ Grid.SetColumn(icon, 0);
+ Grid.SetColumn(textBlock, 1);
+ Button argsButton = new Button();
+ argsButton.Content = "参数";
+ argsButton.Tag = msg as ToolMessageItem;
+ argsButton.Click += ToolArgsButton_OnClick;
+ border.Child = grid;
+ Button resButton = new Button();
+ resButton.Content = "结果";
+ resButton.Tag = msg as ToolMessageItem;
+ resButton.Click += ToolResButton_OnClick;
+ grid.Children.Add(argsButton);
+ Grid.SetColumn(argsButton, 2);
+ grid.Children.Add(resButton);
+ Grid.SetColumn(resButton, 3);
+ return border;
+ }
+
+ private void ToolArgsButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ Button button = sender as Button;
+ ToolMessageItem toolItem = button.Tag as ToolMessageItem;
+ ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(JsonConvert.SerializeObject(toolItem.toolParams),toolItem.toolName+"工具参数");
+ }
+
+ private void ToolResButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ Button button = sender as Button;
+ ToolMessageItem toolItem = button.Tag as ToolMessageItem;
+ ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(toolItem.result,toolItem.toolName+"运行结果");
+ }
+
+ private void TestButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ MessageListItem toolMessageItem = new ToolMessageItem
+ {
+ toolName = "toolName",
+ toolParams = new Dictionary(),
+ type = MessageType.TOOL_MESSAGE,
+ status = "success",
+ content = "JsonConvert.SerializeObject(toolResponse)",
+ id = (timestamp + 1).ToString(),
+ role = "user"
+ };
+ NewMessage_Recall(toolMessageItem);
+ }
+
+ private void ClearButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ idList.Clear();
+ messageDict.Clear();
+ borderItemsDict.Clear();
+ ChatHistoryStackPanel.Children.Clear();
+ QuestionTextbox.Clear();
+ StatusTextBlock.Text = "";
+ }
+
+ private void TopButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ ScrollViewer.ScrollToTop();
+ }
+
+ private void BottomButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ ScrollViewer.ScrollToBottom();
+ }
+
+ private void StopButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ Gateway.StopConversation();
+ StatusTextBlock.Text = "";
+ }
}
}
diff --git a/ui/dockpane/DialogDockpaneViewModel.cs b/ui/dockpane/DialogDockpaneViewModel.cs
index 1d7a4e5..42258fc 100644
--- a/ui/dockpane/DialogDockpaneViewModel.cs
+++ b/ui/dockpane/DialogDockpaneViewModel.cs
@@ -14,6 +14,7 @@ using ArcGIS.Desktop.Layouts;
using ArcGIS.Desktop.Mapping;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -27,8 +28,14 @@ namespace LinkToolAddin.ui.dockpane
internal class DialogDockpaneViewModel : DockPane
{
private const string _dockPaneID = "DialogDockpane";
+
+ public ObservableCollection Items { get; set; }
- protected DialogDockpaneViewModel() { }
+ protected DialogDockpaneViewModel()
+ {
+ Items = new ObservableCollection();
+ Items.Add(new ItemModel(){Content = "adfdfdafdfs"});
+ }
///
/// Show the DockPane.
diff --git a/ui/message/MessageListItem.cs b/ui/message/MessageListItem.cs
index 9b97709..3b0ce37 100644
--- a/ui/message/MessageListItem.cs
+++ b/ui/message/MessageListItem.cs
@@ -5,6 +5,7 @@ public enum MessageType
TOOL_MESSAGE,
CHAT_MESSAGE,
REASON_MESSAGE,
+ END_TAG
}
public interface MessageListItem