Files
ckb-SuperAdmin/Backend/src/components/group/GroupPanel.vue
2025-03-12 12:48:13 +08:00

818 lines
18 KiB
Vue
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-container class="container">
<el-header class="header">
<span>群信息</span>
<el-tooltip content="发送消息" placement="top">
<i class="icon-send el-icon-chat-line-square" @click="sendGroup" />
</el-tooltip>
<i class="el-icon-close" @click="$emit('close')" />
</el-header>
<el-main class="main lum-scrollbar">
<div class="list-item flex">
<p>
<span>群名称</span>
<span class="group-setting-title">{{ detail.groupName }}</span>
</p>
<span
v-show="detail.is_manager"
class="more"
@click="isShowManager = true"
>管理
</span>
</div>
<div class="list-item">
<span>群主</span>
<span class="group-boss-name">{{ detail.groupOwner }}</span>
</div>
<div class="list-item">
<span>我的群昵称</span>
<span v-if="!isEditRemark" class="edit-visit-card">
<span>
{{ detail.visitCard }}
<span v-show="!detail.visitCard" style="font-size: 12px">
添加群名片
</span>
</span>
<i
class="el-icon-edit-outline edit-remark-icon"
@click="
isEditRemark = true
editRemarkText = detail.visitCard
"
/>
</span>
<span v-else>
<input
v-model="editRemarkText"
class="edit-input"
type="text"
v-focus
@keyup.enter="editRemark"
/>
<span class="input-submit" @click="editRemark">确认</span>
</span>
</div>
<div class="list-item flex">
<span>消息免打扰</span>
<el-switch
v-model="detail.disturb"
inactive-color="#e0d6d6"
:disabled="disturbDisabled"
@change="editDisturb"
/>
</div>
<!-- 预留 -->
<div class="list-item flex">
<span>全员禁言</span>
<el-switch v-model="detail.no_message" inactive-color="#e0d6d6" />
</div>
<div class="list-item">
<span>群成员</span>
<span>{{ members.length }} </span>
</div>
<div class="list-item-tips">群主已开启新成员入群可查看所有聊天记录</div>
<div class="list-item">群简介</div>
<div class="list-item-tips">
{{ detail.groupProfile ? detail.groupProfile : '暂无群简介' }}
</div>
<div class="list-item flex">
<span>群公告</span>
<span
v-show="detail.group_notice"
class="more"
@click="isShowGroupNotice = true"
>更多
</span>
</div>
<div class="list-item-tips group-notice">
<span v-if="detail.group_notice.title">
<b>#{{ detail.group_notice.title }}#</b><br />
{{ detail.group_notice.content }}
</span>
<span v-else>暂无群公告</span>
</div>
<div class="list-item">
<p class="group-invite" @click="addGroupMembers">
<i class="el-icon-plus" />
<span>&nbsp;邀请好友</span>
</p>
</div>
<div class="list-item">
<div class="member-box">
<div class="view-box">
<i class="iconfont icon-sousuo i-sousuo" />
<input type="text" placeholder="搜索群成员" v-model="keywords" />
</div>
<el-row class="row-header">
<el-col :span="11">昵称</el-col>
<el-col :span="8">名片</el-col>
<el-col :span="5">性别</el-col>
</el-row>
<template v-if="searchs.length == 0">
<el-row class="row-items">
<el-col :span="24">
<p style="text-align:center;">无数据</p>
</el-col>
</el-row>
</template>
<template v-else>
<el-row
v-for="member in searchs"
:key="member.user_id"
class="row-items"
@click.native="openUserDetail(member.user_id)"
>
<el-col :span="11">
<img
width="20px"
:src="member.avatar"
:onerror="$store.state.detaultAvatar"
/>
<span class="nickname">{{ member.nickname }}</span>
</el-col>
<el-col :span="8">
<span>{{ member.visit_card ? member.visit_card : '-' }}</span>
</el-col>
<el-col :span="5">
<span v-if="member.gender == 1"></span>
<span v-else-if="member.gender == 2"></span>
<span v-else>未知</span>
</el-col>
</el-row>
</template>
</div>
</div>
</el-main>
<el-footer class="footer">
<button @click="isShowSignout = true">退出该群聊</button>
</el-footer>
<!-- 退群提示层 -->
<div class="signout-box no-select" v-show="isShowSignout">
<p v-show="signoutStatus == 0">您确认退出当前群聊吗</p>
<p v-show="signoutStatus == 0">退群后群聊信息将不能查看</p>
<p v-show="signoutStatus == 0" class="signout-btn">
<button @click="signout">确认</button>
<button @click="isShowSignout = false">取消</button>
</p>
<p v-show="signoutStatus == 1" class="signout-btn mt38">
<span style="color: #ccc">
<i class="el-icon-loading" />
正在退出群聊...
</span>
</p>
<p v-show="signoutStatus == 2" class="signout-btn mt38">
<span style="color: #cccccc">退出群聊失败请3(s)后再试...</span>
</p>
<p v-show="signoutStatus == 3" class="signout-btn mt38">
<span style="color: #339e19">
<i class="iconfont icon-success_no_circle" /> 已成功退出群聊...
</span>
</p>
</div>
<!-- 查看好友用户信息 -->
<UserBusinessCard ref="userBusinessCard" />
<!-- 邀请好友组件 -->
<transition name="el-fade-in-linear">
<GroupLaunch
v-if="inviteFriendBox"
:group-id="groupId"
@close="inviteFriendBox = false"
@invite-success="inviteSuccess"
/>
</transition>
<!-- 群管理组件 -->
<transition name="el-fade-in-linear">
<GroupManage
v-if="isShowManager"
:group-id="groupId"
@close="isShowManager = false"
/>
</transition>
<!-- 群公告组件 -->
<transition name="el-fade-in-linear">
<GroupNotice
v-if="isShowGroupNotice"
:group-id="groupId"
@close="isShowGroupNotice = false"
/>
</transition>
</el-container>
</template>
<script>
import { ServeSetNotDisturb } from '@/api/chat'
import {
ServeGroupDetail,
ServeUpdateGroupCard,
ServeSecedeGroup,
ServeGetGroupMembers,
} from '@/api/group'
//创建群聊组件
import GroupLaunch from '@/components/group/GroupLaunch'
import UserBusinessCard from '@/components/user/UserBusinessCard'
import GroupManage from '@/components/group/GroupManage'
import GroupNotice from '@/components/group/GroupNotice'
export default {
name: 'GroupPanel',
components: {
GroupLaunch,
UserBusinessCard,
GroupManage,
GroupNotice,
},
props: {
groupId: {
type: [String, Number],
default: null,
},
},
data() {
return {
detail: {
groupAvatar: '',
groupId: 0,
groupName: '',
groupOwner: '',
groupProfile: '',
disturb: 0,
no_message: false,
visitCard: '',
is_manager: false,
group_notice: [],
},
keywords: '',
members: [],
isEditRemark: false,
editRemarkText: '',
inviteFriendBox: false,
isShowSignout: false,
signoutStatus: 0,
disturbDisabled: false,
// 是否显示群管理窗口
isShowManager: false,
// 是否显示群公告窗口
isShowGroupNotice: false,
}
},
watch: {
groupId: function(value) {
if (value > 0) {
this.loadGroupDetail()
this.loadMembers()
}
},
},
computed: {
searchs() {
return this.keywords == ''
? this.members
: this.members.filter(item => {
return (
item.nickname.match(this.keywords) != null ||
item.user_card.match(this.keywords) != null
)
})
},
},
created() {
if (parseInt(this.groupId) > 0) {
this.loadGroupDetail()
this.loadMembers()
}
},
methods: {
// 加载群组成员列表
loadMembers() {
ServeGetGroupMembers({
group_id: this.groupId,
}).then(res => {
if (res.code == 200) {
this.members = res.data
this.$emit('group-info', {
group_id: this.members.groupId,
members_num: this.members.length,
})
}
})
},
// 加载群信息
loadGroupDetail() {
this.isEditRemark = false
ServeGroupDetail({
group_id: this.groupId,
}).then(res => {
if (res.code == 200) {
let result = res.data
this.detail.groupAvatar = result.avatar
this.detail.groupId = result.group_id
this.detail.userId = res.data.user_id
this.detail.groupName = result.group_name
this.detail.groupOwner = result.manager_nickname
this.detail.groupProfile = result.group_profile
this.detail.disturb = result.not_disturb == 1 ? true : false
this.detail.visitCard = result.visit_card
this.detail.is_manager = result.is_manager
if (result.notice) {
this.detail.group_notice = result.notice
}
}
})
},
// 设置群免打扰状态
editDisturb(value) {
this.disturbDisabled = true
ServeSetNotDisturb({
type: 2,
receive_id: this.groupId,
not_disturb: value ? 1 : 0,
})
.then(res => {
if (res.code == 200) {
this.$emit('disturb-change', {
group_id: this.groupId,
status: value ? 1 : 0,
})
} else {
this.detail.disturb = value ? 0 : 1
}
})
.catch(() => {
this.detail.disturb = value ? 0 : 1
})
.finally(() => {
this.disturbDisabled = false
})
},
// 设置用户群名片
editRemark() {
if (this.editRemarkText == '') {
this.isEditRemark = false
return
}
if (this.detail.visitCard == this.editRemarkText) {
this.isEditRemark = false
return
}
ServeUpdateGroupCard({
group_id: this.groupId,
visit_card: this.editRemarkText,
}).then(res => {
if (res.code == 200) {
this.isEditRemark = false
this.detail.visitCard = this.editRemarkText
}
})
},
// 查看用户信息
openUserDetail(user_id) {
this.$refs.userBusinessCard.open(user_id)
},
// 邀请好友加入群聊
addGroupMembers() {
sessionStorage.setItem('invite_group_id', this.detail.groupId)
this.inviteFriendBox = true
},
// 邀请好友成功之后的回调事件
inviteSuccess() {
this.inviteFriendBox = false
this.loadMembers()
this.$notify({
title: '邀请成功',
message: `好友已成功加入群组...`,
type: 'success',
})
},
// 发送群聊
sendGroup() {
this.$emit('send-group', this.detail.groupId)
},
// 退出群操操作
signout() {
this.signoutStatus = 1
ServeSecedeGroup({
group_id: this.detail.groupId,
})
.then(res => {
if (res.code == 200) {
this.signoutStatus = 3
setTimeout(() => {
this.signoutStatus = 0
this.isShowSignout = false
this.$emit('quit-group')
}, 1500)
} else {
this.signoutStatus = 2
setTimeout(() => {
this.signoutStatus = 0
}, 3000)
}
})
.catch(() => {
this.signoutStatus = 2
setTimeout(() => {
this.signoutStatus = 0
}, 3000)
})
},
},
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
.header {
height: 60px;
line-height: 60px;
padding: 0;
text-align: center;
box-shadow: -1px 0px 5px 0px #cccccc45;
position: relative;
span {
font-size: 16px;
font-weight: 400;
}
.icon-send {
position: absolute;
left: 15px;
top: 22px;
font-size: 18px;
cursor: pointer;
}
.el-icon-close {
position: absolute;
right: 15px;
top: 22px;
font-size: 18px;
cursor: pointer;
}
}
.main {
padding: 0;
}
}
.list-item {
position: relative;
padding: 16px 16px 0;
min-height: 18px;
font-size: 14px;
&.flex {
display: flex;
justify-content: space-between;
}
.edit-visit-card {
position: initial;
color: #a29f9f;
}
.edit-remark-icon {
margin-left: 5px;
color: rgb(169, 184, 187);
position: absolute;
top: 20px;
cursor: pointer;
}
.edit-input {
width: 46%;
height: 25px;
line-height: 25px;
border: 1px solid #92cbff;
padding-left: 5px;
border-radius: 3px;
}
.input-submit {
width: 55px;
text-align: center;
height: 25px;
line-height: 25px;
background-color: #008cee;
border-radius: 2px;
display: inline-block;
color: #fff !important;
font-size: 12px;
margin-left: 10px;
cursor: pointer;
}
.group-setting-title {
max-width: 250px;
display: inline-block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: bottom;
}
.group-boss-name {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-wrap: normal;
max-width: 180px;
position: relative;
top: 4px;
}
.group-invite {
height: 30px;
line-height: 30px;
text-align: center;
color: #877272;
cursor: pointer;
border-radius: 2px;
border: 1px dashed #d9bbbb;
font-size: 13px;
transition: all 0.5s ease-in-out;
&:hover {
color: #ff5722;
border-color: #ff5722;
transform: scale(1.01);
}
}
.more {
color: #409eff;
cursor: pointer;
font-size: 12px;
}
}
.list-item-tips {
font-size: 12px;
color: #b1b1b1;
margin-top: 5px;
padding-left: 16px;
padding-right: 16px;
font-weight: 300;
overflow: hidden;
word-break: break-word;
}
.group-notice {
line-height: 22px;
}
.member-box {
min-height: 180px;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ecebeb;
border-radius: 3px;
.view-box {
width: 100%;
height: 30px;
margin-top: 20px;
margin-bottom: 15px;
position: relative;
input {
width: calc(100% - 40px);
height: 30px;
line-height: 28px;
border-radius: 3px;
border: 1px solid #f1e9e9;
color: #b3b0b0;
font-size: 13px;
padding: 0 10px 0 30px;
&::-webkit-input-placeholder {
color: #ccc9c9;
font-size: 13px;
}
}
.i-sousuo {
color: rgb(179, 176, 176);
position: absolute;
left: 10px;
top: 9px;
}
span {
position: relative;
i {
font-size: 24px;
top: -3px;
left: 10px;
position: absolute;
color: #ccc;
}
}
}
.row-header {
width: 100%;
height: 30px;
margin-bottom: 10px;
border-bottom: 1px solid #e0dddd;
div {
height: 30px;
line-height: 30px;
&:nth-child(2) {
text-align: center;
}
&:nth-child(3) {
text-align: right;
}
}
}
.row-items {
width: 100%;
height: 30px;
margin-bottom: 3px;
font-size: 12px;
cursor: pointer;
&:hover {
background: #f6f6f6;
}
div {
height: 30px;
line-height: 30px;
&:nth-child(2) {
text-align: center;
}
&:nth-child(3) {
text-align: right;
}
}
img {
display: inline-block;
border-radius: 50%;
position: relative;
top: 4px;
}
.nickname {
margin-left: 5px;
&:hover {
color: #3685d6;
}
}
}
}
.signout-box {
width: 100%;
height: 100px;
background: #ffffff;
position: absolute;
z-index: 2;
bottom: 0;
box-shadow: -1px -3px 11px 0px #cccccc82;
-webkit-animation: showFooter 0.35s ease-in-out;
-moz-animation: showFooter 0.35s ease-in-out;
animation: showFooter 0.35s ease-in-out;
p {
&:first-child {
text-align: center;
height: 35px;
line-height: 35px;
}
&:nth-child(2) {
text-align: center;
font-size: 12px;
color: #cccccc;
}
}
.mt38 {
margin-top: 38px;
}
}
.signout-btn {
text-align: center;
margin-top: 10px;
button {
height: 30px;
width: 90px;
line-height: 30px;
background: #007fbb;
border-radius: 3px;
cursor: pointer;
font-size: 14px;
&:first-child {
background: #ff3333;
color: white;
}
&:last-child {
background: #f1eded;
}
}
}
.container .footer {
height: 60px;
padding: 0;
line-height: 60px;
text-align: center;
background-color: #f8f8f8;
button {
width: 180px;
height: 35px;
line-height: 35px;
background: #ed3c3b;
border-radius: 3px;
color: white;
cursor: pointer;
font-size: 12px;
margin: auto auto;
&:active {
background: #f5b8b8;
}
}
}
@keyframes showFooter {
0% {
transform: translateY(75px);
}
to {
transform: translateY(0);
}
}
@-webkit-keyframes showFooter {
0% {
-webkit-transform: translateY(75px);
}
to {
-webkit-transform: translateY(0);
}
}
</style>