Compare commits
6 Commits
d303c8e94e
...
e4c2b7cdcb
Author | SHA1 | Date | |
---|---|---|---|
e4c2b7cdcb | |||
adb57bda88 | |||
4b3062eefa | |||
36342b4dd9 | |||
ae2a447fa4 | |||
f2abedd88e |
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="avatar-module" :style="customStyle">
|
||||
<div class="avatar-module" :style="[customStyle, { background: avatar ? '#fff' : '' }]">
|
||||
<img :src="avatar" v-if="avatar" />
|
||||
<span v-else :style="customTextStyle">{{ text_avatar }}</span>
|
||||
</div>
|
||||
|
748
src/pages/chatSettings/components/selectMemberByAlphabet.vue
Normal file
748
src/pages/chatSettings/components/selectMemberByAlphabet.vue
Normal file
@ -0,0 +1,748 @@
|
||||
<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
|
||||
}
|
||||
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) {
|
||||
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>
|
@ -11,145 +11,19 @@
|
||||
@scroll="onScroll"
|
||||
>
|
||||
<template #top>
|
||||
<customNavbar :title="pageTitle" id="topArea"></customNavbar>
|
||||
<div id="topArea">
|
||||
<customNavbar :title="pageTitle"></customNavbar>
|
||||
</div>
|
||||
</template>
|
||||
<div class="select-members">
|
||||
<div
|
||||
class="search-member"
|
||||
v-if="state.manageType !== 'removeMembers'"
|
||||
>
|
||||
<customInput
|
||||
:searchText="state.searchText"
|
||||
@inputSearchText="inputSearchText"
|
||||
></customInput>
|
||||
</div>
|
||||
<div
|
||||
class="member-list"
|
||||
:style="{
|
||||
padding: state.manageType === 'searchRecord' ? '20rpx 0 0' : '',
|
||||
}"
|
||||
>
|
||||
<div class="member-list-alphabet-anchor-point">
|
||||
<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:
|
||||
state.manageType === 'searchRecord' ||
|
||||
state.manageType === 'removeMembers'
|
||||
? '10rpx 30rpx'
|
||||
: '',
|
||||
}"
|
||||
v-if="alphabetItem?.memberList?.length > 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)"
|
||||
<selectMemberByAlphabet
|
||||
:manageType="state.manageType"
|
||||
:itemStyle="
|
||||
state.manageType === 'searchRecord' ||
|
||||
state.manageType === 'removeMembers'
|
||||
? 'list'
|
||||
: 'card'
|
||||
"
|
||||
>
|
||||
<template
|
||||
#left
|
||||
v-if="state.manageType !== 'searchRecord'"
|
||||
>
|
||||
<div
|
||||
v-if="
|
||||
state.manageType === 'removeMembers' &&
|
||||
item?.is_mine
|
||||
"
|
||||
>
|
||||
<tm-checkbox
|
||||
color="#fff"
|
||||
:transprent="true"
|
||||
:border="0"
|
||||
:disabled="true"
|
||||
></tm-checkbox>
|
||||
</div>
|
||||
<tm-checkbox
|
||||
v-if="
|
||||
!(
|
||||
state.manageType === 'removeMembers' &&
|
||||
item?.is_mine
|
||||
)
|
||||
"
|
||||
:round="10"
|
||||
:color="
|
||||
item?.checkArr?.length > 0 ? '#46299d' : '#B4B4B4'
|
||||
"
|
||||
:outlined="
|
||||
item?.checkArr?.length > 0 ||
|
||||
(state.manageType === 'silence' &&
|
||||
item.is_mute === 1) ||
|
||||
(state.manageType === 'admin' &&
|
||||
(item.leader === 1 || item.leader === 2))
|
||||
? false
|
||||
: true
|
||||
"
|
||||
:value="item.id"
|
||||
:disabled="
|
||||
(state.manageType === 'silence' &&
|
||||
item.is_mute === 1) ||
|
||||
(state.manageType === 'admin' &&
|
||||
(item.leader === 1 || item.leader === 2))
|
||||
"
|
||||
@change="checkBoxChange"
|
||||
></tm-checkbox>
|
||||
</template>
|
||||
</selectMemberItem>
|
||||
</tm-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
:isCreateDepGroup="state.isCreateDepGroup"
|
||||
ref="selectMemberByAlphabetRef"
|
||||
:selectAreaHeight="state.selectAreaHeight"
|
||||
@updateSelectedMembersNum="updateSelectedMembersNum"
|
||||
></selectMemberByAlphabet>
|
||||
<template #bottom v-if="state.manageType !== 'searchRecord'">
|
||||
<div id="footArea">
|
||||
<customBtn
|
||||
v-if="state.manageType !== 'removeMembers'"
|
||||
:isBottom="true"
|
||||
@ -176,126 +50,70 @@
|
||||
:disabled="state.selectedMembersNum == 0 ? true : false"
|
||||
></customBtn>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import customInput from '@/components/custom-input/custom-input.vue'
|
||||
import selectMemberItem from '../components/select-member-item.vue'
|
||||
import selectMemberByAlphabet from '../components/selectMemberByAlphabet.vue'
|
||||
import customBtn from '@/components/custom-btn/custom-btn.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 } from 'vue'
|
||||
import { computed, reactive, ref, onMounted, nextTick } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import {
|
||||
ServeGroupNoSpeak,
|
||||
ServeEditGroupAdmin,
|
||||
ServeGroupAssignAdmin,
|
||||
ServeRemoveMembersGroup,
|
||||
} from '@/api/group/index.js'
|
||||
import { useDialogueStore, useGroupStore, useGroupTypeStore } from '@/store'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
const selectMemberByAlphabetRef = ref(null)
|
||||
|
||||
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 state = reactive({
|
||||
searchText: '', //搜索内容
|
||||
manageType: '', //管理类型
|
||||
alphabet: [], //A-Z列表
|
||||
resultMemberList: [], //按A-Z整理后的人员列表
|
||||
currentAlphabet: 'A', //当前A-Z位置
|
||||
scrollDirection: '', //当前列表滚动方向
|
||||
isAssign: false, //是否指定view
|
||||
selectedMembersNum: 0, //当前选中数量
|
||||
isCreateDepGroup: 0, //是否是创建部门群
|
||||
selectAreaHeight: 0, //选择区域高度
|
||||
})
|
||||
|
||||
watch(
|
||||
() => dialogueParams?.memberList,
|
||||
(newMemberList) => {
|
||||
assembleAlphabetMemberList(newMemberList)
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
watch(
|
||||
() => groupParams?.groupInfo,
|
||||
(newGroupInfo) => {
|
||||
assembleAlphabetMemberList(dialogueParams?.memberList)
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
//获取A-Z tag元素
|
||||
const alphabetElementRefs = ref([])
|
||||
//观察者
|
||||
let observer
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
// console.log(options)
|
||||
if (options.manageType) {
|
||||
state.manageType = options.manageType
|
||||
assembleAlphabetMemberList(dialogueParams?.memberList)
|
||||
}
|
||||
if (options.isCreateDepGroup) {
|
||||
state.isCreateDepGroup = Number(options.isCreateDepGroup)
|
||||
assembleAlphabetMemberList()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
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)
|
||||
let selectAreaHeight = uni.getSystemInfoSync().windowHeight
|
||||
// console.log('页面高度:', uni.getSystemInfoSync().windowHeight)
|
||||
const topAreaQuery = uni.createSelectorQuery()
|
||||
topAreaQuery
|
||||
.select('#topArea')
|
||||
.boundingClientRect((res) => {
|
||||
if (res) {
|
||||
// console.log('元素高度:', res.height)
|
||||
selectAreaHeight = selectAreaHeight - res.height
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
const footAreaQuery = uni.createSelectorQuery()
|
||||
footAreaQuery
|
||||
.select('#footArea')
|
||||
.boundingClientRect((res) => {
|
||||
if (res) {
|
||||
// console.log('元素高度:', res.height)
|
||||
selectAreaHeight = selectAreaHeight - res.height
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
)
|
||||
if (alphabetElementRefs.value.length > 0) {
|
||||
alphabetElementRefs.value.forEach((el, index) =>
|
||||
observeElement(el, index),
|
||||
)
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
// console.log(selectAreaHeight)
|
||||
state.selectAreaHeight = selectAreaHeight + 'px'
|
||||
})
|
||||
})
|
||||
|
||||
@ -314,341 +132,16 @@ const pageTitle = computed(() => {
|
||||
return page_title
|
||||
})
|
||||
|
||||
// 观察者函数
|
||||
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 observeElement = (el, index) => {
|
||||
if (el && observer) {
|
||||
observer.observe(el)
|
||||
}
|
||||
}
|
||||
|
||||
//输入搜索文本
|
||||
const inputSearchText = (e) => {
|
||||
// console.log(e)
|
||||
state.searchText = e
|
||||
}
|
||||
|
||||
//点击item
|
||||
const handleClickItem = (item) => {
|
||||
if (
|
||||
(state.manageType === 'silence' && item.is_mute === 1) ||
|
||||
(state.manageType === 'admin' &&
|
||||
(item.leader === 1 || item.leader === 2)) ||
|
||||
(state.manageType === 'removeMembers' && item.is_mine)
|
||||
) {
|
||||
return
|
||||
}
|
||||
let itemList = dialogueParams.memberList
|
||||
if (
|
||||
state.manageType === 'admin' &&
|
||||
(groupParams.groupInfo.group_type == 2 ||
|
||||
groupParams.groupInfo.group_type == 4 ||
|
||||
state.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) {
|
||||
state.selectedMembersNum += 1
|
||||
} else {
|
||||
state.selectedMembersNum -= 1
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//点击确认选择的成员
|
||||
//确认
|
||||
const confirmSelectMembers = () => {
|
||||
let selectedUserIds = ''
|
||||
let itemList = dialogueParams.memberList
|
||||
let positionInfos = []
|
||||
if (
|
||||
state.manageType === 'admin' &&
|
||||
(groupParams.groupInfo.group_type == 2 ||
|
||||
groupParams.groupInfo.group_type == 4 ||
|
||||
state.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]
|
||||
}
|
||||
}
|
||||
if (
|
||||
ele.checkArr?.length > 0 ||
|
||||
(ele.leader && (ele.leader == 1 || ele.leader == 2))
|
||||
) {
|
||||
if (state.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 (state.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 (state.manageType === 'admin') {
|
||||
if (state.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 (state.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) {
|
||||
useDialogueStore().updateGroupMembers()
|
||||
groupStore.ServeGroupDetail()
|
||||
} else {
|
||||
}
|
||||
})
|
||||
resp.catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//组装A-Z排序的人员列表
|
||||
const assembleAlphabetMemberList = async (newMemberList) => {
|
||||
if (
|
||||
state.manageType === 'searchRecord' ||
|
||||
state.manageType === 'removeMembers'
|
||||
) {
|
||||
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
|
||||
state.resultMemberList = resultMemberList
|
||||
} else {
|
||||
if (
|
||||
(groupParams.groupInfo.group_type == 2 ||
|
||||
groupParams.groupInfo.group_type == 4) &&
|
||||
state.manageType === 'admin'
|
||||
) {
|
||||
let departmentIdsArr = []
|
||||
if (groupParams?.groupInfo?.deptInfos?.length > 0) {
|
||||
groupParams.groupInfo.deptInfos.forEach((item) => {
|
||||
departmentIdsArr.push(item.dept_id)
|
||||
})
|
||||
}
|
||||
getPosiByDep(departmentIdsArr)
|
||||
} else if (state.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 (
|
||||
state.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
|
||||
: 80,
|
||||
)
|
||||
}
|
||||
|
||||
//监听列表滚动
|
||||
const onScroll = (e) => {
|
||||
if (e.detail.deltaY < 0) {
|
||||
state.scrollDirection = 'down'
|
||||
} else if (e.detail.deltaY > 0) {
|
||||
state.scrollDirection = 'up'
|
||||
} else {
|
||||
state.scrollDirection = ''
|
||||
if (selectMemberByAlphabetRef.value) {
|
||||
selectMemberByAlphabetRef.value.confirmSelectMembers()
|
||||
}
|
||||
}
|
||||
|
||||
//选中的人员改变
|
||||
const checkBoxChange = (e) => {
|
||||
if (e) {
|
||||
state.selectedMembersNum += 1
|
||||
} else {
|
||||
state.selectedMembersNum -= 1
|
||||
}
|
||||
//更新选中的人数
|
||||
const updateSelectedMembersNum = (numChange) => {
|
||||
state.selectedMembersNum = state.selectedMembersNum + numChange
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@ -659,48 +152,6 @@ const checkBoxChange = (e) => {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-btn-area {
|
||||
background-color: #fff;
|
||||
padding: 14rpx 32rpx 72rpx;
|
||||
|
@ -111,7 +111,6 @@
|
||||
<span
|
||||
class="nickname pointer"
|
||||
v-show="talkParams.type == 2 && item.float == 'left'"
|
||||
@click="onClickNickname(item)"
|
||||
>
|
||||
<span class="at">@</span>
|
||||
{{ item.nickname }}
|
||||
@ -212,15 +211,13 @@
|
||||
}}
|
||||
</span>
|
||||
<span
|
||||
v-if="state?.quoteInfo?.msg_type === 3"
|
||||
v-if="state?.quoteInfo"
|
||||
class="text-[28rpx] text-[#999]"
|
||||
>
|
||||
{{
|
||||
state?.quoteInfo?.nickname +
|
||||
':' +
|
||||
'[' +
|
||||
$t('msg.type') +
|
||||
']'
|
||||
ChatMsgTypeMapping[state?.quoteInfo?.msg_type]
|
||||
}}
|
||||
</span>
|
||||
<img
|
||||
@ -344,9 +341,99 @@
|
||||
</div>
|
||||
</template>
|
||||
</ZPaging>
|
||||
<tm-drawer
|
||||
placement="bottom"
|
||||
v-model:show="state.isShowMentionSelect"
|
||||
:hideHeader="true"
|
||||
:round="5"
|
||||
:height="state.mentionSelectHeight"
|
||||
>
|
||||
<div
|
||||
class="mention-select-drawer flex flex-row flex-1 flex-row flex-row-center-between"
|
||||
>
|
||||
<div
|
||||
class="cancel-btns flex-row flex flex-row-center-start"
|
||||
style="width: 210rpx;"
|
||||
>
|
||||
<div
|
||||
class="hide-btn"
|
||||
v-if="!state.mentionIsMulSelect"
|
||||
@click="hideMentionSelect"
|
||||
>
|
||||
<img
|
||||
style="width: 40rpx; height: 40rpx;"
|
||||
src="/src/static/image/chatList/mention_select_hide_bg.png"
|
||||
/>
|
||||
<img
|
||||
style="
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -9rpx;
|
||||
margin-top: -5rpx;
|
||||
"
|
||||
src="/src/static/image/chatList/mention_select_hide_icon.png"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
style="flex-shrink: 0; display: block;"
|
||||
class="text-[32rpx] font-regular text-[#191919]"
|
||||
v-if="state.mentionIsMulSelect"
|
||||
@click="changeMentionSelectMul(false)"
|
||||
>
|
||||
{{ $t('cancel') }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-row-center-center flex-col"
|
||||
style="padding: 6rpx 0;"
|
||||
>
|
||||
<text>{{ $t('chat.mention.select') }}</text>
|
||||
</div>
|
||||
<div class="flex-row flex flex-row-center-end" style="width: 210rpx;">
|
||||
<div
|
||||
class="mention-edit-btn"
|
||||
v-if="!state.mentionIsMulSelect"
|
||||
@click="changeMentionSelectMul(true)"
|
||||
>
|
||||
<span class="text-[32rpx] font-regular text-[#191919]">
|
||||
{{ $t('button.multiple.choice') }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mention-done-btn"
|
||||
:class="
|
||||
state?.selectedMembersNum > 0 ? 'mention-done-btn-can-do' : ''
|
||||
"
|
||||
v-if="state.mentionIsMulSelect"
|
||||
@click="confirmMentionSelect"
|
||||
>
|
||||
<span class="text-[32rpx] font-regular text-[#191919]">
|
||||
{{ $t('button.text.done') }}
|
||||
</span>
|
||||
<span
|
||||
class="text-[32rpx] font-regular text-[#191919]"
|
||||
v-if="state?.selectedMembersNum > 0"
|
||||
>
|
||||
{{ '(' + state?.selectedMembersNum + ')' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<selectMemberByAlphabet
|
||||
:manageType="'mention'"
|
||||
ref="selectMemberByAlphabetRef"
|
||||
:selectAreaHeight="state.selectAreaHeight"
|
||||
@updateSelectedMembersNum="updateSelectedMembersNum"
|
||||
:isMulSelect="state.mentionIsMulSelect"
|
||||
@getSelectResult="getSelectResult"
|
||||
@getMentionSelectLists="getMentionSelectLists"
|
||||
></selectMemberByAlphabet>
|
||||
</tm-drawer>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import selectMemberByAlphabet from '../chatSettings/components/selectMemberByAlphabet.vue'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
@ -370,7 +457,11 @@ import {
|
||||
useDialogueListStore,
|
||||
} from '@/store'
|
||||
import addCircleGray from '@/static/image/chatList/addCircleGray.png'
|
||||
import { MessageComponents, ForwardableMessageType } from '@/constant/message'
|
||||
import {
|
||||
MessageComponents,
|
||||
ForwardableMessageType,
|
||||
ChatMsgTypeMapping,
|
||||
} from '@/constant/message'
|
||||
import { formatTime, parseTime } from '@/utils/datetime'
|
||||
import { deltaToMessage, deltaToString, isEmptyDelta } from './util'
|
||||
import smile from '@/static/image/chatList/smile@2x.png'
|
||||
@ -399,6 +490,8 @@ import { onLoad as uniOnload } from '@dcloudio/uni-app'
|
||||
|
||||
Quill.register('formats/emoji', EmojiBlot)
|
||||
|
||||
const selectMemberByAlphabetRef = ref(null)
|
||||
|
||||
const {
|
||||
getDialogueList,
|
||||
updateZpagingRef,
|
||||
@ -433,6 +526,11 @@ const state = ref({
|
||||
sessionId: '',
|
||||
localPageLoadDone: true, //分页加载缓存中的聊天记录是否完毕
|
||||
quoteInfo: null, //引用信息
|
||||
mentionIsMulSelect: false, //是否是多选提醒的人
|
||||
selectedMembersNum: 0, //选中的要提醒的人数
|
||||
mentionSelectHeight: 0, //选择要提醒人的区域高度
|
||||
selectAreaHeight: 0, //选择要提醒人的可选人员列表区域高度
|
||||
isShowMentionSelect: false, //是否显示要提醒人的选择区域
|
||||
})
|
||||
|
||||
uniOnload((options) => {
|
||||
@ -487,6 +585,15 @@ const onSendMessage = (data = {}, callBack) => {
|
||||
|
||||
const onSendMessageClick = () => {
|
||||
let delta = getQuill().getContents()
|
||||
if (state.value.quoteInfo) {
|
||||
delta.ops.unshift({
|
||||
insert: {
|
||||
quote: {
|
||||
id: state.value.quoteInfo.msg_id,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
let data = deltaToMessage(delta)
|
||||
|
||||
if (data.items.length === 0) {
|
||||
@ -503,6 +610,9 @@ const onSendMessageClick = () => {
|
||||
callBack: (ok) => {
|
||||
if (!ok) return
|
||||
getQuill().setContents([], Quill.sources.USER)
|
||||
if (state.value.quoteInfo) {
|
||||
state.value.quoteInfo = null
|
||||
}
|
||||
},
|
||||
})
|
||||
break
|
||||
@ -623,6 +733,14 @@ const onEditorChange = () => {
|
||||
|
||||
let text = deltaToString(delta)
|
||||
|
||||
if (
|
||||
text.length > 0 &&
|
||||
text.slice(-2).trim() === '@' &&
|
||||
talkParams.type === 2
|
||||
) {
|
||||
state.value.isShowMentionSelect = true
|
||||
}
|
||||
|
||||
if (!isEmptyDelta(delta)) {
|
||||
editorDraftStore.items[indexName.value || ''] = JSON.stringify({
|
||||
text: text,
|
||||
@ -855,6 +973,11 @@ const handleDelete = () => {
|
||||
})
|
||||
}
|
||||
|
||||
//更新选中的要提醒的人数
|
||||
const updateSelectedMembersNum = (numChange) => {
|
||||
state.value.selectedMembersNum = state.value.selectedMembersNum + numChange
|
||||
}
|
||||
|
||||
watch(
|
||||
() => zpagingRef.value,
|
||||
(newValue, oldValue) => {
|
||||
@ -934,9 +1057,77 @@ const toUserDetailPage = (userItem) => {
|
||||
})
|
||||
}
|
||||
|
||||
//切换提醒的人选择弹窗多选状态
|
||||
const changeMentionSelectMul = (status) => {
|
||||
state.value.mentionIsMulSelect = status
|
||||
}
|
||||
|
||||
//隐藏要提醒人的选择
|
||||
const hideMentionSelect = () => {
|
||||
state.value.isShowMentionSelect = false
|
||||
}
|
||||
|
||||
//确认要提醒人的选择
|
||||
const confirmMentionSelect = () => {
|
||||
if (state?.value.selectedMembersNum > 0) {
|
||||
if (selectMemberByAlphabetRef.value) {
|
||||
selectMemberByAlphabetRef.value.confirmSelectMembers()
|
||||
}
|
||||
hideMentionSelect()
|
||||
}
|
||||
}
|
||||
|
||||
//获取选择的结果
|
||||
const getSelectResult = (mentionSelect) => {
|
||||
console.log(mentionSelect)
|
||||
getMentionSelectLists(mentionSelect)
|
||||
}
|
||||
|
||||
//处理要提醒人的消息样式
|
||||
const getMentionSelectLists = (mentionSelectList) => {
|
||||
console.log(mentionSelectList)
|
||||
let mentionUserIds = []
|
||||
let mentionUsers = getQuill().getContents().ops //先读出来之前的信息内容
|
||||
mentionUsers[0].insert =
|
||||
mentionUsers[0].insert.slice(0, -2) + mentionUsers[0].insert.slice(-1)
|
||||
console.log(mentionUsers[0].insert)
|
||||
mentionSelectList.forEach((mentionSelectItem) => {
|
||||
mentionUserIds.push(mentionSelectItem.erp_user_id)
|
||||
mentionUserIds.push(mentionSelectItem.id)
|
||||
mentionUsers.push({
|
||||
insert: '@' + mentionSelectItem.nickname + ' ',
|
||||
attributes: {
|
||||
color: '#1890ff',
|
||||
},
|
||||
})
|
||||
})
|
||||
getQuill().setContents(mentionUsers)
|
||||
hideMentionSelect()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
initData()
|
||||
nextTick(() => {
|
||||
state.value.mentionSelectHeight = pxTorPx(
|
||||
uni.getSystemInfoSync().windowHeight * 0.86,
|
||||
)
|
||||
|
||||
state.value.selectAreaHeight =
|
||||
rpxToPx(state.value.mentionSelectHeight) - rpxToPx(90) + 'px'
|
||||
})
|
||||
})
|
||||
|
||||
const pxTorPx = (px) => {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
const rpx = px / (sysInfo.screenWidth / 750)
|
||||
return rpx
|
||||
}
|
||||
|
||||
const rpxToPx = (rpx) => {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
const px = (sysInfo.screenWidth / 750) * rpx
|
||||
return px
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
dialogueStore.setDialogue({})
|
||||
@ -1256,4 +1447,66 @@ onUnmounted(() => {
|
||||
height: 1rpx;
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
|
||||
.mention-select-drawer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 36rpx 32rpx 0;
|
||||
.cancel-btns {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.hide-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
text {
|
||||
}
|
||||
img {
|
||||
width: 18rpx;
|
||||
height: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mention-done-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 6rpx 24rpx;
|
||||
background-color: #f3f3f3;
|
||||
border-radius: 8rpx;
|
||||
flex-shrink: 0;
|
||||
span {
|
||||
color: #bababa;
|
||||
line-height: 40rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.mention-done-btn-can-do {
|
||||
background-color: #46299d;
|
||||
span {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.mention-edit-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
span {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
BIN
src/static/image/chatList/groupAllMember.png
Normal file
BIN
src/static/image/chatList/groupAllMember.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
BIN
src/static/image/chatList/mention_select_hide_bg.png
Normal file
BIN
src/static/image/chatList/mention_select_hide_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 752 B |
BIN
src/static/image/chatList/mention_select_hide_icon.png
Normal file
BIN
src/static/image/chatList/mention_select_hide_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 208 B |
@ -7,7 +7,7 @@ import { createGlobalState, useStorage } from '@vueuse/core'
|
||||
import { uniStorage } from '@/utils/uniStorage.js'
|
||||
|
||||
export const useDialogueListStore = createGlobalState(() => {
|
||||
const dialogueList = useStorage('dialogueList', [], uniStorage)
|
||||
const dialogueList = ref([])
|
||||
const zpagingRef = ref()
|
||||
const virtualList = ref([])
|
||||
|
||||
|
@ -150,5 +150,5 @@
|
||||
"button.text.close": "关闭",
|
||||
"choose.deps.all": "全部",
|
||||
"choose.deps.current": "当前",
|
||||
"msg.type": "图片"
|
||||
"chat.mention.select": "选择提醒的人"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user