SpringBoo+vue3+vite整合讯飞星火3.5通过webscoket实现聊天功能(前端代码)附带展示效果

访问地址:
天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/site

后端文档:

SpringBoo+vue3整合讯飞星火3.5通过webscoket实现聊天功能(全网首发)附带展示效果_springboot websocket vue3-CSDN博客https://blog.csdn.net/qq_53722480/article/details/139107409

1.样式库我使用了 tailwindcss,找到tailwindcss,里面有安装教程,不使用可以跳过,样式自己重新写也可以

2.vue html

复制代码
<template>
<div class="theme-controller bg-base-200 pt-1 pb-1 w-full d-flex justify-center items-center">
<div class="content-container ">
	<!--侧边栏-->
	<div class="side">
		<div class="h-full w-full  bg-base-300 rounded-r-3xl ">
			<div class="side-logo d-flex align-center text-base-0">
				<img style="width: 35px;height: 35px" class="rounded-md" src="../assets/Logo.png"> </img>
				<span class="ml-4 text-2xl font-weight-bold">AI人工智能助手</span>
			</div>
			<div class="side-api d-flex items-center">
				<el-button style="height: 40px;" class="w-36  bg-info border-0">
					<svg t="1715778624612" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4291" width="18" height="18">
						<path d="M760.32 183.466667h-13.653333v-59.733334a57.173333 57.173333 0 0 0-114.346667 0v59.733334H400.213333v-59.733334a57.173333 57.173333 0 0 0-114.346666 0v59.733334h-16.213334c-75.946667 0-138.24 61.44-138.24 138.24v494.08c0 75.946667 61.44 138.24 138.24 138.24H759.466667c75.946667 0 138.24-61.44 138.24-138.24V321.706667c0.853333-75.946667-61.44-138.24-137.386667-138.24zM515.413333 296.96c85.333333 0 154.453333 69.12 154.453334 154.453333 0 85.333333-69.12 154.453333-154.453334 154.453334-85.333333 0-154.453333-69.12-154.453333-154.453334 0-86.186667 69.12-154.453333 154.453333-154.453333zM748.373333 742.4c0 52.906667-42.666667 95.573333-95.573333 95.573333H378.026667c-52.906667 0-95.573333-42.666667-95.573334-95.573333 0-52.906667 42.666667-95.573333 95.573334-95.573333h273.92c52.906667 0 96.426667 42.666667 96.426666 95.573333z" p-id="4292" fill="#ffffff"></path>
					</svg>
					<span class="mt-0.5 ml-1">账户中心</span>
				</el-button>
				<el-button style="height: 40px;" class="w-36  bg-info border-0">
					<svg t="1715779300040" class="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8561" width="18" height="18">
						<path d="M924.17025 258.44833h0.04335c-55.093306 0-103.987667-35.705346-121.41046-88.638413l-5.639017-17.198822C779.74133 99.674415 730.836131 63.940169 675.742825 63.940169H348.239112c-55.093306 0-104.009342 35.734246-121.432134 88.667313L221.175186 169.784629C203.741555 222.728534 154.836357 258.441106 99.743051 258.441106H99.703314c-19.738366 0-35.763145 16.209013-35.763145 36.20025V777.035613h0.469617l397.129861 172.493959a126.731582 126.731582 0 0 0 100.920706 0L959.590214 777.035613h0.234808V294.644969c0-19.991237-15.916406-36.196638-35.654772-36.196639zM895.884854 734.860388l-358.989731 155.992338a62.495193 62.495193 0 0 1-49.931131 0L127.880338 734.860388V320.296897a187.991322 187.991322 0 0 0 31.699152-7.557222 192.21065 192.21065 0 0 0 94.609775-68.997583 193.821798 193.821798 0 0 0 27.714631-53.944551L287.550138 172.598719C296.357265 145.870284 320.748452 127.880338 348.239112 127.880338h327.503713c27.50511 0 51.89991 17.989946 60.688974 44.718381l5.649855 17.187985A193.312444 193.312444 0 0 0 811.715027 285.621096a190.660914 190.660914 0 0 0 52.586273 27.118579 195.34986 195.34986 0 0 0 31.583554 7.557222v414.563491z" fill="#ffffff" p-id="8562"></path><path d="M511.998194 255.999097c-141.383635 0-255.999097 114.615462-255.999097 255.999097S370.614559 768.004516 511.998194 768.004516 768.004516 653.385441 768.004516 511.998194s-114.619075-255.999097-256.006322-255.999097z m177.009507 330.736846a192.904239 192.904239 0 1 1 15.056646-74.737749 191.936105 191.936105 0 0 1-15.071096 74.741361z" fill="#ffffff" p-id="8563"></path><path d="M596.052423 425.393583l-105.392906 105.392906-62.726389-62.72639a31.970084 31.970084 0 0 0-45.213286 45.213286l85.333032 85.333032a31.970084 31.970084 0 0 0 45.213286 0l127.999548-127.999548A31.970084 31.970084 0 0 0 596.052423 425.393583z" fill="#ffffff" p-id="8564"></path>
					</svg>
					<span class="mt-0.5 ml-1">申请接口</span>
				</el-button>
			</div>
			<div class="side-talke d-flex justify-center items-center">
				<div class="talke d-flex justify-center items-center bg-warning cursor-pointer">
					<svg t="1715779790026" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13505" width="21" height="21">
						<path d="M908.8 305.6c-5.4-10.5-16.3-17.8-28.9-17.8-17.8 0-32.2 14.4-32.2 32.1 0 6 1.7 11.7 4.6 16.5l-0.1 0.1c26.9 52.4 42.1 111.8 42.1 174.7 0 211.6-171.6 383.2-383.2 383.2S127.8 722.8 127.8 511.2 299.4 128.1 511 128.1c62.5 0 121.5 15 173.6 41.5l0.2-0.4c4.6 2.6 10 4.1 15.7 4.1 17.8 0 32.2-14.4 32.2-32.1 0-13.1-7.9-24.4-19.3-29.4C652.6 80.9 583.9 63.5 511 63.5 263.7 63.5 63.2 264 63.2 511.2S263.7 958.9 511 958.9s447.7-200.4 447.7-447.7c0-74.1-18-144-49.9-205.6z" fill="#ffffff" p-id="13506"></path><path d="M770.7 219.7a32.2 32.1 0 1 0 64.4 0 32.2 32.1 0 1 0-64.4 0Z" fill="#ffffff" p-id="13507"></path><path d="M512.4 704.1c17.5 0 31.9-14.3 31.9-31.9V544.3h127.8c17.5 0 31.9-14.3 31.9-31.9 0-17.5-14.3-31.9-31.9-31.9H544.3V352.6c0-17.5-14.3-31.9-31.9-31.9-17.5 0-31.9 14.3-31.9 31.9v127.9h-128c-17.5 0-31.9 14.3-31.9 31.9 0 17.6 14.4 31.9 31.9 31.9h128v127.9c0 17.5 14.3 31.9 31.9 31.9z" fill="#ffffff" p-id="13508"></path>
					</svg>
					<span class="ml-1">新建对话</span>
				</div>
			</div>
			<div class="side-history d-flex items-center text-base-0">
				<div class="h-full d-flex flex-column justify-center align-center" @click="modelTypeFun(true)">
					<div class="h-full w-full d-flex justify-center align-center">历时对话</div>
					<div class="w-full h-0.5" :class="modelType? 'bg-amber-50':''"></div>
				</div>
				<div  class="h-full d-flex flex-column justify-center align-center" @click="modelTypeFun(false)">
					<div class="h-full w-full d-flex justify-center align-center">助手列表</div>
					<div  class="w-full h-0.5" :class="modelType? '':'bg-amber-50'"></div>
				</div>
			</div>
			<div class="side-content bg-base-100 touch-pan-y overflow-auto" v-if="modelType">
				<div v-for="(item,index) in historyList" @mouseenter="deleteIndexFun(true,index)" @mouseleave="deleteIndexFun(false,index)" @click="selectItemFun(item)" class="h-14 pl-5 d-flex justify-space-between
				 align-center pr-5 w-full hover:bg-base-200">
					<div class="line-clamp-1">{{item.title}}</div>
					<div v-show="deleteIndex===index" @click="deleteSparkChatFun([item])">
						<svg t="1716195021573" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1505" width="28" height="28">
							<path d="M839.68 307.2H184.32a40.96 40.96 0 0 1 0-81.92h655.36a40.96 40.96 0 1 1 0 81.92zM593.92 184.32h-163.84a40.96 40.96 0 1 1 0-81.92h163.84a40.96 40.96 0 0 1 0 81.92zM389.12 716.8V430.08a40.96 40.96 0 0 1 81.92 0v286.72a40.96 40.96 0 0 1-81.92 0z m163.84 0V430.08a40.96 40.96 0 0 1 81.92 0v286.72a40.96 40.96 0 0 1-81.92 0zM266.24 348.16a40.96 40.96 0 0 1 40.96 40.96v409.6a40.96 40.96 0 0 0 40.96 40.96h327.68a40.96 40.96 0 0 0 40.96-40.96V389.12a40.96 40.96 0 1 1 81.92 0v409.6a122.88 122.88 0 0 1-122.88 122.88H348.16a122.88 122.88 0 0 1-122.88-122.88V389.12a40.96 40.96 0 0 1 40.96-40.96z" fill="#f75959" p-id="1506"></path>
						</svg>
					</div>
				</div>
			</div>
			<div class="side-content bg-base-100 touch-pan-y overflow-auto" v-else>
				<div v-for="item in assistantList" class="h-14 pl-5 d-flex align-center pr-5 w-full hover:bg-base-200">
					 <div :title="item.modelDescribe">
						 <div>{{item.modelName}}</div>
						 <div class="text-xs line-clamp-1">{{item.modelDescribe}}</div>
					 </div>
					 <div></div>
				</div>
			</div>
			<div class="side-foot d-flex pl-5 pr-5 justify-space-between align-center pr-5 w-full ">
				<div class="d-flex align-center">
					<svg t="1715781825072"  viewBox="0 0 1372 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="51787" width="30" height="30">
						<path d="M696.145702 6.492596c230.726809 0 419.60034 179.243574 434.938553 406.13583l0.152511 2.788765 5.882553 1.220086c133.12 28.977021 232.034043 146.083404 235.302128 285.478127l0.065362 7.102639c0 165.408681-134.078638 299.487319-299.48732 299.487319H319.291915C153.905021 1008.705362 19.826383 874.626723 19.826383 709.218043c0-142.488511 100.003404-263.102638 235.367489-292.602554l5.860766-1.198298 0.196085-2.83234C276.392851 188.198128 461.344681 10.392511 688.650894 6.53617z m0 65.361702c-204.647489 0-370.557277 165.909787-370.579064 370.034383l0.522894 31.417191-29.979234 2.941277c-119.17617 11.699745-210.944 112.313191-210.944 232.970894 0 129.307234 104.818383 234.125617 234.125617 234.125617H1073.021277c129.307234 0 234.125617-104.796596 234.125617-234.125617 0-120.657702-91.724255-221.271149-210.900426-232.949107l-29.543489-2.897702 0.043574-29.696-0.065362-8.279149c-3.747404-201.422979-168.197447-363.541787-370.513702-363.541787zM608.909617 379.533617c11.002553 0 20.174979 2.091574 27.539064 6.252936 7.342298 4.161362 13.290213 9.542809 17.821957 16.100766 4.509957 6.53617 8.322723 13.595234 11.438298 21.133617 3.093787 7.538383 7.037277 17.604085 11.830468 30.197107l101.855319 251.577191 2.069788 5.098213c6.601532 16.558298 9.891404 28.759149 9.891404 36.667915 0 9.041702-3.769191 17.320851-11.285787 24.859234a37.147234 37.147234 0 0 1-27.277617 11.329361c-6.209362 0-11.525447-1.132936-15.948256-3.333446a32.680851 32.680851 0 0 1-11.176851-9.06349c-3.006638-3.790979-6.252936-9.651745-9.695319-17.538723a1028.531745 1028.531745 0 0 1-8.932766-20.87217l-18.606298-48.955915h-158.502127l-18.628085 50.001702-1.960852 5.163574c-6.427234 16.689021-11.982979 28.127319-16.645446 34.336681-5.141787 6.819404-13.573447 10.24-25.273192 10.24-9.934979 0-18.693447-3.638468-26.318979-10.893617-7.625532-7.276936-11.438298-15.512511-11.438297-24.750298 0-5.316085 0.871489-10.806468 2.658042-16.471149 1.764766-5.664681 4.706043-13.573447 8.780255-23.682723l99.720171-253.189447 1.786553-4.531745 8.453447-21.65651a132.466383 132.466383 0 0 1 12.767319-25.403915c4.531745-6.754043 10.457872-12.200851 17.821957-16.340426 7.364085-4.183149 16.449362-6.274723 27.25583-6.274723z m282.711149 0c11.89583 0 21.504 3.943489 28.868085 11.830468 7.364085 7.908766 11.02434 19.913532 11.02434 36.057872v307.178213l-0.108936 4.706043c-0.653617 13.791319-4.292085 24.270979-10.915404 31.460766-7.364085 7.974128-16.994043 11.982979-28.868085 11.982978-11.329362 0-20.697872-4.052426-28.04017-12.113702-7.364085-8.061277-11.046128-20.08783-11.046128-36.036085v-307.2l0.130723-5.163574c0.718979-13.399149 4.313872-23.639149 10.762894-30.72 7.276936-7.995915 16.667234-11.982979 28.192681-11.982979z m-283.234043 83.249021l-57.714383 160.898724h116.496341l-58.781958-160.898724z" fill="#ffffff" p-id="51788"></path>
					</svg>
					<span class="ml-2 text-xl">天梦星开发平台</span>
				</div>
				<div class="-rotate-90 cursor-pointer ">
					<svg t="1715780362871" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="44227" width="20" height="20">
						<path d="M484.864 281.2928l-304.64 304.64a38.4 38.4 0 1 0 54.3232 54.3232L512 362.752l277.4528 277.504a38.2976 38.2976 0 0 0 54.272 0 38.4 38.4 0 0 0 0-54.3232l-304.64-304.64a39.424 39.424 0 0 0-54.2208 0z" fill="#ffffff" p-id="44228"></path>
						<path d="M512 12.8C236.7488 12.8 12.8 236.7488 12.8 512s223.9488 499.2 499.2 499.2a496.4864 496.4864 0 0 0 448.3072-279.296 38.4 38.4 0 0 0-68.9152-33.8944A420.096 420.096 0 0 1 512 934.4c-232.9088 0-422.4-189.4912-422.4-422.4S279.0912 89.6 512 89.6s422.4 189.4912 422.4 422.4a38.4 38.4 0 0 0 76.8 0c0-275.2512-223.9488-499.2-499.2-499.2z" fill="#ffffff" p-id="44229"></path>
					</svg>
				</div>
			</div>
		</div>
	</div>
	<!--接收内容聊天框-->
	<div class="content ">
		<div class="content-body" ref="scrollContainer">
			<div class="item-content bg-base-300 rounded-lg position-relative mt-2 p-5" v-for="item in sparkList">
				<div class="position-absolute -mt-5 -ml-16 z-50">
					<el-image style="width: 40px;height: 40px" class="rounded-full" :src="userInfo?.image? configuration.visitFileUrl+userInfo.image :'https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg'"></el-image>
				</div>
				<div v-if="item.type==='send'" class="text-span">
				   {{item.content.text}}
				</div>
				<div v-else>
					<keep-alive v-for="item2 in item.content">
            <div v-if="item2.type" class="w-full bg-base-100 rounded-t-md rounded-r-md mt-2 mb-2 rounded-md">
							<div class="d-flex justify-space-between align-center rounded-t-md rounded-r-md  p-3 w-full bg-base-200">
								<div class="font-weight-bold text-span">{{returnFirst(item2.text)}}</div>
								<div @click="copyContentFun(item2.text)" class="text-sm cursor-pointer">复制代码</div>
							</div>
							<div class="p-3 text-span">
								{{getContent(item2.text)}}
							</div>
						</div>
						<text class="mt-1 text-pretty leading-3 text-span" v-else>{{item2.text}}</text>
					</keep-alive>
				</div>
			</div>
		</div>
		<!--发送请求框-->
		<div class="mt-md-2 w-full d-flex justify-center">
			<div class="content-foot bg-base-300">
				<div class="input-texture">
					<el-input
						v-model="form.content"
						maxlength="2000"
						class="el-input-text"
						:clearable="true"
						:autosize="{ minRows: 2, maxRows: 5 }"
						type="textarea"
						placeholder="在此输入你想了解的内容"
					/>
				</div>
				<div class="foot-btn">
					<div>
					</div>
					<div>
						<el-button style="height: 40px;" @click="sendSocket()" class=" bg-primary border-0 w-20 h-12">发送</el-button>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div v-if="loginShow">
		<login-page @receive-login="receiveLogin"></login-page>
	</div>
</div>
</div>
</template>

3.js 代码 部分代码不能直接用,我把页面源码全部放上来了,你按照自己的需求分析提取相关内容,主要是socket的连接功能,你主要看这个,socket 的连接地址是ws://localhost:8082/websocket/+`{uuid}`

复制代码
<script setup>
import { onBeforeUnmount, onMounted, ref } from 'vue'
import {
	addSparkChat,
	deleteSparkChat,
	queryAllLargeMode,
	querySparkChat,
	updateSparkChat
} from '../interface/sparkApi.js'
import { getSelUserInfo, getVerifyUser } from '../interface/UserApi.js'
import { configuration } from '../../env.product.js'
import { ElMessage } from 'element-plus'
import LoginPage from '../components/loginPage.vue'
let socket = null;
const modelType =ref(true);
const userInfo = ref();
const deleteIndex =ref(-1);
const form =ref({
	content:null,
	userId:null,
	type:"spark",
	historyId:null,
	chatType:null,
});
const historyList = ref([]);
const assistantList = ref([]);
const selectChat = ref({
	modelKey:"",
	list:[],
	title:""
});
const sparkList = ref([]);
const sparkEdit = ref(false);
const loginShow = ref(false);

onMounted(()=>{
	sparkList.value.push({
		content:[{
			text: "我是你的AI智能助手,请问我有什么能帮到您?",
			title: null,
			type: false,
		}],
		type:"back"
	})
	verifyUser();
})


/**
 * 回话记录删除鼠标移入移除事件
 */
function deleteIndexFun(val,index){
	deleteIndex.value=-1;
	if (val){
		deleteIndex.value=index
	}
}
/**
 * 复制代码
 * @param val
 */
function copyContentFun(val){
	const el = document.createElement('textarea');
	el.value = getContent(val);
	document.body.appendChild(el);
	el.select();
	document.execCommand('copy');
	document.body.removeChild(el);
	ElMessage({
		message: '复制成功',
		type: 'success',
		plain: true,
	})
}

/**
 * 返回首个拼音或者字
 * @param s
 * @return {*|null}
 */
function returnFirst(s) {
	const pattern = /```(\w+)/;
	const matches = s.match(pattern);
	return matches ? matches[1] : null;
}
/**
 * 返回正文内容
 * @param item
 * @return {*}
 */
function getContent(item) {
	let title = returnFirst(item);
	let result = (item.replace(/```/g, "\n")).replace(title,"") || item;
	return result;
}

/**
 * 进入页面连接webSocket
 */
 function openSocket() {
	const socketUrl = configuration.ws + userInfo.value.userId;
	if (socket != null) {
		socket.close()
		socket = null
	}
	//创建socket
	socket = new WebSocket(socketUrl)
	//打开事件
	socket.onopen = function () {
	//	console.log("websocket已打开");
	}
	//监听服务器返回的数据信息
	socket.onmessage = msg => {
		let lastIndex = (sparkList.value).length - 1;
		let lastContentIndex = sparkList.value[lastIndex].content.length - 1;
		if (msg.data.indexOf("``") !== -1) {
			if (sparkEdit.value){
				let oldValue = sparkList.value[lastIndex].content[lastContentIndex>=0?lastContentIndex:0].text;
				sparkList.value[lastIndex].content[lastContentIndex>=0?lastContentIndex:0].text=oldValue+""+msg.data
			}else {
				sparkList.value[lastIndex].content.push({
					text: msg.data,
					title: null,
					type: true,
				})
			}
			sparkEdit.value = ! sparkEdit.value;
		}else {
			if (sparkEdit.value){
				let oldValue = sparkList.value[lastIndex].content[lastContentIndex>=0?lastContentIndex:0].text;
				sparkList.value[lastIndex].content[lastContentIndex>=0?lastContentIndex:0].text=oldValue+""+msg.data
			}else {
				sparkList.value[lastIndex].content.push({
					text: msg.data,
					type: false,
				})
			}
		}
	}
	//关闭事件
	socket.onclose = function () {
		addSparkChatFun();
		// console.log("websocket已关闭");
	}
	//发生了错误事件
	socket.onerror = function () {
	//	console.log('websocket发生了错误')
		closeSocket()
	}
}
/**
 * 关闭socket
 */
function closeSocket() {
	if (socket !== null) {
		socket.close()
		socket = null
	}
}

/**
 * 发送socket信息
 */
function sendSocket() {
	sparkEdit.value = false;
	if (socket !== null) {
		let list = sparkList.value;
		let model ={
			content:{
				text:form.value.content,
				type:false
			},
			type:"send"
		};
		let model2 ={
			content:[],
			type:"back"
		};
		sparkList.value=[...list,model,model2];
		socket.send(JSON.stringify(form.value));
		form.value.content = null;
		setTimeout(()=>{
			addSparkChatFun();
		},5000)
	}
}

/**
 * 选中历史对话数据
 */
function selectItemFun(item){
	selectChat.value = item;
	sparkList.value = JSON.parse(item.list);
}

/**
 * 新增/修改会话记录
 */
function addSparkChatFun(){
	if (sparkList.value.length>=1){
		sparkList.value.shift();
		selectChat.value.title=sparkList.value[0].content.text;
		selectChat.value.list=JSON.stringify(sparkList.value);
		if (selectChat.value.id==null){
			addSparkChat(selectChat.value).then(res=>{
			if (res.code===200){
				selectChat.value.id=res.data;
				querySparkChatFun();
			}
			})
		}else {
			updateSparkChat(selectChat.value);
			querySparkChatFun();
		}
	}
}

/**
 * 删除会话记录
 */
function deleteSparkChatFun(val){
	deleteSparkChat(val).then(res=>{
		querySparkChatFun();
		ElMessage({
			message: res.msg,
			type: res.code==200?'success' :'error',
			plain: true,
		})
	})
}


/**
 * 校验用户是否已经登录
 */
function verifyUser() {
	getVerifyUser().then((res) => {
		if (res.code === 200) {
			localStorage.setItem('token', res.data)
			new selUserInfoFun()
		} else {
			loginShow.value = true;
		}
	})
}

/**
 * 接收登录状态
 */
function receiveLogin(e) {
	selUserInfoFun();
}

/**
 * 查询用户信息
 * @constructor
 */
function selUserInfoFun() {
	getSelUserInfo().then((res) => {
		if (res.code === 200) {
			userInfo.value = res.data;
			form.value.userId=res.data.userId;
			querySparkChatFun();
			queryAllLargeModeFun();
			openSocket();
			loginShow.value = false;
		}else {
			loginShow.value = true;
		}
	})
}
/**
 * 查询用户历史记录
 */
function querySparkChatFun(){
	querySparkChat({}).then(res=>{
		if(res.code === 200){
			historyList.value=res.data;
		}
	})
}
/**
 * 查询模型分类
 */
function queryAllLargeModeFun(){
	queryAllLargeMode({}).then(res=>{
		if(res.code === 200){
			form.value.chatType=res.data[0]?.modelKey || null;
			selectChat.value.modelKey=res.data[0]?.modelKey || null;
			assistantList.value=res.data;
		}
	})
}

/**
 * 切换历史/模型分类
 * @param type
 */
function modelTypeFun(type){
	modelType.value=type;
}
/**
 * 页面销毁之前
 */
onBeforeUnmount(() => {
	closeSocket();
})
</script>

4.css

复制代码
<style scoped>
.content-container {
	height: calc(100vh - 74px);
	width: 100%;
	display: flex;
	padding: 4px 0 4px 0;
}
 .side{
   width: 260px;
	 height: 100%;
 }
 .content{
	 width: calc(100% - 310px);
	 height: 100%;
	 display: flex;
	 flex-direction: column;
	 align-items: center;
	 user-select: text;
 }
 .content-body{
	 width: 100%;
	 flex: 1;
	 overflow-y: scroll;
	 display: flex;
   align-items: center;
	 flex-direction: column;
 }
 .item-content{
	 width: 85%;
 }
 .content-foot{
	 width: 85%;
	 min-height: 120px;
	 max-height: 300px;
	 border-radius: 15px;
	 display: flex;
	 align-items: center;
	 flex-direction: column;
	 padding: 5px 0 5px 0;
 }
 .input-texture{
	 width: 98%;
	 height: auto;
 }

 .foot-btn{
   height: 40px;
	 width: 98%;
	 display: flex;
	 justify-content: space-between;
	 align-items: center;
 }
 :deep(.el-textarea__inner) {
	 outline: none;
	 border: none;
	 resize: none;
	 box-shadow: none;
	 background:transparent;
	 font-size: large;
 }
 .side-logo{
   width: 100%;
	 height:100px;
	 padding: 0 20px 0 20px;
 }
 .side-api{
	 width: 100%;
	 height:50px;
	 padding: 0 20px 0 20px;
	 justify-content: space-between;
 }
 .side-talke{
	 width: 100%;
	 height:50px;
	 padding: 0 20px 0 20px;
 }
 .talke{
	 width: 100%;
	 height: 40px;
	 border-radius: 6px;
 }
.side-history{
	width: 100%;
	height:50px;
	justify-content: space-evenly;
}
.side-content{
	width: 100%;
	height: calc(100% - 300px);
}
.side-foot{
	width: 100%;
	height:50px;
}
.text-span{
	white-space: pre-wrap;
}
</style>

备注:样式你不用安装也可以,你根据自己需求重新也可以

相关推荐
passerby606141 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte3 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc