feat(ContactModal): 新增通讯录功能并重构转发联系人界面
- 添加@vicons/tabler图标库依赖 - 启用vueDevTools插件 - 重构ContactModal组件,增加通讯录功能 - 实现部门树形结构展示和员工搜索 - 添加群聊列表展示功能 - 优化界面样式和交互体验
This commit is contained in:
parent
b484bc0823
commit
1946ef8e9c
@ -68,6 +68,7 @@
|
|||||||
"@types/node": "^18.18.5",
|
"@types/node": "^18.18.5",
|
||||||
"@types/vue": "^2.0.0",
|
"@types/vue": "^2.0.0",
|
||||||
"@unocss/reset": "^66.1.1",
|
"@unocss/reset": "^66.1.1",
|
||||||
|
"@vicons/tabler": "^0.13.0",
|
||||||
"@vitejs/plugin-vue": "^4.4.0",
|
"@vitejs/plugin-vue": "^4.4.0",
|
||||||
"@vitejs/plugin-vue-jsx": "^3.0.2",
|
"@vitejs/plugin-vue-jsx": "^3.0.2",
|
||||||
"@vue/tsconfig": "^0.4.0",
|
"@vue/tsconfig": "^0.4.0",
|
||||||
|
@ -159,6 +159,9 @@ importers:
|
|||||||
'@unocss/reset':
|
'@unocss/reset':
|
||||||
specifier: ^66.1.1
|
specifier: ^66.1.1
|
||||||
version: 66.3.0
|
version: 66.3.0
|
||||||
|
'@vicons/tabler':
|
||||||
|
specifier: ^0.13.0
|
||||||
|
version: 0.13.0
|
||||||
'@vitejs/plugin-vue':
|
'@vitejs/plugin-vue':
|
||||||
specifier: ^4.4.0
|
specifier: ^4.4.0
|
||||||
version: 4.6.2(vite@6.3.5(@types/node@18.19.112)(jiti@1.21.7)(less@4.3.0)(sass@1.89.2)(terser@5.43.1))(vue@3.5.17(typescript@5.2.2))
|
version: 4.6.2(vite@6.3.5(@types/node@18.19.112)(jiti@1.21.7)(less@4.3.0)(sass@1.89.2)(terser@5.43.1))(vue@3.5.17(typescript@5.2.2))
|
||||||
@ -1250,6 +1253,9 @@ packages:
|
|||||||
'@vicons/ionicons5@0.13.0':
|
'@vicons/ionicons5@0.13.0':
|
||||||
resolution: {integrity: sha512-zvZKBPjEXKN7AXNo2Na2uy+nvuv6SP4KAMQxpKL2vfHMj0fSvuw7JZcOPCjQC3e7ayssKnaoFVAhbYcW6v41qQ==}
|
resolution: {integrity: sha512-zvZKBPjEXKN7AXNo2Na2uy+nvuv6SP4KAMQxpKL2vfHMj0fSvuw7JZcOPCjQC3e7ayssKnaoFVAhbYcW6v41qQ==}
|
||||||
|
|
||||||
|
'@vicons/tabler@0.13.0':
|
||||||
|
resolution: {integrity: sha512-AykuhiqjszkIoAL/7knIFm6RDOBS1ZmQdJfQ+RNLEah0fVsxykUFCfMBSNZh8lOzC85EtdD1k5g/sv5GYk0Ohg==}
|
||||||
|
|
||||||
'@vitejs/plugin-vue-jsx@3.1.0':
|
'@vitejs/plugin-vue-jsx@3.1.0':
|
||||||
resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
|
resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
@ -5009,6 +5015,8 @@ snapshots:
|
|||||||
|
|
||||||
'@vicons/ionicons5@0.13.0': {}
|
'@vicons/ionicons5@0.13.0': {}
|
||||||
|
|
||||||
|
'@vicons/tabler@0.13.0': {}
|
||||||
|
|
||||||
'@vitejs/plugin-vue-jsx@3.1.0(vite@6.3.5(@types/node@18.19.112)(jiti@1.21.7)(less@4.3.0)(sass@1.89.2)(terser@5.43.1))(vue@3.5.17(typescript@5.2.2))':
|
'@vitejs/plugin-vue-jsx@3.1.0(vite@6.3.5(@types/node@18.19.112)(jiti@1.21.7)(less@4.3.0)(sass@1.89.2)(terser@5.43.1))(vue@3.5.17(typescript@5.2.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.27.4
|
'@babel/core': 7.27.4
|
||||||
|
@ -1,46 +1,164 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="js" setup>
|
||||||
import { ref, computed, onMounted, watch } from 'vue'
|
import { ref, computed, onMounted, watch, reactive, nextTick, getCurrentInstance, h } from 'vue'
|
||||||
import { ServeGetTalkList } from '@/api/chat.js'
|
import { ServeGetTalkList } from '@/api/chat.js'
|
||||||
import { ServeGetGroups } from '@/api/group'
|
import { ServeGetGroups } from '@/api/group'
|
||||||
import XNModal from '@/components/x-naive-ui/x-n-modal/index.vue'
|
import XNModal from '@/components/x-naive-ui/x-n-modal/index.vue'
|
||||||
const emit = defineEmits(['close', 'on-submit'])
|
import { Plus } from '@vicons/tabler'
|
||||||
import { CloseCircle } from '@vicons/ionicons5'
|
import { CloseCircle } from '@vicons/ionicons5'
|
||||||
interface Item {
|
import customModal from '@/components/common/customModal.vue'
|
||||||
id: number
|
import xSearchForm from '@/components/x-naive-ui/x-search-form/index.vue'
|
||||||
type: number
|
import xNDataTable from '@/components/x-naive-ui/x-n-data-table/index.vue'
|
||||||
name: string
|
import flTree from '@/components/flnlayout/tree/flnindex.vue'
|
||||||
avatar: string
|
import { processError, processSuccess } from '@/utils/helper/message.js'
|
||||||
remark: string
|
import { ServeUserGroupChatList } from '@/api/search'
|
||||||
checked: boolean
|
import { GetContactFriendList } from '@/api/chat'
|
||||||
keyword: string
|
import { getUserInfoByERPUserId } from '@/api/user'
|
||||||
}
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useUtil } from '@/hooks/useUtil'
|
||||||
|
import { NButton } from 'naive-ui'
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'on-submit'])
|
||||||
|
|
||||||
|
const { useMessage } = useUtil()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const currentInstance = getCurrentInstance()
|
||||||
|
const $request = currentInstance?.appContext.config.globalProperties?.$request
|
||||||
|
|
||||||
const isShowBox = defineModel('show')
|
const isShowBox = defineModel('show')
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const items = ref<Item[]>([])
|
const items = ref([])
|
||||||
const keywords = ref('')
|
const keywords = ref('')
|
||||||
const loadGroupStatus = ref(false)
|
const loadGroupStatus = ref(false)
|
||||||
defineProps<{
|
const forwardMode = defineProps(['forwardMode'])
|
||||||
forwardMode: number
|
|
||||||
}>()
|
// 通讯录弹窗相关状态
|
||||||
// 搜索过滤器:不再按类型过滤,将好友和群组融合在一起
|
const state = reactive({
|
||||||
|
isShowAddressBookModal: false,
|
||||||
|
customModalStyle: {
|
||||||
|
width: '1288px',
|
||||||
|
height: '846px',
|
||||||
|
backgroundColor: '#F9F9FD'
|
||||||
|
},
|
||||||
|
addressBookSearchConfig: [
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
key: 'nickName',
|
||||||
|
type: 'input',
|
||||||
|
valueType: 'string'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
groupChatListSearchConfig: [
|
||||||
|
{
|
||||||
|
label: '群聊名称',
|
||||||
|
key: 'groupName',
|
||||||
|
type: 'input',
|
||||||
|
valueType: 'string'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
treeData: [],
|
||||||
|
expandedKeys: [],
|
||||||
|
clickKey: 3,
|
||||||
|
treeRefreshCount: 0,
|
||||||
|
treeSelectData: {},
|
||||||
|
addressBookColumns: [
|
||||||
|
{
|
||||||
|
type: 'selection'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '姓名 【工号】',
|
||||||
|
field: 'nickname',
|
||||||
|
width: 200,
|
||||||
|
ellipsis: {
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
render(row, index) {
|
||||||
|
return row.nickName + '【' + row.jobNum + '】'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '岗位名称',
|
||||||
|
field: 'user_position',
|
||||||
|
width: 400,
|
||||||
|
ellipsis: {
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
render(row, index) {
|
||||||
|
let positionNames = Array.isArray(row.depPositions)
|
||||||
|
? row.depPositions.flatMap((dep) =>
|
||||||
|
Array.isArray(dep.positions) ? dep.positions.map((pos) => pos.name) : []
|
||||||
|
)
|
||||||
|
: []
|
||||||
|
return positionNames.join(' , ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
groupChatListColumns: [
|
||||||
|
{
|
||||||
|
title: '群聊名称',
|
||||||
|
field: 'groupName',
|
||||||
|
width: 400,
|
||||||
|
ellipsis: {
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
render(row, index) {
|
||||||
|
return row.group_name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '群类型',
|
||||||
|
field: 'groupType',
|
||||||
|
width: 200,
|
||||||
|
ellipsis: true,
|
||||||
|
render(row, index) {
|
||||||
|
let groupType = row.group_type
|
||||||
|
if (groupType == 1) {
|
||||||
|
return '普通群'
|
||||||
|
} else if (groupType == 2) {
|
||||||
|
return '部门群'
|
||||||
|
} else if (groupType == 3) {
|
||||||
|
return '项目群'
|
||||||
|
} else if (groupType == 4) {
|
||||||
|
return '公司群'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
addressBookData: [],
|
||||||
|
company_name: '',
|
||||||
|
groupChatListData: [],
|
||||||
|
addressBookTableHeight: 524,
|
||||||
|
addressBookTableWidth: 800,
|
||||||
|
addressBookPage: 1,
|
||||||
|
addressBookPageSize: 10,
|
||||||
|
addressBookTotal: 0,
|
||||||
|
addressBookSearchNickName: '',
|
||||||
|
addressBookCurrentTab: 'employeeAddressBook',
|
||||||
|
groupChatListPage: 1,
|
||||||
|
groupChatListPageSize: 10,
|
||||||
|
groupChatListTotal: 0,
|
||||||
|
groupChatListSearchGroupName: '',
|
||||||
|
selectedRowKeys: []
|
||||||
|
})
|
||||||
|
|
||||||
|
// 原有转发功能的过滤器
|
||||||
const searchFilter = computed(() => {
|
const searchFilter = computed(() => {
|
||||||
return items.value.filter((item: Item) => {
|
return items.value.filter((item) => {
|
||||||
return item.name.toLowerCase().includes(keywords.value.toLowerCase())
|
return item.name.toLowerCase().includes(keywords.value.toLowerCase())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const checkedFilter = computed(() => {
|
const checkedFilter = computed(() => {
|
||||||
return items.value.filter((item: Item) => item.checked)
|
return items.value.filter((item) => item.checked)
|
||||||
})
|
})
|
||||||
|
|
||||||
const isCanSubmit = computed(() => {
|
const isCanSubmit = computed(() => {
|
||||||
return !checkedFilter.value.length
|
return !checkedFilter.value.length
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 原有加载数据函数
|
||||||
const onLoad = () => {
|
const onLoad = () => {
|
||||||
onLoadContact()
|
onLoadContact()
|
||||||
// onLoadGroup()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onLoadContact = () => {
|
const onLoadContact = () => {
|
||||||
@ -50,7 +168,7 @@ const onLoadContact = () => {
|
|||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
let list = res.data.items || []
|
let list = res.data.items || []
|
||||||
|
|
||||||
items.value = list.filter((item: any) => ((item.talk_type === 1 && item.receiver_id !== 2) || item.talk_type !== 1)).map((item: any) => {
|
items.value = list.filter((item) => ((item.talk_type === 1 && item.receiver_id !== 2) || item.talk_type !== 1)).map((item) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
checked: false
|
checked: false
|
||||||
@ -63,57 +181,29 @@ const onLoadContact = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// const onLoadGroup = async () => {
|
// 原有转发功能函数
|
||||||
// if (loadGroupStatus.value) {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// loading.value = true
|
|
||||||
// let { code, data } = await ServeGetGroups()
|
|
||||||
// if (code != 200) {
|
|
||||||
// loading.value = false
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let list = data.items.map((item: any) => {
|
|
||||||
// return {
|
|
||||||
// id: item.id,
|
|
||||||
// avatar: item.avatar,
|
|
||||||
// type: 2,
|
|
||||||
// name: item.group_name,
|
|
||||||
// keyword: item.group_name,
|
|
||||||
// remark: '',
|
|
||||||
// checked: false
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
// items.value.push(...list)
|
|
||||||
|
|
||||||
// loading.value = false
|
|
||||||
// loadGroupStatus.value = true
|
|
||||||
// }
|
|
||||||
|
|
||||||
const onMaskClick = () => {
|
const onMaskClick = () => {
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
const onTriggerContact = (item: any) => {
|
const selectType = ref(2)
|
||||||
// 如果是单选模式,先取消所有选中
|
|
||||||
|
const onTriggerContact = (item) => {
|
||||||
if (selectType.value === 1) {
|
if (selectType.value === 1) {
|
||||||
items.value.forEach(contact => {
|
items.value.forEach(contact => {
|
||||||
contact.checked = false
|
contact.checked = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = items.value.find((val: any) => val.id === item.id)
|
let data = items.value.find((val) => val.id === item.id)
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
data.checked = !data.checked
|
data.checked = !data.checked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onRemoveContact = (item: any) => {
|
const onRemoveContact = (item) => {
|
||||||
let data = items.value.find((val: any) => val.id === item.id)
|
let data = items.value.find((val) => val.id === item.id)
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
data.checked = false
|
data.checked = false
|
||||||
@ -125,7 +215,7 @@ const onCancel = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
let data = checkedFilter.value.map((item: any) => {
|
let data = checkedFilter.value.map((item) => {
|
||||||
return {
|
return {
|
||||||
receiver_id: item.receiver_id,
|
receiver_id: item.receiver_id,
|
||||||
talk_type: item.talk_type
|
talk_type: item.talk_type
|
||||||
@ -134,30 +224,208 @@ const onSubmit = () => {
|
|||||||
emit('on-submit', data)
|
emit('on-submit', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1 单选 2 多选
|
// 通讯录弹窗功能函数
|
||||||
const selectType = ref(1)
|
const onCreateContact = () => {
|
||||||
const changeSelectType = () => {
|
state.isShowAddressBookModal = true
|
||||||
selectType.value = selectType.value == 1 ? 2 : 1
|
getTreeData()
|
||||||
|
getDepPoisUser()
|
||||||
// 切换选择模式时清空已选择的联系人
|
getUserGroupChatList()
|
||||||
items.value.forEach(item => {
|
}
|
||||||
item.checked = false
|
|
||||||
|
const closeAddressBookModal = () => {
|
||||||
|
state.isShowAddressBookModal = false
|
||||||
|
resetAddressBookModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
const calcTreeData = (data) => {
|
||||||
|
for (let item of data) {
|
||||||
|
item.key = item.ID
|
||||||
|
item.label = item.name
|
||||||
|
item.title = item.name
|
||||||
|
if (item.sons) {
|
||||||
|
item.children = item.sons
|
||||||
|
calcTreeData(item.children)
|
||||||
|
}
|
||||||
|
delete item.ID
|
||||||
|
delete item.name
|
||||||
|
delete item.sons
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTreeData = () => {
|
||||||
|
let url = '/department/v2/tree/filter'
|
||||||
|
let params = {}
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0 && Array.isArray(res.data.nodes)) {
|
||||||
|
let data = res.data.nodes
|
||||||
|
calcTreeData(data)
|
||||||
|
state.treeData = data
|
||||||
|
state.treeRefreshCount++
|
||||||
|
getDepPoisUser()
|
||||||
|
} else {
|
||||||
|
processError(res.msg || '获取失败!')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError('获取失败!')
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError('获取失败!')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDepPoisUser = () => {
|
||||||
|
let url = '/user/v2/list'
|
||||||
|
let params = {
|
||||||
|
departmentId: state.addressBookSearchNickName ? undefined : state.clickKey,
|
||||||
|
page: state.addressBookPage,
|
||||||
|
pageSize: state.addressBookPageSize,
|
||||||
|
status: 'notactive',
|
||||||
|
nickName: state.addressBookSearchNickName
|
||||||
|
}
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
state.addressBookData = res?.data?.data || []
|
||||||
|
state.addressBookTotal = res?.data?.count || 0
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(()=>{
|
const getUserGroupChatList = () => {
|
||||||
return isShowBox.value
|
let params = {
|
||||||
},(newVal)=>{
|
page: state.groupChatListPage,
|
||||||
if(newVal){
|
page_size: state.groupChatListPageSize,
|
||||||
onLoad()
|
group_name: state.groupChatListSearchGroupName
|
||||||
|
}
|
||||||
|
ServeUserGroupChatList(params).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
state.groupChatListData = res?.data?.items || []
|
||||||
|
state.groupChatListTotal = res?.data?.total || 0
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleTreeClick = ({ selectedKey, tree }) => {
|
||||||
|
state.clickKey = tree.key
|
||||||
|
state.treeSelectData = tree
|
||||||
|
state.addressBookPage = 1
|
||||||
|
getDepPoisUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetAddressBookModal = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
state.addressBookCurrentTab = 'employeeAddressBook'
|
||||||
|
state.addressBookSearchNickName = ''
|
||||||
|
state.groupChatListSearchGroupName = ''
|
||||||
|
state.addressBookTableWidth = 800
|
||||||
|
state.clickKey = 3
|
||||||
|
state.treeRefreshCount++
|
||||||
|
state.addressBookPage = 1
|
||||||
|
state.addressBookPageSize = 10
|
||||||
|
state.groupChatListPage = 1
|
||||||
|
state.groupChatListPageSize = 10
|
||||||
|
state.selectedRowKeys = []
|
||||||
|
getDepPoisUser()
|
||||||
|
getUserGroupChatList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddressBookPagination = (page) => {
|
||||||
|
state.addressBookPage = page
|
||||||
|
getDepPoisUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddressBookPaginationSize = (pageSize) => {
|
||||||
|
state.addressBookPageSize = pageSize
|
||||||
|
state.addressBookPage = 1
|
||||||
|
getDepPoisUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeAddressBookSearch = (value) => {
|
||||||
|
if (!value.nickName?.trim()) {
|
||||||
|
state.addressBookSearchNickName = ''
|
||||||
|
} else {
|
||||||
|
state.addressBookSearchNickName = value.nickName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddressBookTabChange = (value) => {
|
||||||
|
state.addressBookCurrentTab = value
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeGroupChatListSearch = (value) => {
|
||||||
|
if (!value.groupName?.trim()) {
|
||||||
|
state.groupChatListSearchGroupName = ''
|
||||||
|
} else {
|
||||||
|
state.groupChatListSearchGroupName = value.groupName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGroupChatListPagination = (page) => {
|
||||||
|
state.groupChatListPage = page
|
||||||
|
getUserGroupChatList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGroupChatListPaginationSize = (pageSize) => {
|
||||||
|
state.groupChatListPageSize = pageSize
|
||||||
|
state.groupChatListPage = 1
|
||||||
|
getUserGroupChatList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAddressBookCancel = () => {
|
||||||
|
state.isShowAddressBookModal = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAddressBookSubmit = () => {
|
||||||
|
// 用户可自行实现提交逻辑
|
||||||
|
console.log('选中的联系人:', state.selectedRowKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
return isShowBox.value
|
||||||
|
}, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
onLoad()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => state.addressBookSearchNickName, (newValue, oldValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
state.addressBookTableWidth = 1142
|
||||||
|
state.addressBookPage = 1
|
||||||
|
} else {
|
||||||
|
state.addressBookTableWidth = 800
|
||||||
|
state.clickKey = 3
|
||||||
|
state.treeRefreshCount++
|
||||||
|
state.addressBookPage = 1
|
||||||
|
}
|
||||||
|
getDepPoisUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => state.groupChatListSearchGroupName, (newValue, oldValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
state.groupChatListPage = 1
|
||||||
|
} else {
|
||||||
|
state.groupChatListPage = 1
|
||||||
|
}
|
||||||
|
getUserGroupChatList()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<x-n-modal v-model:show="isShowBox" :title="forwardMode === 2 ? '合并转发' : '逐条转发'" style="width: 997px; height: 740px;background-color: #F9F9FD"
|
<x-n-modal v-model:show="isShowBox" :title="forwardMode === 2 ? '合并转发' : '逐条转发'" style="width: 997px; height: 740px;background-color: #F9F9FD"
|
||||||
:on-after-leave="onMaskClick" content-style="display: flex; justify-content: center; align-items: center;">
|
:on-after-leave="onMaskClick" content-style="display: flex; justify-content: center; align-items: center;">
|
||||||
<div class="w-927px h-627px bg-#fff rounded-3px px-35px py-20px">
|
<div class="w-927px h-627px bg-#fff rounded-3px px-35px pb-20px pt-10px">
|
||||||
|
<div class="w-100% flex justify-end mb-5px">
|
||||||
|
<n-button text type="primary" @click="onCreateContact">
|
||||||
|
<template #icon>
|
||||||
|
<Plus />
|
||||||
|
</template>
|
||||||
|
创建新聊天
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
<div class="flex items-center justify-between mb-28px">
|
<div class="flex items-center justify-between mb-28px">
|
||||||
<div class="text-#333639">搜索</div>
|
<div class="text-#333639">搜索</div>
|
||||||
<div class="w-779px h-34px">
|
<div class="w-779px h-34px">
|
||||||
@ -168,11 +436,11 @@ if(newVal){
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<div class="w-260px h-517px rounded-4px border-1px border-solid border-#E5E5E5 px-12px">
|
<div class="w-260px h-517px rounded-4px border-1px border-solid border-#E5E5E5 px-12px">
|
||||||
<div class="border-b-2px border-b-solid border-b-#FBFBFB h-35px flex items-center justify-end">
|
<!-- <div class="border-b-2px border-b-solid border-b-#FBFBFB h-35px flex items-center justify-end">
|
||||||
<n-button text color="#46299D" class="text-14px" @click="changeSelectType">
|
<n-button text color="#46299D" class="text-14px" @click="changeSelectType">
|
||||||
{{ selectType === 1 ? '多选' : '取消多选' }}
|
{{ selectType === 1 ? '多选' : '取消多选' }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div> -->
|
||||||
<div>
|
<div>
|
||||||
<n-virtual-list v-if="!loading" style="max-height: 470px" :item-size="65" :items="searchFilter">
|
<n-virtual-list v-if="!loading" style="max-height: 470px" :item-size="65" :items="searchFilter">
|
||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
@ -259,5 +527,173 @@ if(newVal){
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</x-n-modal>
|
</x-n-modal>
|
||||||
|
|
||||||
|
<!-- 通讯录弹窗 -->
|
||||||
|
<customModal
|
||||||
|
v-model:show="state.isShowAddressBookModal"
|
||||||
|
title="通讯录"
|
||||||
|
:style="state.customModalStyle"
|
||||||
|
:customCloseBtn="true"
|
||||||
|
:closable="false"
|
||||||
|
:customCloseEvent="true"
|
||||||
|
@customCloseModal="closeAddressBookModal"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<div class="custom-modal-content">
|
||||||
|
<n-card style="padding: 0 12px">
|
||||||
|
<n-tabs
|
||||||
|
type="line"
|
||||||
|
@update:value="handleAddressBookTabChange"
|
||||||
|
tab-style="font-size: 16px; font-weight: 600;color: #8B8B8B;"
|
||||||
|
>
|
||||||
|
<n-tab name="employeeAddressBook">员工通讯录</n-tab>
|
||||||
|
<n-tab name="groupChatList">群聊列表</n-tab>
|
||||||
|
</n-tabs>
|
||||||
|
<xSearchForm
|
||||||
|
v-if="state.addressBookCurrentTab == 'employeeAddressBook'"
|
||||||
|
:search-config="state.addressBookSearchConfig"
|
||||||
|
customInputPlaceholder="请输入姓名"
|
||||||
|
@change="changeAddressBookSearch"
|
||||||
|
:cols="3"
|
||||||
|
></xSearchForm>
|
||||||
|
<xSearchForm
|
||||||
|
v-if="state.addressBookCurrentTab == 'groupChatList'"
|
||||||
|
:search-config="state.groupChatListSearchConfig"
|
||||||
|
customInputPlaceholder="请输入群聊名称"
|
||||||
|
@change="changeGroupChatListSearch"
|
||||||
|
:cols="3"
|
||||||
|
></xSearchForm>
|
||||||
|
|
||||||
|
<div class="addressBook-content" v-if="state.addressBookCurrentTab == 'employeeAddressBook'">
|
||||||
|
<div class="addressBook-tree" v-if="!state.addressBookSearchNickName">
|
||||||
|
<fl-tree
|
||||||
|
:data="state.treeData"
|
||||||
|
:expandedKeys="state.expandedKeys"
|
||||||
|
:refreshCount="state.treeRefreshCount"
|
||||||
|
:clickKey="state.clickKey"
|
||||||
|
@triggerTreeClick="handleTreeClick"
|
||||||
|
></fl-tree>
|
||||||
|
</div>
|
||||||
|
<div class="addressBook-table">
|
||||||
|
<xNDataTable
|
||||||
|
:columns="state.addressBookColumns"
|
||||||
|
:data="state.addressBookData"
|
||||||
|
:style="{
|
||||||
|
height: `${state.addressBookTableHeight}px`,
|
||||||
|
width: `${state.addressBookTableWidth}px`
|
||||||
|
}"
|
||||||
|
:row-key="row => row.ID"
|
||||||
|
v-model:checked-row-keys="state.selectedRowKeys"
|
||||||
|
flex-height
|
||||||
|
></xNDataTable>
|
||||||
|
<div class="addressBook-pagination">
|
||||||
|
<n-pagination
|
||||||
|
v-model:page="state.addressBookPage"
|
||||||
|
v-model:page-size="state.addressBookPageSize"
|
||||||
|
:item-count="state.addressBookTotal"
|
||||||
|
show-quick-jumper
|
||||||
|
show-size-picker
|
||||||
|
:page-sizes="[10, 20, 50]"
|
||||||
|
:on-update:page="handleAddressBookPagination"
|
||||||
|
:on-update:page-size="handleAddressBookPaginationSize"
|
||||||
|
>
|
||||||
|
<template #prefix="{ itemCount }"> 共 {{ itemCount }} 条记录 </template>
|
||||||
|
</n-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="groupChatList-content" v-if="state.addressBookCurrentTab == 'groupChatList'">
|
||||||
|
<div class="groupChatList-table">
|
||||||
|
<xNDataTable
|
||||||
|
:columns="state.groupChatListColumns"
|
||||||
|
:data="state.groupChatListData"
|
||||||
|
:style="{
|
||||||
|
height: '523px',
|
||||||
|
width: '1148px'
|
||||||
|
}"
|
||||||
|
flex-height
|
||||||
|
></xNDataTable>
|
||||||
|
<div class="groupChatList-pagination">
|
||||||
|
<n-pagination
|
||||||
|
v-model:page="state.groupChatListPage"
|
||||||
|
v-model:page-size="state.groupChatListPageSize"
|
||||||
|
:item-count="state.groupChatListTotal"
|
||||||
|
show-quick-jumper
|
||||||
|
show-size-picker
|
||||||
|
:page-sizes="[10, 20, 50]"
|
||||||
|
:on-update:page="handleGroupChatListPagination"
|
||||||
|
:on-update:page-size="handleGroupChatListPaginationSize"
|
||||||
|
>
|
||||||
|
<template #prefix="{ itemCount }"> 共 {{ itemCount }} 条记录 </template>
|
||||||
|
</n-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部操作按钮,仅保留展示 -->
|
||||||
|
<div style="display: flex; justify-content: center; align-items: center; padding: 16px 0;">
|
||||||
|
<n-button color="#C7C7C9" class="w-250px 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>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</customModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.custom-modal-content {
|
||||||
|
.addressBook-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.addressBook-tree {
|
||||||
|
width: 328px;
|
||||||
|
height: 524px;
|
||||||
|
overflow: auto;
|
||||||
|
border: 1px solid #efeff5;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 12px 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addressBook-table {
|
||||||
|
:deep(.n-data-table-th) {
|
||||||
|
background-color: #46299d;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.addressBook-pagination {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
padding: 22px 0 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.groupChatList-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.groupChatList-table {
|
||||||
|
:deep(.n-data-table-th) {
|
||||||
|
background-color: #46299d;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.groupChatList-pagination {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
padding: 22px 0 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -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'))||''
|
return JSON.parse(localStorage.getItem('token'))||'46d71a72d8d845ad7ed23eba9bdde260e635407190c2ce1bf7fd22088e41682ea07773ec65cae8946d2003f264d55961f96e0fc5da10eb96d3a348c1664e9644ce2108c311309f398ae8ea1b8200bfd490e5cb6e8c52c9e5d493cbabb163368f8351420451a631dbfa749829ee4cda49b77b5ed2d3dced5d0f2b7dd9ee76ba5465c84a17c23af040cd92b6b2a4ea48befbb5c729dcdad0a9c9668befe84074cc24f78899c1d947f8e7f94c7eda5325b8ed698df729e76febb98549ef3482ae942fb4f4a1c92d21836fa784728f0c5483aab2760a991b6b36e6b10c84f840a6433a6ecc31dee36e8f1c6158818bc89d22184be97f604c74931ddd023225ae1a2ab29c0eb046e9a20174f1110532e4af8498ab46f4375f2e210bae827a6146183f385fdee154fd7bee38deb6ac4c00ae82c77150d5663288f78d678db028bfb7db'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,9 +46,9 @@ export default defineConfig(({ mode }) => {
|
|||||||
vueJsx({}),
|
vueJsx({}),
|
||||||
compressPlugin(),
|
compressPlugin(),
|
||||||
UnoCSS(),
|
UnoCSS(),
|
||||||
// vueDevTools({
|
vueDevTools({
|
||||||
// launchEditor: 'trae',
|
launchEditor: 'trae',
|
||||||
// })
|
})
|
||||||
],
|
],
|
||||||
define: {
|
define: {
|
||||||
__APP_ENV__: env.APP_ENV
|
__APP_ENV__: env.APP_ENV
|
||||||
|
Loading…
Reference in New Issue
Block a user