+

+
+ {{ item.content }}
+
+
+ 哎呀,出问题了...
+
+
+
+ 停止回答
+
+
+
+
+ 复制
-
-
- 复制
-
-
- 重新回答
-
+
+
+ 重新回答
@@ -56,80 +140,77 @@ onMounted(async () => {
@include app('message') {
height: calc(100% - 120px);
overflow: auto;
-
- .content-wrap {
- box-sizing: border-box;
- transform: rotate(180deg);
- .item {
- padding: 0 15px;
- margin-top: 15px;
- transform: rotate(180deg);
- .user,
- .ai {
- display: flex;
+ box-sizing: border-box;
+ .item {
+ padding: 0 15px;
+ margin-top: 15px;
+ .user,
+ .ai {
+ display: flex;
+ }
+ .user {
+ justify-content: flex-end;
+ .content {
+ max-width: calc(100% - 110px);
+ color: #ffffff;
+ padding: 10px 15px;
+ background: linear-gradient(131deg, #009bfc 0%, #00eadb 100%);
+ border-radius: 15px 15px 0px 15px;
}
- .user {
- justify-content: flex-end;
- .content {
- color: #ffffff;
- padding: 10px 15px;
- background: linear-gradient(131deg, #009bfc 0%, #00eadb 100%);
- border-radius: 15px 15px 0px 15px;
- }
- .icon-user {
- width: 40px;
- height: 40px;
- margin-left: 15px;
- }
+ .icon-user {
+ width: 40px;
+ height: 40px;
+ margin-left: 15px;
+ }
+ }
+ .ai {
+ position: relative;
+ margin-bottom: 15px;
+ display: flex;
+ flex-wrap: wrap;
+ .icon-ai {
+ width: 40px;
+ height: 40px;
+ margin-right: 15px;
+ }
+ .icon {
+ margin-right: 5px;
+ }
+ .content {
+ width: calc(100% - 110px);
+ padding: 10px 15px;
+ background: #ffffff;
+ border-radius: 0px 15px 15px 15px;
+ border: 1px solid #e7edef;
}
- .ai {
- position: relative;
- margin-bottom: 15px;
+ .error {
+ color: red;
+ height: 30px;
+ padding-left: 60px;
+ margin-top: 10px;
+ }
+ .stop {
+ height: 30px;
+ color: #4670e3;
+ padding-left: 60px;
+ margin-top: 10px;
+ cursor: pointer;
+ }
+ .btns {
+ width: 100%;
+ height: 30px;
+ padding-left: 60px;
+ margin: 10px auto 0 auto;
display: flex;
- flex-wrap: wrap;
- .icon-ai {
- width: 40px;
- height: 40px;
- margin-right: 15px;
- }
- .content {
- width: calc(100% - 55px);
- padding: 10px 15px;
- background: #ffffff;
- border-radius: 0rpx 15px 15px 15px;
- border: 1px solid #e7edef;
- }
- .error {
- color: red;
- height: 30px;
- padding-left: 60px;
- margin: 10px auto 0 auto;
- }
- .loading {
- height: 30px;
- color: #009dfb;
- padding-left: 60px;
- margin: 20rpx auto 0 auto;
+ align-items: center;
+ .copy {
+ color: #4670e3;
+ margin-right: 20px;
+ cursor: pointer;
}
- .btns {
- width: 100%;
- height: 30px;
- padding-left: 60px;
- margin: 10px auto 0 auto;
- display: flex;
- justify-content: space-between;
- align-items: center;
- .copy {
- color: #009dfb;
- padding: 5px 15px;
- background: #c1effb;
- border-radius: 15px;
- text-align: center;
- margin-right: 20px;
- }
- .reload {
- color: #009dfb;
- }
+ .reload {
+ color: #4670e3;
+ cursor: pointer;
}
}
}
diff --git a/src/design/public.scss b/src/design/public.scss
index 805c4f7..d8f0547 100644
--- a/src/design/public.scss
+++ b/src/design/public.scss
@@ -12,19 +12,14 @@
height: 8px;
}
-// ::-webkit-scrollbar-track {
-// background: transparent;
-// }
-
::-webkit-scrollbar-track {
- background-color: rgba($color: #000000, $alpha: 0.1);
+ background-color: rgba($color: #eeeeee, $alpha: 0.6);
}
::-webkit-scrollbar-thumb {
- background-color: rgba($color: #bdc1c94d, $alpha: 0.2);
+ background-color: rgba($color: #cccccc, $alpha: 0.4);
border-radius: 2px;
- box-shadow: inset 0 0 6px rgba($color: #000000, $alpha: 0.2);
- cursor: pointer;
+ // box-shadow: inset 0 0 6px rgba($color: #000000, $alpha: 0.2);
}
::-webkit-scrollbar-thumb:hover {
diff --git a/src/enums/messageEnum.ts b/src/enums/messageEnum.ts
index 6e191d2..7755b53 100644
--- a/src/enums/messageEnum.ts
+++ b/src/enums/messageEnum.ts
@@ -2,7 +2,7 @@
* @description: 消息类型:ai/user
*/
export enum MessageTypeEnum {
- AI = 'ai',
+ AI = 'bot',
USER = 'user',
}
diff --git a/src/hooks/useMqtt.ts b/src/hooks/useMqtt.ts
index c5e8572..7c5742b 100644
--- a/src/hooks/useMqtt.ts
+++ b/src/hooks/useMqtt.ts
@@ -3,6 +3,7 @@ import { MqttService } from '@/utils/mqtt'
import { useUserStore } from '@/store/moules/userStore/index'
import { useMessageStore } from '@/store/moules/messageStore/index'
import { MessageStatusEnum, MessageTypeEnum } from '@/enums/messageEnum'
+import { sendMessage as sendMessageApi } from '@/api/base/message'
export function useMqtt() {
const userStore = useUserStore()
@@ -30,11 +31,9 @@ export function useMqtt() {
.subscribe(topicKey)
.then(() => {
mqttService.onMessage(topicKey, (messageData: any) => {
- console.log(messageData)
-
if (messageData.message_type === MessageStatusEnum.ACTICON) {
messageStore.setMessageStatus(MessageStatusEnum.ACTICON)
- messageStore.setMessageFirstItem({
+ messageStore.setMessageLastItem({
messageType: MessageTypeEnum.AI,
content: messageData.message_content,
time: String(new Date().getTime()),
@@ -44,7 +43,7 @@ export function useMqtt() {
}
if (messageData.message_type === MessageStatusEnum.END) {
messageStore.setMessageStatus(MessageStatusEnum.END)
- messageStore.setMessageFirstItem({
+ messageStore.setMessageLastItem({
messageType: MessageTypeEnum.AI,
content: messageData.message_content,
time: String(new Date().getTime()),
@@ -54,9 +53,6 @@ export function useMqtt() {
}
})
})
- .catch(() => {
- // uni.hideLoading()
- })
}
/**
@@ -79,8 +75,61 @@ export function useMqtt() {
})
}
+ /**
+ * @description: 取消订阅
+ */
+ const unsubscribe = (topicKey: string) => {
+ mqttService.unsubscribe(topicKey)
+ }
+
+ /**
+ * @description: 关闭连接
+ */
+ const end = () => {
+ console.log('123123123123')
+
+ mqttService.end()
+ }
+
+ /**
+ * @description: 发送消息hook
+ */
+ const sendMessage = async (roleId: number, conversationId: string, question: string): Promise
=> {
+ messageStore.setMessageStatus(MessageStatusEnum.LOADING)
+ messageStore.setMessagePushItem({
+ messageType: MessageTypeEnum.USER,
+ content: question,
+ time: String(new Date().getTime()),
+ avatar: '',
+ })
+ messageStore.setMessagePushItem({
+ messageType: MessageTypeEnum.AI,
+ content: '正在思考中...',
+ time: String(new Date().getTime()),
+ avatar: '',
+ messageStatus: MessageStatusEnum.LOADING,
+ })
+ if (!messageStore.getConversationData) {
+ return
+ }
+
+ try {
+ await sendMessageApi({
+ roleId,
+ conversationId,
+ question,
+ })
+ }
+ catch (error: any) {
+ messageStore.setMessageStatus(MessageStatusEnum.END)
+ }
+ }
+
return {
connect,
subscribe,
+ unsubscribe,
+ end,
+ sendMessage,
}
}
diff --git a/src/store/moules/messageStore/index.ts b/src/store/moules/messageStore/index.ts
index 91dcbd1..976cdc6 100644
--- a/src/store/moules/messageStore/index.ts
+++ b/src/store/moules/messageStore/index.ts
@@ -39,10 +39,14 @@ export const useMessageStore = defineStore('useMessageStore', {
this.messageList.push(item)
},
- setMessageFirstItem(item: MessageItem) {
+ setMessageUnshiftItem(item: MessageItem) {
this.messageList.unshift(item)
},
+ setMessageLastItem(item: MessageItem) {
+ this.messageList[this.messageList.length - 1] = item
+ },
+
setTopicKey(key: string) {
this.topicKey = key
},
diff --git a/src/utils/copyTextToClipboard.ts b/src/utils/copyTextToClipboard.ts
new file mode 100644
index 0000000..5c5ddc3
--- /dev/null
+++ b/src/utils/copyTextToClipboard.ts
@@ -0,0 +1,38 @@
+import { message } from 'ant-design-vue'
+
+export function copyText(text: string, prompt: string | null = '已成功复制到剪切板!') {
+ // 浏览器禁用了非安全域的 navigator.clipboard 对象
+ // 在线上环境会报错 TypeError: Cannot read properties of undefined (reading 'writeText')
+ if (navigator.clipboard && window.isSecureContext) {
+ navigator.clipboard.writeText(text).then(
+ () => {
+ prompt && message.success(prompt)
+ },
+ (error: Error) => {
+ message.error(`复制失败!${error.message}`)
+ },
+ )
+ }
+ else {
+ const textarea = document.createElement('textarea')
+ textarea.value = text
+ document.body.appendChild(textarea)
+ textarea.select()
+
+ try {
+ // 尝试执行复制操作
+ const success = document.execCommand('copy')
+ if (success) {
+ message.success('复制成功')
+ }
+ else {
+ message.error('复制失败')
+ }
+ }
+ catch (error) {
+ message.error(`复制失败:${error}`)
+ }
+
+ document.body.removeChild(textarea)
+ }
+}
diff --git a/src/utils/mqtt.ts b/src/utils/mqtt.ts
index 195758e..901062c 100644
--- a/src/utils/mqtt.ts
+++ b/src/utils/mqtt.ts
@@ -1,4 +1,5 @@
import mqtt from 'mqtt'
+import { message } from 'ant-design-vue'
export interface Options {
host: string
@@ -24,13 +25,11 @@ export class MqttService {
const { protocol, host, port } = this.options
const connectUrl = `${protocol}://${host}:${port}/mqtt`
this.client = mqtt.connect(connectUrl, this.options)
- console.log(this.client)
this.client.on('connect', () => {
- console.log('连接成功')
resolve(true)
})
this.client.on('error', (error: any) => {
- console.log('连接失败!', error)
+ message.error('连接失败!')
reject(error)
})
})
@@ -42,13 +41,12 @@ export class MqttService {
}
return new Promise((resolve, reject) => {
- this.client.subscribe(topic, (err: any) => {
+ this.client?.subscribe(topic, (err: any) => {
if (err) {
- console.log('订阅失败!', err)
+ message.error('订阅失败!请稍后重试')
reject(err)
}
else {
- console.log('订阅成功!', topic)
resolve(true)
}
})
@@ -76,7 +74,7 @@ export class MqttService {
this.client.unsubscribe(topic, (err: any) => {
if (err) {
- console.log('取消订阅失败!', err)
+ message.error('取消订阅失败!!请联系管理员')
}
else {
console.log('取消订阅成功!', topic)
diff --git a/src/views/conversation/index.vue b/src/views/conversation/index.vue
index 5784e56..516b689 100644
--- a/src/views/conversation/index.vue
+++ b/src/views/conversation/index.vue
@@ -1,6 +1,7 @@
@@ -139,7 +184,15 @@ onMounted(() => {
-
+
+