(14-4-01)ChatGPT聊天系统(GPT-3.5/4.0+ Vue+pnpm+SQLite3):系统前端(1)

14.6  系统前端

本项目的前端功能是通过Vue实现的,建立和项目后端API的连接,实现ChatGPT聊天页面功能。在本节的内容中,将详细讲解本项目前端模块的实现过程。

14.6.1  设置代理

编写文件proxy.ts创建Vite开发服务器代理的函数,其作用是在开发环境中将来自前端应用程序的HTTP请求转发到后端API服务器,以便项目测试和调试。在文件文件proxy.ts中定义了一个名为 createViteProxy 的函数,该函数接受如下两个参数:

  1. isOpenProxy:一个布尔值,指示代理是否打开。当代理关闭时,函数将返回 undefined。
  2. viteEnv:一个包含当前Vite环境变量的对象,例如 VITE_APP_API_BASE_URL 等。

文件proxy.ts的主要实现代码如下所示。

import type { ProxyOptions } from 'vite'

export function createViteProxy(isOpenProxy: boolean, viteEnv: ImportMetaEnv) {
  if (!isOpenProxy)
    return

  const proxy: Record<string, string | ProxyOptions> = {
    '/api': {
      target: viteEnv.VITE_APP_API_BASE_URL,
      changeOrigin: true,
      rewrite: path => path.replace('/api/', '/'),
    },
  }

  return proxy
}

如果打开代理,函数createViteProxy()将创建一个名为 proxy 的对象,并使用 viteEnv.VITE_APP_API_BASE_URL 作为后端API服务器的基本URL。然后,它将设置 /api 路径的代理规则,以便将来自前端应用程序的HTTP请求重定向到后端API服务器。同时,还可以通过 rewrite 属性将URL中的路径重写为API服务器的实际路径,例如将 /api/users 重写为 /users。

最后,它将返回代理配置对象(proxy),供Vite开发服务器使用。

14.6.2  HTTP请求

编写文件frontend\src\api\index.ts,功能是在前台页面向后台服务器发送HTTP请求,主要实现代码如下所示。

export function fetchChatAPI<T = any>(
  prompt: string,
  options?: { conversationId?: string; parentMessageId?: string },
  signal?: GenericAbortSignal,
) {
  return post<T>({
    url: '/chat',
    data: { prompt, options },
    signal,
  })
}

export function fetchChatConfig<T = any>() {
  return post<T>({
    url: '/config',
  })
}

export function fetchChatAPIProcess<T = any>(
  params: {
    prompt: string
    options?: { conversationId?: string; parentMessageId?: string }
    baseURI?: string
    accessToken?: string
    isGPT4?: boolean
    signal?: GenericAbortSignal
    onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void },
) {
  const settingStore = useSettingStore()

  return post<T>({
    url: '/chat-process',
    data: { prompt: params.prompt, options: params.options, systemMessage: settingStore.systemMessage, baseURI: params.baseURI, accessToken: params.accessToken, isGPT4: params.isGPT4 },
    signal: params.signal,
    onDownloadProgress: params.onDownloadProgress,
  })
}

export function fetchSession<T>() {
  return post<T>({
    url: '/session',
  })
}

export function fetchVerify<T>(token: string) {
  return post<T>({
    url: '/verify',
    data: { token },
  })
}

在上述代码中实现了用于向服务器发送HTTP请求的方法,它们使用库axios来执行网络请求,并返回Promise对象以便在异步环境中使用。对上述方法的具体说明如下:

  1. 方法fetchChatAPI():向 /chat 接口发送POST请求,传递一个名为 prompt 的字符串参数和一个可选的包含 conversationId 和 parentMessageId 属性的对象,用于获取聊天机器人的回复。该函数返回一个泛型类型 T 的Promise对象,可以通过 then 方法处理响应结果。
  2. 方法fetchChatConfig<T>():向 /config 接口发送POST请求,用于获取聊天机器人的配置信息。该函数返回一个泛型类型 T 的Promise对象,可以通过 then 方法处理响应结果。
  3. 方法fetchChatAPIProcess<T>(params: {...}):向 /chat-process 接口发送POST请求,传递一个包含多个参数的对象,用于获取聊天机器人的回复和处理过程。该函数返回一个泛型类型 T 的Promise对象,可以通过 then 方法处理响应结果。
  4. 方法fetchSession<T>():向 /session 接口发送POST请求,获取当前用户的会话信息。该函数返回一个泛型类型 T 的Promise对象,可以通过 then 方法处理响应结果。
  5. 方法fetchVerify<T>(token: string):向 /verify 接口发送POST请求,传递一个名为 token 的字符串参数,用于验证用户的身份。该函数返回一个泛型类型 T 的Promise对象,可以通过 then 方法处理响应结果。

上述方法都是基于 post 方法封装而成的,其中使用了一些默认请求配置,例如基本URL、请求头、超时时间等。此外,方法fetchChatAPIProcess()还支持在下载过程中获取进度信息,并接受一个可取消的 signal 参数,以便在需要时取消请求。

在实际应用程序中,我们可能需要根据具体业务需求定义更多的HTTP请求函数,并针对不同的接口和数据类型进行适当的错误处理和数据转换。

14.6.3  ChatGPT聊天界面侧边栏

编写文件frontend/src/views/chat/layout/sider/index.vue实现ChatGPT聊天界面的左侧边栏功能,主要实现代码如下所示。

const appStore = useAppStore()
const chatStore = useChatStore()

const { isMobile } = useBasicLayout()
const show = ref(false)

const collapsed = computed(() => appStore.siderCollapsed)

function handleAdd() {
  chatStore.addHistory({ title: 'New Chat', uuid: Date.now(), isEdit: false })
  if (isMobile.value)
    appStore.setSiderCollapsed(true)
}

function handleUpdateCollapsed() {
  appStore.setSiderCollapsed(!collapsed.value)
}

const getMobileClass = computed<CSSProperties>(() => {
  if (isMobile.value) {
    return {
      position: 'fixed',
      zIndex: 50,
    }
  }
  return {}
})

const mobileSafeArea = computed(() => {
  if (isMobile.value) {
    return {
      paddingBottom: 'env(safe-area-inset-bottom)',
    }
  }
  return {}
})

watch(
  isMobile,
  (val) => {
    appStore.setSiderCollapsed(val)
  },
  {
    immediate: true,
    flush: 'post',
  },
)
</script>

<template>
  <NLayoutSider
    :collapsed="collapsed"
    :collapsed-width="0"
    :width="260"
    :show-trigger="isMobile ? false : 'arrow-circle'"
    collapse-mode="transform"
    position="absolute"
    bordered
    :style="getMobileClass"
    @update-collapsed="handleUpdateCollapsed"
  >
    <div class="flex flex-col h-full" :style="mobileSafeArea">
      <main class="flex flex-col flex-1 min-h-0">
        <div class="p-4">
          <NButton dashed block @click="handleAdd">
            {{ $t('chat.newChatButton') }}
          </NButton>
        </div>
        <div class="flex-1 min-h-0 pb-4 overflow-hidden">
          <List />
        </div>
        <div class="p-4">
          <NButton block @click="show = true">
            {{ $t('store.siderButton') }}
          </NButton>
        </div>
      </main>
      <Footer />
    </div>
  </NLayoutSider>
  <template v-if="isMobile">
    <div v-show="!collapsed" class="fixed inset-0 z-40 bg-black/40" @click="handleUpdateCollapsed" />
  </template>
  <PromptStore v-model:visible="show" />
</template>

上述代码使用了多个Vue.js实用工具,例如使用computed、ref、watch等来管理侧边栏的状态和显示内容。在侧边栏中还包括了一个“新建聊天”按钮,用于创建新的聊天会话,并在侧边栏中显示已有的聊天历史记录。同时,在移动设备上,该组件还会自动适应安全区域,并提供了一个可折叠的侧边栏菜单。此外,在侧边栏中还包括了一个Footer组件,用于显示底部的版权信息。最后,该组件还引用了PromptStore组件,并在需要时显示该组件的模态对话框。

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值