bump: 迁移到.net 8
This commit is contained in:
25
Frontend/Components/App.razor
Normal file
25
Frontend/Components/App.razor
Normal file
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<base href="/"/>
|
||||
<link href="css/site.css" rel="stylesheet"/>
|
||||
<link href="_content/AntDesign/css/ant-design-blazor.css" rel="stylesheet" />
|
||||
<link href="Frontend.styles.css" rel="stylesheet">
|
||||
<HeadOutlet @rendermode="@InteractiveServer" />
|
||||
</head>
|
||||
<body>
|
||||
<Routes @rendermode="@InteractiveServer" />
|
||||
|
||||
<text>
|
||||
An error has occurred. This application may not response until reloaded.
|
||||
</text>
|
||||
|
||||
<script src="_content/AntDesign/js/ant-design-blazor.js"></script>
|
||||
<script src="_content/BlazorMonaco/jsInterop.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
<script src="js/helper.js"></script>
|
||||
</body>
|
||||
</html>
|
132
Frontend/Components/ChatZone.razor
Normal file
132
Frontend/Components/ChatZone.razor
Normal file
@@ -0,0 +1,132 @@
|
||||
@using Frontend.Models
|
||||
@using Katheryne.Abstractions
|
||||
@inject IJSRuntime JsRuntime
|
||||
@inject IMessageService MessageService
|
||||
|
||||
<div class="content-zone">
|
||||
<div class="chat-zone" id="chat-scroll-zone">
|
||||
<AntList TItem="ChatMessage" DataSource="@Messages" Split="@false">
|
||||
<ListItem>
|
||||
@if (context.Left)
|
||||
{
|
||||
<div>
|
||||
<MessageBubble Message="context"/>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="margin-left: auto">
|
||||
<MessageBubble Message="context"/>
|
||||
</div>
|
||||
}
|
||||
</ListItem>
|
||||
</AntList>
|
||||
<div style="height: 200px; width: 100%; flex: none">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-zone">
|
||||
<div style="padding: 10px 82px 20px">
|
||||
<div class="input-zone">
|
||||
<GridRow>
|
||||
<GridCol Span="22">
|
||||
<Input TValue="@string" @bind-Value="@MessageSending"
|
||||
Placeholder="输入以对话" Bordered="@false" OnPressEnter="@SendMessageClicked"/>
|
||||
</GridCol>
|
||||
<GridCol Span="2">
|
||||
<Button Type="@ButtonType.Primary" @onclick="@SendMessageClicked">
|
||||
发送
|
||||
</Button>
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal Title="设置您的昵称"
|
||||
Visible="@_setUsernameVisible"
|
||||
OnOk="@SetUsernameOkClicked"
|
||||
OnCancel="@SetUsernameCancelClicked">
|
||||
<div>
|
||||
<Input TValue="@string" Placeholder="用户名"
|
||||
@bind-Value="@_username"
|
||||
OnPressEnter="@SetUsernameOkClicked"/>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
private string MessageSending { get; set; } = string.Empty;
|
||||
private string _username = string.Empty;
|
||||
private bool _setUsernameVisible = false;
|
||||
|
||||
[Parameter]
|
||||
public List<ChatMessage> Messages { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public IChatRobot Robot { get; set; } = null!;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_username))
|
||||
{
|
||||
_setUsernameVisible = true;
|
||||
}
|
||||
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (!firstRender)
|
||||
{
|
||||
JsRuntime.InvokeVoidAsync("scrollToSection");
|
||||
}
|
||||
base.OnAfterRender(firstRender);
|
||||
}
|
||||
|
||||
private void SendMessageClicked()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(MessageSending))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Messages.Add(new ChatMessage
|
||||
{
|
||||
Left = false,
|
||||
Sender = string.IsNullOrEmpty(_username) ? "default" : _username,
|
||||
Text = MessageSending
|
||||
});
|
||||
|
||||
foreach (string answer in Robot.ChatNext(MessageSending))
|
||||
{
|
||||
Messages.Add(new ChatMessage
|
||||
{
|
||||
Left = true,
|
||||
Sender = Robot.RobotName,
|
||||
Text = answer
|
||||
});
|
||||
}
|
||||
|
||||
MessageSending = string.Empty;
|
||||
}
|
||||
|
||||
private void SetUsernameOkClicked()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_username))
|
||||
{
|
||||
MessageService.Warning("昵称不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
_setUsernameVisible = false;
|
||||
}
|
||||
|
||||
private void SetUsernameCancelClicked()
|
||||
{
|
||||
MessageService.Warning("呃呃呃呃,没设置用户名就想走?");
|
||||
}
|
||||
}
|
58
Frontend/Components/ChatZone.razor.css
Normal file
58
Frontend/Components/ChatZone.razor.css
Normal file
@@ -0,0 +1,58 @@
|
||||
.chat-column {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.content-zone {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-height: calc(100vh - 64px);
|
||||
max-height: calc(100vh - 64px);
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
background: linear-gradient(180deg,
|
||||
#f5f4f6,
|
||||
#b5bddf);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-zone {
|
||||
min-width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.chat-zone::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.chat-zone::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
background: #bdbdbd;
|
||||
}
|
||||
|
||||
.chat-zone::-webkit-scrollbar-track {
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.control-zone {
|
||||
min-width: 100%;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
background-color: #b5bddf;
|
||||
display: block;
|
||||
box-shadow: 3px 0 0 #b5bddf;
|
||||
}
|
||||
|
||||
.input-zone {
|
||||
padding: 10px;
|
||||
border-radius: 15px;
|
||||
background-color: white;
|
||||
}
|
84
Frontend/Components/GrammarHelp.razor
Normal file
84
Frontend/Components/GrammarHelp.razor
Normal file
@@ -0,0 +1,84 @@
|
||||
<Modal Title="DSL语法说明"
|
||||
Visible="@_helpVisible"
|
||||
OnOk="@(() => _helpVisible = false)"
|
||||
OnCancel="@(() => _helpVisible = false)">
|
||||
<div>
|
||||
<Title Level="3">语法说明</Title>
|
||||
<Paragraph>
|
||||
凯瑟琳DSL使用和<Text Code>YAML</Text>类似的语法来编写逻辑。语法通过规定机器人的多个阶段和在阶段之间的
|
||||
迁移关系来描述聊天机器人的聊天过程。机器人在启动时处在一个特定的阶段,通过正则表达式匹配用户的输入迁移到下一个阶段
|
||||
并输出对应的内容。
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph>
|
||||
文法拥有三个顶级属性:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<Text Code>robotName</Text> 字符串类型,规定了机器人的名称;
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Text Code>stages</Text> Stage类型的数组,规定了机器人的各个阶段;
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Text Code>beginStageName</Text> 字符串类型,规定了机器人初始阶段,会自动输出该阶段的输出内容。
|
||||
</li>
|
||||
</ul>
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph>
|
||||
Stage类型拥有三个属性:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<Text Code>name</Text> 阶段的名称,是阶段<b>唯一的标识符</b>;
|
||||
</li>
|
||||
<li>
|
||||
<Text Code>transformers</Text> Transformer类型的数组,指定该阶段的迁移规则;
|
||||
</li>
|
||||
<li>
|
||||
<Text Code>answer</Text> 该阶段的输出内容。
|
||||
</li>
|
||||
</ul>
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph>
|
||||
Transformer类型拥有两个属性:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<Text Code>pattern</Text> 匹配用户输入的正则表达式;
|
||||
</li>
|
||||
<li>
|
||||
<Text Code>nextStageName</Text> 匹配成功之后需要迁移到的阶段名。
|
||||
</li>
|
||||
</ul>
|
||||
</Paragraph>
|
||||
|
||||
<Paragraph>
|
||||
在编译阶段编译器会执行如下检查:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<Text Code>transformers</Text> 中的 <Text Code>nextStageName</Text>指定的阶段是否定义;
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Text Code>beginStageName</Text> 指定的阶段是否定义。
|
||||
</li>
|
||||
</ul>
|
||||
</Paragraph>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@code {
|
||||
private bool _helpVisible;
|
||||
|
||||
public void Show()
|
||||
{
|
||||
_helpVisible = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
35
Frontend/Components/MainLayout.razor
Normal file
35
Frontend/Components/MainLayout.razor
Normal file
@@ -0,0 +1,35 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div>
|
||||
<Layout>
|
||||
<Header class="header">
|
||||
<Space >
|
||||
<SpaceItem>
|
||||
<p class="title-text">
|
||||
试作自律型可重编程客服机器人
|
||||
</p>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<p class="subtitle-text">
|
||||
a.k.a 凯瑟琳
|
||||
</p>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<div>
|
||||
<a href="editor/">维护界面</a>
|
||||
</div>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</Header>
|
||||
|
||||
<Layout>
|
||||
<Content>
|
||||
@Body
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</div>
|
||||
|
||||
<AntContainer/>
|
11
Frontend/Components/MainLayout.razor.css
Normal file
11
Frontend/Components/MainLayout.razor.css
Normal file
@@ -0,0 +1,11 @@
|
||||
.title-text {
|
||||
font-size: 2rem;
|
||||
color: white;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.subtitle-text {
|
||||
font-size: 0.8rem;
|
||||
color: grey;
|
||||
margin: 0;
|
||||
}
|
60
Frontend/Components/MessageBubble.razor
Normal file
60
Frontend/Components/MessageBubble.razor
Normal file
@@ -0,0 +1,60 @@
|
||||
@using Frontend.Models
|
||||
|
||||
<div>
|
||||
@if (Message.Left)
|
||||
{
|
||||
<Space Align="start">
|
||||
<SpaceItem>
|
||||
<Avatar Style="background-color: #5d92e4" Size="2.5rem">
|
||||
@Message.Sender.First()
|
||||
</Avatar>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<p style="font-size: 0.8rem; color: rgb(128,128,128)">
|
||||
@Message.Sender
|
||||
</p>
|
||||
<div class="bubble-left">
|
||||
<p class="message-text">
|
||||
@Message.Text
|
||||
</p>
|
||||
</div>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Space Align="start">
|
||||
<SpaceItem>
|
||||
<div>
|
||||
<p style="font-size: 0.8rem; color: rgb(128, 128, 128); text-align: right;">
|
||||
@Message.Sender
|
||||
</p>
|
||||
<div class="bubble-right">
|
||||
<p class="message-text">
|
||||
@Message.Text
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<Avatar Style="background-color: #5d92e4" Size="2.5rem">
|
||||
@Message.Sender.First()
|
||||
</Avatar>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
[Parameter]
|
||||
public ChatMessage Message { get; set; } = new()
|
||||
{
|
||||
Left = true,
|
||||
Sender = "default",
|
||||
Text = "default"
|
||||
};
|
||||
|
||||
}
|
24
Frontend/Components/MessageBubble.razor.css
Normal file
24
Frontend/Components/MessageBubble.razor.css
Normal file
@@ -0,0 +1,24 @@
|
||||
.bubble-left {
|
||||
background-color: white;
|
||||
border-radius: 1px 10px 10px 10px;
|
||||
padding: 5px;
|
||||
min-width: 80px;
|
||||
max-width: 300px;
|
||||
width: fit-content;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.bubble-right {
|
||||
background-color: white;
|
||||
border-radius: 10px 1px 10px 10px;
|
||||
padding: 5px;
|
||||
max-width: 300px;
|
||||
width: fit-content;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.message-text {
|
||||
font-size: 1.1rem;
|
||||
margin: 3px;
|
||||
word-break: break-word;
|
||||
}
|
138
Frontend/Components/Pages/Editor.razor
Normal file
138
Frontend/Components/Pages/Editor.razor
Normal file
@@ -0,0 +1,138 @@
|
||||
@page "/editor"
|
||||
@using Katheryne.Exceptions
|
||||
@using Katheryne.Abstractions
|
||||
@using Frontend.Services
|
||||
@inject NavigationManager Navigation
|
||||
@inject IChatRobotFactory RobotFactory
|
||||
@inject GrammarStorageService GrammarStorage
|
||||
|
||||
<Layout>
|
||||
<Content>
|
||||
<div class="editor-zone">
|
||||
<div class="control-zone">
|
||||
<Space Size="@("0")">
|
||||
<SpaceItem>
|
||||
<Tooltip Placement="@Placement.Bottom"
|
||||
Title="退出语法编辑器">
|
||||
<Button Type="@ButtonType.Text" OnClick="@QuitButtonClicked">
|
||||
退出
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<Tooltip Placement="@Placement.Bottom"
|
||||
Title="编译文法并保存在浏览器缓存中">
|
||||
<Button Type="@ButtonType.Text" @onclick="@CompileGrammarClicked">
|
||||
编译
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<Tooltip Placement="@Placement.Bottom"
|
||||
Title="清除浏览器缓存中的文法">
|
||||
<Button Type="@ButtonType.Text" @onclick="@ClearGrammarClicked">
|
||||
清除
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</SpaceItem>
|
||||
|
||||
<SpaceItem>
|
||||
<Button Type="@ButtonType.Text" @onclick="HelpButtonClicked">
|
||||
帮助
|
||||
</Button>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<StandaloneCodeEditor Id="code-editor" @ref="@_editor"
|
||||
ConstructionOptions="GetEditorConstructionOptions"/>
|
||||
|
||||
<div class="logging-zone">
|
||||
<AntList TItem="@string" DataSource="@_logs" Split="@false" @ref="@_logList">
|
||||
<ListItem Style="padding: 0 0 0">
|
||||
<p class="logging-item">@context</p>
|
||||
</ListItem>
|
||||
</AntList>
|
||||
</div>
|
||||
</div>
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
<GrammarHelp @ref="@_grammarHelp"/>
|
||||
|
||||
@code {
|
||||
private StandaloneCodeEditor _editor = null!;
|
||||
private AntList<string> _logList = null!;
|
||||
private GrammarHelp _grammarHelp = null!;
|
||||
|
||||
private readonly List<string> _logs = new();
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
Log("编辑器加载完成");
|
||||
if (await GrammarStorage.RestoreGrammar())
|
||||
{
|
||||
await _editor.SetValue(RobotFactory.GrammarText);
|
||||
Log("从浏览器中恢复成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("尚未设置语法");
|
||||
}
|
||||
}
|
||||
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
|
||||
private StandaloneEditorConstructionOptions GetEditorConstructionOptions(StandaloneCodeEditor editor)
|
||||
{
|
||||
return new StandaloneEditorConstructionOptions
|
||||
{
|
||||
Language = "yaml",
|
||||
Value = !string.IsNullOrEmpty(RobotFactory.GrammarText) ? RobotFactory.GrammarText : string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
private async Task CompileGrammarClicked()
|
||||
{
|
||||
string grammarText = await _editor.GetValue();
|
||||
|
||||
try
|
||||
{
|
||||
Log("编译文法...");
|
||||
RobotFactory.SetGrammar(grammarText);
|
||||
Log("编译成功!");
|
||||
await GrammarStorage.StoreGrammar();
|
||||
}
|
||||
catch (GrammarException e)
|
||||
{
|
||||
Log($"编译文法遇到错误:{e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void QuitButtonClicked()
|
||||
{
|
||||
Navigation.NavigateTo("/", replace: true);
|
||||
}
|
||||
|
||||
private async Task ClearGrammarClicked()
|
||||
{
|
||||
await GrammarStorage.RemoveGrammar();
|
||||
Log("清除浏览器中的语法成功");
|
||||
}
|
||||
|
||||
private void HelpButtonClicked()
|
||||
{
|
||||
_grammarHelp.Show();
|
||||
}
|
||||
|
||||
private void Log(string message)
|
||||
{
|
||||
_logs.Add($"{DateTime.Now:HH:mm:ss} {message}");
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
17
Frontend/Components/Pages/Editor.razor.css
Normal file
17
Frontend/Components/Pages/Editor.razor.css
Normal file
@@ -0,0 +1,17 @@
|
||||
.editor-zone {
|
||||
height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
.control-zone {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.logging-zone {
|
||||
height: 15%;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.logging-item {
|
||||
margin: 0 0 0;
|
||||
}
|
119
Frontend/Components/Pages/Index.razor
Normal file
119
Frontend/Components/Pages/Index.razor
Normal file
@@ -0,0 +1,119 @@
|
||||
@page "/"
|
||||
@using Frontend.Models
|
||||
@using Frontend.Services
|
||||
@using Katheryne
|
||||
@using Katheryne.Abstractions
|
||||
@inject IChatRobotFactory ChatRobotFactory
|
||||
@inject GrammarStorageService GrammarStorage
|
||||
@inject DefaultChatRobot DefaultRobot
|
||||
|
||||
|
||||
<Layout>
|
||||
<Sider Width="200">
|
||||
<div class="chat-control-zone">
|
||||
<div>
|
||||
<Button Type="@ButtonType.Primary" Size="large" @onclick="@CreateChatClicked">
|
||||
新建对话
|
||||
</Button>
|
||||
|
||||
<div class="chat-list">
|
||||
<AntList TItem="@Chat" DataSource="@_chatDictionary.Values"
|
||||
Split="@false">
|
||||
<ListItem OnClick="@(() => ChangeChatClicked(context.Guid))">
|
||||
<ListItemMeta>
|
||||
<TitleTemplate>
|
||||
@if (context.Selected)
|
||||
{
|
||||
<div class="selected-chat-name">
|
||||
<p style="margin: 5px">@context.Title</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="chat-name">
|
||||
<p style="margin: 5px">@context.Title</p>
|
||||
</div>
|
||||
}
|
||||
</TitleTemplate>
|
||||
</ListItemMeta>
|
||||
</ListItem>
|
||||
</AntList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Sider>
|
||||
|
||||
<Content>
|
||||
<ChatZone Messages="@GetChatMessages()" Robot="@GetChatRobot()"/>
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
@code {
|
||||
private readonly Dictionary<Guid, Chat> _chatDictionary = new();
|
||||
|
||||
private Guid _currentGuid;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await GrammarStorage.RestoreGrammar();
|
||||
|
||||
Chat chat = GetInitChat();
|
||||
_chatDictionary.Add(chat.Guid, chat);
|
||||
_currentGuid = chat.Guid;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private void CreateChatClicked()
|
||||
{
|
||||
Chat chat = GetInitChat();
|
||||
|
||||
_chatDictionary.Add(chat.Guid, chat);
|
||||
_chatDictionary[_currentGuid].Selected = false;
|
||||
_currentGuid = chat.Guid;
|
||||
_chatDictionary[_currentGuid].Selected = true;
|
||||
}
|
||||
|
||||
private void ChangeChatClicked(Guid guid)
|
||||
{
|
||||
_chatDictionary[_currentGuid].Selected = false;
|
||||
_currentGuid = guid;
|
||||
_chatDictionary[_currentGuid].Selected = true;
|
||||
}
|
||||
|
||||
private Chat GetInitChat()
|
||||
{
|
||||
var chat = new Chat
|
||||
{
|
||||
Title = $"对话:{_chatDictionary.Count + 1}",
|
||||
Robot = ChatRobotFactory.GetRobot()
|
||||
};
|
||||
|
||||
foreach (string answer in chat.Robot.OnChatStart())
|
||||
{
|
||||
chat.Messages.Add(new ChatMessage
|
||||
{
|
||||
Sender = chat.Robot.RobotName,
|
||||
Left = true,
|
||||
Text = answer
|
||||
});
|
||||
}
|
||||
chat.Selected = true;
|
||||
|
||||
return chat;
|
||||
}
|
||||
|
||||
private List<ChatMessage> GetChatMessages()
|
||||
{
|
||||
return _chatDictionary.TryGetValue(_currentGuid, out Chat? chat) ? chat.Messages : new List<ChatMessage>();
|
||||
}
|
||||
|
||||
private IChatRobot GetChatRobot()
|
||||
{
|
||||
return _chatDictionary.TryGetValue(_currentGuid, out Chat? chat) ? chat.Robot : DefaultRobot;
|
||||
}
|
||||
}
|
28
Frontend/Components/Pages/Index.razor.css
Normal file
28
Frontend/Components/Pages/Index.razor.css
Normal file
@@ -0,0 +1,28 @@
|
||||
.chat-control-zone {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.selected-chat-name {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 5px 5px 5px;
|
||||
padding: 5px 0 5px;
|
||||
border-radius: 5px;
|
||||
background-color: #bcc9e2;
|
||||
}
|
||||
|
||||
.chat-name {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 5px 5px 5px;
|
||||
padding: 5px 0 5px;
|
||||
border-radius: 5px;
|
||||
background-color: #5d92e4;
|
||||
}
|
||||
|
||||
.chat-list {
|
||||
overflow-y: auto;
|
||||
margin-top: 40px;
|
||||
}
|
12
Frontend/Components/Routes.razor
Normal file
12
Frontend/Components/Routes.razor
Normal file
@@ -0,0 +1,12 @@
|
||||
<Router AppAssembly="@typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
11
Frontend/Components/_Imports.razor
Normal file
11
Frontend/Components/_Imports.razor
Normal file
@@ -0,0 +1,11 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.JSInterop
|
||||
@using AntDesign
|
||||
@using BlazorMonaco
|
||||
@using BlazorMonaco.Editor
|
||||
@using BlazorMonaco.Languages
|
||||
@using Frontend.Components
|
Reference in New Issue
Block a user