接入查询当前用户所在群聊列表接口,并完成整个通讯录模块的交互和样式,包括员工通讯录和群聊列表;并完成对应的聊天会话跳转;新增按条件搜索组件,等待接入历史记录的按条件查询;

This commit is contained in:
wangyifeng 2025-05-16 17:00:28 +08:00
parent 814eb44358
commit c39d5aea88
8 changed files with 1097 additions and 55 deletions

View File

@ -9,3 +9,18 @@ export const ServeSeachQueryAll = (data = {}) => {
export const ServeQueryTalkRecord = (data = {}) => { export const ServeQueryTalkRecord = (data = {}) => {
return post('/api/v1/elasticsearch/query-talk-record', data) return post('/api/v1/elasticsearch/query-talk-record', data)
} }
//查看存在聊天记录的天数
export const ServeTalkDate = (data) => {
return post('/api/v1/talk/date', data)
}
//获取会话Id
export const ServeGetSessionId = (data) => {
return post('/api/v1/talk/session/getId', data)
}
//获取用户所在群聊列表
export const ServeUserGroupChatList = (data) => {
return post('/api/v1/group/user/list', data)
}

View File

@ -29,3 +29,8 @@ export const ServeGetUserDetail = () => {
export const ServeGetUserSetting = () => { export const ServeGetUserSetting = () => {
return get('/api/v1/users/setting') return get('/api/v1/users/setting')
} }
//根据erpUserId查询聊天系统用户详情
export const getUserInfoByERPUserId = (data) => {
return post('/api/v1/users/info', data)
}

View File

@ -223,28 +223,6 @@ const showSearchRecordByConditionModal = () => {
</header> </header>
<main class="el-main main me-scrollbar me-scrollbar-thumb"> <main class="el-main main me-scrollbar me-scrollbar-thumb">
<div class="info-box" v-if="talkType === 1">
<div class="b-box b-box-bottomBorder" @click="showSearchRecordByConditionModal">
<div class="block">
<div class="title">查找聊天记录</div>
<img class="icon-right" src="@/assets/image/icon/arrow-right-grey.png" alt="" />
</div>
</div>
<div class="b-box">
<div class="block">
<div class="title">置顶会话</div>
<n-switch />
</div>
</div>
<div class="b-box">
<div class="block">
<div class="title">消息免打扰</div>
<n-switch />
</div>
</div>
</div>
<div class="info-box" v-if="talkType === 2"> <div class="info-box" v-if="talkType === 2">
<div class="b-box"> <div class="b-box">
<div class="block"> <div class="block">
@ -316,6 +294,29 @@ const showSearchRecordByConditionModal = () => {
</div> </div>
</div> </div>
<div class="info-box">
<div class="b-box b-box-bottomBorder" @click="showSearchRecordByConditionModal">
<div class="block">
<div class="title">查找聊天记录</div>
<img class="icon-right" src="@/assets/image/icon/arrow-right-grey.png" alt="" />
</div>
</div>
<div class="b-box">
<div class="block">
<div class="title">置顶会话</div>
<n-switch />
</div>
</div>
<div class="b-box">
<div class="block">
<div class="title">消息免打扰</div>
<n-switch />
</div>
</div>
</div>
<div class="member-box" v-if="talkType === 2"> <div class="member-box" v-if="talkType === 2">
<div class="flex"> <div class="flex">
<n-input placeholder="搜索" v-model:value="state.keywords" :clearable="true" round> <n-input placeholder="搜索" v-model:value="state.keywords" :clearable="true" round>

View File

@ -0,0 +1,896 @@
<template>
<div class="outer-layer search-by-condition-page">
<div class="root">
<div v-if="state.condition === 'date'" class="search-by-date">
<tm-time-picker
:show="state.showMonthPicker"
:showDetail="{
year: true,
month: true,
day: false,
hour: false,
minute: false,
second: false,
am_pm: false
}"
:showSuffix="{
year: '',
month: ''
}"
:defaultValue="state.nowDate"
format="YYYY年MM月"
start=""
:end="state.maxDate"
@confirm="confirmSelectedMonth"
:round="0"
:title="'请选择聊天日期'"
>
<div class="search-date-picker">
<span class="text-[14px] font-regular">
{{ state.selectedMonth }}
</span>
<img src="@/static/image/search/down-pointer.png" />
</div>
</tm-time-picker>
<tm-calendar-view
:show="true"
:hideTool="true"
:hideButton="true"
:dateStyle="state.dateStyle"
:defaultValue="state.selectedDateArray"
v-model="state.selectedDateArray"
:disabledDate="state.disabledDateArray"
@click="selectDate"
model="day"
:end="state.maxDate"
@getDArray="getDArray"
:showDefault="false"
></tm-calendar-view>
</div>
<div
class="search-by-condition-input-list"
v-if="
state.condition === 'imgAndVideo' ||
state.condition === 'file' ||
state.condition === 'link' ||
state.condition === 'member'
"
:style="{
padding: state.condition === 'imgAndVideo' ? '0 14px' : ''
}"
>
<div
class="search-by-condition-input"
v-if="state.condition === 'file' || state.condition === 'link'"
>
<!-- <customInput
:searchText="state.searchText"
:first_talk_record_infos="state.first_talk_record_infos"
@inputSearchText="inputSearchText"
></customInput> -->
<span
@click="cancelSearch"
class="search-by-condition-input-text text-[16px] font-medium"
>
取消
</span>
</div>
<div class="search-by-condition-list">
<div class="condition-dimensionality">
<div
class="condition-dimensionality-each"
v-for="(conditionItem, conditionIndex) in state.searchResultList"
:key="conditionIndex"
>
<div class="condition-dimensionality-each-month">
<span class="text-[14px] font-regular">
{{ conditionItem.dateMonth }}
</span>
</div>
<div
class="condition-each-resultList"
:class="[
state.condition === 'imgAndVideo' ? 'condition-type-imgAndVideo-result' : ''
]"
>
<div
class="condition-each-resultList-each"
v-for="(item, index) in conditionItem.monthResultList"
:key="index"
:style="{
border:
state.condition === 'imgAndVideo' || state.condition === 'member' ? '0' : '',
padding: state.condition === 'imgAndVideo' ? '0 0 5px' : ''
}"
>
<div class="condition-result-member" v-if="state.condition === 'member'">
<searchItem
@click="toDialogueByMember(item)"
:searchResultKey="'search_by_member_condition'"
:searchItem="item"
:searchText="state.searchText"
:searchRecordDetail="true"
></searchItem>
</div>
<div
class="condition-result-imgAndVideo"
v-if="state.condition === 'imgAndVideo'"
>
<div
class="condition-result-imgAndVideo-area"
v-if="item?.extra?.items?.length > 0"
>
<div
class="condition-result-imgAndVideo-each"
v-for="(imgItem, imgIndex) in item?.extra?.items"
:key="imgIndex"
>
<tm-image
preview
:src="imgItem?.content"
v-if="imgItem?.type == 3"
model="aspectFill"
/>
</div>
</div>
<!-- <div class="condition-result-imgAndVideo-area" v-if="item?.extra?.url">
<template v-if="item?.msg_type === 3">
<tm-image preview :src="item?.extra?.url" model="aspectFill" />
</template>
<template v-else-if="item?.msg_type === 5">
<div class="video-preview" @click="onPlay(item?.extra?.url)">
<tm-image :src="item?.extra?.cover" model="aspectFill" />
<div class="play-icon">
<img :src="playCircle" />
</div>
</div>
</template>
</div> -->
</div>
<div
class="condition-each-result-main"
v-if="state.condition === 'file' || state.condition === 'link'"
>
<searchItem :searchItem="item" :conditionType="state.msg_type"></searchItem>
<span class="text-[12px] font-medium condition-each-result-main-date">
{{ item.dateTime }}
</span>
</div>
<div
class="condition-each-result-attachments"
@click="previewPDF(item)"
v-if="state.condition === 'file' || state.condition === 'link'"
>
<div class="attachment-avatar">
<img :src="item?.extra?.file_avatar" v-if="state.condition === 'file'" />
<img
src="@/static/image/search/result-link-icon.png"
v-if="state.condition === 'link'"
/>
</div>
<div class="attachment-info">
<div class="attachment-info-title">
<span class="text-[14px] font-regular" v-if="state.condition === 'file'">
{{ item?.extra?.name }}
</span>
<span class="text-[14px] font-regular" v-if="state.condition === 'link'">
分享链接
</span>
</div>
<div
class="attachment-sub-info"
:style="{
margin: state.condition === 'file' ? '10px 0 0' : ''
}"
>
<span class="text-[12px] font-regular" v-if="state.condition === 'file'">
{{ item?.extra?.typeText }}
</span>
<span
class="text-[12px] font-regular"
v-if="state.condition === 'file'"
style="margin: 0 0 0 10px;"
>
{{ item?.extra?.fileSize }}
</span>
<span class="text-[12px] font-regular" v-if="state.condition === 'link'">
{{ item?.extra?.content }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- <ZPaging
ref="zPaging"
:show-scrollbar="false"
@query="queryAllSearch"
:refresher-enabled="false"
:auto="false"
:loading-more-default-as-loading="true"
:inside-more="true"
v-model="state.flatList"
>
<template #top v-if="state.showPageTitle">
<customNavbar :title="state.pageTitle"></customNavbar>
</template>
</ZPaging> -->
<teleport to="body">
<div v-show="open" class="video-container">
<video
:src="currentVideoUrl"
controls
@fullscreenchange="fullscreenchange"
:id="currentVideoUrl"
playsinline
webkit-playsinline
x5-playsinline
class="fullscreen-video"
></video>
</div>
</teleport>
</div>
</div>
</template>
<script setup>
// import { useDialogueStore } from '@/store'
// import customInput from '@/components/custom-input/custom-input.vue'
// import playCircle from '@/static/image/chatList/playCircle@2x.png'
// import fileType_PPT from '@/static/image/search/fileType_PPT.png'
// import fileType_EXCEL from '@/static/image/search/fileType_EXCEL.png'
// import fileType_WORD from '@/static/image/search/fileType_WORD.png'
// import fileType_PDF from '@/static/image/search/fileType_PDF.png'
// import fileType_Files from '@/static/image/search/fileType_Files.png'
// 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'
// const zPaging = ref()
// useZPaging(zPaging)
// const dialogueStore = useDialogueStore()
// const dialogueParams = reactive({
// talk_type: computed(() => dialogueStore.talk.talk_type),
// receiver_id: computed(() => dialogueStore.talk.receiver_id)
// })
const dialogueParams = reactive({
talk_type: 1,
receiver_id: 1
})
import { onMounted, reactive, computed, ref, nextTick, watch } from 'vue'
import searchItem from './searchItem.vue'
import { ServeFindTalkRecords } from '@/api/chat.js'
import { ServeTalkDate, ServeGetSessionId } from '@/api/search.js'
import { parseTime } from '@/utils/datetime'
import { fileFormatSize, fileSuffix } from '@/utils/strings'
let nowDay = new Date().setHours(0, 0, 0, 0)
const props = defineProps({
conditionType: {
//
type: String,
default: ''
}
})
const state = reactive({
pageTitle: '', //
dateStyle: [], //
nowDate: new Date(nowDay), //
maxDate: new Date(nowDay), //
selectedDateArray: Array(new Date(nowDay)), //
showMonthPicker: false, //
selectedMonth: new Date(nowDay), //
disabledDateArray: [], //
dArray: [], //
showPageTitle: false, //
searchText: '', //
first_talk_record_infos: Object,
searchResultList: [], //
cursor: 0, //
msg_type: 0, //
group_member_id: 0, //id
flatList: [] //
})
watch(
() => props?.conditionType,
(newVal, oldVal) => {
console.log(newVal, oldVal)
state.condition = newVal
if (newVal) {
if (newVal === 'member') {
state.showPageTitle = true
state.pageTitle = '按群成员查找'
state.group_member_id = options.groupMemberId
queryAllSearch()
} else if (newVal === 'date') {
state.showPageTitle = true
state.pageTitle = '按日期查找'
ServeQueryTalkDate(parseTime(state.nowDate, '{y}{m}'))
} else if (newVal === 'imgAndVideo') {
state.showPageTitle = true
state.pageTitle = '图片与视频'
state.msg_type = '3,5'
queryAllSearch()
} else if (newVal === 'file') {
console.log(dialogueParams)
let first_talk_record_infos = {
receiver_name: '文件'
}
state.first_talk_record_infos = Object.assign(
{},
state.first_talk_record_infos,
first_talk_record_infos
)
state.msg_type = 6
queryAllSearch()
} else if (newVal === 'link') {
console.log(dialogueParams)
let first_talk_record_infos = {
receiver_name: '链接'
}
state.first_talk_record_infos = Object.assign(
{},
state.first_talk_record_infos,
first_talk_record_infos
)
state.msg_type = 14
queryAllSearch()
}
}
},
{
immediate: true,
deep: true
}
)
const videoContext = ref()
const open = ref(false)
const currentVideoUrl = ref('')
const fullscreenchange = (e) => {
if (!e.detail.fullScreen) {
videoContext.value.stop()
videoContext.value.seek(0)
open.value = false
}
}
async function onPlay(url) {
currentVideoUrl.value = url
open.value = true
// DOM
await nextTick()
//
videoContext.value = uni.createVideoContext(url, getCurrentInstance())
setTimeout(() => {
//
videoContext.value.requestFullScreen({ direction: 2 })
//
setTimeout(() => {
videoContext.value.play()
}, 100)
}, 200)
}
onMounted(() => {
state.selectedMonth = parseTime(state.selectedMonth, '{y}年{m}月')
state.dateStyle = [
{
date: state.nowDate, //
text: false, //
color: '#46299D', //.
extra: '今天' //
}
]
})
//
const ServeQueryTalkDate = (month) => {
let params = {
month: month,
talk_type: dialogueParams.talk_type, //12
receiver_id: dialogueParams.receiver_id //id
}
const resp = ServeTalkDate(params)
console.log(resp)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
if (data && data.length > 0) {
const formattedData = data.map(
(item) => item.substring(0, 4) + '/' + item.substring(4, 6) + '/' + item.substring(6, 8)
)
let disabledDateArray = state.dArray.filter((dIt) => !formattedData.includes(dIt))
disabledDateArray = disabledDateArray.map((item) => item.replace(/\//g, '-'))
console.log(disabledDateArray)
state.disabledDateArray = disabledDateArray
} else {
state.disabledDateArray = state.dArray
}
} else {
}
})
resp.catch(() => {})
}
//
const selectDate = async (e) => {
if (e == parseTime(state.nowDate, '{y}/{m}/{d}')) {
console.log('==今日')
state.dateStyle = [
{
date: state.nowDate, //
text: false, //
color: '#46299D', //.
extra: '今天' //
}
]
} else {
state.dateStyle = [
{
date: state.nowDate, //
text: false, //
color: '', //.
extra: '今天' //
},
{
date: new Date(e), //
text: false, //
color: '#46299D' //.
}
]
}
const sessionId = await getSessionId(dialogueParams.talk_type, dialogueParams.receiver_id)
uni.navigateTo({
url:
'/pages/dialog/index?sessionId=' +
sessionId +
'&keepDialogInfo=1' +
'&recordDate=' +
parseTime(e, '{y}-{m}-{d}')
})
}
//Id
const getSessionId = (talk_type, receiver_id) => {
return new Promise((resolve, reject) => {
let params = {
talkType: talk_type,
receiverId: receiver_id
}
const resp = ServeGetSessionId(params)
console.log(resp)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
resolve(data?.sessionId)
} else {
}
})
resp.catch(() => {})
})
}
//
const confirmSelectedMonth = (e) => {
console.log(e)
state.selectedMonth = parseTime(e, '{y}年{m}月')
// console.log()
let newDate = new Date(e)
newDate.setHours(0, 0, 0, 0)
newDate.setDate(1)
state.selectedDateArray = Array(new Date(newDate))
state.dateStyle = [
{
date: state.nowDate, //
text: false, //
color: '', //.
extra: '今天' //
}
]
ServeQueryTalkDate(parseTime(e, '{y}{m}'))
}
//
const getDArray = (dArray) => {
state.dArray = dArray
}
//
const inputSearchText = (e) => {
state.searchText = e
state.cursor = 0
queryAllSearch()
}
//
const cancelSearch = () => {
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack({
delta: 1
})
} else {
uni.reLaunch({
url: '/pages/index/index'
})
}
}
//
const queryAllSearch = () => {
let params = {
talk_type: dialogueParams.talk_type, //12
receiver_id: dialogueParams.receiver_id, //idid
msg_type: state.msg_type, //0:;2:;3:;4:;5:;6:;7:;9:;11;12
cursor: state.cursor, //
limit: 10, //
no_limit: '', //1
direction: 'up', //downup
start_time: '',
end_time: '',
group_member_user_id: state.group_member_id, //id
file_name: state.msg_type === 6 ? state.searchText : ''
}
console.log(params)
const resp = ServeFindTalkRecords(params)
console.log(resp)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
// cursor0searchResultList
let dateList = state.cursor === 0 ? [] : state.searchResultList
let noMore = false
if (data?.items?.length > 0) {
data.items.forEach((item) => {
item.dateTime = parseTime(item?.created_at, '{m}/{d}')
if (item?.extra) {
item.extra.fileSize = fileFormatSize(item?.extra?.size)
item.extra.typeText = item?.extra?.name ? fileSuffix(item?.extra?.name) : ''
item.extra.file_avatar = fileTypeAvatar(item?.extra?.typeText)
console.log(item.extra.type)
}
let year = new Date(item.created_at).getFullYear()
let month = new Date(item.created_at).getMonth() + 1
let dateMonth =
year == state.nowDate.getFullYear() && month == state.nowDate.getMonth() + 1
? '这个月'
: year + '年' + month + '月'
if (dateList.length > 0) {
let hasAdd = false
dateList.forEach((dateItem) => {
if (dateItem.dateMonth === dateMonth) {
dateItem.monthResultList.push(item)
hasAdd = true
}
})
if (!hasAdd) {
console.log(dateList)
dateList.push({
dateMonth: dateMonth,
monthResultList: [item]
})
}
} else {
dateList.push({
dateMonth: dateMonth,
monthResultList: [item]
})
}
})
} else {
noMore = true
}
//
state.searchResultList = dateList
// z-paging
state.flatList = dateList.reduce((acc, group) => {
return acc.concat(group.monthResultList)
}, [])
if (state.cursor === 0) {
// zPaging.value?.complete(state.flatList)
} else {
// zPaging.value?.completeByNoMore(state.flatList, noMore)
}
state.cursor = data?.cursor
} else {
if (state.cursor === 0) {
state.searchResultList = []
state.flatList = []
}
// zPaging.value?.complete([])
}
})
resp.catch(() => {
if (state.cursor === 0) {
state.searchResultList = []
state.flatList = []
}
// zPaging.value?.complete([])
})
}
//
const fileTypeAvatar = (fileType) => {
// let file_type_avatar = fileType_Files
// if (fileType) {
// if (fileType === 'ppt' || fileType === 'pptx') {
// file_type_avatar = fileType_PPT
// } else if (fileType === 'pdf') {
// file_type_avatar = fileType_PDF
// } else if (fileType === 'doc' || fileType === 'docx') {
// file_type_avatar = fileType_WORD
// } else if (fileType === 'xls' || fileType === 'xlsx') {
// file_type_avatar = fileType_EXCEL
// } else {
// file_type_avatar = fileType_Files
// }
// }
// return file_type_avatar
return ''
}
const previewPDF = (item) => {
console.log(item)
if (typeof plus !== 'undefined') {
downloadAndOpenFile(item)
} else {
document.addEventListener('plusready', () => {
downloadAndOpenFile(item)
})
}
}
const downloadAndOpenFile = (item) => {
uni.showLoading({ title: '加载中...', mask: true })
const downloadUrl = item?.extra?.path
const options = {
filename: '_doc/downloads/' //
}
const dtask = plus.downloader.createDownload(downloadUrl, options, function (d, status) {
if (status === 200) {
uni.hideLoading()
const filePath = d.filename
plus.runtime.openFile(
filePath,
{},
function () {},
function (error) {}
)
} else {
uni.hideLoading()
}
})
dtask.start()
}
//
const toDialogueByMember = async (msgInfo) => {
const sessionId = await getSessionId(dialogueParams.talk_type, dialogueParams.receiver_id)
uni.navigateTo({
url:
'/pages/dialog/index?sessionId=' +
sessionId +
'&keepDialogInfo=1' +
'&msgInfo=' +
encodeURIComponent(JSON.stringify(msgInfo))
})
}
</script>
<style scoped lang="scss">
.search-by-date {
.search-date-picker {
padding: 10px 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
span {
line-height: 20px;
color: #999999;
}
img {
width: 9px;
height: 6px;
margin: 0 0 0 13px;
}
}
}
body:deep(.text-overflow-1) {
color: #666666 !important;
line-height: 22px !important;
font-size: 16px !important;
font-weight: bold !important;
}
body:deep(.tmicon-times-circle-fill) {
width: 19px;
height: 19px;
}
body:deep(.round-3) {
background: linear-gradient(to right, #674bbc, #46299d);
}
.search-by-condition-input-list {
padding: 10px 24px 0 21px;
.search-by-condition-input {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.search-by-condition-input-text {
flex-shrink: 0;
margin: 0 0 0 10px;
color: #46299d;
}
}
.search-by-condition-list {
.condition-dimensionality {
.condition-dimensionality-each {
.condition-dimensionality-each-month {
padding: 12px 0 5px;
span {
line-height: 20px;
color: #999999;
}
}
.condition-each-resultList {
.condition-each-resultList-each {
border-bottom: 1px solid #f8f8f8;
padding: 0 0 10px;
.condition-each-result-main {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.condition-each-result-main-date {
line-height: 17px;
color: #999999;
}
}
.condition-each-result-attachments {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 12px 15px;
background-color: #f3f3f3;
border-radius: 4px;
.attachment-avatar {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex-shrink: 0;
img {
width: 48px;
height: 48px;
}
}
.attachment-info {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
margin: 0 0 0 11px;
.attachment-info-title {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
span {
line-height: 20px;
color: #191919;
word-break: break-all;
}
}
.attachment-sub-info {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
span {
line-height: 17px;
color: #999999;
word-break: break-all;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}
}
.condition-type-imgAndVideo-result {
border-bottom: 0;
padding: 0;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
.condition-each-resultList-each {
.condition-result-imgAndVideo {
margin: 0 3px;
:deep(.overflow) {
width: 82px !important;
height: 82px !important;
}
.condition-result-imgAndVideo-area {
:deep(.overflow) {
width: 82px !important;
height: 82px !important;
}
:deep(.round-0) {
width: 82px !important;
height: 82px !important;
}
.video-preview {
position: relative;
width: 82px;
height: 82px;
cursor: pointer;
.play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
img {
width: 40px !important;
height: 40px !important;
}
}
}
}
}
}
}
}
}
}
}
.video-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: #000;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.fullscreen-video {
width: 100%;
height: 100%;
object-fit: contain;
}
</style>

View File

@ -235,7 +235,10 @@ const inputSearchText = (e) => {
} }
// ES- // ES-
const queryAllSearch = () => { const queryAllSearch = (doClearSearchResult) => {
if (doClearSearchResult) {
state.searchResult = null
}
let params = { let params = {
key: state.searchText, // key: state.searchText, //
size: props.searchResultPageSize size: props.searchResultPageSize
@ -329,12 +332,9 @@ const queryAllSearch = () => {
state.searchResult = data state.searchResult = data
} else { } else {
// //
if ( data[paginationKey] = (state.searchResult?.[paginationKey] || []).concat(
paginationKey && data[paginationKey]
Array.isArray((state?.searchResult && state?.searchResult[paginationKey]) || []) )
) {
data[paginationKey] = state.searchResult[paginationKey].concat(data[paginationKey])
}
state.searchResult = data state.searchResult = data
} }
@ -513,8 +513,8 @@ const clickSearchItem = (searchResultKey, searchItem) => {
} }
// //
const doLoadMore = () => { const doLoadMore = (doClearSearchResult) => {
queryAllSearch() queryAllSearch(doClearSearchResult)
} }
// doLoadMore // doLoadMore

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'))||'79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b896fc262d304ff89c0c77d33d884b0d50cb245a5ce4e0a66c9b041b7859ba0c0c9d942cd23551c1e1259cc5b726b936bffd334ead575db2f7cfd9f3316b61487d115c4cf634d764124b986a7dc71dec603' return JSON.parse(localStorage.getItem('token'))||'79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b894e81e7367079550f5bfe506cb1d1874de13cb7696a188e09b47b9997c92972e501cbcaf2601dc4d1981a2f9bdbfe2ddef970f3e2d760b94e5947f9fe004528f5214a8cd9a92de884cc64bfa32d716e25'
} }
/** /**

View File

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, computed, watch } from 'vue' import { reactive, computed, watch } from 'vue'
import { NDrawer, NCard } from 'naive-ui' import { NDrawer, NCard, NTag } from 'naive-ui'
import { useUserStore, useDialogueStore, useUploadsStore } from '@/store' import { useUserStore, useDialogueStore, useUploadsStore } from '@/store'
import PanelHeader from './panel/PanelHeader.vue' import PanelHeader from './panel/PanelHeader.vue'
import PanelContent from './panel/PanelContent.vue' import PanelContent from './panel/PanelContent.vue'
@ -9,6 +9,7 @@ import GroupPanel from '@/components/group/GroupPanel.vue'
import GroupNotice from '@/components/group/GroupNotice.vue' import GroupNotice from '@/components/group/GroupNotice.vue'
import UploadsModal from '@/components/base/UploadsModal.vue' import UploadsModal from '@/components/base/UploadsModal.vue'
import customModal from '@/components/common/customModal.vue' import customModal from '@/components/common/customModal.vue'
import historyRecord from '@/components/search/searchByCondition.vue'
const userStore = useUserStore() const userStore = useUserStore()
const dialogueStore = useDialogueStore() const dialogueStore = useDialogueStore()
@ -39,7 +40,9 @@ const state = reactive({
height: '740px', height: '740px',
backgroundColor: '#F9F9FD' backgroundColor: '#F9F9FD'
}, // }, //
searchRecordByConditionText: ''// searchRecordByConditionText: '', //
conditionTag: '', //
conditionType: '' //
}) })
const events = { const events = {
@ -63,6 +66,22 @@ watch(
const onPanelHeaderEvent = (eventType: string) => { const onPanelHeaderEvent = (eventType: string) => {
events[eventType] && events[eventType]() events[eventType] && events[eventType]()
} }
///
const changeConditionTag = (tag) => {
console.log(tag)
state.conditionType = tag
if (tag === 'file') {
state.conditionTag = '文件'
} else if (tag === 'imgAndVideo') {
state.conditionTag = '图片与视频'
} else if (tag === 'date') {
state.conditionTag = '日期'
} else if (tag === 'member') {
state.conditionTag = '群成员'
} else {
state.conditionTag = ''
}
}
</script> </script>
<template> <template>
@ -150,7 +169,7 @@ const onPanelHeaderEvent = (eventType: string) => {
<customModal <customModal
v-model:show="state.isShowSearchRecordByConditionModal" v-model:show="state.isShowSearchRecordByConditionModal"
title="与“{{ talkParams.username }}”的聊天记录" :title='`与“${talkParams.username}”的聊天记录`'
:style="state.customSearchRecordByConditionModalStyle" :style="state.customSearchRecordByConditionModalStyle"
:customCloseBtn="true" :customCloseBtn="true"
:closable="false" :closable="false"
@ -169,22 +188,27 @@ const onPanelHeaderEvent = (eventType: string) => {
<template #clear-icon> <template #clear-icon>
<img src="@/assets/image/icon/close-btn-grey-line.png" alt="close" /> <img src="@/assets/image/icon/close-btn-grey-line.png" alt="close" />
</template> </template>
<template #prefix>
<n-tag closable v-if="state.conditionTag" @close="changeConditionTag('')">
{{ state.conditionTag }}
</n-tag>
</template>
</n-input> </n-input>
</div> </div>
<div class="search-area-condition"> <div class="search-area-condition">
<span>文件</span> <span @click="changeConditionTag('file')">文件</span>
<span>图片与视频</span> <span @click="changeConditionTag('imgAndVideo')">图片与视频</span>
<span>日期</span> <span @click="changeConditionTag('date')">日期</span>
<span>群成员</span> <span @click="changeConditionTag('member')">群成员</span>
</div> </div>
</n-card> </n-card>
</div> </div>
<div class="search-record-modal-content"> <div class="search-record-modal-content">
<n-card style="padding: 0 12px;"> <n-card style="padding: 0 12px;">
<div class="search-record-card" v-if="state.searchRecordByConditionText"> <div class="search-record-card" v-if="state.searchRecordByConditionText || state.conditionType">
<historyRecord :conditionType="state.conditionType" />
</div> </div>
<div class="search-record-empty" v-if="!state.searchRecordByConditionText"> <div class="search-record-empty" v-if="!state.searchRecordByConditionText && !state.conditionType">
<img src="@/assets/image/chatList/search-empty.png" alt="" /> <img src="@/assets/image/chatList/search-empty.png" alt="" />
<span>无内容</span> <span>无内容</span>
</div> </div>
@ -224,7 +248,7 @@ const onPanelHeaderEvent = (eventType: string) => {
padding: 22px 0 11px; padding: 22px 0 11px;
span { span {
font-size: 14px; font-size: 14px;
color: #46299D; color: #46299d;
font-weight: 400; font-weight: 400;
line-height: 20px; line-height: 20px;
margin: 0 62px 0 0; margin: 0 62px 0 0;
@ -242,7 +266,6 @@ const onPanelHeaderEvent = (eventType: string) => {
box-shadow: 0 3px 6px 1px rgba(188, 188, 188, 0.18); box-shadow: 0 3px 6px 1px rgba(188, 188, 188, 0.18);
} }
.search-record-card { .search-record-card {
} }
.search-record-empty { .search-record-empty {
display: flex; display: flex;

View File

@ -7,7 +7,8 @@ import {
reactive, reactive,
onBeforeMount, onBeforeMount,
getCurrentInstance, getCurrentInstance,
h h,
nextTick
} from 'vue' } from 'vue'
import { onBeforeRouteUpdate } from 'vue-router' import { onBeforeRouteUpdate } from 'vue-router'
import { useDialogueStore, useTalkStore } from '@/store' import { useDialogueStore, useTalkStore } from '@/store'
@ -36,7 +37,11 @@ import xNDataTable from '@/components/x-naive-ui/x-n-data-table/index.vue'
import flTree from '@/components/flnlayout/tree/flnindex.vue' import flTree from '@/components/flnlayout/tree/flnindex.vue'
import { processError, processSuccess } from '@/utils/helper/message.js' import { processError, processSuccess } from '@/utils/helper/message.js'
import chatAppSearchList from '@/components/search/searchList.vue' import chatAppSearchList from '@/components/search/searchList.vue'
import { ServeSeachQueryAll, ServeQueryTalkRecord } from '@/api/search' import { ServeSeachQueryAll, ServeQueryTalkRecord, ServeUserGroupChatList } from '@/api/search'
import { getUserInfoByERPUserId } from '@/api/user'
import { useRouter } from 'vue-router'
const router = useRouter()
const currentInstance = getCurrentInstance() const currentInstance = getCurrentInstance()
const $request = currentInstance?.appContext.config.globalProperties?.$request const $request = currentInstance?.appContext.config.globalProperties?.$request
@ -179,7 +184,7 @@ const state = reactive({
field: 'groupName', field: 'groupName',
width: 200, width: 200,
render(row, index) { render(row, index) {
return row.groupName return row.group_name
} }
}, },
{ {
@ -188,7 +193,16 @@ const state = reactive({
width: 400, width: 400,
ellipsis: true, ellipsis: true,
render(row, index) { render(row, index) {
return row.groupType let groupType = row.group_type
if (groupType == 1) {
return '普通群'
} else if (groupType == 2) {
return '部门群'
} else if (groupType == 3) {
return '项目群'
} else if (groupType == 4) {
return '公司群'
}
} }
}, },
{ {
@ -275,10 +289,39 @@ watch(
state.addressBookTableWidth = 800 state.addressBookTableWidth = 800
state.clickKey = 3 state.clickKey = 3
state.treeRefreshCount++ state.treeRefreshCount++
state.addressBookPage = 1
} }
getDepPoisUser() getDepPoisUser()
} }
) )
watch(
() => state.groupChatListSearchGroupName,
(newValue, oldValue) => {
if (newValue) {
state.groupChatListPage = 1
} else {
state.groupChatListPage = 1
}
getUserGroupChatList()
}
)
// watch(
// () => state.searchRecordText,
// (newValue, oldValue) => {
// console.log(newValue, 'newValue')
// state.ServeQueryTalkRecordParams = encodeURIComponent(
// JSON.stringify({
// talk_type: 0, //12
// receiver_id: 0, //
// last_group_id: 0, //id
// last_member_id: 0, //id
// last_receiver_user_name: '', //
// last_receiver_group_name: '' //
// })
// )
// }
// )
// //
const loadStatus = computed(() => talkStore.loadStatus) const loadStatus = computed(() => talkStore.loadStatus)
@ -338,6 +381,7 @@ onBeforeRouteUpdate(onInitialize)
onBeforeMount(() => { onBeforeMount(() => {
getTreeData() getTreeData()
getUserGroupChatList()
}) })
onMounted(() => { onMounted(() => {
@ -412,8 +456,40 @@ const getDepPoisUser = () => {
}) })
} }
// //
const handleEnterChat = (row) => { const handleEnterChat = async (row) => {
console.log(row) console.log(row)
if (state.addressBookCurrentTab === 'employeeAddressBook') {
//
await getUserInfoByERPUserId({ erp_user_id: row.ID }).then((res) => {
// console.log(res)
if (res.code === 200) {
let sysUserInfo = res.data
talkStore.toTalk(1, sysUserInfo.sys_id, router)
}
})
} else if (state.addressBookCurrentTab === 'groupChatList') {
//
talkStore.toTalk(2, row.id, router)
}
state.isShowAddressBookModal = false
resetAddressBookModal()
}
//
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
getDepPoisUser()
getUserGroupChatList()
})
} }
// //
const handleAddressBookPagination = (page) => { const handleAddressBookPagination = (page) => {
@ -442,16 +518,40 @@ const handleAddressBookTabChange = (value) => {
// //
const changeGroupChatListSearch = (value) => { const changeGroupChatListSearch = (value) => {
console.log(value, 'value') console.log(value, 'value')
if (!value.groupName?.trim()) {
state.groupChatListSearchGroupName = ''
} else {
state.groupChatListSearchGroupName = value.groupName
} }
}
//
const getUserGroupChatList = () => {
let params = {
page: state.groupChatListPage,
page_size: state.groupChatListPageSize,
group_name: state.groupChatListSearchGroupName
}
ServeUserGroupChatList(params).then((res) => {
// console.log(res)
if (res.code === 200) {
state.groupChatListData = res?.data?.items || []
state.groupChatListTotal = res?.data?.total || 0
}
})
}
// //
const handleGroupChatListPagination = (value) => { const handleGroupChatListPagination = (value) => {
console.log(value, 'value') console.log(value, 'value')
state.groupChatListPage = value state.groupChatListPage = value
getUserGroupChatList()
} }
// //
const handleGroupChatListPaginationSize = (value) => { const handleGroupChatListPaginationSize = (value) => {
console.log(value, 'value') console.log(value, 'value')
state.groupChatListPageSize = value state.groupChatListPageSize = value
state.groupChatListPage = 1
getUserGroupChatList()
} }
// //
const handleClickSearchItem = (searchText, searchResultKey, talk_type, receiver_id, res) => { const handleClickSearchItem = (searchText, searchResultKey, talk_type, receiver_id, res) => {
@ -467,7 +567,9 @@ const handleClickSearchItem = (searchText, searchResultKey, talk_type, receiver_
talk_type: talk_type //12 talk_type: talk_type //12
}) })
) )
searchDetailListRef.value?.doLoadMore() nextTick(() => {
searchDetailListRef.value?.doLoadMore(true)
})
} }
} }
//item //item