优化代码

This commit is contained in:
pengxiaolong
2025-08-15 22:11:55 +08:00
parent 15335e8921
commit ce21a633ec
9 changed files with 540 additions and 72 deletions

View File

@@ -59,12 +59,13 @@
<script setup>
import { ref, watch, onMounted, onUnmounted } from "vue";
import { getVxQrcode, getScanResult, login } from "@/api/account"; // 导入登录接口
import { getVxQrcode, getScanResult, login, getOtp} from "@/api/account"; // 导入登录接口
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { tokenStore, UserStore } from '@/stores/notice'
import { setStorage , getStorage } from '@/utils/storage.js';
import { goEasyLink } from '@/utils/goeasy.js';
import { ElLoading } from "element-plus";
const router = useRouter();
const refname = ref("");
const refEmail = ref(""); // 邮箱
@@ -73,6 +74,7 @@ const refSwitch = ref(false); // 登录切换/true:微信登录/false:邮箱登
const Qrcode = ref(""); // 二维码
const token = tokenStore()
const user = UserStore()
const info = ref({})
// 登录
function EmailLogin() {
// // 邮箱验证
@@ -98,19 +100,32 @@ function EmailLogin() {
// email: refEmail.value,
password: refpassword.value,
}).then((res) => {
console.log(res);
token.setToken(res.token);
setStorage("token", res.token);
setStorage("email", refEmail.value);
setStorage("password", refpassword.value);
user.setUser(res);
setStorage("user", res);
// otp/getopt 调用
goEasyLink().then(() => {
info.value = res
getOtp().then((res) => {
const data = {
id: String(info.value.id),
avatar: info.value.headerIcon,
nickname: info.value.nickName,
key: res,
}
goEasyLink(data).then(() => {
loading.close();
router.push("/nav");
}).catch((err) => {
ElMessage.error("登录失败:"+err.content);
loading.close();
});
}).catch((err) => {
loading.close();
});
}).catch((err) => {
loading.close();
});
}
// 登录切换
@@ -132,7 +147,6 @@ function register() {
function fetchQrcode() {
getVxQrcode().then((res) => {
Qrcode.value = res;
console.log(res);
});
}
//查询微信扫码是否成功

View File

@@ -6,20 +6,31 @@
<el-splitter-panel size="17%" min="17%" max="25%">
<!-- 会话列表 -->
<div class="demo-panel">
<div
v-infinite-scroll="load"
infinite-scroll-distance="100px"
class="chatList"
style="overflow: auto"
>
<div class="chatItem" v-for="(item, index) in chatList" :key="index">
<div class="Avatar"></div>
<div class="chatList" style="overflow: auto">
<div
class="chatItem"
v-for="(item, index) in chatList"
:key="index"
@click="handleClick(item)"
:style="{ background: handleClickdata == item ? '#f5f5f5' : '' }"
>
<el-badge
:value="item.unread > 0 ? item.unread : ''"
:max="999"
class="item"
>
<div class="Avatar">
<img class="Avatar-img" :src="item.data.avatar" alt="" />
</div>
</el-badge>
<div class="chatContent">
<div class="PersonalInfo">
<div class="name">名称</div>
<div class="time">07-29 14:00</div>
<div class="name">{{ item.data.nickname }}</div>
<div class="time">
{{ TimestamptolocalTime(item.lastMessage.timestamp) }}
</div>
</div>
<div class="chatText">最后一条消息</div>
<div class="chatText">{{ item.lastMessage.payload.text }}</div>
</div>
</div>
</div>
@@ -29,19 +40,87 @@
<el-splitter layout="vertical">
<el-splitter-panel>
<!-- 消息列表 -->
<div class="demo-panel"></div>
<div class="demo-panel">
<div class="chatlist" v-if="handleClickdata != null" style="overflow: auto" ref="chatlistContainer">
<div
class="chatmessages"
v-for="(item, index) in messageslist"
:key="index"
>
<!-- 对方消息 -->
<div
class="messageOtherSide"
v-if="item.senderId == handleClickdata.userId"
>
<!-- 头像 -->
<div class="messageAvatar">
<img
class="Avatar-img"
:src="handleClickdata.data.avatar"
alt=""
/>
</div>
<!-- 三角 -->
<div class="OtherTriangle" v-if="item.type == 'text'" />
<!-- 消息内容 -->
<div class="messageContent" :style="{padding:item.type == 'text'?' 10px 20px 10px 20px':'0'}">
<!-- 文本消息 -->
<div v-if="item.type == 'text'">
{{ item.payload.text }}
</div>
<!-- 图片消息 -->
<PictureMessage :item="item" v-if="item.type == 'image'"></PictureMessage>
</div>
</div>
<!-- 自己消息 -->
<div class="messageMySide" v-if="item.senderId == user.id">
<!-- 消息内容 -->
<div class="messageMyContent" :style="{padding:item.type == 'text'?' 10px 20px 10px 20px':''}">
<!-- 文本消息 -->
<div v-if="item.type == 'text'">
{{ item.payload.text }}
</div>
<!-- 图片消息 -->
<PictureMessage :item="item" v-if="item.type == 'image'"></PictureMessage>
</div>
<div class="MyTriangle" v-if="item.type == 'text'" />
<div class="messageAvatar">
<img class="Avatar-img" :src="headerIcon" alt="" />
</div>
</div>
</div>
</div>
</div>
</el-splitter-panel>
<el-splitter-panel size="20%" min="20%" max="40%">
<!-- 输入框 -->
<div class="demo-panel">
<div class="inputBox">
<div class="Console">
<div class="Console-content">
</div>
<!-- 控制面板 -->
<div class="Console-content">
<!-- 其他的消息 -->
<div class="chat-input-other">
<!-- 图片消息 -->
<div class="chat-input-img">
<img class="chat-input-img-img" src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Album.png" alt="">
</div>
<!-- 邀请消息 -->
<div class="chat-input-img">
<img class="chat-input-img-img" src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/chat_invite.png" alt="">
</div>
</div>
<!-- 发送按钮 -->
<div class="chat-input-Send">发送</div>
</div>
</div>
<div class="input">
<textarea
<textarea
v-model="textarea"
class="textarea"
style="width: 100%; height: 100%"
@@ -64,53 +143,118 @@ import {
onMounted, // 组件挂载完成后执行
onUpdated, // 组件更新后执行
onUnmounted, // 组件销毁前执行
nextTick, // 确保DOM更新完成
} from "vue";
const refname = ref("");
import { goEasyGetConversations, goEasyGetMessages } from "@/utils/goeasy.js";
import { TimestamptolocalTime } from "@/utils/timeConversion.js";
import { IMloginStore } from "@/stores/notice.js";
import { goeasy } from "../../main";
import GoEasy from "goeasy";
import { getPromiseStorage } from "@/utils/storage.js";
import PictureMessage from "@/components/chatMessage/PictureMessage";
var im = goeasy.im;
const counter = IMloginStore();
const textarea = ref(""); // 输入框内容
const chatList = ref([
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
]);
const chatList = ref([]); // 会话列表
const handleClickdata = ref(null); // 选中会话
const messageslist = ref([]); //消息列表
const user = ref(null); // 用户信息
const headerIcon = ref(null); // 用户头像
const chatlistContainer = ref(null); // 聊天列表容器引用
const isLoading = ref(false); // 防止重复加载
function load() {
console.log("加载更多",textarea.value);
} // 加载更多
// 加载更多消息
function loadMore() {
if (isLoading.value) return;
isLoading.value = true;
// 这里添加加载更多消息逻辑/加载完后才改为false
getMoreMessages();
}
watch(refname, async (newQuestion, oldQuestion) => {
// 变化后执行
});
// 滚动事件处理
function scrollHandler() {
const container = chatlistContainer.value;
if (container && container.scrollTop <= 0) {
loadMore();
}
}
//选中会话
function handleClick(item) {
handleClickdata.value = item;
console.log(item);
goEasyGetMessages({
id: item.userId,
timestamp: null,
}).then((res) => {
console.log(res);
messageslist.value = res;
nextTick(() => {
if (chatlistContainer.value) {
chatlistContainer.value.scrollTop = chatlistContainer.value.scrollHeight;
}
});
chatlistContainer.value.addEventListener('scroll', scrollHandler);
});
}
//获取更多消息
function getMoreMessages() {
goEasyGetMessages({
id: handleClickdata.value.userId,
timestamp: messageslist.value[0].timestamp,
}).then((res) => {
isLoading.value = false;
messageslist.value.unshift(...res);
});
}
//更新后的最新会话列表
function onConversationsUpdated(conversations) {
chatList.value = conversations;
}
//获取会话列表
function getChatList() {
goEasyGetConversations().then((res) => {
chatList.value = res.content.conversations;
console.log(chatList.value);
});
}
watch(counter, (newQuestion, oldQuestion) => {
setTimeout(() => {
getChatList();
}, 300);
}),
{ deep: true };
onMounted(() => {
// 组件挂载完成后执行
getPromiseStorage("user")
.then((res) => {
user.value = res;
headerIcon.value = user.value.headerIcon;
console.log(user.value);
})
.catch((err) => {
console.log(err);
});
if (counter.IMstate == true) {
getChatList();
}
setTimeout(() => {
im.on(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, onConversationsUpdated);
}, 1000);
});
onUpdated(() => {
// 组件更新后执行
});
onUnmounted(() => {
// 组件销毁前执行
// 移除滚动事件监听
if (chatlistContainer.value) {
chatlistContainer.value.removeEventListener('scroll', scrollHandler);
}
});
</script>
@@ -151,13 +295,18 @@ onUnmounted(() => {
.Avatar {
width: 50px;
height: 50px;
border-radius: 50%;
border-radius: 10px;
margin-left: 10px;
background-color: #f5f5f5;
}
.Avatar-img {
width: 100%;
height: 100%;
border-radius: 10px;
}
.chatContent {
margin-left: 10px;
width: calc(100% - 80px);
margin-left: 30px;
width: calc(100% - 100px);
height: 60%;
display: flex;
flex-direction: column;
@@ -189,6 +338,76 @@ onUnmounted(() => {
overflow: hidden;
text-overflow: ellipsis; /* 显示省略号 */
}
.chatlist {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.chatmessages {
width: 100%;
height: auto;
margin-top: 20px;
}
.messageOtherSide {
width: 100%;
height: auto;
display: flex;
align-items: self-start;
}
.messageMySide {
width: 100%;
height: auto;
display: flex;
justify-content: end;
align-items: self-start;
}
.messageAvatar {
width: 50px;
height: 50px;
border-radius: 10px;
margin-right: 20px;
margin-left: 20px;
background-color: #f5f5f5;
}
.OtherTriangle {
width: 0;
height: 0;
border-top: 10px solid transparent;
border-right: 10px solid #f5f5f5;
border-bottom: 10px solid transparent;
margin-top: 12px;
}
.MyTriangle {
width: 0;
height: 0;
border-top: 10px solid transparent;
border-left: 10px solid #7bbd0093;
border-bottom: 10px solid transparent;
margin-top: 12px;
}
.messageContent {
max-width: 30%;
height: auto;
min-height: 20px;
background-color: #f5f5f5;
border-radius: 10px;
font-size: 20px;
word-break: break-all; /* 强制换行(适合中文) */
overflow-wrap: break-word; /* 长单词换行(适合英文) */
white-space: normal; /* 允许自动换行 */
}
.messageMyContent {
max-width: 30%;
height: auto;
min-height: 20px;
background-color: #7bbd0093;
border-radius: 10px;
font-size: 20px;
word-break: break-all; /* 强制换行(适合中文) */
overflow-wrap: break-word; /* 长单词换行(适合英文) */
white-space: normal; /* 允许自动换行 */
}
.inputBox {
width: 100%;
height: 100%;
@@ -203,21 +422,66 @@ onUnmounted(() => {
align-items: center;
justify-content: center;
}
.Console-content{
.Console-content {
width: 98%;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.chat-input-other{
display: flex;
align-items: center;
}
.chat-input-img{
width: 40px;
height: 40px;
border-radius: 10px;
display: flex;
margin-left: 10px;
justify-content: center;
align-items: center;
transition: all 0.4s ease;
}
.chat-input-img:hover{
background-color: #d4d4d4;
}
.chat-input-img-img{
width: 30px;
height: 30px;
}
.chat-input-Send {
width: 10%;
height: 80%;
text-align: center;
line-height: 40px;
font-size: 16px;
color: #03aba8;
border-radius: 10px;
margin-right: 6px;
transition: all 0.4s ease;
}
.chat-input-Send:hover {
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.3);
background-color: #03aba82d;
// color: #ffffff;
}
.chat-input-Send:active{
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.input {
width: 98%;
height: calc(100% - 70px);
}
.textarea{
.textarea {
width: 100%;
height: 100%;
border: none;
outline: none;
overflow: hidden;
background-color:#ffffff00;
resize:none;
background-color: #ffffff00;
resize: none;
}
</style>

View File

@@ -843,6 +843,10 @@ onUnmounted(() => {
background-color: #03aba82d;
// color: #ffffff;
}
.chat-input-Send:active{
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.chat-input-Textarea {
width: 100%;
height: 60px;

View File

@@ -1,7 +1,7 @@
<template>
<div class="common-layout">
<el-container>
<!-- 左侧导航栏 -->
<!-- 左侧导航栏 -->
<el-aside class="nav-aside">
<Appaside></Appaside>
</el-aside>
@@ -15,8 +15,49 @@
<script setup>
import Appaside from "/src/components/Appaside.vue";
import { ref, watch, onMounted, onUnmounted } from "vue";
import { getOtp } from "@/api/account";
const user = ref(null); // 用户信息
import { goEasyLink } from "@/utils/goeasy.js";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import {getPromiseStorage } from "@/utils/storage.js";
const router = useRouter();
//自动链接IM
function autoLinkIM() {
getOtp()
.then((res) => {
const data = {
id: String(user.value.id),
avatar: user.value.headerIcon,
nickname: user.value.nickName,
key: res,
};
goEasyLink(data)
.then(() => {
console.log("IM链接成功");
})
.catch((err) => {
ElMessage.error("聊天系统链接失败");
router.push("/");
});
})
.catch((err) => {
ElMessage.error("聊天系统获取失败");
router.push("/");
});
}
onMounted(() => {
getPromiseStorage("user")
.then((res) => {
user.value = res;
autoLinkIM() //自动链接IM
})
.catch((err) => {
console.log(err);
});
});
</script>
<style lang="less">
@@ -43,4 +84,4 @@ html {
// background-image: linear-gradient(0deg, @bg-Sidebar-color-top, @bg-color);
// border: 2px solid @border-color;
}
</style>
</style>