《通义千问AI落地—中》:前端实现

一、前言

本文源自微博客且已获授权,请尊重版权.

书接上文,上文中,我们介绍了通义千问AI落地的后端接口。那么,接下来我们将继续介绍前端如何调用接口以及最后的效果;首先看效果:

result.gif

上述就是落地到本微博客以后的页面效果,由于是基于落在现有项目之上,因此什么登录注册等基本功能都省去了,言归正传,下面我们将正式介绍通义千问AI落地的前端实现。

二、前端实现

2.1、前端依赖

前端所需依赖基本如下(本项目前端是基于Nuxtjs的,这样又益与SSE,所以有nuxt相关依赖):

    "dependencies": {
        "@nuxtjs/axios": "^5.13.6",
        "dayjs": "^1.11.12",
        "element-ui": "^2.15.1",
        "highlight.js": "^11.9.0", //代码高亮组件
        "mavon-editor": "^2.10.4",  //富文本展示
        "nuxt": "^2.0.0",
        "@stomp/stompjs": "^6.0.0",  // 
        "ws": "^7.0.0"  //websocket
    }

2.2、页面布局

如上动图所示,前端项目主要是左右分布。其中,左侧负责管理各个session会话,包括激活会话、展示会话、删除会话等;
右侧则主要负责消息处理,包括消息收发、处理GPT生成的消息等。由于使用组件化开发,因此各个组件比较多,接下来的内容将采用 总-分 结构介绍。

2.2.1、主聊天页面

主聊天页面聚合了左侧的session管理和右侧的消息管理,内容如下:

<template>
    <!-- 最外层页面于窗口同宽,使聊天面板居中 -->
    <div class="home-view">
        <!-- 整个聊天面板 -->
        <div class="chat-panel">
            <!-- 左侧的会话列表 -->
            <div class="session-panel hidden-sm-and-down">
                <div class="title">ChatGPT助手</div>
                <div class="description">构建你的AI助手</div>
                <div class="session-list">
                    <SessionItem
                        v-for="(session, index) in sessionList"
                        :key="session.id+index"
                        :active="session.id === activeSession.id"
                        :session="sessionList[index]"
                        class="session"
                        @click.native="sessionSwitch(session,index)"
                        @delete="deleteSession"
                    >
                    </SessionItem>
                </div>
                <div class="button-wrapper">
                    <div class="new-session">
                        <el-button @click="createSession">
                            <el-icon :size="15" class="el-icon-circle-plus-outline"></el-icon>
                            新的聊天
                        </el-button>
                    </div>
                </div>
            </div>
            <!-- 右侧的消息记录 -->
            <div class="message-panel">
                <!-- 会话名称 -->
                <div class="header">
                    <div class="front">
                        <div v-if="!isEdit" class="title">
                            <el-input style="font-size: 20px"
                                      v-model="activeSession.topic"
                                      @keyup.enter.native="editTopic()"
                            ></el-input>
                        </div>
                        <div v-else class="title" style="margin-top: 6px;" @dblclick="editTopic()">
                            {
  { activeSession.topic }}
                        </div>
                        <div class="description">与ChatGPT的 {
  { activeSession?.messageSize ?? 0 }} 条对话</div>
                    </div>
                    <!-- 尾部的编辑按钮 -->
                    <div class="rear">
                        <i v-if="isEdit" @click="editTopic" class="el-icon-edit rear-icon"></i>
                        <i v-else @click="editTopic" class="el-icon-check rear-icon"></i>
                    </div>
                </div>
                <el-divider></el-divider>
                <div class="message-list" id="messageListId">
                    <!-- 过渡效果 -->
                    <transition-group name="list">
                        <message-row
                            v-for="(message, index) in activeSession.messages"
                            :key="message.id+`${index}`"
                            :message="message"
                        ></message-row>
                    </transition-group>
                </div>
                <div class="toBottom" v-if="!this.isScrolledToBottom">
                    <el-tooltip class="item" effect="light" content="直达最新" placement="top-center">
                        <el-button class="el-icon-bottom bottom-icon" @click="toBottom"></el-button>
                    </el-tooltip>
                </div>
                <!-- 监听发送事件 -->
                <MessageInput @send="sendMessage" :isSend="isSend"></MessageInput>
            </div>
        </div>
    </div>
</template>
<script>
import MessageInput from '@/components/gpt/MessageInput'
import MessageRow from '@/components/gpt/MessageRow'
import SessionItem from "@/components/gpt/SessionItem";
import {Client} from "@stomp/stompjs";
import dayjs from "dayjs";
import {scrollToBottom} from '@/utils/CommonUtil'

export default {
    name: 'gpt',
    layout: 'gpt',
    middleware: 'auth', //权限中间件,要求用户登录以后才能使用
    components: {
        MessageInput, MessageRow, SessionItem
    },
    created() {
        this.loadChart();
    },
    mounted() {
        this.handShake()
        this.$nextTick(() => {
            this.messageListEl = document.getElementById('messageListId');
            if (this.messageListEl) {
                this.messageListEl.addEventListener('scroll', this.onScroll);
            }
        });
    },
    beforeUnmount() {
        this.closeClient();
    },
    beforeDestroy() {
        if (this.messageListEl) {
            this.messageListEl.removeEventListener('scroll', this.onScroll);
        }
    },
    watch: {
        activeSession(newVal) {
            if (newVal) {
                //确保dom加载完毕
                this.$nextTick(() => {
                    this.toBottom();
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值