chat-app/src/pages/chatSettings/components/selectMemberByAlphabet.vue

757 lines
21 KiB
Vue
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>
<div class="select-member-by-alphabet">
<ZPaging
ref="zPaging"
:show-scrollbar="false"
:use-virtual-list="true"
:virtual-list-col="5"
:refresher-enabled="false"
:loading-more-enabled="false"
@scroll="onScroll"
:fixed="false"
:height="props?.selectAreaHeight"
>
<div class="select-members">
<div class="search-member" v-if="props?.manageType !== 'removeMembers'">
<customInput
:searchText="state.searchText"
@inputSearchText="inputSearchText"
></customInput>
</div>
<div
class="member-list"
:style="{
padding: props?.manageType === 'searchRecord' ? '20rpx 0 0' : '',
}"
>
<div
class="member-list-alphabet-anchor-point"
:style="{
top: props?.manageType === 'mention' ? '90rpx' : '',
}"
>
<div
class="member-list-alphabet-anchor-point-each"
v-for="(alphabetItem, alphabetIndex) in state?.alphabet"
:key="alphabetIndex"
:style="{
margin: state?.alphabet?.length > 17 ? '0' : '',
}"
@click.stop="scrollToView(alphabetItem)"
>
<span
class="text-[32rpx] font-regular"
:style="{
color:
state.currentAlphabet === alphabetItem ? '#7A58DE' : '',
}"
>
{{ alphabetItem }}
</span>
</div>
</div>
<div
class="member-list-alphabet"
v-for="(alphabetItem, alphabetIndex) in state.resultMemberList"
:key="alphabetIndex"
>
<div
class="member-list-alphabet-key"
:style="{
padding:
props?.manageType === 'searchRecord' ||
props?.manageType === 'removeMembers' ||
props?.manageType === 'mention'
? '10rpx 30rpx'
: '',
}"
v-if="
alphabetItem?.memberList?.length > 0 &&
alphabetItem?.key !== '0'
"
:id="alphabetItem.key"
:ref="
(el) => {
if (el) alphabetElementRefs[alphabetIndex] = el
}
"
>
<span class="text-[32rpx] font-regular">
{{ alphabetItem.key }}
</span>
</div>
<div v-if="alphabetItem?.memberList?.length > 0">
<div
class="member-list-each"
v-for="(item, index) in alphabetItem?.memberList"
:key="index"
>
<tm-checkbox-group v-model="item.checkArr">
<selectMemberItem
:groupType="groupParams.groupInfo.group_type"
:memberItem="item"
@clickItem="handleClickItem(item)"
:manageType="props?.manageType"
:itemStyle="
props?.manageType === 'searchRecord' ||
props?.manageType === 'removeMembers' ||
props?.manageType === 'mention'
? 'list'
: 'card'
"
>
<template #left v-if="props?.manageType !== 'searchRecord'">
<div
v-if="
props?.manageType === 'removeMembers' && item?.is_mine
"
>
<tm-checkbox
color="#fff"
:transprent="true"
:border="0"
:disabled="true"
></tm-checkbox>
</div>
<tm-checkbox
v-if="
!(
props?.manageType === 'removeMembers' &&
item?.is_mine
) && props?.isMulSelect
"
:round="10"
:color="
item?.checkArr?.length > 0 ? '#46299d' : '#B4B4B4'
"
:outlined="
item?.checkArr?.length > 0 ||
(props?.manageType === 'silence' &&
item.is_mute === 1) ||
(props?.manageType === 'admin' &&
(item.leader === 1 || item.leader === 2))
? false
: true
"
:value="item.id"
:disabled="
(props?.manageType === 'silence' &&
item.is_mute === 1) ||
(props?.manageType === 'admin' &&
(item.leader === 1 || item.leader === 2))
"
@change="checkBoxChange"
></tm-checkbox>
</template>
</selectMemberItem>
</tm-checkbox-group>
</div>
</div>
</div>
</div>
</div>
</ZPaging>
</div>
</template>
<script setup>
import customInput from '@/components/custom-input/custom-input.vue'
import selectMemberItem from '../components/select-member-item.vue'
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
import {
computed,
onMounted,
reactive,
ref,
watch,
nextTick,
defineProps,
defineEmits,
} from 'vue'
import {
ServeGroupNoSpeak,
ServeEditGroupAdmin,
ServeGroupAssignAdmin,
ServeRemoveMembersGroup,
} from '@/api/group/index.js'
import { useDialogueStore, useGroupStore, useGroupTypeStore } from '@/store'
const emits = defineEmits([
'updateSelectedMembersNum',
'getSelectResult',
'getMentionSelectLists',
])
const zPaging = ref()
useZPaging(zPaging)
const groupStore = useGroupStore()
const groupParams = reactive({
groupInfo: computed(() => groupStore.groupInfo),
})
const groupTypeStore = useGroupTypeStore()
const groupTypeParams = reactive({
departmentAllPositions: computed(() => groupTypeStore.departmentAllPositions),
})
const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
memberList: computed(() => {
const lowerCaseSearchText = state?.searchText.toLowerCase()
return dialogueStore.members.filter((item) =>
state?.searchText
? item.nickname.toLowerCase().includes(lowerCaseSearchText)
: true,
)
}),
receiverId: computed(() => dialogueStore.talk.receiver_id),
})
const props = defineProps({
manageType: {
//管理类型
type: String,
default: '',
},
isCreateDepGroup: {
//是否是创建部门群
type: Number,
default: 0,
},
selectAreaHeight: {
//选择区域高度
type: String,
default: '',
},
isMulSelect: {
//是否开启多选
type: Boolean,
default: true,
},
})
const state = reactive({
searchText: '', //搜索内容
alphabet: [], //A-Z列表
currentAlphabet: 'A', //当前A-Z位置
resultMemberList: [], //按A-Z整理后的人员列表
isAssign: false, //是否指定view
scrollDirection: '', //当前列表滚动方向
})
watch(
() => dialogueParams?.memberList,
(newMemberList) => {
assembleAlphabetMemberList(newMemberList)
},
{ deep: true },
)
watch(
() => groupParams?.groupInfo,
(newGroupInfo) => {
assembleAlphabetMemberList(dialogueParams?.memberList)
},
{ deep: true },
)
watch(
() => props?.isMulSelect,
(newIsMulSelect) => {
if (props?.manageType === 'mention') {
if (!newIsMulSelect) {
state.resultMemberList.unshift({
key: '0',
memberList: [
{
avatar: '/src/static/image/chatList/groupAllMember.png',
erp_user_id: 0,
gender: 0,
is_mute: 0,
key: '0',
leader: 0,
nickname: '所有人',
remark: '',
user_id: 0,
},
],
})
} else {
if (state.resultMemberList[0].key === '0') {
state.resultMemberList.splice(0, 1)
}
}
}
},
{ deep: true, immediate: true },
)
//获取A-Z tag元素
const alphabetElementRefs = ref([])
//观察者
let observer
onMounted(() => {
if (props?.manageType) {
assembleAlphabetMemberList(dialogueParams?.memberList)
}
if (props?.isCreateDepGroup) {
assembleAlphabetMemberList()
}
dialogueParams.memberList.forEach((ele) => {
ele.checkArr = []
})
const options = {
root: null, // 使用浏览器窗口作为根容器
threshold: 1.0, // 当元素100%离开视口时触发
}
observer = new IntersectionObserver(handleIntersection, options)
nextTick(() => {
watch(
alphabetElementRefs,
(newAlphabetElementRefs) => {
if (Array.isArray(newAlphabetElementRefs)) {
newAlphabetElementRefs.forEach((el, index) => {
observeElement(el, index)
})
}
},
{ immediate: true, deep: true },
)
if (alphabetElementRefs.value.length > 0) {
alphabetElementRefs.value.forEach((el, index) =>
observeElement(el, index),
)
}
})
})
//观察元素
const observeElement = (el, index) => {
if (el && observer) {
observer.observe(el)
}
}
// 观察者函数
const handleIntersection = (entries) => {
if (state.isAssign) {
state.isAssign = false
return
}
entries.forEach((entry) => {
if (!entry.isIntersecting && state.scrollDirection === 'down') {
state.currentAlphabet = entry.target.id
} else if (entry.isIntersecting && state.scrollDirection === 'up') {
if (state?.alphabet?.length > 1) {
state?.alphabet.forEach((item, index) => {
if (item === entry.target.id && index > 0) {
state.currentAlphabet = state?.alphabet[index - 1]
}
})
} else {
state.currentAlphabet = entry.target.id
}
}
})
}
//输入搜索文本
const inputSearchText = (e) => {
// console.log(e)
state.searchText = e
}
//点击item
const handleClickItem = (item) => {
if (
(props?.manageType === 'silence' && item.is_mute === 1) ||
(props?.manageType === 'admin' &&
(item.leader === 1 || item.leader === 2)) ||
(props?.manageType === 'removeMembers' && item.is_mine) ||
(props?.manageType === 'mention' && !props?.isMulSelect)
) {
if (props?.manageType === 'mention' && !props?.isMulSelect) {
emits('getMentionSelectLists', [item])
}
return
}
if(props?.manageType === 'searchRecord'){
uni.navigateTo({
url: '/pages/search/searchByCondition/index?condition=member&groupMemberId=' + item.id
})
return
}
let itemList = dialogueParams.memberList
if (
props?.manageType === 'admin' &&
(groupParams.groupInfo.group_type == 2 ||
groupParams.groupInfo.group_type == 4 ||
props?.isCreateDepGroup === 1)
) {
itemList = state.resultMemberList[0].memberList
}
itemList.forEach((ele) => {
if (ele.id == item.id) {
ele.checkArr = ele.checkArr?.length > 0 ? [] : [item.id]
if (ele.checkArr?.length > 0) {
emits('updateSelectedMembersNum', 1)
} else {
emits('updateSelectedMembersNum', -1)
}
}
})
}
//组装A-Z排序的人员列表
const assembleAlphabetMemberList = async (newMemberList) => {
if (
props?.manageType === 'searchRecord' ||
props?.manageType === 'removeMembers' ||
props?.manageType === 'mention'
) {
const resultMemberList = ref([])
const alphabet = Array.from({ length: 26 }, (_, i) =>
String.fromCharCode(i + 65),
)
let tempAlphabet = []
alphabet.forEach((letter) => {
const matchedItems = newMemberList.filter((item) => item.key === letter)
if (matchedItems.length > 0) {
tempAlphabet.push(letter)
}
resultMemberList.value.push({
key: letter,
memberList: matchedItems.length ? matchedItems : [],
})
})
state.alphabet = tempAlphabet
if (props?.manageType === 'mention' && !props?.isMulSelect) {
resultMemberList.value.unshift({
key: '0',
memberList: [
{
avatar: '/src/static/image/chatList/groupAllMember.png',
erp_user_id: 0,
gender: 0,
is_mute: 0,
key: '0',
leader: 0,
nickname: '所有人',
remark: '',
user_id: 0,
},
],
})
}
state.resultMemberList = resultMemberList
} else {
if (
(groupParams.groupInfo.group_type == 2 ||
groupParams.groupInfo.group_type == 4) &&
props?.manageType === 'admin'
) {
let departmentIdsArr = []
if (groupParams?.groupInfo?.deptInfos?.length > 0) {
groupParams.groupInfo.deptInfos.forEach((item) => {
departmentIdsArr.push(item.dept_id)
})
}
getPosiByDep(departmentIdsArr)
} else if (props?.isCreateDepGroup === 1) {
let departmentIdsArr = []
if (groupTypeStore?.depCheckedKeys?.value?.length > 0) {
groupTypeStore.depCheckedKeys.value.forEach((item) => {
departmentIdsArr.push(item.ID)
})
}
getPosiByDep(departmentIdsArr)
} else {
state.resultMemberList = [
{
key: '',
memberList: newMemberList,
},
]
}
}
}
//按部门获取岗位
const getPosiByDep = async (departmentIdsArr) => {
await groupTypeStore.getPositionByDepartment({
IDs: departmentIdsArr,
})
let departmentAllPositions = []
if (groupTypeParams?.departmentAllPositions?.value?.length > 0) {
groupTypeParams?.departmentAllPositions?.value?.forEach((item) => {
item?.AllPositions?.forEach((positionItem) => {
departmentAllPositions.push({
nickname: item.name + '-' + positionItem.name,
id: item.ID + '-' + positionItem.ID,
checkArr: [],
positionInfo: {
dept_id: item.ID,
dept_name: item.name,
position_id: positionItem.ID,
position_name: positionItem.name,
},
})
})
})
}
if (groupParams?.groupInfo?.groupAdminList?.length > 0) {
groupParams?.groupInfo?.groupAdminList.forEach((item) => {
departmentAllPositions.forEach((idsItem) => {
if (item.dept_id + '-' + item.position_id == idsItem.id) {
idsItem.leader = 1
}
})
})
}
if (
props?.isCreateDepGroup === 1 &&
groupTypeStore?.groupAdmins?.value?.length > 0
) {
departmentAllPositions.forEach((allPos) => {
groupTypeStore.groupAdmins.value.forEach((admin) => {
if (allPos.id === admin.id) {
allPos.checkArr = [allPos.id]
}
})
})
}
if (state?.searchText) {
const lowerCaseSearchText = state?.searchText.toLowerCase()
departmentAllPositions = departmentAllPositions.filter((item) =>
state?.searchText
? item.nickname.toLowerCase().includes(lowerCaseSearchText)
: true,
)
}
state.resultMemberList = [
{
key: '',
memberList: departmentAllPositions,
},
]
}
//滚动到指定的view
const scrollToView = (alphabet) => {
state.currentAlphabet = alphabet
state.isAssign = true
console.log()
zPaging.value?.scrollIntoViewById(
alphabet,
document.getElementById('topArea')?.clientHeight
? document.getElementById('topArea').clientHeight - 1
: props?.manageType === 'mention'
? 140
: 80,
)
}
//监听列表滚动
const onScroll = (e) => {
if (e.detail.deltaY < 0) {
state.scrollDirection = 'down'
} else if (e.detail.deltaY > 0) {
state.scrollDirection = 'up'
} else {
state.scrollDirection = ''
}
}
//选中的人员改变
const checkBoxChange = (e) => {
if (e) {
emits('updateSelectedMembersNum', 1)
} else {
emits('updateSelectedMembersNum', -1)
}
}
//点击确认选择的成员
const confirmSelectMembers = () => {
let selectedUserIds = ''
let itemList = dialogueParams.memberList
let positionInfos = []
let selectUserInfos = []
if (
props?.manageType === 'admin' &&
(groupParams.groupInfo.group_type == 2 ||
groupParams.groupInfo.group_type == 4 ||
props?.isCreateDepGroup === 1)
) {
itemList = state.resultMemberList[0].memberList
}
itemList.forEach((ele) => {
if (ele.checkArr?.length > 0) {
if (!selectedUserIds) {
selectedUserIds = String(ele.checkArr[0])
} else {
selectedUserIds += ',' + ele.checkArr[0]
}
selectUserInfos.push(ele)
}
if (
ele.checkArr?.length > 0 ||
(ele.leader && (ele.leader == 1 || ele.leader == 2))
) {
if (props?.isCreateDepGroup === 1) {
let posInfo = Object.assign({}, ele.positionInfo, {
name: ele.nickname,
id: ele.id,
})
positionInfos.push(posInfo)
} else {
positionInfos.push(ele.positionInfo)
}
}
})
console.log(selectedUserIds)
if (selectedUserIds) {
if (props?.manageType === 'silence') {
let params = {
mode: 1, //1禁言2解禁
group_id: dialogueParams.receiverId, //群id
user_ids: selectedUserIds, //用户ids
}
console.log(params)
const resp = ServeGroupNoSpeak(params)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
useDialogueStore().updateGroupMembers()
} else {
}
})
resp.catch(() => {})
} else if (props?.manageType === 'admin') {
if (props?.isCreateDepGroup === 1) {
// console.log(positionInfos)
groupTypeStore.groupAdmins.value = positionInfos
uni.navigateBack({
delta: 1,
})
} else {
if (
groupParams.groupInfo.group_type == 1 ||
groupParams.groupInfo.group_type == 3
) {
let params = {
mode: 1, //1管理员2不是管理员
group_id: dialogueParams.receiverId, //群id
user_ids: selectedUserIds,
}
console.log(params)
const resp = ServeGroupAssignAdmin(params)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
useDialogueStore().updateGroupMembers()
} else {
}
})
resp.catch(() => {})
} else if (
groupParams.groupInfo.group_type == 2 ||
groupParams.groupInfo.group_type == 4
) {
let params = {
source: 'app',
id: dialogueParams.receiverId,
deptInfos: groupParams.groupInfo.deptInfos,
positionInfos: positionInfos,
}
console.log(params)
const resp = ServeEditGroupAdmin(params)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
groupStore.ServeGroupDetail()
} else {
}
})
resp.catch(() => {})
}
}
} else if (props?.manageType === 'removeMembers') {
let params = {
group_id: dialogueParams.receiverId, //群id
members_ids: selectedUserIds, //群成员id批量的话逗号分割
}
console.log(params)
const resp = ServeRemoveMembersGroup(params)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
// console.error(-selectedUserIds.split(',').length)
emits('updateSelectedMembersNum', -selectedUserIds.split(',').length)
useDialogueStore().updateGroupMembers()
groupStore.ServeGroupDetail()
} else {
}
})
resp.catch(() => {})
} else if (props?.manageType === 'mention') {
emits('getSelectResult', selectUserInfos)
}
}
}
// 暴露确认方法
defineExpose({
confirmSelectMembers,
})
</script>
<style lang="scss" scoped>
.select-member-by-alphabet {
.select-members {
padding: 20rpx 32rpx;
.search-member {
padding: 22rpx 16rpx;
background-color: #fff;
}
.member-list {
.member-list-alphabet-anchor-point {
position: fixed;
right: 32rpx;
top: 0;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.member-list-alphabet-anchor-point-each {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0 0 14rpx;
span {
width: 52rpx;
text-align: center;
line-height: 44rpx;
color: $theme-text;
}
}
}
.member-list-alphabet {
.member-list-alphabet-key {
background-color: #f3f3f3;
span {
line-height: 44rpx;
color: $theme-text;
}
}
}
}
}
}
</style>