feat(ContactModal): 添加群聊选择功能并优化联系人选择逻辑

- 新增群聊选择表格列和状态管理
- 优化联系人选择逻辑,支持单选和多选模式
- 调整弹窗高度和按钮样式
- 分离员工通讯录和群聊列表的提交处理
This commit is contained in:
xingyy 2025-08-28 11:03:59 +08:00
parent 6fc34c13b8
commit f730571232
2 changed files with 66 additions and 30 deletions

View File

@ -34,6 +34,7 @@ const forwardMode = defineProps(['forwardMode'])
// //
const state = reactive({ const state = reactive({
selectedGroupRowKeys: [],
isShowAddressBookModal: false, isShowAddressBookModal: false,
customModalStyle: { customModalStyle: {
width: '1288px', width: '1288px',
@ -94,6 +95,9 @@ const state = reactive({
} }
], ],
groupChatListColumns: [ groupChatListColumns: [
{
type: 'selection'
},
{ {
title: '群聊名称', title: '群聊名称',
field: 'groupName', field: 'groupName',
@ -127,7 +131,7 @@ const state = reactive({
addressBookData: [], addressBookData: [],
company_name: '', company_name: '',
groupChatListData: [], groupChatListData: [],
addressBookTableHeight: 524, addressBookTableHeight: 500,
addressBookTableWidth: 800, addressBookTableWidth: 800,
addressBookPage: 1, addressBookPage: 1,
addressBookPageSize: 10, addressBookPageSize: 10,
@ -189,16 +193,29 @@ const onMaskClick = () => {
const selectType = ref(2) const selectType = ref(2)
const onTriggerContact = (item) => { const onTriggerContact = (item) => {
const clicked = items.value.find((val) => val.id === item.id)
if (!clicked) return
if (selectType.value === 1) { if (selectType.value === 1) {
//
items.value.forEach(contact => { items.value.forEach(contact => {
contact.checked = false contact.checked = false
}) })
clicked.checked = true
return
} }
let data = items.value.find((val) => val.id === item.id) //
if (!clicked.checked) {
if (data) { const checked = items.value.filter(c => c.checked)
data.checked = !data.checked const currentType = checked.length ? checked[0].talk_type : null
if (currentType && currentType !== clicked.talk_type) {
//
items.value.forEach(c => { if (c.checked) c.checked = false })
}
clicked.checked = true
} else {
clicked.checked = false
} }
} }
@ -353,6 +370,12 @@ const changeAddressBookSearch = (value) => {
const handleAddressBookTabChange = (value) => { const handleAddressBookTabChange = (value) => {
state.addressBookCurrentTab = value state.addressBookCurrentTab = value
//
if (value === 'employeeAddressBook') {
state.selectedGroupRowKeys = []
} else if (value === 'groupChatList') {
state.selectedRowKeys = []
}
} }
const changeGroupChatListSearch = (value) => { const changeGroupChatListSearch = (value) => {
@ -379,6 +402,7 @@ const onAddressBookCancel = () => {
} }
const onAddressBookSubmit = async () => { const onAddressBookSubmit = async () => {
if (state.addressBookCurrentTab === 'employeeAddressBook') {
if (!Array.isArray(state.selectedRowKeys) || state.selectedRowKeys.length === 0) { if (!Array.isArray(state.selectedRowKeys) || state.selectedRowKeys.length === 0) {
processError('请选择联系人') processError('请选择联系人')
return return
@ -403,6 +427,16 @@ const onAddressBookSubmit = async () => {
} catch (e) { } catch (e) {
processError('发送失败,请稍后重试') processError('发送失败,请稍后重试')
} }
} else if (state.addressBookCurrentTab === 'groupChatList') {
if (!Array.isArray(state.selectedGroupRowKeys) || state.selectedGroupRowKeys.length === 0) {
processError('请选择群聊')
return
}
const data = state.selectedGroupRowKeys.map((gid) => ({ receiver_id: gid, talk_type: 2 }))
emit('on-submit', data)
state.isShowAddressBookModal = false
}
} }
watch(() => { watch(() => {
@ -540,7 +574,7 @@ watch(() => state.groupChatListSearchGroupName, (newValue, oldValue) => {
</span> </span>
<span v-else>请选择联系人</span> <span v-else>请选择联系人</span>
</div> </div>
<div class="flex justify-center items-center"> <div class="flex justify-center items-center ">
<n-button color="#C7C7C9" class="w-250px h-34px text-14px text-#fff mr-10px" @click="onCancel">取消</n-button> <n-button color="#C7C7C9" class="w-250px h-34px text-14px text-#fff mr-10px" @click="onCancel">取消</n-button>
<n-button color="#46299D" class="w-250px h-34px text-14px text-#fff" <n-button color="#46299D" class="w-250px h-34px text-14px text-#fff"
@click="onSubmit" :disabled="isCanSubmit">发送</n-button> @click="onSubmit" :disabled="isCanSubmit">发送</n-button>
@ -633,9 +667,11 @@ watch(() => state.groupChatListSearchGroupName, (newValue, oldValue) => {
:columns="state.groupChatListColumns" :columns="state.groupChatListColumns"
:data="state.groupChatListData" :data="state.groupChatListData"
:style="{ :style="{
height: '523px', height: '500px',
width: '1148px' width: '1148px'
}" }"
:row-key="row => row.id"
v-model:checked-row-keys="state.selectedGroupRowKeys"
flex-height flex-height
></xNDataTable> ></xNDataTable>
<div class="groupChatList-pagination"> <div class="groupChatList-pagination">
@ -656,9 +692,9 @@ watch(() => state.groupChatListSearchGroupName, (newValue, oldValue) => {
</div> </div>
<!-- 底部操作按钮仅保留展示 --> <!-- 底部操作按钮仅保留展示 -->
<div style="display: flex; justify-content: center; align-items: center; padding: 16px 0;"> <div style="display: flex; justify-content: center; align-items: center; padding: 10px 0;">
<n-button color="#C7C7C9" class="w-250px h-34px text-14px text-#fff mr-10px" @click="onAddressBookCancel">取消</n-button> <n-button color="#C7C7C9" class="w-200px h-34px text-14px text-#fff mr-10px" @click="onAddressBookCancel">取消</n-button>
<n-button color="#46299D" class="w-250px h-34px text-14px text-#fff" @click="onAddressBookSubmit">发送</n-button> <n-button color="#46299D" class="w-200px h-34px text-14px text-#fff" @click="onAddressBookSubmit">发送</n-button>
</div> </div>
</n-card> </n-card>
</div> </div>
@ -675,7 +711,7 @@ watch(() => state.groupChatListSearchGroupName, (newValue, oldValue) => {
.addressBook-tree { .addressBook-tree {
width: 328px; width: 328px;
height: 524px; height: 500px;
overflow: auto; overflow: auto;
border: 1px solid #efeff5; border: 1px solid #efeff5;
border-radius: 4px; border-radius: 4px;

View File

@ -18,7 +18,7 @@ export function isLoggedIn() {
*/ */
export function getAccessToken() { export function getAccessToken() {
// return storage.get(AccessToken) || '' // return storage.get(AccessToken) || ''
return JSON.parse(localStorage.getItem('token'))||'46d71a72d8d845ad7ed23eba9bdde260e635407190c2ce1bf7fd22088e41682ea07773ec65cae8946d2003f264d55961f96e0fc5da10eb96d3a348c1664e9644ce2108c311309f398ae8ea1b8200bfd490e5cb6e8c52c9e5d493cbabb163368f8351420451a631dbfa749829ee4cda49b77b5ed2d3dced5d0f2b7dd9ee76ba5465c84a17c23af040cd92b6b2a4ea48befbb5c729dcdad0a9c9668befe84074cc24f78899c1d947f8e7f94c7eda5325b8ed698df729e76febb98549ef3482ae942fb4f4a1c92d21836fa784728f0c5483aab2760a991b6b36e6b10c84f840a6433a6ecc31dee36e8f1c6158818bc89d22184be97f604c74931ddd023225ae1a2ab29c0eb046e9a20174f1110532e4af8498ab46f4375f2e210bae827a6146183f385fdee154fd7bee38deb6ac4c00ae82c77150d5663288f78d678db028bfb7db' return JSON.parse(localStorage.getItem('token'))||'46d71a72d8d845ad7ed23eba9bdde260e635407190c2ce1bf7fd22088e41682ea07773ec65cae8946d2003f264d55961f96e0fc5da10eb96d3a348c1664e9644ce2108c311309f398ae8ea1b8200bfd490e5cb6e8c52c9e5d493cbabb163368f8351420451a631dbfa749829ee4cda49b77b5ed2d3dced5d0f2b7dd9ee76ba5465c84a17c23af040cd92b6b2a4ea48befbb5c729dcdad0a9c9668befe84074cc24f78899c1d947f8e7f94c7eda5325b8ed698df729e76febb98549ef3482ae942fb4f4a1c92d21836fa784728f0c5483aab2760a991b6b36e6b10c84f840a6433a6ecc31dee36e8f1c6158818bc89d2255563bc58403f27383b042a2a3b70cfd7a005ba858457a5f0ae0c6ebfc51cbe9b95318d19d4c01987709638e27778193a0e3ecc0a31b940529ef07f5b054d55af57770cad3d97738f3e9fbd7f6a2805b'
} }
/** /**