Bez popisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

editor.component.html 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <div class="editor-container">
  2. <!-- 顶部工具栏 -->
  3. <mat-toolbar color="primary" class="editor-toolbar">
  4. <button mat-icon-button (click)="goBack()" aria-label="返回">
  5. <mat-icon>arrow_back</mat-icon>
  6. </button>
  7. <span class="toolbar-title">
  8. @if (project) {
  9. {{ project.title }}
  10. <span class="project-subtitle">{{ project.agent_name }}</span>
  11. } @else {
  12. 项目编辑器
  13. }
  14. </span>
  15. <span class="spacer"></span>
  16. <!-- SSE连接状态 -->
  17. <span class="sse-status" [class.connected]="sseConnected" [class.disconnected]="!sseConnected">
  18. <mat-icon>{{ sseConnected ? 'wifi' : 'wifi_off' }}</mat-icon>
  19. <span class="sse-text">{{ sseConnected ? '已连接' : '已断开' }}</span>
  20. </span>
  21. @if (isLoading) {
  22. <mat-spinner diameter="24" class="toolbar-spinner"></mat-spinner>
  23. }
  24. </mat-toolbar>
  25. <!-- 错误提示 -->
  26. @if (showError) {
  27. <div class="error-banner">
  28. <mat-icon class="error-icon">warning</mat-icon>
  29. <div class="error-content">
  30. <div class="error-title">{{ errorTitle }}</div>
  31. <div class="error-message">{{ errorMessage }}</div>
  32. </div>
  33. </div>
  34. }
  35. <!-- 主内容区域 -->
  36. <div class="editor-content">
  37. @if (!project) {
  38. <div class="loading-state">
  39. @if (isLoading) {
  40. <mat-spinner diameter="40"></mat-spinner>
  41. <p>加载项目中...</p>
  42. } @else {
  43. <div class="error-state">
  44. <mat-icon class="error-icon">error_outline</mat-icon>
  45. <h3>项目不存在或无法加载</h3>
  46. <button mat-raised-button color="primary" (click)="goBack()">返回首页</button>
  47. </div>
  48. }
  49. </div>
  50. } @else {
  51. <!-- 消息容器 -->
  52. <div class="messages-container" #messagesContainer>
  53. @for (message of messages; track message.id) {
  54. <app-chat-message [message]="message"></app-chat-message>
  55. }
  56. @if (messages.length === 0) {
  57. <div class="empty-messages">
  58. <mat-icon class="empty-icon">chat</mat-icon>
  59. <h3>开始对话</h3>
  60. <p>发送消息开始与AI助手对话</p>
  61. </div>
  62. }
  63. </div>
  64. <!-- 输入区域 -->
  65. <div class="input-container">
  66. <mat-form-field appearance="outline" class="message-input">
  67. <mat-label>输入消息...</mat-label>
  68. <textarea
  69. matInput
  70. #messageInput
  71. [(ngModel)]="userInput"
  72. (keydown)="onSendMessage($event)"
  73. [disabled]="isSending"
  74. rows="2"
  75. placeholder="输入消息,按Enter发送,Shift+Enter换行"
  76. ></textarea>
  77. <button
  78. mat-icon-button
  79. matSuffix
  80. (click)="sendMessage()"
  81. [disabled]="!userInput.trim() || isSending"
  82. aria-label="发送消息"
  83. >
  84. @if (isSending) {
  85. <mat-spinner diameter="20"></mat-spinner>
  86. } @else {
  87. <mat-icon>send</mat-icon>
  88. }
  89. </button>
  90. </mat-form-field>
  91. </div>
  92. }
  93. </div>
  94. </div>