2023-03-30 21:52:55 +08:00
|
|
|
|
import QtQuick
|
|
|
|
|
import QtQuick.Layouts
|
|
|
|
|
import QtQuick.Controls
|
|
|
|
|
import FluentUI
|
|
|
|
|
import Controller
|
|
|
|
|
import QtQuick.Dialogs
|
2023-03-17 14:05:27 +08:00
|
|
|
|
|
|
|
|
|
FluWindow {
|
|
|
|
|
|
2023-04-22 18:08:11 +08:00
|
|
|
|
title:"ChatGPT"
|
2023-03-17 14:05:27 +08:00
|
|
|
|
width: 680
|
|
|
|
|
height: 600
|
|
|
|
|
minimumWidth: 500
|
|
|
|
|
minimumHeight: 600
|
|
|
|
|
|
2023-03-20 21:28:12 +08:00
|
|
|
|
onInitArgument:
|
|
|
|
|
(argument)=>{
|
|
|
|
|
scrollview.focus = true
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 14:05:27 +08:00
|
|
|
|
ChatController{
|
|
|
|
|
id:controller
|
|
|
|
|
|
|
|
|
|
onResponseDataChanged: {
|
|
|
|
|
appendMessage(false,responseData)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ListModel{
|
|
|
|
|
id:model_message
|
|
|
|
|
ListElement{
|
|
|
|
|
isMy:false
|
|
|
|
|
text:"欢迎使用ChatGPT"
|
|
|
|
|
}
|
|
|
|
|
ListElement{
|
|
|
|
|
isMy:true
|
|
|
|
|
text:"好的,3Q"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FluAppBar{
|
|
|
|
|
id:appbar
|
|
|
|
|
title:"ChatGPT"
|
2023-03-30 21:52:55 +08:00
|
|
|
|
width:parent.width
|
2023-03-17 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Component{
|
|
|
|
|
id:com_text
|
|
|
|
|
TextEdit {
|
2023-03-18 20:20:59 +08:00
|
|
|
|
id:item_text
|
2023-03-17 17:56:50 +08:00
|
|
|
|
text: message
|
2023-03-17 14:05:27 +08:00
|
|
|
|
wrapMode: Text.WrapAnywhere
|
|
|
|
|
readOnly: true
|
|
|
|
|
selectByMouse: true
|
|
|
|
|
selectByKeyboard: true
|
2023-03-18 20:20:59 +08:00
|
|
|
|
selectedTextColor: Qt.rgba(51,153,255,1)
|
2023-03-17 14:05:27 +08:00
|
|
|
|
color:FluColors.Black
|
|
|
|
|
selectionColor: {
|
2023-03-28 21:37:10 +08:00
|
|
|
|
if(FluTheme.dark){
|
2023-03-17 14:05:27 +08:00
|
|
|
|
return FluTheme.primaryColor.lighter
|
|
|
|
|
}else{
|
|
|
|
|
return FluTheme.primaryColor.dark
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
width: Math.min(list_message.width-200,600,implicitWidth)
|
2023-03-18 20:20:59 +08:00
|
|
|
|
TapHandler{
|
|
|
|
|
acceptedButtons: Qt.RightButton
|
|
|
|
|
onTapped: {
|
|
|
|
|
menu_item.showMenu(item_text.selectedText)
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-17 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FluArea{
|
|
|
|
|
id:layout_content
|
|
|
|
|
anchors{
|
|
|
|
|
top: appbar.bottom
|
|
|
|
|
left: parent.left
|
|
|
|
|
right: parent.right
|
|
|
|
|
bottom: layout_bottom.top
|
|
|
|
|
margins: 10
|
|
|
|
|
}
|
2023-03-28 21:37:10 +08:00
|
|
|
|
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(245/255,245/255,245/255,1)
|
2023-03-17 14:05:27 +08:00
|
|
|
|
ListView{
|
|
|
|
|
id:list_message
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
model:model_message
|
|
|
|
|
clip: true
|
|
|
|
|
ScrollBar.vertical: FluScrollBar {}
|
|
|
|
|
preferredHighlightBegin: 0
|
|
|
|
|
preferredHighlightEnd: 0
|
|
|
|
|
highlightMoveDuration: 0
|
|
|
|
|
header:Item{
|
|
|
|
|
width: list_message.width
|
|
|
|
|
height:20
|
|
|
|
|
}
|
|
|
|
|
footer:Item{
|
|
|
|
|
width: list_message.width
|
|
|
|
|
height:20
|
|
|
|
|
}
|
|
|
|
|
delegate: Item{
|
|
|
|
|
width: ListView.view.width
|
|
|
|
|
height: childrenRect.height
|
|
|
|
|
|
|
|
|
|
FluRectangle{
|
|
|
|
|
id:item_avatar
|
|
|
|
|
width: 30
|
|
|
|
|
height: 30
|
|
|
|
|
radius:[15,15,15,15]
|
|
|
|
|
anchors{
|
|
|
|
|
right: isMy ? parent.right : undefined
|
|
|
|
|
rightMargin: isMy ? 20 : undefined
|
|
|
|
|
left: isMy ? undefined : parent.left
|
|
|
|
|
leftMargin: isMy ? undefined : 20
|
|
|
|
|
top:parent.top
|
|
|
|
|
}
|
|
|
|
|
Image {
|
|
|
|
|
asynchronous: true
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
sourceSize: Qt.size(100,100)
|
2023-04-27 09:38:57 +08:00
|
|
|
|
source: isMy ? "qrc:/example/res/svg/avatar_2.svg" : "qrc:/example/res/image/logo_openai.png"
|
2023-03-17 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle{
|
|
|
|
|
id:item_layout_content
|
|
|
|
|
color: isMy ? "#FF95EC69" : "#FFFFFF"
|
|
|
|
|
width: item_msg_loader.width+10
|
|
|
|
|
height: item_msg_loader.height+10
|
|
|
|
|
radius: 3
|
|
|
|
|
anchors{
|
|
|
|
|
top: item_avatar.top
|
|
|
|
|
right: isMy ? item_avatar.left : undefined
|
|
|
|
|
rightMargin: isMy ? 10 : undefined
|
|
|
|
|
left: isMy ? undefined : item_avatar.right
|
|
|
|
|
leftMargin: isMy ? undefined : 10
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Loader{
|
|
|
|
|
id:item_msg_loader
|
2023-03-17 17:56:50 +08:00
|
|
|
|
property var message: model.text
|
2023-03-17 14:05:27 +08:00
|
|
|
|
anchors.centerIn: parent
|
|
|
|
|
sourceComponent: com_text
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Item{
|
|
|
|
|
id:item_layout_bottom
|
|
|
|
|
width: parent.width
|
|
|
|
|
anchors.top: item_layout_content.bottom
|
|
|
|
|
height: 20
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FluArea{
|
|
|
|
|
id:layout_bottom
|
|
|
|
|
height: 90
|
|
|
|
|
anchors{
|
|
|
|
|
bottom: parent.bottom
|
|
|
|
|
bottomMargin: 10
|
|
|
|
|
left: parent.left
|
|
|
|
|
right: parent.right
|
|
|
|
|
leftMargin: 10
|
|
|
|
|
rightMargin: 10
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ScrollView{
|
2023-03-20 21:28:12 +08:00
|
|
|
|
id:scrollview
|
2023-03-17 14:05:27 +08:00
|
|
|
|
anchors{
|
|
|
|
|
bottom: parent.bottom
|
|
|
|
|
left: parent.left
|
|
|
|
|
right: button_send.left
|
|
|
|
|
bottomMargin: 10
|
|
|
|
|
leftMargin: 10
|
|
|
|
|
rightMargin: 10
|
|
|
|
|
}
|
|
|
|
|
height: Math.min(textbox.implicitHeight,64)
|
2023-04-06 00:29:33 +08:00
|
|
|
|
FluMultilineTextBox{
|
2023-03-17 14:05:27 +08:00
|
|
|
|
id:textbox
|
2023-03-20 21:28:12 +08:00
|
|
|
|
focus:true
|
|
|
|
|
placeholderText: "请输入消息"
|
2023-03-17 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FluFilledButton{
|
|
|
|
|
id:button_send
|
|
|
|
|
text:controller.isLoading ? timer_loading.loadingText :"发送"
|
|
|
|
|
anchors{
|
|
|
|
|
bottom: parent.bottom
|
|
|
|
|
right: parent.right
|
|
|
|
|
bottomMargin: 10
|
|
|
|
|
rightMargin: 10
|
|
|
|
|
}
|
|
|
|
|
width: 60
|
|
|
|
|
disabled: controller.isLoading
|
|
|
|
|
onClicked:{
|
|
|
|
|
var text = textbox.text
|
|
|
|
|
appendMessage(true,text)
|
|
|
|
|
controller.sendMessage(text)
|
|
|
|
|
textbox.clear()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timer{
|
|
|
|
|
id:timer_loading
|
|
|
|
|
property int count : 0
|
|
|
|
|
property string loadingText : ""
|
|
|
|
|
interval: 500
|
|
|
|
|
running: controller.isLoading
|
|
|
|
|
repeat: true
|
|
|
|
|
onTriggered: {
|
|
|
|
|
switch(count%3){
|
|
|
|
|
case 0:
|
|
|
|
|
loadingText = "."
|
|
|
|
|
break
|
|
|
|
|
case 1:
|
|
|
|
|
loadingText = ".."
|
|
|
|
|
break
|
|
|
|
|
case 2:
|
|
|
|
|
loadingText = "..."
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
loadingText = ""
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
count++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-18 20:20:59 +08:00
|
|
|
|
FluMenu{
|
|
|
|
|
id:menu_item
|
|
|
|
|
focus: false
|
|
|
|
|
property string selectedText: ""
|
|
|
|
|
FluMenuItem{
|
|
|
|
|
text:"复制"
|
|
|
|
|
onClicked: {
|
|
|
|
|
controller.clipText(menu_item.selectedText)
|
|
|
|
|
showSuccess("复制成功")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function showMenu(text){
|
|
|
|
|
menu_item.selectedText = text
|
|
|
|
|
menu_item.popup()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 14:05:27 +08:00
|
|
|
|
function appendMessage(isMy,text){
|
|
|
|
|
model_message.append({isMy:isMy,text:text})
|
|
|
|
|
list_message.positionViewAtEnd()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|