Package | Mục đích |
---|---|
Syncfusion.Blazor.Diagram | Thư viện tạo sơ đồ tương tác |
Syncfusion.Blazor.Themes | Giao diện theme cho component |
Program.cs
, thêm đoạn cấu hình sau để đăng ký Syncfusion Blazor Service:builder.Services.AddSyncfusionBlazor();
builder.Services.AddRazorPages();builder.Services.AddServerSideBlazor();
public class DiagramOpenAIService{ private readonly HttpClient _httpClient; private readonly string _apiKey; private readonly string _deploymentName;
public DiagramOpenAIService(HttpClient httpClient, string apiKey, string deploymentName) { _httpClient = httpClient; _apiKey = apiKey; _deploymentName = deploymentName; }
// Các phương thức xử lý API sẽ ở bước sau.}
Program.cs
, đăng ký dịch vụ này cùng với các cấu hình cho API key, endpoint và deployment:string apiKey = "your-api-key";string deploymentName = "your-deployment-name";string endpoint = "your-endpoint-url";
builder.Services.AddTransient<DiagramOpenAIService>(service =>{ var httpClient = new HttpClient { BaseAddress = new Uri(endpoint) }; return new DiagramOpenAIService(httpClient, apiKey, deploymentName);});
Lưu ý:
App.razor
hoặc trang chính:<head> <link href="_content/Syncfusion.Blazor.Themes/tailwind.css" rel="stylesheet" /></head><body> <script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script></body>
Index.razor
, khai báo và cấu hình component diagram:@using Syncfusion.Blazor.Diagram
<SfDiagramComponent @ref="Diagram" Width="100%" Height="700px" @bind-Nodes="nodes" @bind-Connectors="connectors" ScrollChanged="ScrollChanged" CollectionChanging="CollectionChanging"> <Layout Type="LayoutType.MindMap" HorizontalSpacing="@HorizontalSpacing" VerticalSpacing="@VerticalSpacing"></Layout> <ScrollSettings ScrollLimit="@scrollLimit" CurrentZoom="@CurrentZoom" MaxZoom="@maxZoom" MinZoom="@minZoom"/> <SnapSettings Constraints="@SnapConstraint"></SnapSettings> <PageSettings MultiplePage="true"></PageSettings> <CommandManager Commands="@commands" Execute="@ExecuteCommand" CanExecute="@CanExecute"></CommandManager></SfDiagramComponent>
Chú ý: Thư viện hỗ trợ nhiều sự kiện và tính năng như kéo thả, undo/redo, phóng to thu nhỏ,… giúp sơ đồ linh hoạt và thân thiện người dùng.
SfDialog
, SfButton
và SfTextBox
tạo hộp thoại nhập prompt và gợi ý có sẵn:<SfFab IconCss="e-icons e-ai-chat" Content="AI Assist" OnClick="OnFabClicked"></SfFab>
<SfDialog Width="570px" IsModal="true" ShowCloseIcon="true" CssClass="custom-dialog" Visible="@ShowAIAssistDialog"> <DialogTemplates> <Header><span class="e-icons e-ai-chat"></span> AI Assist</Header> <Content> <p>Suggested Prompts</p> <SfButton @onclick="() => GenerateMindMap(MobileBankingPrompt)">Mindmap diagram for Mobile banking registration</SfButton> <SfButton @onclick="() => GenerateMindMap(OrganizationalResearchPrompt)">Mindmap diagram for Organizational research</SfButton> <SfButton @onclick="() => GenerateMindMap(MeetingAgendaPrompt)">Mindmap diagram for Meeting agenda</SfButton>
<div style="display: flex; margin-top:20px;"> <SfTextBox @bind-Value="OpenAIPrompt" Placeholder="Enter your prompt..."></SfTextBox> <SfButton @onclick="GenerateTextToMindmap" IsPrimary="true" CssClass="e-icons e-send"></SfButton> </div> </Content> </DialogTemplates> <DialogEvents Closed="DialogClose"></DialogEvents></SfDialog>
@code
:public bool ShowAIAssistDialog { get; set; } = false;public string OpenAIPrompt { get; set; }
public void OnFabClicked(){ ShowAIAssistDialog = !ShowAIAssistDialog;}
public void DialogClose(object args){ ShowAIAssistDialog = false;}
public async void GenerateMindMap(string value){ OpenAIPrompt = value; await GenerateTextToMindmap();}
public async Task GenerateTextToMindmap(){ ShowAIAssistDialog = false; await ChatGptService.ConvertTextToMindMap(OpenAIPrompt, Diagram);}
public async Task ConvertTextToMindMap(string prompt, SfDiagramComponent Diagram){ var requestContent = new { messages = new[] { new { role = "system", content = "You are an expert in creating mind map diagram data sources. Generate a structured data source for a mind map based on the user's query, using tab indentation to indicate hierarchy. The root parent should have no indentation, while each subsequent child level should be indented by one tab space. Avoid using any symbols such as '+' or '-' before any level of data." }, new { role = "user", content = $"Generate the mindmap diagram data source for the following prompt: {prompt}." } }, max_tokens = 500, temperature = 0.9 };
var requestBody = new StringContent(JsonSerializer.Serialize(requestContent), Encoding.UTF8, "application/json");
var requestMessage = new HttpRequestMessage(HttpMethod.Post, $"openai/deployments/{_deploymentName}/chat/completions?api-version=2023-05-15") { Content = requestBody };
requestMessage.Headers.Add("api-key", _apiKey);
var response = await _httpClient.SendAsync(requestMessage); response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync(); var jsonResponse = JsonDocument.Parse(responseContent); var mermaidData = jsonResponse.RootElement.GetProperty("choices")[0].GetProperty("message").GetProperty("content").GetString();
await Diagram.LoadDiagramFromMermaidAsync(mermaidData);}