Compare commits
2 Commits
383abed2e8
...
04dcbdf331
Author | SHA1 | Date | |
---|---|---|---|
04dcbdf331 | |||
fa2098c565 |
2
components.d.ts
vendored
2
components.d.ts
vendored
@ -30,6 +30,8 @@ declare module 'vue' {
|
|||||||
LoginMessage: typeof import('./src/components/talk/message/LoginMessage.vue')['default']
|
LoginMessage: typeof import('./src/components/talk/message/LoginMessage.vue')['default']
|
||||||
Message: typeof import('./src/components/x-message/message/index.vue')['default']
|
Message: typeof import('./src/components/x-message/message/index.vue')['default']
|
||||||
MixedMessage: typeof import('./src/components/talk/message/MixedMessage.vue')['default']
|
MixedMessage: typeof import('./src/components/talk/message/MixedMessage.vue')['default']
|
||||||
|
NButton: typeof import('naive-ui')['NButton']
|
||||||
|
NIcon: typeof import('naive-ui')['NIcon']
|
||||||
PageAnimation: typeof import('./src/components/page-animation/index.vue')['default']
|
PageAnimation: typeof import('./src/components/page-animation/index.vue')['default']
|
||||||
RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default']
|
RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
@ -38,7 +38,19 @@ export const ServeTopTalkList = (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清除聊天消息未读数服务接口
|
// 清除聊天消息未读数服务接口
|
||||||
export const ServeClearTalkUnreadNum = (data) => {
|
export const ServeClearTalkUnreadNum = (data, unReadNum) => {
|
||||||
|
console.log("=======chatApp==UnreadNum",unReadNum)
|
||||||
|
if (typeof plus !== 'undefined') {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
//all里面第一个是入口webview
|
||||||
|
OAWebView[0].evalJS(`updateUnreadMsgNumReduce('${unReadNum}')`)
|
||||||
|
} else {
|
||||||
|
document.addEventListener('plusready', () => {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
//all里面第一个是入口webview
|
||||||
|
OAWebView[0].evalJS(`updateUnreadMsgNumReduce('${unReadNum}')`)
|
||||||
|
})
|
||||||
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/talk/unread/clear',
|
url: '/api/v1/talk/unread/clear',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -5,8 +5,16 @@ import { parseTime } from '@/utils/datetime'
|
|||||||
import * as message from '@/constant/message'
|
import * as message from '@/constant/message'
|
||||||
import { formatTalkItem, palyMusic, formatTalkRecord } from '@/utils/talk'
|
import { formatTalkItem, palyMusic, formatTalkRecord } from '@/utils/talk'
|
||||||
// import { isElectronMode } from '@/utils/common'
|
// import { isElectronMode } from '@/utils/common'
|
||||||
import { ServeClearTalkUnreadNum, ServeCreateTalkList } from '@/api/chat/index.js'
|
import {
|
||||||
import { useTalkStore, useDialogueStore,useDialogueListStore,useGroupStore } from '@/store'
|
ServeClearTalkUnreadNum,
|
||||||
|
ServeCreateTalkList,
|
||||||
|
} from '@/api/chat/index.js'
|
||||||
|
import {
|
||||||
|
useTalkStore,
|
||||||
|
useDialogueStore,
|
||||||
|
useDialogueListStore,
|
||||||
|
useGroupStore,
|
||||||
|
} from '@/store'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 好友状态事件
|
* 好友状态事件
|
||||||
@ -49,7 +57,7 @@ class Talk extends Base {
|
|||||||
this.receiver_id = resource.receiver_id
|
this.receiver_id = resource.receiver_id
|
||||||
this.talk_type = resource.talk_type
|
this.talk_type = resource.talk_type
|
||||||
// this.fileNum = resource.file_num
|
// this.fileNum = resource.file_num
|
||||||
if(resource.file_num){
|
if (resource.file_num) {
|
||||||
resource.data.file_num = resource.file_num
|
resource.data.file_num = resource.file_num
|
||||||
}
|
}
|
||||||
this.resource = resource.data
|
this.resource = resource.data
|
||||||
@ -98,7 +106,6 @@ class Talk extends Base {
|
|||||||
play() {
|
play() {
|
||||||
// 客户端有消息提示
|
// 客户端有消息提示
|
||||||
// if (isElectronMode()) return
|
// if (isElectronMode()) return
|
||||||
|
|
||||||
// useSettingsStore().isPromptTone && palyMusic()
|
// useSettingsStore().isPromptTone && palyMusic()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +125,17 @@ class Talk extends Base {
|
|||||||
this.insertTalkRecord()
|
this.insertTalkRecord()
|
||||||
} else {
|
} else {
|
||||||
this.updateTalkItem()
|
this.updateTalkItem()
|
||||||
|
if (typeof plus !== 'undefined') {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
//all里面第一个是入口webview
|
||||||
|
OAWebView[0].evalJS(`updateUnreadMsgNumAdd()`)
|
||||||
|
} else {
|
||||||
|
document.addEventListener('plusready', () => {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
//all里面第一个是入口webview
|
||||||
|
OAWebView[0].evalJS(`updateUnreadMsgNumAdd()`)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +150,6 @@ class Talk extends Base {
|
|||||||
// lang: 'zh-CN',
|
// lang: 'zh-CN',
|
||||||
// body: '您有新的消息请注意查收'
|
// body: '您有新的消息请注意查收'
|
||||||
// })
|
// })
|
||||||
|
|
||||||
// notification.onclick = () => {
|
// notification.onclick = () => {
|
||||||
// notification.close()
|
// notification.close()
|
||||||
// }
|
// }
|
||||||
@ -160,7 +177,7 @@ class Talk extends Base {
|
|||||||
|
|
||||||
ServeCreateTalkList({
|
ServeCreateTalkList({
|
||||||
talk_type,
|
talk_type,
|
||||||
receiver_id
|
receiver_id,
|
||||||
}).then(({ code, data }) => {
|
}).then(({ code, data }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
let item = formatTalkItem(data)
|
let item = formatTalkItem(data)
|
||||||
@ -175,8 +192,8 @@ class Talk extends Base {
|
|||||||
*/
|
*/
|
||||||
insertTalkRecord() {
|
insertTalkRecord() {
|
||||||
let record = this.resource
|
let record = this.resource
|
||||||
let newRecord = formatTalkRecord(this.getAccountId(), this.resource);
|
let newRecord = formatTalkRecord(this.getAccountId(), this.resource)
|
||||||
const {addDialogueRecord,addChatRecord} = useDialogueListStore()
|
const { addDialogueRecord, addChatRecord } = useDialogueListStore()
|
||||||
// 群成员变化的消息,需要更新群成员列表
|
// 群成员变化的消息,需要更新群成员列表
|
||||||
if ([1102, 1103, 1104, 1115].includes(record.msg_type)) {
|
if ([1102, 1103, 1104, 1115].includes(record.msg_type)) {
|
||||||
useDialogueStore().updateGroupMembers()
|
useDialogueStore().updateGroupMembers()
|
||||||
@ -194,13 +211,15 @@ class Talk extends Base {
|
|||||||
avatar: record.extra.group_avatar,
|
avatar: record.extra.group_avatar,
|
||||||
})
|
})
|
||||||
// 更新会话列表中的会话信息
|
// 更新会话列表中的会话信息
|
||||||
const dialogue = useDialogueListStore().getDialogueList(`${record.talk_type}_${record.receiver_id}`)
|
const dialogue = useDialogueListStore().getDialogueList(
|
||||||
|
`${record.talk_type}_${record.receiver_id}`,
|
||||||
|
)
|
||||||
if (dialogue) {
|
if (dialogue) {
|
||||||
dialogue.talk.username = record.extra.group_name
|
dialogue.talk.username = record.extra.group_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addDialogueRecord([newRecord],'add')
|
addDialogueRecord([newRecord], 'add')
|
||||||
addChatRecord(this.getIndexName(),newRecord)
|
addChatRecord(this.getIndexName(), newRecord)
|
||||||
useDialogueStore().addDialogueRecord(newRecord)
|
useDialogueStore().addDialogueRecord(newRecord)
|
||||||
|
|
||||||
if (!this.isCurrSender()) {
|
if (!this.isCurrSender()) {
|
||||||
@ -208,7 +227,7 @@ class Talk extends Base {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
ws.emit('im.message.read', {
|
ws.emit('im.message.read', {
|
||||||
receiver_id: this.sender_id,
|
receiver_id: this.sender_id,
|
||||||
msg_ids: [this.resource.msg_id]
|
msg_ids: [this.resource.msg_id],
|
||||||
})
|
})
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
@ -218,7 +237,8 @@ class Talk extends Base {
|
|||||||
if (!el) return
|
if (!el) return
|
||||||
|
|
||||||
// 判断的滚动条是否在底部
|
// 判断的滚动条是否在底部
|
||||||
const isBottom = Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight
|
const isBottom =
|
||||||
|
Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight
|
||||||
|
|
||||||
if (isBottom || record.user_id == this.getAccountId()) {
|
if (isBottom || record.user_id == this.getAccountId()) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -231,14 +251,15 @@ class Talk extends Base {
|
|||||||
useTalkStore().updateItem({
|
useTalkStore().updateItem({
|
||||||
index_name: this.getIndexName(),
|
index_name: this.getIndexName(),
|
||||||
msg_text: this.getTalkText(),
|
msg_text: this.getTalkText(),
|
||||||
updated_at: parseTime(new Date())
|
updated_at: parseTime(new Date()),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (this.talk_type == 1 && this.getAccountId() !== this.sender_id) {
|
if (this.talk_type == 1 && this.getAccountId() !== this.sender_id) {
|
||||||
ServeClearTalkUnreadNum({
|
//不在此处维护未读消息数量
|
||||||
talk_type: 1,
|
// ServeClearTalkUnreadNum({
|
||||||
receiver_id: this.sender_id
|
// talk_type: 1,
|
||||||
})
|
// receiver_id: this.sender_id,
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,11 +270,13 @@ class Talk extends Base {
|
|||||||
useTalkStore().updateMessage({
|
useTalkStore().updateMessage({
|
||||||
index_name: this.getIndexName(),
|
index_name: this.getIndexName(),
|
||||||
msg_text: this.getTalkText(),
|
msg_text: this.getTalkText(),
|
||||||
updated_at: parseTime(new Date())
|
updated_at: parseTime(new Date()),
|
||||||
})
|
})
|
||||||
if(this.resource.msg_type == 1116){
|
if (this.resource.msg_type == 1116) {
|
||||||
// 更新会话列表中的会话信息
|
// 更新会话列表中的会话信息
|
||||||
const dialogue = useDialogueListStore().getDialogueList(`${this.resource.talk_type}_${this.resource.receiver_id}`)
|
const dialogue = useDialogueListStore().getDialogueList(
|
||||||
|
`${this.resource.talk_type}_${this.resource.receiver_id}`,
|
||||||
|
)
|
||||||
if (dialogue) {
|
if (dialogue) {
|
||||||
dialogue.talk.username = this.resource.extra.group_name
|
dialogue.talk.username = this.resource.extra.group_name
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="avatarImg">
|
<div class="avatarImg">
|
||||||
<avatarModule
|
<avatarModule
|
||||||
:mode="2"
|
:mode="props?.data?.group_type === 0 ? 1 : 2"
|
||||||
:avatar="props?.data?.avatar"
|
:avatar="props?.data?.avatar"
|
||||||
:groupType="props?.data?.group_type"
|
:groupType="props?.data?.group_type"
|
||||||
|
:userName="props?.data?.name"
|
||||||
:customStyle="{ width: '96rpx', height: '96rpx' }"
|
:customStyle="{ width: '96rpx', height: '96rpx' }"
|
||||||
|
:customTextStyle="{
|
||||||
|
fontSize: '32rpx',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#fff',
|
||||||
|
lineHeight: '44rpx',
|
||||||
|
}"
|
||||||
></avatarModule>
|
></avatarModule>
|
||||||
</div>
|
</div>
|
||||||
<div class="chatInfo">
|
<div class="chatInfo">
|
||||||
@ -30,16 +37,18 @@
|
|||||||
class="text-[#171717] text-[32rpx] font-medium leading-[44rpx]"
|
class="text-[#171717] text-[32rpx] font-medium leading-[44rpx]"
|
||||||
>
|
>
|
||||||
<span>{{ props.data.name }}</span>
|
<span>{{ props.data.name }}</span>
|
||||||
<span v-if="props.data.talk_type === 2">({{ props.data.group_member_num }})</span>
|
<span v-if="props.data.talk_type === 2">
|
||||||
|
({{ props.data.group_member_num }})
|
||||||
|
</span>
|
||||||
<span v-if="props.data.group_type === 2" class="depTag tag">
|
<span v-if="props.data.group_type === 2" class="depTag tag">
|
||||||
部门
|
部门
|
||||||
</span>
|
</span>
|
||||||
<span v-if="props.data.group_type === 3" class="projectTag tag">
|
<span v-if="props.data.group_type === 3" class="projectTag tag">
|
||||||
项目
|
项目
|
||||||
</span>
|
</span>
|
||||||
<span v-if="props.data.group_type === 4" class="companyTag tag">
|
<span v-if="props.data.group_type === 4" class="companyTag tag">
|
||||||
公司
|
公司
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -127,7 +136,7 @@ const cellClick = () => {
|
|||||||
opacity: 40%;
|
opacity: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag{
|
.tag {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -142,16 +151,16 @@ const cellClick = () => {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.companyTag {
|
.companyTag {
|
||||||
border: 1px solid #7a58de;
|
border: 1px solid #7a58de;
|
||||||
color: #7a58de;
|
color: #7a58de;
|
||||||
}
|
}
|
||||||
.depTag {
|
.depTag {
|
||||||
border: 1px solid #377ec6;
|
border: 1px solid #377ec6;
|
||||||
color: #377ec6;
|
color: #377ec6;
|
||||||
}
|
}
|
||||||
.projectTag {
|
.projectTag {
|
||||||
border: 1px solid #c1681c;
|
border: 1px solid #c1681c;
|
||||||
color: #c1681c;
|
color: #c1681c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textEllipsis {
|
.textEllipsis {
|
||||||
|
@ -219,7 +219,7 @@ watch(
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
talkStore.loadTalkList()
|
talkStore.loadTalkList()
|
||||||
console.log(talkStore.talkItems)
|
console.log(talkStore.talkItems)
|
||||||
items.value = lodash.cloneDeep(talkStore.talkItems)
|
items.value = lodash.cloneDeep(talkStore.talkItems).filter(item=>item.is_dismiss === 0 && item.is_quit === 0)
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
dialogueStore.setForwardType('')
|
dialogueStore.setForwardType('')
|
||||||
|
@ -544,6 +544,7 @@ const talkParams = reactive({
|
|||||||
isDismiss: computed(() => dialogueStore.isDismiss),
|
isDismiss: computed(() => dialogueStore.isDismiss),
|
||||||
isQuit: computed(() => dialogueStore.isQuit),
|
isQuit: computed(() => dialogueStore.isQuit),
|
||||||
adminList: computed(() => dialogueStore.getAdminList),
|
adminList: computed(() => dialogueStore.getAdminList),
|
||||||
|
unReadNum: computed(() => dialogueStore.unreadNum),
|
||||||
})
|
})
|
||||||
|
|
||||||
const state = ref({
|
const state = ref({
|
||||||
@ -597,11 +598,12 @@ uniOnUnload(() => {
|
|||||||
ServeClearTalkUnreadNum({
|
ServeClearTalkUnreadNum({
|
||||||
talk_type: Number(talkParams.type),
|
talk_type: Number(talkParams.type),
|
||||||
receiver_id: Number(talkParams.receiver_id),
|
receiver_id: Number(talkParams.receiver_id),
|
||||||
}).then(() => {
|
},talkParams.unReadNum).then(() => {
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: talkParams.index_name,
|
index_name: talkParams.index_name,
|
||||||
unread_num: 0,
|
unread_num: 0,
|
||||||
})
|
})
|
||||||
|
dialogueStore.clearUnreadNum()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const handleEmojiPanel = () => {
|
const handleEmojiPanel = () => {
|
||||||
|
@ -107,6 +107,9 @@ import { useSessionMenu } from '@/hooks'
|
|||||||
const talkStore = useTalkStore()
|
const talkStore = useTalkStore()
|
||||||
const { onToTopTalk, onRemoveTalk } = useSessionMenu()
|
const { onToTopTalk, onRemoveTalk } = useSessionMenu()
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
|
const dialogueParams = reactive({
|
||||||
|
unReadNum: computed(() => dialogueStore.unreadNum),
|
||||||
|
})
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -135,11 +138,12 @@ const cellClick = () => {
|
|||||||
ServeClearTalkUnreadNum({
|
ServeClearTalkUnreadNum({
|
||||||
talk_type: props.data.talk_type,
|
talk_type: props.data.talk_type,
|
||||||
receiver_id: props.data.receiver_id,
|
receiver_id: props.data.receiver_id,
|
||||||
}).then(() => {
|
},dialogueParams.unReadNum).then(() => {
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: props.data.index_name,
|
index_name: props.data.index_name,
|
||||||
unread_num: 0,
|
unread_num: 0,
|
||||||
})
|
})
|
||||||
|
dialogueStore.clearUnreadNum()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
@ -138,6 +138,9 @@ const isEmptyViewShow = ref(false)
|
|||||||
const talkStore = useTalkStore()
|
const talkStore = useTalkStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
|
const dialogueParams = reactive({
|
||||||
|
unReadNum: computed(() => dialogueStore.unreadNum),
|
||||||
|
})
|
||||||
const { userInfo } = useAuth()
|
const { userInfo } = useAuth()
|
||||||
|
|
||||||
const topItems = computed(() => talkStore.topItems)
|
const topItems = computed(() => talkStore.topItems)
|
||||||
@ -244,11 +247,12 @@ onLoad((options) => {
|
|||||||
ServeClearTalkUnreadNum({
|
ServeClearTalkUnreadNum({
|
||||||
talk_type: openSession.talk_type,
|
talk_type: openSession.talk_type,
|
||||||
receiver_id: openSession.receiver_id,
|
receiver_id: openSession.receiver_id,
|
||||||
}).then(() => {
|
},dialogueParams.unReadNum).then(() => {
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: openSession.index_name,
|
index_name: openSession.index_name,
|
||||||
unread_num: 0,
|
unread_num: 0,
|
||||||
})
|
})
|
||||||
|
dialogueStore.clearUnreadNum()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
@ -54,6 +54,9 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
//是否退群/移出群
|
//是否退群/移出群
|
||||||
isQuit: false,
|
isQuit: false,
|
||||||
|
|
||||||
|
//未读消息数量
|
||||||
|
unreadNum:0,
|
||||||
|
|
||||||
// 群成员列表
|
// 群成员列表
|
||||||
members: [],
|
members: [],
|
||||||
|
|
||||||
@ -90,6 +93,11 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
this.online = status
|
this.online = status
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 更新未读消息数量-清空未读
|
||||||
|
clearUnreadNum() {
|
||||||
|
this.unreadNum = 0
|
||||||
|
},
|
||||||
|
|
||||||
// 更新对话信息
|
// 更新对话信息
|
||||||
setDialogue(data = {}) {
|
setDialogue(data = {}) {
|
||||||
this.online = data.is_online == 1
|
this.online = data.is_online == 1
|
||||||
@ -107,6 +115,8 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
this.isDismiss = data?.is_dismiss === 1 ? true : false
|
this.isDismiss = data?.is_dismiss === 1 ? true : false
|
||||||
this.isQuit = data?.is_quit === 1 ? true : false
|
this.isQuit = data?.is_quit === 1 ? true : false
|
||||||
|
|
||||||
|
this.unreadNum = data?.unread_num || 0
|
||||||
|
|
||||||
this.members = []
|
this.members = []
|
||||||
if (data.talk_type == 2) {
|
if (data.talk_type == 2) {
|
||||||
this.updateGroupMembers()
|
this.updateGroupMembers()
|
||||||
|
@ -42,6 +42,7 @@ export const useDialogueListStore = createGlobalState(() => {
|
|||||||
isShowSessionList: dialogue.isShowSessionList,
|
isShowSessionList: dialogue.isShowSessionList,
|
||||||
isDismiss: dialogue.isDismiss,
|
isDismiss: dialogue.isDismiss,
|
||||||
isQuit: dialogue.isQuit,
|
isQuit: dialogue.isQuit,
|
||||||
|
unreadNum: dialogue.unreadNum,
|
||||||
members: dialogue.members.map(member => ({
|
members: dialogue.members.map(member => ({
|
||||||
id: member.id,
|
id: member.id,
|
||||||
nickname: member.nickname,
|
nickname: member.nickname,
|
||||||
|
Loading…
Reference in New Issue
Block a user