mirror of https://gitee.com/godoos/godoos.git
13 changed files with 799 additions and 4 deletions
@ -0,0 +1,105 @@ |
|||||
|
<script setup lang="ts"> |
||||
|
import { useChatStore } from '@/stores/chat'; |
||||
|
import { Search } from '@element-plus/icons-vue'; |
||||
|
const store = useChatStore() |
||||
|
onMounted(() => { |
||||
|
store.initChat() |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<el-container class="container"> |
||||
|
<!--菜单--> |
||||
|
<el-aside class="menu"> |
||||
|
<chat-menu /> |
||||
|
</el-aside> |
||||
|
<el-container class="side" v-if="store.currentNavId < 3"> |
||||
|
<!--搜索栏--> |
||||
|
<el-header class="search" v-if="store.currentNavId < 2"> |
||||
|
<el-input placeholder="搜索" :prefix-icon="Search" class="search-input" v-model="store.search" /> |
||||
|
</el-header> |
||||
|
<!--好友列表--> |
||||
|
<el-main class="list"> |
||||
|
<el-scrollbar> |
||||
|
<chat-msg-list v-if="store.currentNavId == 0" /> |
||||
|
<chat-user-list v-if="store.currentNavId == 1" /> |
||||
|
<chat-work-list v-if="store.currentNavId == 2" /> |
||||
|
</el-scrollbar> |
||||
|
</el-main> |
||||
|
</el-container> |
||||
|
<el-container class="chat-box"> |
||||
|
<chat-box v-if="store.currentNavId < 2" /> |
||||
|
</el-container> |
||||
|
<el-container class="chat-setting" v-if="store.currentNavId == 5"> |
||||
|
<ChatUserSetting /> |
||||
|
</el-container> |
||||
|
</el-container> |
||||
|
|
||||
|
</template> |
||||
|
<style scoped> |
||||
|
.container { |
||||
|
display: flex; |
||||
|
height: 100%; |
||||
|
width: 100%; |
||||
|
overflow-y: hidden; |
||||
|
overflow-x: hidden; |
||||
|
} |
||||
|
|
||||
|
.menu { |
||||
|
width: 65px; |
||||
|
background-color: #2E2E2E; |
||||
|
overflow-y: hidden; |
||||
|
overflow-x: hidden; |
||||
|
-webkit-app-region: drag; |
||||
|
} |
||||
|
|
||||
|
.side { |
||||
|
flex: 1; |
||||
|
/* 占据剩余宽度 */ |
||||
|
max-height: max-content; |
||||
|
border-right: 1px solid #edebeb; |
||||
|
overflow-y: hidden; |
||||
|
overflow-x: hidden; |
||||
|
background-color: #F7F7F7; |
||||
|
} |
||||
|
|
||||
|
.search { |
||||
|
width: 100%; |
||||
|
/* 占据整个宽度 */ |
||||
|
|
||||
|
height: 50px; |
||||
|
padding: 0; |
||||
|
-webkit-app-region: drag; |
||||
|
} |
||||
|
|
||||
|
.search-input { |
||||
|
width: calc(100% - 20px); |
||||
|
/* 减去左右边距 */ |
||||
|
margin: 10px; |
||||
|
-webkit-app-region: no-drag; |
||||
|
--el-input-placeholder-color: #818181 !important; |
||||
|
--el-input-icon-color: #5D5D5D !important; |
||||
|
} |
||||
|
|
||||
|
.list { |
||||
|
width: 100%; |
||||
|
/* 占据整个宽度 */ |
||||
|
padding: 0; |
||||
|
overflow-y: hidden; |
||||
|
overflow-x: hidden; |
||||
|
} |
||||
|
|
||||
|
.chat-box { |
||||
|
flex: 3; |
||||
|
/* 占据剩余宽度的三倍 */ |
||||
|
max-height: max-content; |
||||
|
background-color: #F5F5F5; |
||||
|
} |
||||
|
|
||||
|
.chat-setting { |
||||
|
width: calc(100% - 65px); |
||||
|
/* 占据整个宽度 */ |
||||
|
height: 100%; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,170 @@ |
|||||
|
<script setup lang="ts"> |
||||
|
import { useChatStore } from '@/stores/chat'; |
||||
|
const store = useChatStore() |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<div class="chatbox-main" v-if="store.targetUserId > 0"> |
||||
|
<!--聊天顶部区--> |
||||
|
<el-header class="chat-header"> |
||||
|
<div class="header-title">{{ store.targetUserInfo.username }}</div> |
||||
|
</el-header> |
||||
|
<!--聊天主体区--> |
||||
|
<el-main class="msg-main"> |
||||
|
<el-scrollbar ref="store.scrollbarRef"> |
||||
|
<div ref="store.innerRef"> |
||||
|
<ChatMessage /> |
||||
|
</div> |
||||
|
</el-scrollbar> |
||||
|
</el-main> |
||||
|
<el-footer class="msg-footer"> |
||||
|
<!--聊天输入选项--> |
||||
|
<div class="input-option"> |
||||
|
<el-icon :size="20" class="input-option-icon"> |
||||
|
<Picture /> |
||||
|
</el-icon> |
||||
|
<el-icon :size="20" class="input-option-icon"> |
||||
|
<Link /> |
||||
|
</el-icon> |
||||
|
<el-icon :size="20" class="input-option-icon"> |
||||
|
<Delete /> |
||||
|
</el-icon> |
||||
|
</div> |
||||
|
<!--聊天输入区--> |
||||
|
<div class="input-textarea"> |
||||
|
<el-input type="textarea" maxlength="1000" resize="none" class="textarea" |
||||
|
@keyup.enter.exact="store.sendMessage" v-model="store.message" /> |
||||
|
</div> |
||||
|
<!--聊天发送按钮--> |
||||
|
<el-tooltip placement="top" content="按enter键发送,按ctrl+enter键换行"> |
||||
|
<el-icon :size="22" class="input-button"> |
||||
|
<Promotion /> |
||||
|
</el-icon> |
||||
|
</el-tooltip> |
||||
|
</el-footer> |
||||
|
</div> |
||||
|
<div class="no-message-container" v-else> |
||||
|
<el-icon :size="180" color="#0078d7"> |
||||
|
<ChatDotRound /> |
||||
|
</el-icon> |
||||
|
</div> |
||||
|
</template> |
||||
|
<style scoped> |
||||
|
.chatbox-main { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.chat-header { |
||||
|
width: 100%; |
||||
|
/* 占据整个宽度 */ |
||||
|
height: 50px; |
||||
|
line-height: 50px; |
||||
|
padding: 0; |
||||
|
-webkit-app-region: drag; |
||||
|
} |
||||
|
|
||||
|
header-title { |
||||
|
font-size: 20px; |
||||
|
text-align: left; |
||||
|
margin-left: 15px; |
||||
|
} |
||||
|
|
||||
|
.msg-main { |
||||
|
width: 100%; |
||||
|
/* 占据整个宽度 */ |
||||
|
height: calc(70% - 50px); |
||||
|
padding: 0; |
||||
|
border-top-width: 1px; |
||||
|
border-bottom-width: 1px; |
||||
|
border-left-width: 0; |
||||
|
border-right-width: 0; |
||||
|
border-color: #D6D6D6; |
||||
|
border-style: solid; |
||||
|
} |
||||
|
.msg-footer { |
||||
|
width: 100%; |
||||
|
/* 占据整个宽度 */ |
||||
|
height: 30%; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
.input-option { |
||||
|
height: 20px; |
||||
|
padding: 5px; |
||||
|
} |
||||
|
|
||||
|
.input-option-icon { |
||||
|
color: #494949; |
||||
|
margin-left: 20px; |
||||
|
margin-top: 5px; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.input-textarea { |
||||
|
height: calc(100% - 50px); |
||||
|
width: calc(100% - 20px); |
||||
|
/* 减去左右边距 */ |
||||
|
margin: 10px; |
||||
|
} |
||||
|
|
||||
|
.textarea { |
||||
|
font-size: 16px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
line-height: 1.5; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
overflow-y: hidden; |
||||
|
overflow-x: hidden; |
||||
|
--el-input-border-radius: 0; |
||||
|
--el-input-border-color: transparent; |
||||
|
--el-input-hover-border-color: transparent; |
||||
|
--el-input-clear-hover-color: transparent; |
||||
|
--el-input-focus-border-color: transparent; |
||||
|
} |
||||
|
|
||||
|
.input-button { |
||||
|
position: absolute; |
||||
|
bottom: 12px; |
||||
|
right: 12px; |
||||
|
width: 30px; |
||||
|
/* 缩小宽度 */ |
||||
|
height: 30px; |
||||
|
/* 减小高度 */ |
||||
|
border-radius: 50%; |
||||
|
/* 较小的圆角 */ |
||||
|
background-color: #E8F0FE; |
||||
|
/* 浅蓝色,符合Win11的轻量风格 */ |
||||
|
color: #0078D4; |
||||
|
/* 使用Win11的强调色作为文字颜色 */ |
||||
|
font-weight: bold; |
||||
|
border: 1px solid #B3D4FC; |
||||
|
/* 添加边框,保持简洁风格 */ |
||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); |
||||
|
/* 轻微阴影 */ |
||||
|
transition: all 0.2s ease; |
||||
|
/* 快速过渡效果 */ |
||||
|
} |
||||
|
|
||||
|
.input-button:hover { |
||||
|
background-color: #D1E4FF; |
||||
|
/* 悬浮时颜色略深,保持浅色调 */ |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
/* 稍微增强阴影 */ |
||||
|
} |
||||
|
|
||||
|
.input-button:active { |
||||
|
background-color: #B3D4FC; |
||||
|
/* 按下时颜色更深,但依然保持清新 */ |
||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0.1); |
||||
|
/* 回复初始阴影 */ |
||||
|
transform: translateY(1px); |
||||
|
/* 微小下移,模拟按下 */ |
||||
|
} |
||||
|
.no-message-container { |
||||
|
height: 100%; |
||||
|
margin: 120px auto; |
||||
|
text-align: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,72 @@ |
|||||
|
<script setup> |
||||
|
import {ref} from "vue"; |
||||
|
import { useChatStore } from "@/stores/chat"; |
||||
|
import {Setting as SettingIcon} from "@element-plus/icons-vue"; |
||||
|
const store = useChatStore() |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<el-row> |
||||
|
<el-avatar shape="square" :size="40" class="userAvatar" :src="store.userInfo.avatar"/> |
||||
|
</el-row> |
||||
|
<el-row @click="store.setCurrentNavId(0)"> |
||||
|
<el-icon v-if="store.currentNavId === 0" class="menu-icon-on"> |
||||
|
<ChatLineRound /> |
||||
|
</el-icon> |
||||
|
<el-icon v-else class="menu-icon"> |
||||
|
<ChatRound /> |
||||
|
</el-icon> |
||||
|
</el-row> |
||||
|
<el-row @click="store.setCurrentNavId(1)"> |
||||
|
<el-icon v-if="store.currentNavId === 1" class="menu-icon-on"> |
||||
|
<UserFilled /> |
||||
|
</el-icon> |
||||
|
<el-icon v-else class="menu-icon"> |
||||
|
<User /> |
||||
|
</el-icon> |
||||
|
</el-row> |
||||
|
<el-row @click="store.setCurrentNavId(2)"> |
||||
|
<el-icon v-if="store.currentNavId === 2" class="menu-icon-on"> |
||||
|
<Platform /> |
||||
|
</el-icon> |
||||
|
<el-icon v-else class="menu-icon"> |
||||
|
<Monitor /> |
||||
|
</el-icon> |
||||
|
</el-row> |
||||
|
<el-row @click="store.setCurrentNavId(5)"> |
||||
|
<el-icon v-if="store.currentNavId === 5" class="menu-icon-on"> |
||||
|
<SettingIcon /> |
||||
|
</el-icon> |
||||
|
<el-icon v-else class="menu-icon"> |
||||
|
<SettingIcon /> |
||||
|
</el-icon> |
||||
|
</el-row> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
.userAvatar { |
||||
|
margin: 30px auto 10px; |
||||
|
-webkit-app-region: no-drag |
||||
|
} |
||||
|
|
||||
|
.menu-icon { |
||||
|
margin: 20px auto; |
||||
|
font-size: 25px; |
||||
|
color: #8F8F8F; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.menu-icon-on { |
||||
|
margin: 20px auto; |
||||
|
font-size: 25px; |
||||
|
color: #07C160; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
/* 新增样式 */ |
||||
|
.floating-button { |
||||
|
position: fixed; |
||||
|
bottom: 20px; |
||||
|
right: 20px; |
||||
|
z-index: 1000; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,166 @@ |
|||||
|
<script setup lang="ts"> |
||||
|
import { useChatStore } from '@/stores/chat'; |
||||
|
const store = useChatStore() |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<div v-for="item in store.msgList"> |
||||
|
<!--聊天记录-用户--> |
||||
|
<div v-if="item.userInfo.id === store.targetUserId"> |
||||
|
<div class="chat-item"> |
||||
|
<el-row> |
||||
|
<el-col :span="8" /> |
||||
|
<el-col :span="14"> |
||||
|
<el-row> |
||||
|
<el-col :span="24"> |
||||
|
<div class="chat-name-me">{{ item.userInfo.username }}</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<div class="bubble-me" @contextmenu.prevent="store.showContextMenu($event, item.id)"> |
||||
|
<div class="chat-font"> |
||||
|
{{ item.content }} |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :span="2"> |
||||
|
<div class="chat-avatar"> |
||||
|
<el-avatar shape="square" style="margin: 0;float: left" :size="32" class="userAvatar" |
||||
|
:src="item.userInfo.avatar" /> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!--聊天记录-好友--> |
||||
|
<div v-else> |
||||
|
<div class="chat-item"> |
||||
|
<el-row> |
||||
|
<el-col :span="2"> |
||||
|
<div class="chat-avatar"> |
||||
|
<el-avatar shape="square" style="margin: 0;float: right" :size="32" class="userAvatar" |
||||
|
:src="item.userInfo.avatar" /> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :span="14"> |
||||
|
<el-row> |
||||
|
<el-col :span="24"> |
||||
|
<div class="chat-name-other">{{ item.userInfo.username }}</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<div class="bubble-other"> |
||||
|
<div class="chat-font"> |
||||
|
{{ item.content }} |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :span="8" /> |
||||
|
</el-row> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div v-if="item.type === 1"> |
||||
|
<div class="withdraw"> |
||||
|
{{ item.userInfo.id === store.targetUserId ? "你" : item.userInfo.username }}撤回了一条消息 |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!--悬浮菜单--> |
||||
|
<div class="context-menu" v-if="store.contextMenu.visible" |
||||
|
:style="{ top: `${store.contextMenu.y}px`, left: `${store.contextMenu.x}px` }"> |
||||
|
<div v-for="item in store.contextMenu.list" class="context-menu-item"> |
||||
|
<div class="context-menu-item-font" @click="store.handleContextMenu(item.id)"> |
||||
|
{{ item.label }} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
.bubble-me { |
||||
|
background-color: #95EC69; |
||||
|
float: right; |
||||
|
border-radius: 4px; |
||||
|
margin-right: 5px; |
||||
|
margin-top: 5px; |
||||
|
} |
||||
|
|
||||
|
.bubble-me:hover { |
||||
|
background-color: #89D961; |
||||
|
} |
||||
|
|
||||
|
.chat-name-me { |
||||
|
font-size: 14px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
line-height: 1.5; |
||||
|
color: #B2B2B2; |
||||
|
float: right; |
||||
|
margin-right: 5px; |
||||
|
} |
||||
|
|
||||
|
.bubble-other { |
||||
|
background-color: #FFFFFF; |
||||
|
float: left; |
||||
|
border-radius: 4px; |
||||
|
margin-left: 5px; |
||||
|
margin-top: 5px; |
||||
|
} |
||||
|
|
||||
|
.bubble-other:hover { |
||||
|
background-color: #EBEBEB; |
||||
|
} |
||||
|
|
||||
|
.chat-name-other { |
||||
|
font-size: 14px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
line-height: 1.5; |
||||
|
color: #B2B2B2; |
||||
|
float: left; |
||||
|
margin-left: 5px; |
||||
|
} |
||||
|
|
||||
|
.chat-font { |
||||
|
margin: 8px; |
||||
|
font-size: 15px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
|
||||
|
.chat-avatar { |
||||
|
margin: 5px; |
||||
|
} |
||||
|
|
||||
|
.chat-item { |
||||
|
margin: 5px; |
||||
|
} |
||||
|
|
||||
|
.withdraw { |
||||
|
text-align: center; |
||||
|
font-size: 13px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
color: #999999; |
||||
|
line-height: 3.2; |
||||
|
} |
||||
|
|
||||
|
.context-menu { |
||||
|
position: fixed; |
||||
|
background-color: white; |
||||
|
z-index: 9999; |
||||
|
border: 1px solid #cccc; |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.context-menu-item { |
||||
|
width: 80px; |
||||
|
height: 30px; |
||||
|
} |
||||
|
|
||||
|
.context-menu-item:hover { |
||||
|
background-color: #E2E2E2; |
||||
|
} |
||||
|
|
||||
|
.context-menu-item-font { |
||||
|
font-size: 14px; |
||||
|
text-align: center; |
||||
|
font-family: Arial, sans-serif; |
||||
|
line-height: 2.2; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,71 @@ |
|||||
|
<script setup> |
||||
|
import { ref } from "vue"; |
||||
|
import { useChatStore } from "@/stores/chat"; |
||||
|
const store = useChatStore() |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<div v-for="item in store.chatList"> |
||||
|
<div class="list-item" @click="store.changeChatList(item)" |
||||
|
:style="{ backgroundColor: item.id === store.targetUserId ? '#C4C4C4' : '' }"> |
||||
|
<el-row> |
||||
|
<el-col :span="6"> |
||||
|
<el-avatar shape="square" :size="40" class="avatar" :src="item.avatar" /> |
||||
|
</el-col> |
||||
|
<el-col :span="18"> |
||||
|
<el-row> |
||||
|
<el-col :span="18"> |
||||
|
<div class="previewName">{{ item.name }}</div> |
||||
|
</el-col> |
||||
|
<el-col :span="6"> |
||||
|
<div class="previewTime">{{ item.previewTimeFormat }}</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<el-row> |
||||
|
<div v-if="item.previewType === 0" class="previewChat">{{ item.previewMessage }}</div> |
||||
|
<div v-if="item.previewType === 1" class="previewChat">{{ item.userId === id ? "你" : "\"" + item.name + |
||||
|
"\""}}撤回了一条消息</div> |
||||
|
</el-row> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
.list-item { |
||||
|
width: 100%; |
||||
|
height: 60px; |
||||
|
} |
||||
|
|
||||
|
.list-item:hover { |
||||
|
background-color: #D0D0D0; |
||||
|
} |
||||
|
|
||||
|
.avatar { |
||||
|
margin: 10px |
||||
|
} |
||||
|
|
||||
|
.previewName { |
||||
|
margin-top: 10px; |
||||
|
font-size: 15px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
|
||||
|
.previewChat { |
||||
|
font-size: 14px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.previewTime { |
||||
|
float: right; |
||||
|
margin-top: 10px; |
||||
|
margin-right: 10px; |
||||
|
font-size: 12px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
color: #999999; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,71 @@ |
|||||
|
<script setup> |
||||
|
import { ref } from "vue"; |
||||
|
import { useChatStore } from "@/stores/chat"; |
||||
|
const store = useChatStore() |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<div v-for="item in store.chatList"> |
||||
|
<div class="list-item" @click="store.changeChatList(item)" |
||||
|
:style="{ backgroundColor: item.id === store.targetUserId ? '#C4C4C4' : '' }"> |
||||
|
<el-row> |
||||
|
<el-col :span="6"> |
||||
|
<el-avatar shape="square" :size="40" class="avatar" :src="item.avatar" /> |
||||
|
</el-col> |
||||
|
<el-col :span="18"> |
||||
|
<el-row> |
||||
|
<el-col :span="18"> |
||||
|
<div class="previewName">{{ item.name }}</div> |
||||
|
</el-col> |
||||
|
<el-col :span="6"> |
||||
|
<div class="previewTime">{{ item.previewTimeFormat }}</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<el-row> |
||||
|
<div v-if="item.previewType === 0" class="previewChat">{{ item.previewMessage }}</div> |
||||
|
<div v-if="item.previewType === 1" class="previewChat">{{ item.userId === id ? "你" : "\"" + item.name + |
||||
|
"\""}}撤回了一条消息</div> |
||||
|
</el-row> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
.list-item { |
||||
|
width: 240px; |
||||
|
height: 60px; |
||||
|
} |
||||
|
|
||||
|
.list-item:hover { |
||||
|
background-color: #D0D0D0; |
||||
|
} |
||||
|
|
||||
|
.avatar { |
||||
|
margin: 10px |
||||
|
} |
||||
|
|
||||
|
.previewName { |
||||
|
margin-top: 10px; |
||||
|
font-size: 15px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
|
||||
|
.previewChat { |
||||
|
font-size: 14px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.previewTime { |
||||
|
float: right; |
||||
|
margin-top: 10px; |
||||
|
margin-right: 10px; |
||||
|
font-size: 12px; |
||||
|
font-family: Arial, sans-serif; |
||||
|
color: #999999; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,23 @@ |
|||||
|
<template> |
||||
|
<el-form :model="form" label-width="auto" style="padding: 30px;"> |
||||
|
<el-form-item label="昵称"> |
||||
|
<el-input v-model="form.nickname" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" @click="onSubmit">保存</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { reactive } from 'vue' |
||||
|
|
||||
|
// do not use same name with ref |
||||
|
const form = reactive({ |
||||
|
nickname: '', |
||||
|
}) |
||||
|
|
||||
|
const onSubmit = () => { |
||||
|
console.log('submit!') |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,10 @@ |
|||||
|
<script setup> |
||||
|
import { ref } from "vue"; |
||||
|
import { useChatStore } from "@/stores/chat"; |
||||
|
const store = useChatStore() |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
|
||||
|
</template> |
@ -0,0 +1,86 @@ |
|||||
|
import { defineStore } from 'pinia' |
||||
|
import emojiList from "@/assets/emoji.json" |
||||
|
import { getSystemConfig } from '@/system/config' |
||||
|
export const useChatStore = defineStore('chatStore', () => { |
||||
|
const userList: any = ref([]) // 用户列表
|
||||
|
const chatList: any = ref([]) // 消息列表
|
||||
|
const msgList: any = ref([]) //聊天消息列表
|
||||
|
const userInfo: any = ref({}) |
||||
|
const showChooseFile = ref(false) |
||||
|
const currentPage = ref(1) |
||||
|
const pageSize = ref(50) |
||||
|
const scrollbarRef = ref() |
||||
|
const innerRef = ref() |
||||
|
const config = getSystemConfig() |
||||
|
const currentNavId = ref(0) |
||||
|
const message: any = ref() |
||||
|
const targetUserInfo:any = ref({}) |
||||
|
const targetUserId = ref(0) |
||||
|
const search = ref('') |
||||
|
const contextMenu = ref({ |
||||
|
visible: false, |
||||
|
chatMessageId: 0, |
||||
|
list: [ |
||||
|
{ |
||||
|
id: 2, |
||||
|
label: '撤回', |
||||
|
} |
||||
|
], |
||||
|
x: 0, |
||||
|
y: 0 |
||||
|
}) |
||||
|
const initChat = () => { |
||||
|
if(config.userInfo.avatar == ''){ |
||||
|
config.userInfo.avatar = '/logo.png' |
||||
|
} |
||||
|
userInfo.value = config.userInfo |
||||
|
} |
||||
|
const setCurrentNavId = (id: number) => { |
||||
|
currentNavId.value = id |
||||
|
} |
||||
|
const sendMessage = async () => { |
||||
|
await setScrollToBottom() |
||||
|
} |
||||
|
const setScrollToBottom = async () => { |
||||
|
await nextTick() |
||||
|
const max = innerRef.value.clientHeight |
||||
|
scrollbarRef.value.setScrollTop(max) |
||||
|
} |
||||
|
const changeChatList = async (item:any) => { |
||||
|
// const res = await getChatList(id)
|
||||
|
// chatList.value = res.data
|
||||
|
} |
||||
|
const handleContextMenu = async (id: number) => { |
||||
|
contextMenu.value.visible = false; |
||||
|
} |
||||
|
const showContextMenu = (event: any, id: number) => { |
||||
|
contextMenu.value.visible = true; |
||||
|
contextMenu.value.chatMessageId = id; |
||||
|
contextMenu.value.x = event.x; |
||||
|
contextMenu.value.y = event.y; |
||||
|
} |
||||
|
return { |
||||
|
emojiList, |
||||
|
userList, |
||||
|
chatList, |
||||
|
msgList, |
||||
|
userInfo, |
||||
|
search, |
||||
|
showChooseFile, |
||||
|
currentPage, |
||||
|
pageSize, |
||||
|
scrollbarRef, |
||||
|
innerRef, |
||||
|
currentNavId, |
||||
|
targetUserInfo, |
||||
|
targetUserId, |
||||
|
message, |
||||
|
contextMenu, |
||||
|
initChat, |
||||
|
setCurrentNavId, |
||||
|
sendMessage, |
||||
|
changeChatList, |
||||
|
handleContextMenu, |
||||
|
showContextMenu |
||||
|
} |
||||
|
}) |
Loading…
Reference in new issue