Browse Source

采美AI 助手

zhengjinyi 11 months ago
parent
commit
7c87d5113e

+ 7 - 3
common/css/iconfont.scss

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 1519039 */
-  src: url('//at.alicdn.com/t/c/font_1519039_9tmdq3dgdhu.woff2?t=1719457092531') format('woff2'),
-       url('//at.alicdn.com/t/c/font_1519039_9tmdq3dgdhu.woff?t=1719457092531') format('woff'),
-       url('//at.alicdn.com/t/c/font_1519039_9tmdq3dgdhu.ttf?t=1719457092531') format('truetype');
+  src: url('//at.alicdn.com/t/c/font_1519039_1hleu97y1mi.woff2?t=1722216368869') format('woff2'),
+       url('//at.alicdn.com/t/c/font_1519039_1hleu97y1mi.woff?t=1722216368869') format('woff'),
+       url('//at.alicdn.com/t/c/font_1519039_1hleu97y1mi.ttf?t=1722216368869') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,10 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-fasong:before {
+  content: "\e61b";
+}
+
 .icon-weixin:before {
   content: "\e665";
 }

+ 6 - 0
pages.json

@@ -594,6 +594,12 @@
 					"style": {
 						"navigationBarTitleText": "线下转账"
 					}
+				},
+				{
+					"path": "chats/index",
+					"style": {
+						"navigationBarTitleText": "采美AI助手"
+					}
 				}
 				
 			]

+ 107 - 0
pages/user/chats/components/chat-html.vue

@@ -0,0 +1,107 @@
+<template>
+    <view>
+        <view v-for="(chat, index) in messages" :key="index" class="cm_ai_answer"
+            :class="chat.from === 'me' ? 'user' : ''">
+            <view class="cm_ai_html" :class="chat.from === 'me' ? 'user' : ''">
+                <template v-if="chat.from === 'me'">
+                    {{ chat.question }}
+                </template>
+                <template v-else>
+                   <!-- <image v-if="isLoading" class="cm_ai_html_loading" src="https://static.caimei365.com/app/img/chat/icon-loading@2x.gif" /> -->
+                   <!-- <template v-else> -->
+                       <text v-if="chat.typing">{{ chat.question.substring(0, chat.currentLength) }}</text>
+                       <text v-else>{{ chat.question }}</text>  
+                   <!-- </template> -->
+                </template>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+    export default {
+        name: 'chatHtml',
+        props: {
+            messages: {
+                type: Array
+            }
+        },
+        data() {
+            return {
+                chatList: [],
+            }
+        },
+        created() {
+           
+        },
+        computed: {
+
+        },
+        watch: {
+            messages: {
+                handler: function(val) {
+                    console.log('messages', val)
+                    this.startTypingEffect(this.messages[this.messages.length - 1])
+                }
+            }
+        },
+        methods: {
+            startTypingEffect(message) {
+                if (!message.typing) {
+                    message.typing = true // 标记为正在打字  
+                    let currentLength = 0
+                    const typeEffect = () => {
+                        if (currentLength < message.question.length) {
+                            message.currentLength++ // 增加已显示的文本长度  
+                            // 如果需要,可以在这里添加一些性能优化或条件检查  
+                            setTimeout(typeEffect, 50) // 每100毫秒增加一个字符  
+                        } else {
+                            message.typing = false // 打字完成  
+                        }
+                    }
+                    typeEffect() // 开始打字效果  
+                }
+            }
+        }
+    }
+</script>
+
+<style lang="scss">
+    .cm_ai_answer {
+        width: 100%;
+        height: auto;
+        box-sizing: border-box;
+        position: relative;
+        margin: 20rpx 0;
+        display: flex;
+        justify-content: flex-start;
+
+        &.user {
+            justify-content: flex-end;
+        }
+
+        .cm_ai_html {
+            min-height: 80rpx;
+            border-radius: 0 30rpx 30rpx 30rpx;
+            line-height: 1.5715;
+            background-color: #FFFFFF;
+            box-sizing: border-box;
+            padding: 20rpx;
+            font-size: 30rpx;
+            color: #666666;
+
+            &.user {
+                min-height: 80rpx;
+                border-radius: 30rpx 30rpx 0 30rpx;
+                background-color: rgba(255, 91, 0, 0.1);
+                font-size: 30rpx;
+                color: #333333;
+            }
+
+            .cm_ai_html_loading {
+                width: 60rpx;
+                height: 14rpx;
+            }
+        }
+    }
+</style>

+ 208 - 0
pages/user/chats/index.vue

@@ -0,0 +1,208 @@
+<template>
+    <view class="container">
+        <view class="cm_ai_container_main">
+            <view class="cm_ai_container">
+                <!--提问回答element-->
+                <view class="cm_ai_answer_main" id="cm_ai_answer">
+                    <chat-html ref="chatHtml" :messages='messages' />
+                </view>
+                <!--提问文本框-->
+                <view class="cm_ai_content">
+                    <view class="cm_ai_input">
+                        <input class="cm_ai_textarea" v-model="questionTextarea" placeholder="请输入您想了解的内容"
+                            @confirm="handleAskQuestion" />
+                        <view class="cm_ai_button" :class="isLoading ? 'none' : ''" @click="handleAskQuestion">
+                            <text class="iconfont icon-fasong"></text>
+                        </view>
+                    </view>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+    import { mapState, mapMutations } from 'vuex'
+    import chatHtml from './components/chat-html' //地址信息
+    export default {
+        components: {
+            chatHtml
+        },
+        data() {
+            return {
+                StaticUrl: this.$Static,
+                isIphoneX: this.$store.state.isIphoneX,
+                isLoading: false,
+                chatParams: {
+                    userId: '',
+                    question: ''
+                },
+                questionTextarea: '',
+                probeChatId: '',
+                probeIndex: 0,
+                messages: []
+            }
+        },
+        onLoad(option) {
+
+        },
+        filters: {
+
+        },
+        computed: {
+            ...mapState(['hasLogin', 'userInfo', ])
+        },
+        methods: {
+            async initGetStotage() {
+                const userInfo = await this.$api.getStorage()
+                this.chatParams.userId = userInfo.userId
+                this.questionTextarea = ''
+            },
+            async handleAskQuestion() {
+                this.chatParams.question = this.questionTextarea
+                if (this.isLoading) { return }
+                if (!this.chatParams.question) {
+                    this.$util.msg('请输入内容', 2000)
+                    return
+                }
+                this.messages.push({ question: this.chatParams.question, from: 'me', typing: false,
+                    currentLength: 0 })
+                if (this.probeIndex === 0) {
+                    this.messages.push({ question: `老板,稍等一下哈,我为你查询一下${this.chatParams.question}的相关信息。`, from: 'bot',
+                        typing: false, currentLength: 0 })
+                }
+                this.isLoading = true
+                setTimeout(() => {
+                    if (this.probeIndex === 0) {
+                        this.handleUserNewChat(this.chatParams)
+
+                    } else {
+                        this.handleUserSecondChat({ chatId: this.probeChatId, ...this.chatParams })
+                    }
+                }, 1000)
+            },
+            async handleUserNewChat(chatParams) {
+                try {
+                    this.questionTextarea = ''
+                    const res = await this.UserService.userNewChat(chatParams)
+                    const data = res.data
+                    this.probeIndex++
+                    this.probeChatId = data.chatId
+                    this.messages.push({ question: data.result, from: 'bot', typing: false, currentLength: 0 })
+                    this.isLoading = false
+                } catch (error) {
+                    console.error('Error fetching new chats:', error)
+                }
+            },
+            async handleUserSecondChat(chatParams) {
+                try {
+                    this.questionTextarea = ''
+                    const res = await this.UserService.userSecondChat(chatParams)
+                    const data = res.data
+                    this.messages.push({ question: data.result, from: 'bot', typing: false, currentLength: 0 })
+                    this.isLoading = false
+                } catch (error) {
+                    console.error('Error fetching new chats:', error)
+                }
+            }
+        },
+        onShow() {
+            this.initGetStotage()
+        }
+    }
+</script>
+
+<style lang="scss">
+    page {
+        width: 100%;
+        height: 100%;
+        background-color: #FFFFFF;
+    }
+
+    .cm_ai_container_main {
+        width: 100%;
+        height: 100%;
+        background-image: radial-gradient(circle at 14% 85%, #e7ecf7 0, rgba(231, 236, 247, 0) 37%), radial-gradient(circle at 3.4% 3.7%, rgba(245, 237, 241, .5) 0, rgba(245, 237, 241, 0) 28%), radial-gradient(circle at 100% 18%, #e8ebea 0, hsla(160, 7%, 92%, 0) 30%), linear-gradient(180deg, #f5f4f6, #e6ebf7);
+
+        .cm_ai_container {
+            width: 100%;
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            box-sizing: border-box;
+            padding: 0 24rpx 40rpx 24rpx;
+
+            .cm_ai_content {
+                width: 100%;
+                height: 88rpx;
+                background-color: #FFFFFF;
+                box-shadow: 0 16rpx 20rpx 0 rgba(174, 167, 223, .2);
+                border-radius: 40rpx;
+                box-sizing: border-box;
+                padding: 14rpx 24rpx;
+                margin: 20rpx 0;
+                position: relative;
+
+                .cm_ai_input {
+                    display: flex;
+                    align-items: center;
+                    justify-content: space-between;
+                    width: 100%;
+                    height: 60rpx;
+                    overflow: hidden;
+                    box-sizing: border-box;
+                    padding-right: 60rpx;
+                    position: relative;
+
+                    input {
+                        width: 100%;
+                        height: 60rpx !important;
+                        font-size: 24rpx;
+                        line-height: 60rpx;
+                        background-color: transparent;
+                        border: none;
+                        box-shadow: none;
+                        overflow: auto;
+                        scrollbar-width: none;
+                        resize: none;
+                        box-sizing: border-box;
+                        padding-left: 4rpx;
+                    }
+
+                    .cm_ai_button {
+                        width: 60rpx;
+                        height: 60rpx;
+                        line-height: 60rpx;
+                        border-radius: 20rpx;
+                        display: inline-flex;
+                        align-items: center;
+                        justify-content: center;
+                        font-size: 24rpx;
+                        position: absolute;
+                        right: 0;
+
+                        &.none {
+                            background-image: radial-gradient(circle at 14% 85%, #e7ecf7 0, rgba(231, 236, 247, 0) 37%);
+
+                            .icon-fasong {
+                                color: #e6e6e6;
+                            }
+                        }
+
+                        .icon-fasong {
+                            font-size: 50rpx;
+                            color: #ff5b00;
+                        }
+                    }
+                }
+            }
+
+            .cm_ai_answer_main {
+                width: 100%;
+                min-height: 600rpx;
+                overflow-y: auto;
+                flex: 9;
+            }
+        }
+    }
+</style>

+ 27 - 0
services/user.service.js

@@ -1034,4 +1034,31 @@ export default class UserService {
             isLoading: true
         })
     }
+    /**
+    * @采美AI助手-提问
+    * @param:userId 用户userId
+    * @param:question 问题
+    */
+    userNewChat(data = {}) {
+        return this.AjaxService.get({
+            url: '/user/chat/new/chat',
+            data,
+            isLoading: true,
+            loadText:'AI分析中...'    
+        })
+    }
+    /**
+    * @采美AI助手-追问
+    * @param:chatId chatId
+    * @param:userId 用户userId
+    * @param:question 问题
+    */
+    userSecondChat(data = {}) {
+        return this.AjaxService.get({
+            url: '/user/chat/second/chat',
+            data,
+            isLoading: true,
+            loadText:'AI分析中...'    
+        })
+    }
 }