处理解散群聊、退出群聊按钮的可视权限;使用naiveUI的infiniteScroll组件代替overflowY,并用自带的load事件代替v-loadmore指令,重新整理复用的搜索列表组件,整理传参、数据处理等,解决参数混乱、数据处理混乱问题

This commit is contained in:
wangyifeng 2025-05-20 19:58:16 +08:00
parent 8694921f25
commit 41dbb8c872
4 changed files with 162 additions and 145 deletions

1
components.d.ts vendored
View File

@ -62,6 +62,7 @@ declare module 'vue' {
NotificationApi: typeof import('./src/components/common/NotificationApi.vue')['default']
NPopover: typeof import('naive-ui')['NPopover']
NRadio: typeof import('naive-ui')['NRadio']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSpin: typeof import('naive-ui')['NSpin']
NTag: typeof import('naive-ui')['NTag']
NVirtualList: typeof import('naive-ui')['NVirtualList']

View File

@ -663,7 +663,10 @@ const handleEditGroupNameConfirm = () => {
清空聊天记录
</n-button>
<n-button
v-if="isAdmin || isLeader"
v-if="
(isAdmin || isLeader) &&
(state.detail.group_type === 1 || state.detail.group_type === 3)
"
class="btn"
type="error"
ghost
@ -671,7 +674,13 @@ const handleEditGroupNameConfirm = () => {
>
解散该群
</n-button>
<n-button class="btn" type="error" ghost @click="showChatSettingOperateModal('quit')">
<n-button
class="btn"
type="error"
ghost
@click="showChatSettingOperateModal('quit')"
v-if="state.detail.group_type === 1 || state.detail.group_type === 3"
>
退出群聊
</n-button>
</div>

View File

@ -1,60 +1,65 @@
<template>
<div class="search-list">
<div class="search-result">
<div class="search-result-list">
<div
class="search-result-each-part"
v-for="(searchResultValue, searchResultKey, searchResultIndex) in state.searchResult"
:key="searchResultKey"
>
<n-infinite-scroll
:style="{ maxHeight: props.searchResultMaxHeight }"
@load="doLoadMore"
>
<div class="search-result">
<div class="search-result-list">
<div
class="search-result-part"
v-if="
Array.isArray(state?.searchResult[searchResultKey]) &&
state?.searchResult[searchResultKey].length > 0 &&
searchResultKey !== 'group_infos' &&
searchResultKey !== 'group_member_infos'
"
class="search-result-each-part"
v-for="(searchResultValue, searchResultKey, searchResultIndex) in state.searchResult"
:key="searchResultKey"
>
<div class="result-title">
<span class="text-[14px] font-regular">
{{ getResultKeysValue(searchResultKey) }}
</span>
</div>
<div class="result-list">
<div
class="result-list-each"
v-for="(item, index) in state?.searchResult[searchResultKey]"
:key="index"
>
<searchItem
@click="clickSearchItem(searchResultKey, item)"
v-if="(props.listLimit && index < 3) || !props.listLimit"
:searchResultKey="searchResultKey"
:searchItem="item"
:searchText="state.searchText"
:searchRecordDetail="props.searchRecordDetail"
:isClickStay="
props.useClickStay &&
typeof state.clickStayItem === 'string' &&
state.clickStayItem === `${item.talk_type}_${item.receiver_id}`
"
></searchItem>
</div>
</div>
<div
class="result-has-more"
v-if="getHasMoreResult(searchResultKey)"
@click="toMoreResultPage(searchResultKey)"
class="search-result-part"
v-if="
Array.isArray(state?.searchResult[searchResultKey]) &&
state?.searchResult[searchResultKey].length > 0 &&
searchResultKey !== 'group_infos' &&
searchResultKey !== 'group_member_infos'
"
>
<span class="text-[14px] font-regular">
{{ getHasMoreResult(searchResultKey) }}
</span>
<div class="result-title">
<span class="text-[14px] font-regular">
{{ getResultKeysValue(searchResultKey) }}
</span>
</div>
<div class="result-list">
<div
class="result-list-each"
v-for="(item, index) in state?.searchResult[searchResultKey]"
:key="index"
>
<searchItem
@click="clickSearchItem(searchResultKey, item)"
v-if="(props.listLimit && index < 3) || !props.listLimit"
:searchResultKey="searchResultKey"
:searchItem="item"
:searchText="state.searchText"
:searchRecordDetail="props.searchRecordDetail"
:isClickStay="
props.useClickStay &&
typeof state.clickStayItem === 'string' &&
state.clickStayItem === `${item.talk_type}_${item.receiver_id}`
"
></searchItem>
</div>
</div>
<div
class="result-has-more"
v-if="getHasMoreResult(searchResultKey)"
@click="toMoreResultPage(searchResultKey)"
>
<span class="text-[14px] font-regular">
{{ getHasMoreResult(searchResultKey) }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</n-infinite-scroll>
<!-- <ZPaging
ref="zPaging"
:show-scrollbar="false"
@ -131,6 +136,7 @@
// const zPaging = ref()
// useZPaging(zPaging)
import { NInfiniteScroll } from 'naive-ui'
import searchItem from './searchItem.vue'
import { ref, reactive, defineEmits, defineProps, onMounted, watch } from 'vue'
@ -138,8 +144,7 @@ const emits = defineEmits([
'toMoreResultPage',
'lastIdChange',
'clickSearchItem',
'clickStayItemChange',
'doLoadMore'
'clickStayItemChange'
])
const state = reactive({
@ -148,7 +153,9 @@ const state = reactive({
searchResult: null, //
pageNum: 1, //
uid: 12303, //id
clickStayItem: '' //item
clickStayItem: '', //item
hasMore: true, //
loading: false //
})
const props = defineProps({
@ -190,7 +197,11 @@ const props = defineProps({
useClickStay: {
type: Boolean,
default: false
} //使
}, //使
searchResultMaxHeight: {
type: String,
default: '677px'
} //
})
onMounted(() => {
@ -212,9 +223,12 @@ watch(
watch(
() => props.searchText,
(newVal, oldVal) => {
queryAllSearch()
//
state.clickStayItem = ''
emits('clickStayItemChange', state.clickStayItem)
//
emits('lastIdChange', 0, 0, 0, '', '')
queryAllSearch()
}
)
@ -223,15 +237,11 @@ const inputSearchText = (e) => {
if (e.trim() != state.searchText.trim()) {
state.pageNum = 1
state.searchResult = null //
emits('lastIdChange', 0, 0, 0, '', '')
}
state.searchText = e.trim()
if (!e.trim()) {
state.searchResult = null //
emits('lastIdChange', 0, 0, 0, '', '')
}
// zPaging.value?.reload()
queryAllSearch()
}
// ES-
@ -354,6 +364,11 @@ const queryAllSearch = (doClearSearchResult) => {
total = data.group_record_count
}
}
if (total < props.searchResultPageSize) {
state.hasMore = false
} else {
state.hasMore = true
}
// zPaging.value?.completeByTotal([data], total)
} else {
state.searchResult = data
@ -383,6 +398,7 @@ const queryAllSearch = (doClearSearchResult) => {
// zPaging.value?.complete(state.searchResult ? [state.searchResult] : [])
}
})
return resp
}
//
@ -514,13 +530,15 @@ const clickSearchItem = (searchResultKey, searchItem) => {
//
const doLoadMore = (doClearSearchResult) => {
if (!state.hasMore || state.loading) {
return
}
state.loading = true
queryAllSearch(doClearSearchResult)
.finally(() => {
state.loading = false
})
}
// doLoadMore
defineExpose({
doLoadMore
})
</script>
<style lang="scss" scoped>
.search-list {

View File

@ -254,7 +254,18 @@ const state = reactive({
searchRecordText: '', //
ServeQueryTalkRecordParams: '', //
ServeQueryTalkRecordDetailParams: '', //
isShowSearchRecordDetailInfo: false //
isShowSearchRecordDetailInfo: false, //
// searchList searchDetailList
searchList: {
searchText: '',
apiParams: '',
lastId: undefined as any
},
searchDetailList: {
searchText: '',
apiParams: '',
lastId: undefined as any
}
})
const items = computed((): ISession[] => {
@ -303,22 +314,29 @@ watch(
}
)
// watch(
// () => state.searchRecordText,
// (newValue, oldValue) => {
// console.log(newValue, 'newValue')
// state.ServeQueryTalkRecordParams = encodeURIComponent(
// JSON.stringify({
// talk_type: 0, //12
// receiver_id: 0, //
// last_group_id: 0, //id
// last_member_id: 0, //id
// last_receiver_user_name: '', //
// last_receiver_group_name: '' //
// })
// )
// }
// )
//
watch(
() => state.searchRecordText,
(newVal, oldVal) => {
//
state.searchList.searchText = newVal
state.searchList.apiParams = encodeURIComponent(JSON.stringify({
talk_type: 0,
receiver_id: 0,
last_group_id: 0,
last_member_id: 0,
last_receiver_user_name: '',
last_receiver_group_name: ''
}))
state.searchList.lastId = undefined
//
state.searchDetailList.searchText = newVal
state.searchDetailList.apiParams = ''
state.searchDetailList.lastId = undefined
//
state.isShowSearchRecordDetailInfo = false
}
)
//
const loadStatus = computed(() => talkStore.loadStatus)
@ -558,16 +576,19 @@ const handleClickSearchItem = (searchText, searchResultKey, talk_type, receiver_
const result = JSON.parse(decodeURIComponent(res))
console.log(result)
if (searchResultKey === 'general_infos') {
state.ServeQueryTalkRecordDetailParams = encodeURIComponent(
JSON.stringify({
last_group_id: 0, //id
last_member_id: 0, //id
receiver_id: receiver_id, //
talk_type: talk_type //12
})
)
//
state.isShowSearchRecordDetailInfo = false
state.searchDetailList.apiParams = encodeURIComponent(JSON.stringify({
last_group_id: 0,
last_member_id: 0,
receiver_id: receiver_id,
talk_type: talk_type
}))
state.searchDetailList.searchText = state.searchRecordText
state.searchDetailList.lastId = undefined
//
nextTick(() => {
searchDetailListRef.value?.doLoadMore(true)
state.isShowSearchRecordDetailInfo = true
})
}
}
@ -586,52 +607,20 @@ const searchListRef = ref()
// ref
const searchDetailListRef = ref()
//
const loadMoreRecordList = () => {
searchListRef.value?.doLoadMore()
// lastIdChange
const handleSearchListLastIdChange = (last_id, last_group_id, last_member_id, last_receiver_user_name, last_receiver_group_name) => {
state.searchList.lastId = { last_id, last_group_id, last_member_id, last_receiver_user_name, last_receiver_group_name }
state.searchList.apiParams = encodeURIComponent(JSON.stringify({
...JSON.parse(decodeURIComponent(state.searchList.apiParams)),
last_id, last_group_id, last_member_id, last_receiver_user_name, last_receiver_group_name
}))
}
//
const loadMoreRecordDetail = () => {
searchDetailListRef.value?.doLoadMore()
}
const handleMoreRecordLastIdChange = (
last_id,
last_group_id,
last_member_id,
last_receiver_user_name,
last_receiver_group_name
) => {
let idChanges = {
last_id,
last_group_id,
last_member_id,
last_receiver_user_name,
last_receiver_group_name
}
state.ServeQueryTalkRecordParams = encodeURIComponent(
JSON.stringify(
Object.assign({}, JSON.parse(decodeURIComponent(state.ServeQueryTalkRecordParams)), idChanges)
)
)
}
const handleRecordDetailLastIdChange = (last_id, last_group_id, last_member_id) => {
let idChanges = {
last_id,
last_group_id,
last_member_id
}
state.ServeQueryTalkRecordDetailParams = encodeURIComponent(
JSON.stringify(
Object.assign(
{},
JSON.parse(decodeURIComponent(state.ServeQueryTalkRecordDetailParams)),
idChanges
)
)
)
const handleSearchDetailListLastIdChange = (last_id, last_group_id, last_member_id) => {
state.searchDetailList.lastId = { last_id, last_group_id, last_member_id }
state.searchDetailList.apiParams = encodeURIComponent(JSON.stringify({
...JSON.parse(decodeURIComponent(state.searchDetailList.apiParams)),
last_id, last_group_id, last_member_id
}))
}
</script>
@ -653,7 +642,7 @@ const handleRecordDetailLastIdChange = (last_id, last_group_id, last_member_id)
<n-dropdown
trigger="click"
:options="state.chatSearchOptions"
style="width: 248px; height: 677px; overflow-y: scroll;"
style="width: 248px; height: 677px;"
>
<n-input
placeholder="搜索好友 / 群聊"
@ -865,34 +854,36 @@ const handleRecordDetailLastIdChange = (last_id, last_group_id, last_member_id)
</n-input>
</div>
<div class="search-record-card" v-if="state.searchRecordText">
<div class="search-record-list" v-loadmore="loadMoreRecordList">
<div class="search-record-list">
<chatAppSearchList
ref="searchListRef"
:searchResultPageSize="10"
:listLimit="false"
:apiRequest="ServeQueryTalkRecord"
:apiParams="state.ServeQueryTalkRecordParams"
:searchText="state.searchRecordText"
:apiParams="state.searchList.apiParams"
:searchText="state.searchList.searchText"
:isPagination="true"
searchResultKey="general_infos"
@clickSearchItem="handleClickSearchItem"
:useClickStay="true"
@clickStayItemChange="handleClickStayItemChange"
@lastIdChange="handleMoreRecordLastIdChange"
@lastIdChange="handleSearchListLastIdChange"
:searchResultMaxHeight="'517px'"
></chatAppSearchList>
</div>
<div class="search-record-detail" v-loadmore="loadMoreRecordDetail">
<div class="search-record-detail">
<chatAppSearchList
ref="searchDetailListRef"
v-if="state.isShowSearchRecordDetailInfo"
:searchResultPageSize="10"
:listLimit="false"
:apiRequest="ServeQueryTalkRecord"
:apiParams="state.ServeQueryTalkRecordDetailParams"
:searchText="state.searchRecordText"
:apiParams="state.searchDetailList.apiParams"
:searchText="state.searchDetailList.searchText"
:isPagination="true"
:searchRecordDetail="true"
@lastIdChange="handleRecordDetailLastIdChange"
@lastIdChange="handleSearchDetailListLastIdChange"
:searchResultMaxHeight="'517px'"
></chatAppSearchList>
</div>
</div>
@ -1087,13 +1078,11 @@ html[theme-mode='dark'] {
width: 260px;
height: 517px;
border: 1px solid #efeff5;
overflow-y: scroll;
}
.search-record-detail {
width: 578px;
height: 517px;
border: 1px solid #efeff5;
overflow-y: scroll;
}
}
.search-record-empty {