diff options
author | kaixiliu <liukaixi@chinamobile.com> | 2025-01-17 17:01:17 +0800 |
---|---|---|
committer | kaixiliu <liukaixi@chinamobile.com> | 2025-01-20 11:35:33 +0800 |
commit | 6f8694edd30c021bea991ce5a7adf85359f9a6d8 (patch) | |
tree | 6ee41c9ab98a413771dd7729dce97e14137f5ece | |
parent | d67b4b25e73bba60cc72a5c1c68e178d9ad93b3c (diff) |
Optimize your code and the Q&A assistant page has a shortcut to send questions.15.0.1
Issue-ID: USECASEUI-844
Change-Id: I652edab1945e3c2366fea388d6e3d8e5360d2922
Signed-off-by: kaixiliu <liukaixi@chinamobile.com>
8 files changed, 81 insertions, 33 deletions
diff --git a/usecaseui-portal/src/app/views/maas/use/code-block.directive.ts b/usecaseui-portal/src/app/views/maas/use/code-block.directive.ts index 31247184..08efe92c 100644 --- a/usecaseui-portal/src/app/views/maas/use/code-block.directive.ts +++ b/usecaseui-portal/src/app/views/maas/use/code-block.directive.ts @@ -1,4 +1,4 @@ -import { AfterViewChecked, AfterViewInit, Directive, ElementRef, Renderer2 } from '@angular/core'; +import { Directive, ElementRef, Renderer2, Input } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { NzMessageService } from 'ng-zorro-antd'; import { ClipboardService } from 'ngx-clipboard'; @@ -6,33 +6,36 @@ import { ClipboardService } from 'ngx-clipboard'; @Directive({ selector: '[appCodeBlock]' }) -export class CodeBlockDirective implements AfterViewChecked { +export class CodeBlockDirective { + @Input() set appCodeBlock(status: string) { + if (status === 'finished') { + setTimeout(() => { + this.setCopyButton(); + }, 0); + + } + } constructor(private el: ElementRef, private renderer: Renderer2, private clipboardService: ClipboardService, private message: NzMessageService, private translate: TranslateService ) { } - ngAfterViewChecked() { - this.setCopyButton(); - } - -setCopyButton() { - const preElements = this.el.nativeElement.querySelectorAll('pre'); - - preElements.forEach(pre => { - const codeElement = pre.querySelector('code'); - const copyButtonExists = pre.querySelector('button.copy-button'); - if (codeElement && !copyButtonExists) { - const copyButton = this.renderer.createElement('button'); - this.renderer.addClass(copyButton, 'copy-button'); - this.renderer.setProperty(copyButton, 'innerHTML', 'Copy'); - this.renderer.listen(copyButton, 'click', () => { - this.clipboardService.copyFromContent(codeElement.innerText); - this.message.success(this.translate.instant('maas.copy_to_clipboard')); - }); - this.renderer.insertBefore(pre, copyButton, codeElement); - } - }); -} + setCopyButton() { + const preElements = this.el.nativeElement.querySelectorAll('pre'); + preElements.forEach(pre => { + const codeElement = pre.querySelector('code'); + const copyButtonExists = pre.querySelector('button.copy-button'); + if (codeElement && !copyButtonExists) { + const copyButton = this.renderer.createElement('button'); + this.renderer.addClass(copyButton, 'copy-button'); + this.renderer.setProperty(copyButton, 'innerHTML', 'Copy'); + this.renderer.listen(copyButton, 'click', () => { + this.clipboardService.copyFromContent(codeElement.innerText); + this.message.success(this.translate.instant('maas.copy_to_clipboard')); + }); + this.renderer.insertBefore(pre, copyButton, codeElement); + } + }); + } } diff --git a/usecaseui-portal/src/app/views/maas/use/use-application.component.html b/usecaseui-portal/src/app/views/maas/use/use-application.component.html index 6509fbbe..25c39f7b 100644 --- a/usecaseui-portal/src/app/views/maas/use/use-application.component.html +++ b/usecaseui-portal/src/app/views/maas/use/use-application.component.html @@ -45,7 +45,7 @@ [nz-tooltip]="'maas.copy' | translate"></span> </div> <span class="answer-text"> - <markdown appCodeBlock class="markdown answer-markdown" [ngClass]="{'hidden-cursor': chat.status==='finished'}" *ngIf="chat.answer else default" [data]="chat.answer"></markdown> + <markdown appCodeBlock="{{chat.status}}" class="markdown answer-markdown" [ngClass]="{'hidden-cursor': chat.status==='finished'}" *ngIf="chat.answer else default" [data]="chat.answer"></markdown> <ng-template #default> <span class="answer default" [ngClass]="{'hidden-cursor': chat.status==='finished'}" #answerText> </span> @@ -57,7 +57,7 @@ </div> <div class="input-wrapper"> - <textarea nzAutosize nz-input [(ngModel)]="question" class="text-input question-input"></textarea> + <textarea #questionInput nzAutosize nz-input [(ngModel)]="question" class="text-input question-input" placeholder="{{'maas.questionPlaceholder' | translate}}" nzSize="small"></textarea> <div class="send-wrapper" [ngClass]="{'stop-wrapper': isGeneratingAnswer}"> <div class="icon" (click)="doAction()" [ngClass]="{'send-disabled': !isGeneratingAnswer &&!question, 'send-enabled': question && !isGeneratingAnswer, 'stop-generating': isGeneratingAnswer}" diff --git a/usecaseui-portal/src/app/views/maas/use/use-application.component.less b/usecaseui-portal/src/app/views/maas/use/use-application.component.less index bb2e0d12..d57a6900 100644 --- a/usecaseui-portal/src/app/views/maas/use/use-application.component.less +++ b/usecaseui-portal/src/app/views/maas/use/use-application.component.less @@ -105,6 +105,7 @@ } .answer-text { + max-width: 100%; margin: 8px 0; background-color: white; display: inline-block; diff --git a/usecaseui-portal/src/app/views/maas/use/use-application.component.ts b/usecaseui-portal/src/app/views/maas/use/use-application.component.ts index b02a2d60..f0ce4f7e 100644 --- a/usecaseui-portal/src/app/views/maas/use/use-application.component.ts +++ b/usecaseui-portal/src/app/views/maas/use/use-application.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, OnInit, Renderer2, ViewChild } from '@angular/core'; +import { Component, ElementRef, OnInit, Renderer2, ViewChild, OnDestroy } from '@angular/core'; import { NzMessageService } from 'ng-zorro-antd'; import { SSE } from "sse.js"; import { ActivatedRoute } from '@angular/router'; @@ -12,7 +12,7 @@ export type Chat = { question: string, answer: string, questionId: string, statu templateUrl: './use-application.component.html', styleUrls: ['./use-application.component.less'] }) -export class UseApplicationComponent implements OnInit { +export class UseApplicationComponent implements OnInit, OnDestroy { question: string; communicationMessage: string; chatHistory: Chat[] = []; @@ -25,12 +25,16 @@ export class UseApplicationComponent implements OnInit { isGeneratingAnswer: boolean = false; stopGenerating = this.translate.instant('maas.stopGenerating'); questionId = ''; + @ViewChild('questionInput') questionInput: ElementRef; + private keydownListener: () => void; + perHight = 21; constructor( private message: NzMessageService, private route: ActivatedRoute, private myhttp: MaasApi, private translate: TranslateService, - private maasService: MaasService + private maasService: MaasService, + private renderer: Renderer2 ) { } async ngOnInit() { @@ -39,8 +43,15 @@ export class UseApplicationComponent implements OnInit { this.queryParams = params; this.selectedName = this.queryParams.id || this.selectedName; }); + this.keydownListener = this.renderer.listen(this.questionInput.nativeElement, 'keydown', this.handleKeyDown.bind(this)); } + ngOnDestroy() { + if (this.keydownListener) { + this.keydownListener(); + } + } + close() { if (this.currentSSE) { this.currentSSE.close(); @@ -125,4 +136,29 @@ export class UseApplicationComponent implements OnInit { deleteQuestion(questionId: string): void { this.chatHistory = this.chatHistory.filter(item => item.questionId !== questionId); } + + handleKeyDown(event: KeyboardEvent) { + if (event.key === 'Enter') { + if (event.shiftKey || event.ctrlKey || event.altKey) { + const TextareaDom = this.questionInput.nativeElement; + const height = parseInt(TextareaDom.style.height.split('px')[0], 10) + this.perHight; + TextareaDom.style.height = `${height}px`; + if(event.ctrlKey || event.altKey) { + const index = TextareaDom.selectionStart; + const val = TextareaDom.value; + TextareaDom.value = `${val.slice(0, index)}\n${val.slice(index)}`; + TextareaDom.selectionStart = index + 1; + TextareaDom.selectionEnd = index + 1; + } + } else { + event.preventDefault(); + if (this.isGeneratingAnswer) { + this.message.warning(this.translate.instant('maas.is_chatting')); + } else { + this.doAction(); + } + + } + } + } } diff --git a/usecaseui-portal/src/assets/i18n/cn.json b/usecaseui-portal/src/assets/i18n/cn.json index 883439bd..2c5567a3 100644 --- a/usecaseui-portal/src/assets/i18n/cn.json +++ b/usecaseui-portal/src/assets/i18n/cn.json @@ -199,6 +199,8 @@ "application": { "deleteApplicationContent": "确认删除该应用?删除后数据无法恢复,请确认!", "promptTip": "提示词需要大于20个字符" - } + }, + "questionPlaceholder": "输入问题,发送 [Enter]/换行 [Ctrl(Alt/Shift) + Enter]", + "is_chatting": "正在聊天中...请等待结束" } }
\ No newline at end of file diff --git a/usecaseui-portal/src/assets/i18n/cn_maas.json b/usecaseui-portal/src/assets/i18n/cn_maas.json index a6fcab57..7aa4981a 100644 --- a/usecaseui-portal/src/assets/i18n/cn_maas.json +++ b/usecaseui-portal/src/assets/i18n/cn_maas.json @@ -17,7 +17,9 @@ "application": { "deleteApplicationContent": "确认删除该应用?删除后数据无法恢复,请确认!", "promptTip": "提示词需要大于20个字符" - } + }, + "questionPlaceholder" : "输入问题,发送 [Enter]/换行 [Ctrl(Alt/Shift) + Enter]", + "is_chatting": "正在聊天中...请等待结束" } }
\ No newline at end of file diff --git a/usecaseui-portal/src/assets/i18n/en.json b/usecaseui-portal/src/assets/i18n/en.json index f68588fc..7e2f55ab 100644 --- a/usecaseui-portal/src/assets/i18n/en.json +++ b/usecaseui-portal/src/assets/i18n/en.json @@ -199,6 +199,8 @@ "application": { "deleteApplicationContent": "Confirm deletion of this application? Data cannot be recovered after deletion, please confirm!", "promptTip": "The prompt needs to be larger than 20 characters." - } + }, + "questionPlaceholder": "Enter a Question, Press [Enter] to Send / Press [Ctrl(Alt/Shift) + Enter] for New Line", + "is_chatting": "Chatting in progress... please wait until it finishes" } }
\ No newline at end of file diff --git a/usecaseui-portal/src/assets/i18n/en_maas.json b/usecaseui-portal/src/assets/i18n/en_maas.json index a53c56be..ed85771c 100644 --- a/usecaseui-portal/src/assets/i18n/en_maas.json +++ b/usecaseui-portal/src/assets/i18n/en_maas.json @@ -17,6 +17,8 @@ "application": { "deleteApplicationContent": "Confirm deletion of this application? Data cannot be recovered after deletion, please confirm!", "promptTip": "The prompt needs to be larger than 20 characters." - } + }, + "questionPlaceholder" : "Enter a Question, Press [Enter] to Send / Press [Ctrl(Alt/Shift) + Enter] for New Line", + "is_chatting": "Chatting in progress... please wait until it finishes" } }
\ No newline at end of file |