基于html5 开发的仿ChatGPT的前端UI项目,采用了VUE3 + TypeScript等技术选型开发,实现了基本的消息会话、PDF会话、新增会话、删除会话、会话历史、Token统计等新增功能。

- 消息会话、新建会话、会话历史、删除会话、Token统计、PDF文件上传等功能代码如下:
<script setup lang='ts'>
import { ref } from 'vue'
import { useRoute } from 'vue-router'
import { router } from '@/router'
import { useScroll } from './hooks/useScroll'
import VuePdfApp from "vue3-pdf-app"
import "vue3-pdf-app/dist/icons/main.css"
import { encode } from 'gpt-tokenizer'
const { scrollRef, scrollToBottom } = useScroll()
// Conversation and PDF preview panel toggle control
let showTab = ref<string>("nav-tab-chat")
let tabWidth = ref<string>("")
// vue3-pdf-app UI configuration
let pdfFile = ref<string>("")
const config = ref<{}>({
sidebar: true,
toolbar: {
toolbarViewerLeft: {
findbar: true,
previous: true,
next: true,
pageNumber: false,
},
toolbarViewerRight: {
presentationMode: true,
openFile: false,
print: false,
download: false,
viewBookmark: false,
},
toolbarViewerMiddle: {
zoomOut: true,
zoomIn: true,
scaleSelectContainer: true,
}
},
})
// Message input box
const prompt = ref<string>('')
// Loading state and button state
const buttonDisabled = ref<boolean>(false)
// Get uuid from URL params
const route = useRoute()
let { uuid } = route.params as { uuid: string }
interface Conversation {
title: string;
uuid: string;
isEdit: boolean;
createDate: string;
lastChatContent: string;
active: boolean;
}
interface Message {
send: {
model: string;
messages: {
role: string;
content: string;
fileName: any;
fileSize: number;
}[];
temperature: number;
};
loading: boolean;
receive?: {
model: string;
choices: {
message?: {
content: string;
};
delta: {
content: string;
};
}[];
};
}
// Conversation list and message list
var conversationList = ref<Conversation[]>([])
var messageList = ref<Message[]>([]);
let conversations = window.localStorage.getItem("chatStore")
if(conversations){
conversationList.value = JSON.parse(conversations)
}
// Check if new conversation
if (!uuid || uuid === '0') {
uuid = Date.now().toString()
// Initialize empty conversation
if(!conversations){
conversationList.value.push({
title: 'New Chat',
uuid: uuid,
isEdit: false,
createDate: new Date().toLocaleString(),
lastChatContent: 'Hello I am ChatGPT3.5...',
active: true
})
}else{
// If has history, get last conversation
let lastConversation = conversationList.value[conversationList.value.length-1]
uuid = lastConversation.uuid
let messages = window.localStorage.getItem(uuid)
if(messages) {
messageList.value = JSON.parse(messages)
}
router.push({ name: 'Chat', params: { uuid } })
}
}else{
// Load current conversation messages
let messages = window.localStorage.getItem(uuid)
if(messages) {
messageList.value = JSON.parse(messages)
}
conversationList.value.forEach((item, index) => {
if(item.uuid == uuid){
item.active = true
}else{
item.active = false
}
})
scrollToBottom()
}
// Set active conversation
function handleAdd() {
// Reset the message record of the new conversation
messageList.value = []
// Reset the active status of the conversation list
conversationList.value.forEach((item, index) => {
item.active = false
})
// Initialize an empty conversation
uuid = Date.now().toString()
conversationList.value.unshift({
title: "New Chat",
uuid: uuid,
isEdit: false,
createDate: new Date().toLocaleString(),
lastChatContent: 'Hello I am ChatGPT3.5...',
active: true
})
// Save the conversation to local storage
window.localStorage.setItem("chatStore", JSON.stringify(conversationList.value))
}
// Menu toggle
function handleMenu(){
let rootbody = document.getElementById("rootbody")
if (rootbody) {
if(rootbody.classList.value==""){
rootbody.classList.value="open-sidebar-menu"
}else{
rootbody.classList.value=""
}
}
}
// Switch conversation
function handleSwitch(selectedUuid: string) {
uuid = selectedUuid
// Reset message record of the new conversation
let messages = window.localStorage.getItem(selectedUuid)
if(messages){
messageList.value = JSON.parse(messages)
}else{
messageList.value = []
}
// Reset active status of the conversation list
conversationList.value.forEach((item, index) => {
if(item.uuid == selectedUuid){
item.active = true
}else{
item.active = false
}
})
router.push({ name: 'Chat', params: { uuid } })
}
// File upload related
var fileName = ref()
var fileSize = ref<number>(0)
var formattedFileSize = ref<string>('0B')
var fileUploadCard = ref<boolean>(false)
var fileContent = ref()
// Handle file upload
function handleUpload(e: Event) {
const target = e.target as HTMLInputElement;
if(target.files && target.files[0].size >= 5 * 1024 * 1024){
alert('Maximum file size limit is 5MB')
return
}else if (!target.files || target.files.length === 0) {
alert('Please select a file')
return
}
// Set file upload style
fileName.value = target.files[0].name
fileSize.value = target.files[0].size
formatFileSize()
// Preview PDF
showTab.value = 'nav-tab-doc'
tabWidth.value = 'width: 60%'
pdfFile.value = URL.createObjectURL(target.files[0])


1825

被折叠的 条评论
为什么被折叠?



