如何合并两段代码
<template>
<div class="chat-panel">
<div class="chat-title">影剧坊-小影AI</div>
<div class="message-panel" id="message-panel">
<div class="message-list">
<div
:class="['message-item', item.type == 1 ? 'ai-item' : '']"
v-for="(item, index) in messageList"
:id="'item' + index"
>
<template v-if="item.type == 0">
<div class="message-content">
<div class="content-inner">{{ item.content }}</div>
</div>
<div class="user-icon">用户</div>
</template>
<template v-else>
<div class="user-icon">小影</div>
<div class="message-content ai-item">
<MdPreview
previewTheme="vuepress"
:codeFoldable="false"
editorId="preview"
:modelValue="item.content.join('')"
/>
<div class="loading" v-if="item.loading">
<img src="../assets/ArkTS.gif" width="90" />
<!--HW设计规范加载动画-->
</div>
</div>
</template>
</div>
</div>
</div>
<div class="send-panel">
<el-form :model="formData" ref="formDataRef" @submit.prevent>
<!-- 下拉框 -->
<el-form-item label="模型">
<el-select clearable placeholder="选择模型" v-model="formData.model">
<el-option
value="deepseek-r1:1.5b"
label="deepseek-r1:1.5b"
></el-option>
<el-option value="4.0Ultra" label="科大讯飞"></el-option>
</el-select>
</el-form-item>
<!--input输入-->
<el-form-item label="" prop="content">
<el-input
type="textarea"
:rows="3"
clearable
placeholder="这是一个预设文字"
v-model="formData.content"
@keyup="keySend"
></el-input>
</el-form-item>
<!--input输入-->
<el-form-item label="" prop="" class="send-btn">
<el-button type="primary" @click="sendMessage" :disabled="loading"
>发送(ctrl+enter)</el-button
>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import {
ref,
reactive,
getCurrentInstance,
nextTick,
onMounted,
onUnmounted,
} from "vue";
const { proxy } = getCurrentInstance();
import { MdPreview, MdCatalog } from "md-editor-v3";
import "md-editor-v3/lib/style.css";
const formData = ref({
model: "deepseek-r1:1.5b",
});
const messageList = ref([]);
const loading = ref(false);
const keySend = (event) => {
if (!(event.ctrlKey && event.key === "Enter")) {
return;
}
sendMessage();
};
const sendMessage = () => {
const message = formData.value.content;
if (!message) {
ElMessage({
type: "warning",
message: "请输入内容",
duration: 2000,
});
return;
}
messageList.value.push({
type: 0,
content: message,
});
messageList.value.push({
type: 1,
content: [],
loading: true,
});
loading.value = true;
const eventSource = new EventSource(
`/api/stream?model=${formData.value.model}&message=${message}`
);
formData.value.content = "";
eventSource.onmessage = (event) => {
let response = event.data;
console.log(response);
if (response == "end") {
close();
return;
}
response = JSON.parse(response).content;
messageList.value[messageList.value.length - 1].content.push(response);
//滚动到底部
nextTick(() => {
const content = document.getElementById("message-panel");
content.scrollTop = content.scrollHeight;
});
};
eventSource.onerror = (error) => {
close();
};
const close = () => {
eventSource.close();
messageList.value[messageList.value.length - 1].loading = false;
loading.value = false;
};
};
</script>
<style lang="scss" scoped>
.chat-panel {
background: #eff0f6;
height: calc(90vh);
.chat-title {
text-align: center;
font-size: 20px;
font-weight: bold;
}
.message-panel {
position: relative;
//height: calc(10vh - 234px);
overflow: auto;
padding-bottom: 10px;
.message-list {
margin: 0px auto;
width: 600px;
//聊天框宽
.message-item {
margin: 10px 0px;
display: flex;
.user-icon {
width: 40px;
height: 40px;
line-height: 40px;
border-radius: 20px;
background: #f4e002;
color: rgb(5, 4, 4);
//用户的头像背景颜色
text-align: center;
margin-left: 10px;
}
.message-content {
flex: 1;
margin-left: 10px;
align-items: center;
display: flex;
justify-content: flex-end;
}
.content-inner {
background: #ff0a59f7;
//用户的对话框背景颜色
border-radius: 5px;
padding: 10px;
color: rgb(255, 255, 255);
}
}
.ai-item {
line-height: 23px;
.message-content {
display: block;
background: rgb(255, 255, 255);
border-radius: 5px;
}
.user-icon {
background: #36d01b78;
//小影的头像背景颜色
margin-left: 0px;
}
:deep(.md-editor-previewOnly) {
border-radius: 5px;
background: #ffffff;
//小影的对话框背景颜色
}
:deep(.md-editor-preview-wrapper) {
padding: 10px;
}
.loading {
text-align: center;
}
}
}
}
.send-panel {
position: relative;
margin: 5px auto 0px;
width: 800px;
background: #fff;
border-radius: 5px;
padding: 10px;
.send-btn {
text-align: right;
margin-bottom: 0px;
padding: 5px;
:deep(.el-form-item__content) {
justify-content: flex-end;
}
}
:deep(.el-textarea__inner) {
border: 0 !important;
resize: none !important;
box-shadow: none;
}
}
}
.no-data {
text-align: center;
color: #5f5f5f79;
}
</style>
第二段
<template>
<div
class="container-body ucenter"
:style="{ width: proxy.globalInfo.bodyWidth + 'px' }"
>
<div class="user-banner">
<router-link to="/" class="a-link">首页</router-link>
<span class="iconfont icon-right"></span>
<span>个人中心</span>
</div>
<div class="ucenter-panel">
<div class="user-side">
<!--头像信息-->
<div class="avatar-panel">
<div
class="edit-btn a-link"
v-if="isCurrentUser"
@click="updateUserInfo"
>
修改资料
</div>
<div class="avatar-inner">
<Avatar :userId="userInfo.userId" :width="120"></Avatar>
</div>
<div class="nick-name">
<span>{{ userInfo.nickName }}</span>
<span v-if="userInfo.sex == 0" class="iconfont icon-woman"></span>
<span v-if="userInfo.sex == 1" class="iconfont icon-man"></span>
</div>
<div class="desc">
{{ userInfo.personDescription }}
</div>
</div>
<!--扩展信息-->
<div class="user-extend-panel">
<div class="info-item">
<div class="label iconfont icon-integral">积分</div>
<div
class="value a-link"
v-if="isCurrentUser"
@click="showIntegralRecord"
>
{{ userInfo.currentIntegral }}
</div>
<div v-else class="value">{{ userInfo.currentIntegral }}</div>
</div>
<div class="info-item">
<div class="label iconfont icon-like">获赞</div>
<div class="value">{{ userInfo.likeCount }}</div>
</div>
<div class="info-item">
<div class="label iconfont icon-post">发帖</div>
<div class="value">{{ userInfo.postCount }}</div>
</div>
<div class="info-item">
<div class="label iconfont icon-register">加入</div>
<div class="value">{{ userInfo.joinTime }}</div>
</div>
<div class="info-item">
<div class="label iconfont icon-login">最后登录</div>
<div class="value">{{ userInfo.lastLoginTime }}</div>
</div>
</div>
** <!--在这里写入需要合并的代码以保证效果-->**
</div>
<div class="article-panel">
<el-tabs :model-value="activeTabName" @tab-change="changeTab">
<el-tab-pane label="发帖" :name="0"></el-tab-pane>
<el-tab-pane label="评论" :name="1"></el-tab-pane>
<el-tab-pane label="点赞" :name="2"></el-tab-pane>
<el-tab-pane label="看过" :name="3"></el-tab-pane>
</el-tabs>
<div class="article-list">
<DataList
:loading="loading"
:dataSource="articleListInfo"
@loadData="loadArticle"
noDataMsg="暂无相关文章"
>
<template #default="{ data }">
<ArticleListItem
:data="data"
:showEdit="activeTabName == 0 && isCurrentUser"
:showComment="showComment"
></ArticleListItem>
</template>
</DataList>
</div>
</div>
</div>
<!--修改用户信息-->
<UcenterEditUserInfo
ref="ucenterEditUserInfoRef"
@resetUserInfo="resetUserInfoHandler"
></UcenterEditUserInfo>
<!--用户积分记录-->
<UserIntegralRecord ref="ucenterIntegralRecordRef"></UserIntegralRecord>
</div>
</template>
<script setup>
import ArticleListItem from "@/views/forum/ArticleListItem.vue";
import UcenterEditUserInfo from "./UcenterEditUserInfo.vue";
import UserIntegralRecord from "./UserIntegralRecord.vue";
import { ref, reactive, getCurrentInstance, onMounted, watch } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useStore } from "vuex";
const { proxy } = getCurrentInstance();
const router = useRouter();
const route = useRoute();
const store = useStore();
const api = {
getUserInfo: "/ucenter/getUserInfo",
loadUserArticle: "/ucenter/loadUserArticle",
};
const userId = ref(null);
const userInfo = ref({});
const loadUserInfo = async () => {
let result = await proxy.Request({
url: api.getUserInfo,
params: {
userId: userId.value,
},
errorCallback: () => {
setTimeout(() => {
router.push("/");
}, 1500);
},
});
if (!result) {
return;
}
userInfo.value = result.data;
};
//右侧文章
const activeTabName = ref(0);
const changeTab = (type) => {
activeTabName.value = type;
loadArticle();
};
const loading = ref(false);
const articleListInfo = ref({});
const loadArticle = async () => {
loading.value = true;
let params = {
pageNo: articleListInfo.value.pageNo,
type: activeTabName.value,
userId: userId.value,
};
let result = await proxy.Request({
url: api.loadUserArticle,
params: params,
showLoading: false,
});
loading.value = false;
if (!result) {
return;
}
articleListInfo.value = result.data;
};
const isCurrentUser = ref(false);
//重新设置当前用户
const resetCurrentUser = () => {
const loginUserInfo = store.getters.getLoginUserInfo;
if (loginUserInfo && loginUserInfo.userId === userId.value) {
isCurrentUser.value = true;
} else {
isCurrentUser.value = false;
}
};
watch(
() => store.state.loginUserInfo,
(newVal, oldVal) => {
resetCurrentUser();
},
{ immediate: true, deep: true }
);
watch(
() => route.params.userId,
(newVal, oldVal) => {
if (newVal) {
userId.value = newVal;
resetCurrentUser();
loadUserInfo();
loadArticle();
}
},
{ immediate: true, deep: true }
);
//修改用户信息
const ucenterEditUserInfoRef = ref(null);
const updateUserInfo = () => {
ucenterEditUserInfoRef.value.showEditUserInfoDialog(userInfo.value);
};
const resetUserInfoHandler = (data) => {
userInfo.value = data;
};
//获取用户积分记录
const ucenterIntegralRecordRef = ref(null);
const showIntegralRecord = () => {
ucenterIntegralRecordRef.value.showRecord();
};
const showComment = ref(false);
watch(
() => store.state.sysSetting,
(newVal, oldVal) => {
if (newVal) {
showComment.value = newVal.commentOpen;
}
},
{ immediate: true, deep: true }
);
</script>
<style lang="scss">
.ucenter {
.user-banner {
color: #9ba7b9;
line-height: 35px;
.icon-right {
padding: 0px 5px;
}
}
.ucenter-panel {
display: flex;
.user-side {
width: 300px;
margin-right: 10px;
margin-bottom: 300px;
.avatar-panel {
background: #fff;
text-align: center;
padding: 10px;
.edit-btn {
text-align: right;
font-size: 14px;
}
.avatar-inner {
display: flex;
justify-content: center;
}
.nick-name {
.iconfont {
margin-left: 5px;
color: var(--link);
}
}
.desc {
margin-top: 5px;
text-align: left;
font-size: 14px;
color: #929393;
}
}
.user-extend-panel {
margin-top: 10px;
background: #fff;
padding: 10px;
.info-item {
display: flex;
justify-content: space-between;
line-height: 30px;
.label {
font-size: 13px;
}
.label::before {
font-size: 22px;
color: #888888;
padding-right: 5px;
}
.value {
font-size: 13px;
}
}
}
}
.article-panel {
flex: 1;
background: #fff;
padding: 0px 10px 10px 10px;
}
}
}
</style>