Merge branch 'main' into xingyy
This commit is contained in:
commit
02ba7af6eb
7
env/.env.test
vendored
7
env/.env.test
vendored
@ -2,7 +2,10 @@ ENV = 'development'
|
|||||||
|
|
||||||
VITE_BASE=/
|
VITE_BASE=/
|
||||||
VUE_APP_PREVIEW=false
|
VUE_APP_PREVIEW=false
|
||||||
VITE_BASE_API=http://114.218.158.24:8503
|
#VITE_BASE_API=http://192.168.88.21:9503
|
||||||
|
|
||||||
|
#VITE_SOCKET_API=ws://192.168.88.21:9504
|
||||||
|
VITE_BASE_API=http://114.218.158.24:8503
|
||||||
|
VITE_SOCKET_API=ws://114.218.158.24:8504
|
||||||
VITE_EPR_BASEURL=http://114.218.158.24:9020
|
VITE_EPR_BASEURL=http://114.218.158.24:9020
|
||||||
VITE_SOCKET_API=ws://114.218.158.24:8504
|
|
||||||
VUE_APP_WEBSITE_NAME=""
|
VUE_APP_WEBSITE_NAME=""
|
@ -80,7 +80,7 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:show', 'cancel', 'confirm'])
|
const emit = defineEmits(['update:show', 'cancel', 'confirm', 'customCloseModal'])
|
||||||
|
|
||||||
const show = computed({
|
const show = computed({
|
||||||
get: () => props.show,
|
get: () => props.show,
|
||||||
@ -111,7 +111,7 @@ const state = reactive({
|
|||||||
|
|
||||||
const handleCloseModal = () => {
|
const handleCloseModal = () => {
|
||||||
if (props.customCloseEvent) {
|
if (props.customCloseEvent) {
|
||||||
emit('closeModal')
|
emit('customCloseModal')
|
||||||
} else {
|
} else {
|
||||||
show.value = false
|
show.value = false
|
||||||
}
|
}
|
||||||
|
49
src/components/confirm-box/index.vue
Normal file
49
src/components/confirm-box/index.vue
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import XNModal from '@/components/x-naive-ui/x-n-modal/index.vue'
|
||||||
|
const emit = defineEmits(['cancel','confirm'])
|
||||||
|
const show=defineModel('show')
|
||||||
|
const props = defineProps({
|
||||||
|
title:{
|
||||||
|
type:String,
|
||||||
|
default:'提示'
|
||||||
|
},
|
||||||
|
content:{
|
||||||
|
type:String,
|
||||||
|
default:'内容'
|
||||||
|
},
|
||||||
|
cancelText:{
|
||||||
|
type:String,
|
||||||
|
default:'取消'
|
||||||
|
},
|
||||||
|
confirmText:{
|
||||||
|
type:String,
|
||||||
|
default:'确定'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<XNModal v-model:show="show" :closable="false" class="w-724px" content-style="padding:0px" @after-leave="emit('after-leave')">
|
||||||
|
<div class="flex flex-col w-full px-25px pb-49px">
|
||||||
|
<div class="text-20px text-#1F2225 w-full text-center border-b-1px border-b-solid border-b-#E9E9E9 py-20px">{{ title }}</div>
|
||||||
|
<div class="py-60px text-center text-20px text-#1F2225">
|
||||||
|
{{ content }}
|
||||||
|
</div>
|
||||||
|
<div class="flex w-full justify-center">
|
||||||
|
<n-button color="#C7C7C9" class="text-14px text-#fff w-161px h-34px mr-10px"
|
||||||
|
@click="() => { show=false; emit('cancel') }"
|
||||||
|
>{{ cancelText }}</n-button>
|
||||||
|
<n-button color="#46299D" class="text-14px text-#fff w-161px h-34px"
|
||||||
|
@click="() => { show=false; emit('confirm') }"
|
||||||
|
>{{ confirmText }}</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</XNModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
32
src/components/confirm-box/service.js
Normal file
32
src/components/confirm-box/service.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { createVNode, nextTick, render } from 'vue'
|
||||||
|
import ConfirmBox from './index.vue'
|
||||||
|
|
||||||
|
export function confirmBox(options) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const container = document.createElement('div')
|
||||||
|
document.body.appendChild(container)
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
...options,
|
||||||
|
show: false,
|
||||||
|
onCancel: () => {
|
||||||
|
reject()
|
||||||
|
|
||||||
|
},
|
||||||
|
onAfterLeave:()=>{
|
||||||
|
render(null, container)
|
||||||
|
document.body.removeChild(container)
|
||||||
|
},
|
||||||
|
onConfirm: () => {
|
||||||
|
resolve()
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const vnode = createVNode(ConfirmBox, props)
|
||||||
|
render(vnode, container)
|
||||||
|
nextTick(() => {
|
||||||
|
vnode.component.props.show = true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
@ -663,7 +663,10 @@ const handleEditGroupNameConfirm = () => {
|
|||||||
清空聊天记录
|
清空聊天记录
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
v-if="isAdmin || isLeader"
|
v-if="
|
||||||
|
(isAdmin || isLeader) &&
|
||||||
|
(state.detail.group_type === 1 || state.detail.group_type === 3)
|
||||||
|
"
|
||||||
class="btn"
|
class="btn"
|
||||||
type="error"
|
type="error"
|
||||||
ghost
|
ghost
|
||||||
@ -671,7 +674,13 @@ const handleEditGroupNameConfirm = () => {
|
|||||||
>
|
>
|
||||||
解散该群
|
解散该群
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button class="btn" type="error" ghost @click="showChatSettingOperateModal('quit')">
|
<n-button
|
||||||
|
class="btn"
|
||||||
|
type="error"
|
||||||
|
ghost
|
||||||
|
@click="showChatSettingOperateModal('quit')"
|
||||||
|
v-if="state.detail.group_type === 1 || state.detail.group_type === 3"
|
||||||
|
>
|
||||||
退出群聊
|
退出群聊
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
@ -731,7 +740,8 @@ const handleEditGroupNameConfirm = () => {
|
|||||||
|
|
||||||
<UserCardModal
|
<UserCardModal
|
||||||
v-model:show="state.isShowUserCardModal"
|
v-model:show="state.isShowUserCardModal"
|
||||||
v-model:uid="(state.userInfo as any).erp_user_id"
|
v-model:uid="(state.userInfo as any).user_id"
|
||||||
|
:euid="(state.userInfo as any).erp_user_id"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -200,10 +200,10 @@
|
|||||||
>
|
>
|
||||||
<div class="attachment-avatar">
|
<div class="attachment-avatar">
|
||||||
<img :src="item?.extra?.file_avatar" v-if="state.condition === 'file'" />
|
<img :src="item?.extra?.file_avatar" v-if="state.condition === 'file'" />
|
||||||
<img
|
<!-- <img
|
||||||
src="@/static/image/search/result-link-icon.png"
|
src="@/static/image/search/result-link-icon.png"
|
||||||
v-if="state.condition === 'link'"
|
v-if="state.condition === 'link'"
|
||||||
/>
|
/> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="attachment-info">
|
<div class="attachment-info">
|
||||||
<div class="attachment-info-title">
|
<div class="attachment-info-title">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
:class="props?.conditionType ? 'search-item-condition' : ''"
|
:class="props?.conditionType ? 'search-item-condition' : ''"
|
||||||
v-if="resultName"
|
v-if="resultName"
|
||||||
:style="{
|
:style="{
|
||||||
'margin': props.searchResultKey === 'talk_record_infos_receiver' ? '12px 0 0' : '',
|
margin: props.searchResultKey === 'talk_record_infos_receiver' ? '12px 0 0' : '',
|
||||||
'background-color': props.isClickStay ? '#EEE9F8' : ''
|
'background-color': props.isClickStay ? '#EEE9F8' : ''
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
@ -70,6 +70,9 @@
|
|||||||
:text="resultDetail"
|
:text="resultDetail"
|
||||||
:searchText="props.searchText"
|
:searchText="props.searchText"
|
||||||
/>
|
/>
|
||||||
|
<div class="searchRecordDetail-fastLocal" v-if="searchRecordDetail">
|
||||||
|
<span>定位到聊天位置</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-item-pointer" v-if="pointerIconSrc">
|
<div class="search-item-pointer" v-if="pointerIconSrc">
|
||||||
@ -270,7 +273,7 @@ const resultDetail = computed(() => {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.search-item-avatar{
|
.search-item-avatar {
|
||||||
position: relative;
|
position: relative;
|
||||||
.info-tag {
|
.info-tag {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -320,10 +323,24 @@ const resultDetail = computed(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.info-detail-searchRecordDetail {
|
.info-detail-searchRecordDetail {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
span {
|
span {
|
||||||
color: #191919;
|
color: #191919;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
.searchRecordDetail-fastLocal {
|
||||||
|
display: none;
|
||||||
|
line-height: 20px;
|
||||||
|
span {
|
||||||
|
color: #46299d;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.search-item-pointer {
|
.search-item-pointer {
|
||||||
@ -339,7 +356,7 @@ const resultDetail = computed(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.search-item::after{
|
.search-item::after {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -355,5 +372,11 @@ const resultDetail = computed(() => {
|
|||||||
}
|
}
|
||||||
.search-item:hover {
|
.search-item:hover {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
|
|
||||||
|
.info-detail-searchRecordDetail {
|
||||||
|
.searchRecordDetail-fastLocal {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="search-list">
|
<div class="search-list">
|
||||||
|
<n-infinite-scroll
|
||||||
|
:style="{ maxHeight: props.searchResultMaxHeight }"
|
||||||
|
:distance="47"
|
||||||
|
@load="doLoadMore"
|
||||||
|
>
|
||||||
<div class="search-result">
|
<div class="search-result">
|
||||||
<div class="search-result-list">
|
<div class="search-result-list">
|
||||||
<div
|
<div
|
||||||
@ -15,12 +20,19 @@
|
|||||||
searchResultKey !== 'group_infos' &&
|
searchResultKey !== 'group_infos' &&
|
||||||
searchResultKey !== 'group_member_infos'
|
searchResultKey !== 'group_member_infos'
|
||||||
"
|
"
|
||||||
|
:style="{ margin: props.useCustomTitle ? '0' : '' }"
|
||||||
>
|
>
|
||||||
<div class="result-title">
|
<!-- <div class="result-title" v-if="!props.useCustomTitle">
|
||||||
<span class="text-[14px] font-regular">
|
<span class="text-[14px] font-regular">
|
||||||
{{ getResultKeysValue(searchResultKey) }}
|
{{ getResultKeysValue(searchResultKey) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div> -->
|
||||||
|
<slot
|
||||||
|
name="result-title"
|
||||||
|
:getResultKeysValue="getResultKeysValue"
|
||||||
|
:searchResultKey="searchResultKey"
|
||||||
|
:searchResultIndex="searchResultIndex"
|
||||||
|
></slot>
|
||||||
<div class="result-list">
|
<div class="result-list">
|
||||||
<div
|
<div
|
||||||
class="result-list-each"
|
class="result-list-each"
|
||||||
@ -55,6 +67,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</n-infinite-scroll>
|
||||||
<!-- <ZPaging
|
<!-- <ZPaging
|
||||||
ref="zPaging"
|
ref="zPaging"
|
||||||
:show-scrollbar="false"
|
:show-scrollbar="false"
|
||||||
@ -131,6 +144,7 @@
|
|||||||
// const zPaging = ref()
|
// const zPaging = ref()
|
||||||
// useZPaging(zPaging)
|
// useZPaging(zPaging)
|
||||||
|
|
||||||
|
import { NInfiniteScroll } from 'naive-ui'
|
||||||
import searchItem from './searchItem.vue'
|
import searchItem from './searchItem.vue'
|
||||||
import { ref, reactive, defineEmits, defineProps, onMounted, watch } from 'vue'
|
import { ref, reactive, defineEmits, defineProps, onMounted, watch } from 'vue'
|
||||||
|
|
||||||
@ -139,7 +153,7 @@ const emits = defineEmits([
|
|||||||
'lastIdChange',
|
'lastIdChange',
|
||||||
'clickSearchItem',
|
'clickSearchItem',
|
||||||
'clickStayItemChange',
|
'clickStayItemChange',
|
||||||
'doLoadMore'
|
'resultTotalCount'
|
||||||
])
|
])
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@ -148,7 +162,9 @@ const state = reactive({
|
|||||||
searchResult: null, //搜索结果
|
searchResult: null, //搜索结果
|
||||||
pageNum: 1, //当前请求数据页数
|
pageNum: 1, //当前请求数据页数
|
||||||
uid: 12303, //当前用户id
|
uid: 12303, //当前用户id
|
||||||
clickStayItem: '' //点击停留的item
|
clickStayItem: '', //点击停留的item
|
||||||
|
hasMore: true, //是否还有更多数据
|
||||||
|
loading: false //加载锁
|
||||||
})
|
})
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -190,7 +206,15 @@ const props = defineProps({
|
|||||||
useClickStay: {
|
useClickStay: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
} //是否使用点击停留样式
|
}, //是否使用点击停留样式
|
||||||
|
searchResultMaxHeight: {
|
||||||
|
type: String,
|
||||||
|
default: '677px'
|
||||||
|
}, //搜索结果最大高度
|
||||||
|
useCustomTitle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
} //是否使用自定义标题
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -212,28 +236,21 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => props.searchText,
|
() => props.searchText,
|
||||||
(newVal, oldVal) => {
|
(newVal, oldVal) => {
|
||||||
queryAllSearch()
|
// 同步更新 state.searchText
|
||||||
|
state.searchText = newVal
|
||||||
|
// 清空搜索结果
|
||||||
|
state.searchResult = null
|
||||||
|
// 重置页码
|
||||||
|
state.pageNum = 1
|
||||||
|
//重置点击停留列表项
|
||||||
state.clickStayItem = ''
|
state.clickStayItem = ''
|
||||||
emits('clickStayItemChange', state.clickStayItem)
|
emits('clickStayItemChange', state.clickStayItem)
|
||||||
|
//重置搜索条件
|
||||||
|
emits('lastIdChange', 0, 0, 0, '', '')
|
||||||
|
queryAllSearch()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
//输入搜索文本
|
|
||||||
const inputSearchText = (e) => {
|
|
||||||
if (e.trim() != state.searchText.trim()) {
|
|
||||||
state.pageNum = 1
|
|
||||||
state.searchResult = null // 清空搜索结果
|
|
||||||
emits('lastIdChange', 0, 0, 0, '', '')
|
|
||||||
}
|
|
||||||
state.searchText = e.trim()
|
|
||||||
if (!e.trim()) {
|
|
||||||
state.searchResult = null // 清空搜索结果
|
|
||||||
emits('lastIdChange', 0, 0, 0, '', '')
|
|
||||||
}
|
|
||||||
// zPaging.value?.reload()
|
|
||||||
queryAllSearch()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ES搜索聊天记录-主页搜索什么都有、指定用户、指定群、群与用户概览
|
// ES搜索聊天记录-主页搜索什么都有、指定用户、指定群、群与用户概览
|
||||||
const queryAllSearch = (doClearSearchResult) => {
|
const queryAllSearch = (doClearSearchResult) => {
|
||||||
if (doClearSearchResult) {
|
if (doClearSearchResult) {
|
||||||
@ -354,6 +371,12 @@ const queryAllSearch = (doClearSearchResult) => {
|
|||||||
total = data.group_record_count
|
total = data.group_record_count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (total < props.searchResultPageSize) {
|
||||||
|
state.hasMore = false
|
||||||
|
} else {
|
||||||
|
state.hasMore = true
|
||||||
|
}
|
||||||
|
emits('resultTotalCount', total)
|
||||||
// zPaging.value?.completeByTotal([data], total)
|
// zPaging.value?.completeByTotal([data], total)
|
||||||
} else {
|
} else {
|
||||||
state.searchResult = data
|
state.searchResult = data
|
||||||
@ -383,6 +406,7 @@ const queryAllSearch = (doClearSearchResult) => {
|
|||||||
// zPaging.value?.complete(state.searchResult ? [state.searchResult] : [])
|
// zPaging.value?.complete(state.searchResult ? [state.searchResult] : [])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
//点击取消搜索
|
//点击取消搜索
|
||||||
@ -514,13 +538,14 @@ const clickSearchItem = (searchResultKey, searchItem) => {
|
|||||||
|
|
||||||
//加载更多数据
|
//加载更多数据
|
||||||
const doLoadMore = (doClearSearchResult) => {
|
const doLoadMore = (doClearSearchResult) => {
|
||||||
queryAllSearch(doClearSearchResult)
|
if (!state.hasMore || state.loading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.loading = true
|
||||||
|
queryAllSearch(doClearSearchResult).finally(() => {
|
||||||
|
state.loading = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暴露doLoadMore方法给父组件
|
|
||||||
defineExpose({
|
|
||||||
doLoadMore
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.search-list {
|
.search-list {
|
||||||
@ -555,7 +580,7 @@ defineExpose({
|
|||||||
// padding: 0 10px;
|
// padding: 0 10px;
|
||||||
|
|
||||||
.search-result-part {
|
.search-result-part {
|
||||||
margin: 18px 0 0;
|
// margin: 18px 0 0;
|
||||||
|
|
||||||
.result-title {
|
.result-title {
|
||||||
padding: 0 10px 5px;
|
padding: 0 10px 5px;
|
||||||
|
@ -71,9 +71,8 @@ function getFileExtension(filename) {
|
|||||||
// 切换播放状态
|
// 切换播放状态
|
||||||
const togglePlay = () => {
|
const togglePlay = () => {
|
||||||
isPlaying.value = !isPlaying.value
|
isPlaying.value = !isPlaying.value
|
||||||
|
|
||||||
if (props.extra.is_uploading && props.extra.upload_id) {
|
if (props.extra.is_uploading && props.extra.upload_id) {
|
||||||
const action = isPlaying.value ? 'resumeUpload' : 'pauseUpload'
|
const action = isPlaying.value ? 'pauseUpload' : 'resumeUpload'
|
||||||
uploadsStore[action](props.extra.upload_id)
|
uploadsStore[action](props.extra.upload_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +112,7 @@ const handleDownload = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="file-message" @click="handleClick">
|
<div class="file-message flex flex-col" @click="handleClick">
|
||||||
<!-- 文件头部信息 -->
|
<!-- 文件头部信息 -->
|
||||||
<div class="file-header">
|
<div class="file-header">
|
||||||
<!-- 文件名 -->
|
<!-- 文件名 -->
|
||||||
@ -123,8 +122,8 @@ const handleDownload = () => {
|
|||||||
<img class="file-icon" :src="fileInfo.icon" alt="文件图标">
|
<img class="file-icon" :src="fileInfo.icon" alt="文件图标">
|
||||||
|
|
||||||
<!-- 上传进度圆环 - 上传状态 -->
|
<!-- 上传进度圆环 - 上传状态 -->
|
||||||
<div v-if="extra.is_uploading" class="progress-overlay">
|
<div v-if="extra.is_uploading&&extra.percentage>0" class="progress-overlay">
|
||||||
<div class="circle-progress-container" @click="togglePlay">
|
<div class="circle-progress-container" @click.stop="togglePlay">
|
||||||
<svg class="circle-progress" width="20" height="20" viewBox="0 0 20 20">
|
<svg class="circle-progress" width="20" height="20" viewBox="0 0 20 20">
|
||||||
<!-- 底色圆环 -->
|
<!-- 底色圆环 -->
|
||||||
<circle
|
<circle
|
||||||
@ -150,20 +149,21 @@ const handleDownload = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 暂停/播放图标 -->
|
<!-- 暂停/播放图标 -->
|
||||||
<g v-if="isPlaying" class="pause-icon">
|
|
||||||
|
<g v-if="isPlaying" class="play-icon">
|
||||||
|
<rect x="6" y="6" width="8" height="8" :fill="fileInfo.color" />
|
||||||
|
</g>
|
||||||
|
<g v-else class="pause-icon">
|
||||||
<rect x="7" y="5" width="2" height="10" :fill="fileInfo.color" />
|
<rect x="7" y="5" width="2" height="10" :fill="fileInfo.color" />
|
||||||
<rect x="11" y="5" width="2" height="10" :fill="fileInfo.color" />
|
<rect x="11" y="5" width="2" height="10" :fill="fileInfo.color" />
|
||||||
</g>
|
</g>
|
||||||
<g v-else class="play-icon">
|
|
||||||
<rect x="6" y="6" width="8" height="8" :fill="fileInfo.color" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 文件大小信息 -->
|
<!-- 文件大小信息 -->
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center grow-1">
|
||||||
<div class="file-size">{{ fileFormatSize(extra.size) }}</div>
|
<div class="file-size">{{ fileFormatSize(extra.size) }}</div>
|
||||||
<div class="flex items-center" v-if="!extra.is_uploading">
|
<div class="flex items-center" v-if="!extra.is_uploading">
|
||||||
<div class="flex items-center" @click.stop="handleDownload"> <img class="w-11.7px h-11.74px mr-7px" src="@/assets/image/dofd.png" alt=""> <span class="text-12px text-#46299D">下载</span></div>
|
<div class="flex items-center" @click.stop="handleDownload"> <img class="w-11.7px h-11.74px mr-7px" src="@/assets/image/dofd.png" alt=""> <span class="text-12px text-#46299D">下载</span></div>
|
||||||
@ -178,6 +178,7 @@ const handleDownload = () => {
|
|||||||
.file-message {
|
.file-message {
|
||||||
width: 243px;
|
width: 243px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
height: 110px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
@ -205,6 +206,7 @@ const handleDownload = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-icon-container {
|
.file-icon-container {
|
||||||
|
height: 48px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +230,6 @@ const handleDownload = () => {
|
|||||||
.file-size {
|
.file-size {
|
||||||
color: #747474;
|
color: #747474;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 5px 0 11px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.circle-progress-container {
|
.circle-progress-container {
|
||||||
|
@ -35,7 +35,7 @@ const img = (src: string, width = 200) => {
|
|||||||
:class="{ left: data.float === 'left' }"
|
:class="{ left: data.float === 'left' }"
|
||||||
:style="img(extra.url, 350)"
|
:style="img(extra.url, 350)"
|
||||||
>
|
>
|
||||||
<n-image :src="extra.url" />
|
<n-image class="h-149px" :src="extra.url" />
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@ -44,9 +44,6 @@ const img = (src: string, width = 200) => {
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: var(--im-message-left-bg-color);
|
background: var(--im-message-left-bg-color);
|
||||||
min-width: 30px;
|
|
||||||
min-height: 30px;
|
|
||||||
max-width:240px;
|
|
||||||
height:149px
|
height:149px
|
||||||
&.left {
|
&.left {
|
||||||
background: var(--im-message-right-bg-color);
|
background: var(--im-message-right-bg-color);
|
||||||
|
@ -137,7 +137,8 @@ function resumeUpload(e) {
|
|||||||
|
|
||||||
<!-- <n-image :src="extra.cover" preview-disabled /> -->
|
<!-- <n-image :src="extra.cover" preview-disabled /> -->
|
||||||
<video :src="props.extra.url" :controls="false"></video>
|
<video :src="props.extra.url" :controls="false"></video>
|
||||||
|
<!-- 上传进度时的黑色半透明蒙层 -->
|
||||||
|
<div v-if="extra.is_uploading && !uploadFailed" class="upload-mask"></div>
|
||||||
<!-- 上传进度显示 -->
|
<!-- 上传进度显示 -->
|
||||||
<div v-if="extra.is_uploading && !uploadFailed" class="upload-progress">
|
<div v-if="extra.is_uploading && !uploadFailed" class="upload-progress">
|
||||||
<n-progress
|
<n-progress
|
||||||
@ -245,6 +246,17 @@ function resumeUpload(e) {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upload-mask {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.45);
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.upload-progress {
|
.upload-progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
@ -255,6 +267,7 @@ function resumeUpload(e) {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
.upload-control {
|
.upload-control {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -11,6 +11,17 @@ interface Params {
|
|||||||
limit: number
|
limit: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SpecialParams extends Params {
|
||||||
|
msg_id?: string
|
||||||
|
cursor?: number
|
||||||
|
direction?: 'up' | 'down'
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LoadOptions {
|
||||||
|
specifiedMsg?: SpecialParams
|
||||||
|
middleMsgCreatedAt?: string
|
||||||
|
}
|
||||||
|
|
||||||
export const useTalkRecord = (uid: number) => {
|
export const useTalkRecord = (uid: number) => {
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
|
|
||||||
@ -25,9 +36,19 @@ export const useTalkRecord = (uid: number) => {
|
|||||||
receiver_id: 0,
|
receiver_id: 0,
|
||||||
talk_type: 0,
|
talk_type: 0,
|
||||||
status: 0,
|
status: 0,
|
||||||
cursor: 0
|
cursor: 0,
|
||||||
|
specialParams: undefined as SpecialParams | undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 重置 loadConfig
|
||||||
|
const resetLoadConfig = () => {
|
||||||
|
loadConfig.receiver_id = 0
|
||||||
|
loadConfig.talk_type = 0
|
||||||
|
loadConfig.status = 0
|
||||||
|
loadConfig.cursor = 0
|
||||||
|
loadConfig.specialParams = undefined
|
||||||
|
}
|
||||||
|
|
||||||
const onJumpMessage = (msgid: string) => {
|
const onJumpMessage = (msgid: string) => {
|
||||||
const element = document.getElementById(msgid)
|
const element = document.getElementById(msgid)
|
||||||
if (!element) {
|
if (!element) {
|
||||||
@ -135,8 +156,160 @@ export const useTalkRecord = (uid: number) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前消息的最小 sequence
|
||||||
|
const getMinSequence = () => {
|
||||||
|
console.error('records.value', records.value)
|
||||||
|
if (!records.value.length) return 0
|
||||||
|
console.error(Math.min(...records.value.map(item => item.sequence)))
|
||||||
|
return Math.min(...records.value.map(item => item.sequence))
|
||||||
|
}
|
||||||
|
// 获取当前消息的最大 sequence
|
||||||
|
const getMaxSequence = () => {
|
||||||
|
if (!records.value.length) return 0
|
||||||
|
return Math.max(...records.value.map(item => item.sequence))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载数据主入口,支持指定消息定位模式
|
||||||
|
* @param params 原有参数
|
||||||
|
* @param options 可选,{ specifiedMsg } 指定消息对象
|
||||||
|
*/
|
||||||
|
const onLoad = (params: Params, options?: LoadOptions) => {
|
||||||
|
// 如果会话切换,重置所有状态
|
||||||
|
if (params.talk_type !== loadConfig.talk_type || params.receiver_id !== loadConfig.receiver_id) {
|
||||||
|
resetLoadConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConfig.cursor = 0
|
||||||
|
loadConfig.receiver_id = params.receiver_id
|
||||||
|
loadConfig.talk_type = params.talk_type
|
||||||
|
|
||||||
|
console.error('onLoad', params, options)
|
||||||
|
|
||||||
|
// 新增:支持指定消息定位模式,参数以传入为准合并
|
||||||
|
if (options?.specifiedMsg?.cursor !== undefined) {
|
||||||
|
loadConfig.specialParams = { ...options.specifiedMsg } // 记录特殊参数,供分页加载用
|
||||||
|
console.error('options', options)
|
||||||
|
loadConfig.status = 0 // 复用主流程 loading 状态
|
||||||
|
// 以 params 为基础,合并 specifiedMsg 的所有字段(只要有就覆盖)
|
||||||
|
const contextParams = {
|
||||||
|
...params,
|
||||||
|
...options.specifiedMsg
|
||||||
|
}
|
||||||
|
ServeTalkRecords(contextParams).then(({ data, code }) => {
|
||||||
|
if (code !== 200) {
|
||||||
|
loadConfig.status = 2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dialogueStore.clearDialogueRecord()
|
||||||
|
const items = (data.items || []).map((item: ITalkRecord) => formatTalkRecord(uid, item))
|
||||||
|
dialogueStore.unshiftDialogueRecord(items.reverse())
|
||||||
|
loadConfig.status = items.length >= contextParams.limit ? 1 : 2
|
||||||
|
loadConfig.cursor = data.cursor
|
||||||
|
nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const el = document.getElementById('imChatPanel')
|
||||||
|
const target = document.getElementById(options.specifiedMsg?.msg_id || '')
|
||||||
|
if (el && target) {
|
||||||
|
const containerRect = el.getBoundingClientRect()
|
||||||
|
const targetRect = target.getBoundingClientRect()
|
||||||
|
const offset = targetRect.top - containerRect.top
|
||||||
|
// 居中
|
||||||
|
const scrollTo = el.scrollTop + offset - el.clientHeight / 2 + target.clientHeight / 2
|
||||||
|
el.scrollTo({ top: scrollTo, behavior: 'smooth' })
|
||||||
|
|
||||||
|
addClass(target, 'border')
|
||||||
|
setTimeout(() => removeClass(target, 'border'), 3000)
|
||||||
|
} else if (el) {
|
||||||
|
el.scrollTop = el.scrollHeight
|
||||||
|
}
|
||||||
|
}, 50)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConfig.specialParams = undefined // 普通模式清空
|
||||||
|
// 原有逻辑
|
||||||
|
load(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向上加载更多(兼容特殊参数模式)
|
||||||
const onRefreshLoad = () => {
|
const onRefreshLoad = () => {
|
||||||
|
console.error('loadConfig.status', loadConfig.status)
|
||||||
if (loadConfig.status == 1) {
|
if (loadConfig.status == 1) {
|
||||||
|
console.log('specialParams', loadConfig.specialParams)
|
||||||
|
// 判断是否是特殊参数模式
|
||||||
|
if (loadConfig.specialParams && typeof loadConfig.specialParams === 'object') {
|
||||||
|
// 检查特殊参数是否与当前会话匹配
|
||||||
|
if (loadConfig.specialParams.talk_type === loadConfig.talk_type &&
|
||||||
|
loadConfig.specialParams.receiver_id === loadConfig.receiver_id) {
|
||||||
|
// 特殊参数模式下,direction: 'up',cursor: 当前最小 sequence
|
||||||
|
onLoad(
|
||||||
|
{
|
||||||
|
receiver_id: loadConfig.receiver_id,
|
||||||
|
talk_type: loadConfig.talk_type,
|
||||||
|
limit: 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
specifiedMsg: {
|
||||||
|
...loadConfig.specialParams,
|
||||||
|
direction: 'up',
|
||||||
|
cursor: getMinSequence()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// 如果不匹配,重置为普通模式
|
||||||
|
resetLoadConfig()
|
||||||
|
load({
|
||||||
|
receiver_id: loadConfig.receiver_id,
|
||||||
|
talk_type: loadConfig.talk_type,
|
||||||
|
limit: 30
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 原有逻辑
|
||||||
|
load({
|
||||||
|
receiver_id: loadConfig.receiver_id,
|
||||||
|
talk_type: loadConfig.talk_type,
|
||||||
|
limit: 30
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向下加载更多(兼容特殊参数模式)
|
||||||
|
const onLoadMoreDown = () => {
|
||||||
|
// 判断是否是特殊参数模式
|
||||||
|
if (loadConfig.specialParams && typeof loadConfig.specialParams === 'object') {
|
||||||
|
// 检查特殊参数是否与当前会话匹配
|
||||||
|
if (loadConfig.specialParams.talk_type === loadConfig.talk_type &&
|
||||||
|
loadConfig.specialParams.receiver_id === loadConfig.receiver_id) {
|
||||||
|
onLoad(
|
||||||
|
{
|
||||||
|
receiver_id: loadConfig.receiver_id,
|
||||||
|
talk_type: loadConfig.talk_type,
|
||||||
|
limit: 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
specifiedMsg: {
|
||||||
|
...loadConfig.specialParams,
|
||||||
|
direction: 'down',
|
||||||
|
cursor: getMaxSequence()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// 如果不匹配,重置为普通模式
|
||||||
|
resetLoadConfig()
|
||||||
|
load({
|
||||||
|
receiver_id: loadConfig.receiver_id,
|
||||||
|
talk_type: loadConfig.talk_type,
|
||||||
|
limit: 30
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
load({
|
load({
|
||||||
receiver_id: loadConfig.receiver_id,
|
receiver_id: loadConfig.receiver_id,
|
||||||
talk_type: loadConfig.talk_type,
|
talk_type: loadConfig.talk_type,
|
||||||
@ -145,13 +318,5 @@ export const useTalkRecord = (uid: number) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onLoad = (params: Params) => {
|
return { loadConfig, records, onLoad, onRefreshLoad, onLoadMoreDown, onJumpMessage, resetLoadConfig }
|
||||||
loadConfig.cursor = 0
|
|
||||||
loadConfig.receiver_id = params.receiver_id
|
|
||||||
loadConfig.talk_type = params.talk_type
|
|
||||||
|
|
||||||
load(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
return { loadConfig, records, onLoad, onRefreshLoad, onJumpMessage }
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,12 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
// 聊天记录
|
// 聊天记录
|
||||||
records: [],
|
records: [],
|
||||||
|
|
||||||
|
// 查询指定消息上下文的消息信息
|
||||||
|
specifiedMsg: '',
|
||||||
|
|
||||||
|
// 是否是手动切换会话
|
||||||
|
isManualSwitch: false,
|
||||||
|
|
||||||
// 新消息提示
|
// 新消息提示
|
||||||
unreadBubble: 0,
|
unreadBubble: 0,
|
||||||
|
|
||||||
@ -88,6 +94,12 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
this.unreadBubble = 0
|
this.unreadBubble = 0
|
||||||
this.isShowEditor = data?.is_robot === 0
|
this.isShowEditor = data?.is_robot === 0
|
||||||
|
|
||||||
|
// 只在手动切换会话时清空 specifiedMsg
|
||||||
|
// if (this.isManualSwitch) {
|
||||||
|
// this.specifiedMsg = ''
|
||||||
|
// this.isManualSwitch = false
|
||||||
|
// }
|
||||||
|
|
||||||
this.members = []
|
this.members = []
|
||||||
if (data.talk_type == 2) {
|
if (data.talk_type == 2) {
|
||||||
this.updateGroupMembers()
|
this.updateGroupMembers()
|
||||||
|
@ -79,28 +79,6 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
findItemByClientId(clientUploadId: string): UploadItem | undefined {
|
findItemByClientId(clientUploadId: string): UploadItem | undefined {
|
||||||
return this.items.find((item) => item.client_upload_id === clientUploadId)
|
return this.items.find((item) => item.client_upload_id === clientUploadId)
|
||||||
},
|
},
|
||||||
|
|
||||||
// // 暂停文件上传
|
|
||||||
// pauseUpload(uploadId: string) {
|
|
||||||
// const item = this.findItem(uploadId)
|
|
||||||
// if (!item) return
|
|
||||||
|
|
||||||
// item.is_paused = true
|
|
||||||
// console.log(`暂停上传: ${uploadId}`)
|
|
||||||
// },
|
|
||||||
|
|
||||||
// 恢复文件上传
|
|
||||||
// resumeUpload(uploadId: string) {
|
|
||||||
// const item = this.findItem(uploadId)
|
|
||||||
// if (!item) return
|
|
||||||
|
|
||||||
// item.is_paused = false
|
|
||||||
// console.log(`恢复上传: ${uploadId}`)
|
|
||||||
|
|
||||||
// // 继续上传
|
|
||||||
// this.triggerUpload(uploadId)
|
|
||||||
// },
|
|
||||||
|
|
||||||
// 发送上传消息
|
// 发送上传消息
|
||||||
async sendUploadMessage(item: any) {
|
async sendUploadMessage(item: any) {
|
||||||
try {
|
try {
|
||||||
@ -119,8 +97,7 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
file: File,
|
file: File,
|
||||||
talkType: number,
|
talkType: number,
|
||||||
receiverId: number,
|
receiverId: number,
|
||||||
username: string,
|
clientUploadId: string,
|
||||||
uploadId: string,
|
|
||||||
onProgress: (percentage: number) => void,
|
onProgress: (percentage: number) => void,
|
||||||
onComplete: (data: any) => void
|
onComplete: (data: any) => void
|
||||||
) {
|
) {
|
||||||
@ -147,13 +124,11 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
talk_type: talkType,
|
talk_type: talkType,
|
||||||
receiver_id: receiverId,
|
receiver_id: receiverId,
|
||||||
upload_id: upload_id,
|
upload_id: upload_id,
|
||||||
client_upload_id: uploadId, // 客户端生成的上传ID,用于前端标识
|
client_upload_id: clientUploadId, // 客户端生成的上传ID,用于前端标识
|
||||||
uploadIndex: 0,
|
uploadIndex: 0,
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
status: 0, // 文件上传状态 0:等待上传 1:上传中 2:上传完成 3:网络异常
|
status: 0, // 文件上传状态 0:等待上传 1:上传中 2:上传完成 3:网络异常
|
||||||
files: fileChunks,
|
files: fileChunks,
|
||||||
avatar: '',
|
|
||||||
username: username,
|
|
||||||
is_paused: false,
|
is_paused: false,
|
||||||
onProgress: onProgress,
|
onProgress: onProgress,
|
||||||
onComplete: onComplete,
|
onComplete: onComplete,
|
||||||
@ -162,7 +137,7 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
this.isShow = false // 不显示上传管理抽屉
|
this.isShow = false // 不显示上传管理抽屉
|
||||||
|
|
||||||
// 开始上传分片
|
// 开始上传分片
|
||||||
this.triggerUpload(upload_id, uploadId)
|
this.triggerUpload(upload_id, clientUploadId)
|
||||||
} else {
|
} else {
|
||||||
message.error(res.message)
|
message.error(res.message)
|
||||||
onProgress(-1) // 通知上传失败
|
onProgress(-1) // 通知上传失败
|
||||||
@ -198,12 +173,12 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
|
|
||||||
// 上传当前分片
|
// 上传当前分片
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const res = await ServeFileSubareaUpload(form)
|
const res = await ServeFileSubareaUpload(form)
|
||||||
|
|
||||||
// 获取最新的项目状态,确保仍然存在且没有被暂停
|
// 获取最新的项目状态,确保仍然存在且没有被暂停
|
||||||
const updatedItem = this.findItem(uploadId)
|
const updatedItem:any = this.findItem(uploadId)
|
||||||
if (!updatedItem || updatedItem.is_paused) return
|
if(updatedItem.is_paused) return
|
||||||
|
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
// 当前分片上传成功,增加索引
|
// 当前分片上传成功,增加索引
|
||||||
updatedItem.uploadIndex++
|
updatedItem.uploadIndex++
|
||||||
@ -230,12 +205,12 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
this.triggerUpload(uploadId, clientUploadId)
|
this.triggerUpload(uploadId, clientUploadId)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
updatedItem.onProgress(-1)
|
||||||
// 上传失败处理
|
// 上传失败处理
|
||||||
console.error(`分片上传失败,错误码: ${res.code},错误信息: ${res.message || '未知错误'}`);
|
console.error(`分片上传失败,错误码: ${res.code},错误信息: ${res.message || '未知错误'}`);
|
||||||
updatedItem.status = 3
|
updatedItem.status = 3
|
||||||
|
|
||||||
// 尝试重试当前分片
|
|
||||||
this.retryUpload(uploadId, clientUploadId, res.message || '上传失败,请重试')
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("分片上传错误:", error);
|
console.error("分片上传错误:", error);
|
||||||
@ -248,37 +223,10 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
if (updatedItem.is_paused) return
|
if (updatedItem.is_paused) return
|
||||||
|
|
||||||
updatedItem.status = 3
|
updatedItem.status = 3
|
||||||
|
|
||||||
// 尝试重试当前分片
|
|
||||||
this.retryUpload(uploadId, clientUploadId, '网络错误,正在重试')
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 重试上传
|
|
||||||
retryUpload(uploadId: string, clientUploadId?: string, errorMessage?: string) {
|
|
||||||
const item = this.findItem(uploadId)
|
|
||||||
if (!item) return
|
|
||||||
|
|
||||||
// 如果有暂停/恢复按钮,先告知用户上传出错
|
|
||||||
if (item.onProgress) {
|
|
||||||
item.onProgress(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示错误提示
|
|
||||||
message.warning(errorMessage)
|
|
||||||
|
|
||||||
// 创建一个5秒后自动重试的机制
|
|
||||||
setTimeout(() => {
|
|
||||||
const currentItem = this.findItem(uploadId)
|
|
||||||
if (!currentItem) return
|
|
||||||
|
|
||||||
// 如果用户没有手动暂停,则自动重试
|
|
||||||
if (!currentItem.is_paused) {
|
|
||||||
console.log('正在重试上传分片...');
|
|
||||||
this.triggerUpload(uploadId, clientUploadId)
|
|
||||||
}
|
|
||||||
}, 5000)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 完成上传
|
// 完成上传
|
||||||
async completeUpload(item: UploadItem, clientUploadId: string) {
|
async completeUpload(item: UploadItem, clientUploadId: string) {
|
||||||
|
@ -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'))||'79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b89eb1ea28c6224649ca60080b7243593f7462085111e3bd3868564aa9a65a16e171ba833d4955a4555f3376cb64b66eb2304dafb03f182fe1719d09e84d345954edbf75b17358196e1378893c8c97b56a6'
|
return JSON.parse(localStorage.getItem('token'))||'46d71a72d8d845ad7ed23eba9bdde260e635407190c2ce1bf7fd22088e41682ea07773ec65cae8946d2003f264d55961f96e0fc5da10eb96d3a348c1664e9644ce2108c311309f398ae8ea1b8200bfd490e5cb6e8c52c9e5d493cbabb163368f8351420451a631dbfa749829ee4cda49b77b5ed2d3dced5d0f2b7dd9ee76ba5465c84a17c23af040cd92b6b2a4ea48befbb5c729dcdad0a9c9668befe84074cc24f78899c1d947f8e7f94c7eda5325b8ed698df729e76febb98549ef3482ae942fb4f4a1c92d21836fa784728f0c5483aab2760a991b6b36e6b10c84f840a6433a6ecc31dee36e8f1c6158818bc89d22cb993eb73d0e2c0e0c8f627f3a8550a8e846cd26e5ec6abe0b57b0470a33b33c4b097d9fc113aa020f9751b55320b4f6b3f812fa4cc357f90f8db108a250b14e477c1e1b2292799d3c8831f7a47de2d6'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +31,8 @@ const talkParams = reactive({
|
|||||||
online: computed(() => dialogueStore.online),
|
online: computed(() => dialogueStore.online),
|
||||||
keyboard: computed(() => dialogueStore.keyboard),
|
keyboard: computed(() => dialogueStore.keyboard),
|
||||||
num: computed(() => dialogueStore.members.length),
|
num: computed(() => dialogueStore.members.length),
|
||||||
avatar:computed(() => dialogueStore.talk.avatar)
|
avatar:computed(() => dialogueStore.talk.avatar),
|
||||||
|
specifiedMsg: computed(() => dialogueStore.specifiedMsg)
|
||||||
})
|
})
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@ -394,6 +395,7 @@ const handleGroupNoticeModalShow = (isAdmin) => {
|
|||||||
:talk_type="talkParams.type"
|
:talk_type="talkParams.type"
|
||||||
:receiver_id="talkParams.receiver_id"
|
:receiver_id="talkParams.receiver_id"
|
||||||
:index_name="talkParams.index_name"
|
:index_name="talkParams.index_name"
|
||||||
|
:specifiedMsg="talkParams.specifiedMsg"
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
@ -544,7 +546,7 @@ const handleGroupNoticeModalShow = (isAdmin) => {
|
|||||||
@confirm="handleGroupNoticeModalConfirm"
|
@confirm="handleGroupNoticeModalConfirm"
|
||||||
@cancel="handleGroupNoticeModalCancel"
|
@cancel="handleGroupNoticeModalCancel"
|
||||||
:customCloseEvent="state.groupNoticeEditMode === 2 ? true : false"
|
:customCloseEvent="state.groupNoticeEditMode === 2 ? true : false"
|
||||||
@closeModal="handleGroupNoticeModalClose"
|
@customCloseModal="handleGroupNoticeModalClose"
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="group-notice-modal-content">
|
<div class="group-notice-modal-content">
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
NButton,
|
NButton,
|
||||||
NPagination
|
NPagination
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import { Search, Plus } from '@icon-park/vue-next'
|
import { Search, Plus, Right } from '@icon-park/vue-next'
|
||||||
import TalkItem from './TalkItem.vue'
|
import TalkItem from './TalkItem.vue'
|
||||||
import Skeleton from './Skeleton.vue'
|
import Skeleton from './Skeleton.vue'
|
||||||
import { ServeClearTalkUnreadNum } from '@/api/chat'
|
import { ServeClearTalkUnreadNum } from '@/api/chat'
|
||||||
@ -39,7 +39,7 @@ 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, ServeUserGroupChatList } from '@/api/search'
|
import { ServeSeachQueryAll, ServeQueryTalkRecord, ServeUserGroupChatList } from '@/api/search'
|
||||||
import { getUserInfoByERPUserId } from '@/api/user'
|
import { getUserInfoByERPUserId } from '@/api/user'
|
||||||
|
import HighlightText from '@/components/search/highLightText.vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@ -66,21 +66,10 @@ const renderChatAppSearch = () => {
|
|||||||
return h(
|
return h(
|
||||||
chatAppSearchList,
|
chatAppSearchList,
|
||||||
{
|
{
|
||||||
// searchResultKey: 'user_infos',
|
|
||||||
// searchItem: {
|
|
||||||
// avatar:
|
|
||||||
// 'https://e-cdn.fontree.cn/fonchain-main/prod/image/18248/avatar/a0b2bee7-947f-465a-986e-10a1b2b87032.png',
|
|
||||||
// created_at: '2025-03-27 14:44:23',
|
|
||||||
// erp_user_id: 18248,
|
|
||||||
// id: 44,
|
|
||||||
// mobile: '18994430450',
|
|
||||||
// nickname: '周俊耀'
|
|
||||||
// },
|
|
||||||
// searchText: '周'
|
|
||||||
searchResultPageSize: 3,
|
searchResultPageSize: 3,
|
||||||
listLimit: true,
|
listLimit: true,
|
||||||
apiRequest: ServeSeachQueryAll,
|
apiRequest: ServeSeachQueryAll,
|
||||||
searchText: '王',
|
searchText: searchKeyword.value,
|
||||||
onClickSearchItem: (searchText, searchResultKey, talk_type, receiver_id, res) => {
|
onClickSearchItem: (searchText, searchResultKey, talk_type, receiver_id, res) => {
|
||||||
console.log(searchText, searchResultKey, talk_type, receiver_id)
|
console.log(searchText, searchResultKey, talk_type, receiver_id)
|
||||||
const result = JSON.parse(decodeURIComponent(res))
|
const result = JSON.parse(decodeURIComponent(res))
|
||||||
@ -103,7 +92,29 @@ const renderChatAppSearch = () => {
|
|||||||
console.log(searchResultKey, searchText)
|
console.log(searchResultKey, searchText)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{}
|
{
|
||||||
|
'result-title': ({ getResultKeysValue, searchResultKey, searchResultIndex }) => {
|
||||||
|
return h(
|
||||||
|
'div',
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
padding: searchResultIndex === 0 ? '6px 10px 5px' : '18px 10px 5px',
|
||||||
|
borderBottom: '1px solid #f8f8f8'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h(
|
||||||
|
'span',
|
||||||
|
{
|
||||||
|
class: 'text-[14px] font-regular',
|
||||||
|
style: 'line-height: 20px; color: #999999;'
|
||||||
|
},
|
||||||
|
getResultKeysValue(searchResultKey)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +265,19 @@ const state = reactive({
|
|||||||
searchRecordText: '', // 搜索聊天记录文本
|
searchRecordText: '', // 搜索聊天记录文本
|
||||||
ServeQueryTalkRecordParams: '', // 搜索聊天记录参数
|
ServeQueryTalkRecordParams: '', // 搜索聊天记录参数
|
||||||
ServeQueryTalkRecordDetailParams: '', // 搜索聊天记录详情参数
|
ServeQueryTalkRecordDetailParams: '', // 搜索聊天记录详情参数
|
||||||
isShowSearchRecordDetailInfo: false // 是否显示搜索聊天记录详情
|
isShowSearchRecordDetailInfo: false, // 是否显示搜索聊天记录详情
|
||||||
|
// 拆分 searchList 和 searchDetailList 独立状态
|
||||||
|
searchList: {
|
||||||
|
searchText: '',
|
||||||
|
apiParams: '',
|
||||||
|
lastId: undefined as any
|
||||||
|
},
|
||||||
|
searchDetailList: {
|
||||||
|
searchText: '',
|
||||||
|
apiParams: '',
|
||||||
|
lastId: undefined as any,
|
||||||
|
total: 0
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const items = computed((): ISession[] => {
|
const items = computed((): ISession[] => {
|
||||||
@ -310,22 +333,31 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// watch(
|
// 监听搜索关键字变化,重置所有相关状态
|
||||||
// () => state.searchRecordText,
|
watch(
|
||||||
// (newValue, oldValue) => {
|
() => state.searchRecordText,
|
||||||
// console.log(newValue, 'newValue')
|
(newVal, oldVal) => {
|
||||||
// state.ServeQueryTalkRecordParams = encodeURIComponent(
|
// 重置左侧
|
||||||
// JSON.stringify({
|
state.searchList.searchText = newVal
|
||||||
// talk_type: 0, //1私聊2群聊
|
state.searchList.apiParams = encodeURIComponent(
|
||||||
// receiver_id: 0, //查详情的时候需传入
|
JSON.stringify({
|
||||||
// last_group_id: 0, //最后一条群id
|
talk_type: 0,
|
||||||
// last_member_id: 0, //最后一条用户id
|
receiver_id: 0,
|
||||||
// last_receiver_user_name: '', //最后一条用户名
|
last_group_id: 0,
|
||||||
// last_receiver_group_name: '' //最后一条群名
|
last_member_id: 0,
|
||||||
// })
|
last_receiver_user_name: '',
|
||||||
// )
|
last_receiver_group_name: ''
|
||||||
// }
|
})
|
||||||
// )
|
)
|
||||||
|
state.searchList.lastId = undefined
|
||||||
|
// 重置右侧
|
||||||
|
state.searchDetailList.searchText = newVal
|
||||||
|
state.searchDetailList.apiParams = ''
|
||||||
|
state.searchDetailList.lastId = undefined
|
||||||
|
// 关闭右侧详情
|
||||||
|
state.isShowSearchRecordDetailInfo = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// 列表加载状态
|
// 列表加载状态
|
||||||
const loadStatus = computed(() => talkStore.loadStatus)
|
const loadStatus = computed(() => talkStore.loadStatus)
|
||||||
@ -335,12 +367,14 @@ const indexName = computed(() => dialogueStore.index_name)
|
|||||||
|
|
||||||
// 切换会话
|
// 切换会话
|
||||||
const onTabTalk = (item: ISession, follow = false) => {
|
const onTabTalk = (item: ISession, follow = false) => {
|
||||||
console.log('onTabTalk');
|
console.log('onTabTalk')
|
||||||
|
|
||||||
if (item.index_name === indexName.value) return
|
if (item.index_name === indexName.value) return
|
||||||
|
|
||||||
searchKeyword.value = ''
|
searchKeyword.value = ''
|
||||||
|
|
||||||
|
dialogueStore.isManualSwitch = true
|
||||||
|
|
||||||
// 更新编辑信息
|
// 更新编辑信息
|
||||||
dialogueStore.setDialogue(item)
|
dialogueStore.setDialogue(item)
|
||||||
|
|
||||||
@ -565,19 +599,43 @@ const handleClickSearchItem = (searchText, searchResultKey, talk_type, receiver_
|
|||||||
const result = JSON.parse(decodeURIComponent(res))
|
const result = JSON.parse(decodeURIComponent(res))
|
||||||
console.log(result)
|
console.log(result)
|
||||||
if (searchResultKey === 'general_infos') {
|
if (searchResultKey === 'general_infos') {
|
||||||
state.ServeQueryTalkRecordDetailParams = encodeURIComponent(
|
// 先清空右侧
|
||||||
|
state.isShowSearchRecordDetailInfo = false
|
||||||
|
state.searchDetailList.apiParams = encodeURIComponent(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
last_group_id: 0, //最后一条群id
|
last_group_id: 0,
|
||||||
last_member_id: 0, //最后一条用户id
|
last_member_id: 0,
|
||||||
receiver_id: receiver_id, //查详情的时候需传入
|
receiver_id: receiver_id,
|
||||||
talk_type: talk_type //1私聊2群聊
|
talk_type: talk_type
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
state.searchDetailList.searchText = state.searchRecordText
|
||||||
|
state.searchDetailList.lastId = undefined
|
||||||
|
// 再显示
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
searchDetailListRef.value?.doLoadMore(true)
|
state.isShowSearchRecordDetailInfo = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//处理点击搜索结果item
|
||||||
|
const handleClickSearchResultItem = (searchText, searchResultKey, talk_type, receiver_id, res) => {
|
||||||
|
const result = JSON.parse(decodeURIComponent(res))
|
||||||
|
console.error(result, 'result')
|
||||||
|
// 根据搜索结果, 指定用于查询指定消息上下文的sequence
|
||||||
|
dialogueStore.specifiedMsg = encodeURIComponent(
|
||||||
|
JSON.stringify({
|
||||||
|
talk_type,
|
||||||
|
receiver_id,
|
||||||
|
msg_id: result.msg_id,
|
||||||
|
cursor: result.sequence - 15 > 0 ? result.sequence - 15 : 0,
|
||||||
|
direction: 'down',
|
||||||
|
sort_sequence: 'asc',
|
||||||
|
create_time: result.created_at
|
||||||
|
})
|
||||||
|
)
|
||||||
|
console.error(dialogueStore.specifiedMsg, 'dialogueStore.specifiedMsg')
|
||||||
|
talkStore.toTalk(talk_type, receiver_id, router)
|
||||||
|
}
|
||||||
//处理点击停留item变化
|
//处理点击停留item变化
|
||||||
const handleClickStayItemChange = (item) => {
|
const handleClickStayItemChange = (item) => {
|
||||||
if (item) {
|
if (item) {
|
||||||
@ -593,53 +651,63 @@ const searchListRef = ref()
|
|||||||
// 定义搜索详情列表组件的ref
|
// 定义搜索详情列表组件的ref
|
||||||
const searchDetailListRef = ref()
|
const searchDetailListRef = ref()
|
||||||
|
|
||||||
//搜索聊天记录列表加载更多
|
// lastIdChange 事件区分来源
|
||||||
const loadMoreRecordList = () => {
|
const handleSearchListLastIdChange = (
|
||||||
searchListRef.value?.doLoadMore()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索聊天记录详情列表加载更多
|
|
||||||
const loadMoreRecordDetail = () => {
|
|
||||||
searchDetailListRef.value?.doLoadMore()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleMoreRecordLastIdChange = (
|
|
||||||
last_id,
|
last_id,
|
||||||
last_group_id,
|
last_group_id,
|
||||||
last_member_id,
|
last_member_id,
|
||||||
last_receiver_user_name,
|
last_receiver_user_name,
|
||||||
last_receiver_group_name
|
last_receiver_group_name
|
||||||
) => {
|
) => {
|
||||||
let idChanges = {
|
state.searchList.lastId = {
|
||||||
last_id,
|
last_id,
|
||||||
last_group_id,
|
last_group_id,
|
||||||
last_member_id,
|
last_member_id,
|
||||||
last_receiver_user_name,
|
last_receiver_user_name,
|
||||||
last_receiver_group_name
|
last_receiver_group_name
|
||||||
}
|
}
|
||||||
state.ServeQueryTalkRecordParams = encodeURIComponent(
|
state.searchList.apiParams = encodeURIComponent(
|
||||||
JSON.stringify(
|
JSON.stringify({
|
||||||
Object.assign({}, JSON.parse(decodeURIComponent(state.ServeQueryTalkRecordParams)), idChanges)
|
...JSON.parse(decodeURIComponent(state.searchList.apiParams)),
|
||||||
)
|
last_id,
|
||||||
|
last_group_id,
|
||||||
|
last_member_id,
|
||||||
|
last_receiver_user_name,
|
||||||
|
last_receiver_group_name
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const handleSearchDetailListLastIdChange = (last_id, last_group_id, last_member_id) => {
|
||||||
const handleRecordDetailLastIdChange = (last_id, last_group_id, last_member_id) => {
|
state.searchDetailList.lastId = { last_id, last_group_id, last_member_id }
|
||||||
let idChanges = {
|
state.searchDetailList.apiParams = encodeURIComponent(
|
||||||
|
JSON.stringify({
|
||||||
|
...JSON.parse(decodeURIComponent(state.searchDetailList.apiParams)),
|
||||||
last_id,
|
last_id,
|
||||||
last_group_id,
|
last_group_id,
|
||||||
last_member_id
|
last_member_id
|
||||||
}
|
})
|
||||||
state.ServeQueryTalkRecordDetailParams = encodeURIComponent(
|
|
||||||
JSON.stringify(
|
|
||||||
Object.assign(
|
|
||||||
{},
|
|
||||||
JSON.parse(decodeURIComponent(state.ServeQueryTalkRecordDetailParams)),
|
|
||||||
idChanges
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关闭搜索聊天记录模态框
|
||||||
|
const handleCloseSearchRecordModal = () => {
|
||||||
|
state.isShowSearchRecordModal = false
|
||||||
|
state.searchRecordText = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取搜索结果总数
|
||||||
|
const getResultTotalCount = (total) => {
|
||||||
|
state.searchDetailList.total = total
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进入搜索结果聊天
|
||||||
|
const handleEnterSearchResultChat = () => {
|
||||||
|
const searchResult = JSON.parse(decodeURIComponent(state.searchDetailList.apiParams))
|
||||||
|
talkStore.toTalk(searchResult.talk_type, searchResult.receiver_id, router)
|
||||||
|
state.isShowSearchRecordModal = false
|
||||||
|
state.searchRecordText = ''
|
||||||
|
searchKeyword.value = ''
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -660,7 +728,7 @@ const handleRecordDetailLastIdChange = (last_id, last_group_id, last_member_id)
|
|||||||
<n-dropdown
|
<n-dropdown
|
||||||
trigger="click"
|
trigger="click"
|
||||||
:options="state.chatSearchOptions"
|
:options="state.chatSearchOptions"
|
||||||
style="width: 248px; height: 677px; overflow-y: scroll;"
|
style="width: 248px; height: 677px;"
|
||||||
>
|
>
|
||||||
<n-input
|
<n-input
|
||||||
placeholder="搜索好友 / 群聊"
|
placeholder="搜索好友 / 群聊"
|
||||||
@ -854,6 +922,8 @@ const handleRecordDetailLastIdChange = (last_id, last_group_id, last_member_id)
|
|||||||
:style="state.customSearchRecordModalStyle"
|
:style="state.customSearchRecordModalStyle"
|
||||||
:customCloseBtn="true"
|
:customCloseBtn="true"
|
||||||
:closable="false"
|
:closable="false"
|
||||||
|
:customCloseEvent="true"
|
||||||
|
@customCloseModal="handleCloseSearchRecordModal"
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="search-record-modal-content">
|
<div class="search-record-modal-content">
|
||||||
@ -872,34 +942,54 @@ const handleRecordDetailLastIdChange = (last_id, last_group_id, last_member_id)
|
|||||||
</n-input>
|
</n-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-record-card" v-if="state.searchRecordText">
|
<div class="search-record-card" v-if="state.searchRecordText">
|
||||||
<div class="search-record-list" v-loadmore="loadMoreRecordList">
|
<div class="search-record-list">
|
||||||
<chatAppSearchList
|
<chatAppSearchList
|
||||||
ref="searchListRef"
|
ref="searchListRef"
|
||||||
:searchResultPageSize="10"
|
:searchResultPageSize="10"
|
||||||
:listLimit="false"
|
:listLimit="false"
|
||||||
:apiRequest="ServeQueryTalkRecord"
|
:apiRequest="ServeQueryTalkRecord"
|
||||||
:apiParams="state.ServeQueryTalkRecordParams"
|
:apiParams="state.searchList.apiParams"
|
||||||
:searchText="state.searchRecordText"
|
:searchText="state.searchList.searchText"
|
||||||
:isPagination="true"
|
:isPagination="true"
|
||||||
searchResultKey="general_infos"
|
searchResultKey="general_infos"
|
||||||
@clickSearchItem="handleClickSearchItem"
|
@clickSearchItem="handleClickSearchItem"
|
||||||
:useClickStay="true"
|
:useClickStay="true"
|
||||||
@clickStayItemChange="handleClickStayItemChange"
|
@clickStayItemChange="handleClickStayItemChange"
|
||||||
@lastIdChange="handleMoreRecordLastIdChange"
|
@lastIdChange="handleSearchListLastIdChange"
|
||||||
|
:searchResultMaxHeight="'517px'"
|
||||||
></chatAppSearchList>
|
></chatAppSearchList>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-record-detail" v-loadmore="loadMoreRecordDetail">
|
<div class="search-record-detail">
|
||||||
|
<div class="search-record-detail-header" v-if="state.isShowSearchRecordDetailInfo">
|
||||||
|
<HighlightText
|
||||||
|
class="text-[14px] text-[#B0B0B0] leading-[20px]"
|
||||||
|
:text="
|
||||||
|
state.searchDetailList.total +
|
||||||
|
'条与“' +
|
||||||
|
state.searchRecordText +
|
||||||
|
'”相关的搜索结果'
|
||||||
|
"
|
||||||
|
:searchText="state.searchRecordText"
|
||||||
|
/>
|
||||||
|
<div class="search-record-detail-header-btn" @click="handleEnterSearchResultChat">
|
||||||
|
<span>进入聊天</span>
|
||||||
|
<n-icon :component="Right" color="#46299D" size="14px" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<chatAppSearchList
|
<chatAppSearchList
|
||||||
ref="searchDetailListRef"
|
ref="searchDetailListRef"
|
||||||
v-if="state.isShowSearchRecordDetailInfo"
|
v-if="state.isShowSearchRecordDetailInfo"
|
||||||
:searchResultPageSize="10"
|
:searchResultPageSize="10"
|
||||||
:listLimit="false"
|
:listLimit="false"
|
||||||
:apiRequest="ServeQueryTalkRecord"
|
:apiRequest="ServeQueryTalkRecord"
|
||||||
:apiParams="state.ServeQueryTalkRecordDetailParams"
|
:apiParams="state.searchDetailList.apiParams"
|
||||||
:searchText="state.searchRecordText"
|
:searchText="state.searchDetailList.searchText"
|
||||||
:isPagination="true"
|
:isPagination="true"
|
||||||
:searchRecordDetail="true"
|
:searchRecordDetail="true"
|
||||||
@lastIdChange="handleRecordDetailLastIdChange"
|
@lastIdChange="handleSearchDetailListLastIdChange"
|
||||||
|
:searchResultMaxHeight="'469px'"
|
||||||
|
@resultTotalCount="getResultTotalCount"
|
||||||
|
@clickSearchItem="handleClickSearchResultItem"
|
||||||
></chatAppSearchList>
|
></chatAppSearchList>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1094,13 +1184,33 @@ html[theme-mode='dark'] {
|
|||||||
width: 260px;
|
width: 260px;
|
||||||
height: 517px;
|
height: 517px;
|
||||||
border: 1px solid #efeff5;
|
border: 1px solid #efeff5;
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
}
|
||||||
.search-record-detail {
|
.search-record-detail {
|
||||||
width: 578px;
|
width: 578px;
|
||||||
height: 517px;
|
height: 517px;
|
||||||
border: 1px solid #efeff5;
|
border: 1px solid #efeff5;
|
||||||
overflow-y: scroll;
|
.search-record-detail-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 14px 4px 14px 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
.search-record-detail-header-btn {
|
||||||
|
line-height: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
span {
|
||||||
|
line-height: 20px;
|
||||||
|
color: #46299d;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.search-record-empty {
|
.search-record-empty {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useDialogueStore } from '@/store'
|
import { useDialogueStore } from '@/store'
|
||||||
import { Share, ShareThree, Delete, Close } from '@icon-park/vue-next'
|
import {confirmBox} from '@/components/confirm-box/service.js'
|
||||||
|
|
||||||
import ContactModal from '@/components/user/ContactModal.vue'
|
import ContactModal from '@/components/user/ContactModal.vue'
|
||||||
|
|
||||||
@ -31,12 +31,19 @@ const onSingleForward = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onMultiDelete = () => {
|
const onMultiDelete = () => {
|
||||||
// 批量删除
|
confirmBox({
|
||||||
|
content:'确定删除聊天记录',
|
||||||
|
confirmText:'删除'
|
||||||
|
}).then(()=>{
|
||||||
let msgIds = dialogueStore.selectItems.map((item: any) => item.msg_id)
|
let msgIds = dialogueStore.selectItems.map((item: any) => item.msg_id)
|
||||||
|
|
||||||
if (!msgIds.length) return
|
if (!msgIds.length) return
|
||||||
|
|
||||||
|
dialogueStore.ApiDeleteRecord(msgIds)
|
||||||
|
|
||||||
|
})
|
||||||
|
// 批量删除
|
||||||
|
|
||||||
dialogueStore.ApiDeleteRecord(msgIds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onContactModal = (data: { receiver_id: number; talk_type: number }[]) => {
|
const onContactModal = (data: { receiver_id: number; talk_type: number }[]) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { watch, onMounted, ref } from 'vue'
|
import { watch, onMounted, ref, nextTick } from 'vue'
|
||||||
import { NDropdown, NCheckbox } from 'naive-ui'
|
import { NDropdown, NCheckbox } from 'naive-ui'
|
||||||
import { Loading, MoreThree, ToTop } from '@icon-park/vue-next'
|
import { Loading, MoreThree, ToTop } from '@icon-park/vue-next'
|
||||||
import { bus } from '@/utils/event-bus'
|
import { bus } from '@/utils/event-bus'
|
||||||
@ -13,10 +13,11 @@ import SkipBottom from './SkipBottom.vue'
|
|||||||
import { ITalkRecord } from '@/types/chat'
|
import { ITalkRecord } from '@/types/chat'
|
||||||
import { EditorConst } from '@/constant/event-bus'
|
import { EditorConst } from '@/constant/event-bus'
|
||||||
import { useInject, useTalkRecord, useUtil } from '@/hooks'
|
import { useInject, useTalkRecord, useUtil } from '@/hooks'
|
||||||
import { ExclamationCircleFilled } from '@ant-design/icons-vue';
|
import { ExclamationCircleFilled } from '@ant-design/icons-vue'
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import RevokeMessage from '@/components/talk/message/RevokeMessage.vue'
|
import RevokeMessage from '@/components/talk/message/RevokeMessage.vue'
|
||||||
import { voiceToText } from '@/api/chat.js'
|
import { voiceToText } from '@/api/chat.js'
|
||||||
|
import {confirmBox} from '@/components/confirm-box/service.js'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
uid: {
|
uid: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@ -33,6 +34,10 @@ const props = defineProps({
|
|||||||
index_name: {
|
index_name: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
specifiedMsg: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -237,15 +242,15 @@ const onContextMenu = (e: any, item: ITalkRecord) => {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onConvertText =async (data: ITalkRecord) => {
|
const onConvertText = async (data: ITalkRecord) => {
|
||||||
console.log('data',data)
|
console.log('data', data)
|
||||||
data.is_convert_text = 1
|
data.is_convert_text = 1
|
||||||
const res = await voiceToText({msgId:data.msg_id,voiceUrl:data.extra.url})
|
const res = await voiceToText({ msgId: data.msg_id, voiceUrl: data.extra.url })
|
||||||
if(res.code == 200){
|
if (res.code == 200) {
|
||||||
data.extra.content = res.data.convText
|
data.extra.content = res.data.convText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const onloseConvertText=(data: ITalkRecord)=>{
|
const onloseConvertText = (data: ITalkRecord) => {
|
||||||
data.is_convert_text = 0
|
data.is_convert_text = 0
|
||||||
}
|
}
|
||||||
const evnets = {
|
const evnets = {
|
||||||
@ -257,7 +262,7 @@ const evnets = {
|
|||||||
quote: onQuoteMessage,
|
quote: onQuoteMessage,
|
||||||
collect: onCollectImage,
|
collect: onCollectImage,
|
||||||
convertText: onConvertText,
|
convertText: onConvertText,
|
||||||
closeConvertText:onloseConvertText
|
closeConvertText: onloseConvertText
|
||||||
}
|
}
|
||||||
|
|
||||||
// 会话列表右键菜单回调事件
|
// 会话列表右键菜单回调事件
|
||||||
@ -277,18 +282,55 @@ const onRowClick = (item: ITalkRecord) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(props, () => {
|
const lastParams = ref('')
|
||||||
onLoad({ ...props, limit: 30 })
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
// 监听整个 props 对象的变化
|
||||||
onLoad({ ...props, limit: 30 })
|
watch(
|
||||||
})
|
() => props,
|
||||||
|
async (newProps) => {
|
||||||
|
await nextTick()
|
||||||
|
let specialParams = undefined
|
||||||
|
console.error(newProps, 'newProps')
|
||||||
|
if (newProps.specifiedMsg) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(decodeURIComponent(newProps.specifiedMsg))
|
||||||
|
// 只有会话id和参数都匹配才进入特殊模式
|
||||||
|
if (parsed.talk_type === newProps.talk_type && parsed.receiver_id === newProps.receiver_id) {
|
||||||
|
specialParams = parsed
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
onLoad(
|
||||||
|
{
|
||||||
|
receiver_id: newProps.receiver_id,
|
||||||
|
talk_type: newProps.talk_type,
|
||||||
|
limit: 30
|
||||||
|
},
|
||||||
|
specialParams ? { specifiedMsg: specialParams } : undefined
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// onMounted(() => {
|
||||||
|
// onLoad({ ...props, limit: 30 })
|
||||||
|
// })
|
||||||
|
const retry=(item:any)=>{
|
||||||
|
confirmBox({
|
||||||
|
content:'确定重发吗'
|
||||||
|
}).then(()=>{
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<div id="imChatPanel" class="me-scrollbar me-scrollbar-thumb talk-container" @scroll="onPanelScroll($event)">
|
<div
|
||||||
|
id="imChatPanel"
|
||||||
|
class="me-scrollbar me-scrollbar-thumb talk-container"
|
||||||
|
@scroll="onPanelScroll($event)"
|
||||||
|
>
|
||||||
<!-- 数据加载状态栏 -->
|
<!-- 数据加载状态栏 -->
|
||||||
<div class="load-toolbar pointer">
|
<div class="load-toolbar pointer">
|
||||||
<span v-if="loadConfig.status == 0"> 正在加载数据中 ... </span>
|
<span v-if="loadConfig.status == 0"> 正在加载数据中 ... </span>
|
||||||
@ -296,23 +338,42 @@ onMounted(() => {
|
|||||||
<span v-else class="no-more"> 没有更多消息了 </span>
|
<span v-else class="no-more"> 没有更多消息了 </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="message-item" v-for="(item, index) in records" :key="item.msg_id" :id="item.msg_id">
|
<div
|
||||||
|
class="message-item"
|
||||||
|
v-for="(item, index) in records"
|
||||||
|
:key="item.msg_id"
|
||||||
|
:id="item.msg_id"
|
||||||
|
>
|
||||||
<!-- 系统消息 -->
|
<!-- 系统消息 -->
|
||||||
<div v-if="item.msg_type >= 1000" class="message-box">
|
<div v-if="item.msg_type >= 1000" class="message-box">
|
||||||
<component :is="MessageComponents[item.msg_type] || 'unknown-message'" :extra="item.extra" :data="item" />
|
<component
|
||||||
|
:is="MessageComponents[item.msg_type] || 'unknown-message'"
|
||||||
|
:extra="item.extra"
|
||||||
|
:data="item"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 撤回消息 -->
|
<!-- 撤回消息 -->
|
||||||
<div v-else-if="item.is_revoke == 1" class="message-box">
|
<div v-else-if="item.is_revoke == 1" class="message-box">
|
||||||
<revoke-message :login_uid="uid" :data="item" :user_id="item.user_id" :nickname="item.nickname" :talk_type="item.talk_type"
|
<revoke-message
|
||||||
:datetime="item.created_at" />
|
:login_uid="uid"
|
||||||
|
:data="item"
|
||||||
|
:user_id="item.user_id"
|
||||||
|
:nickname="item.nickname"
|
||||||
|
:talk_type="item.talk_type"
|
||||||
|
:datetime="item.created_at"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="message-box record-box" :class="{
|
<div
|
||||||
|
v-else
|
||||||
|
class="message-box record-box"
|
||||||
|
:class="{
|
||||||
'direction-rt': item.float == 'right',
|
'direction-rt': item.float == 'right',
|
||||||
'multi-select': dialogueStore.isOpenMultiSelect,
|
'multi-select': dialogueStore.isOpenMultiSelect,
|
||||||
'multi-select-check': item.isCheck
|
'multi-select-check': item.isCheck
|
||||||
}">
|
}"
|
||||||
|
>
|
||||||
<!-- 多选按钮 -->
|
<!-- 多选按钮 -->
|
||||||
<aside v-if="dialogueStore.isOpenMultiSelect" class="checkbox-column shrink-0">
|
<aside v-if="dialogueStore.isOpenMultiSelect" class="checkbox-column shrink-0">
|
||||||
<n-checkbox size="small" :checked="item.isCheck" @update:checked="item.isCheck = !item.isCheck" />
|
<n-checkbox size="small" :checked="item.isCheck" @update:checked="item.isCheck = !item.isCheck" />
|
||||||
@ -320,29 +381,53 @@ onMounted(() => {
|
|||||||
<!-- 头像信息 -->
|
<!-- 头像信息 -->
|
||||||
|
|
||||||
<aside class="avatar-column">
|
<aside class="avatar-column">
|
||||||
<im-avatar class="pointer" :src="item.avatar" :size="42" :username="item.nickname"
|
<im-avatar
|
||||||
@click="showUserInfoModal(item.erp_user_id,item.user_id)" />
|
class="pointer"
|
||||||
|
:src="item.avatar"
|
||||||
|
:size="42"
|
||||||
|
:username="item.nickname"
|
||||||
|
@click="showUserInfoModal(item.erp_user_id, item.user_id)"
|
||||||
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!-- 主体信息 -->
|
<!-- 主体信息 -->
|
||||||
<main class="main-column">
|
<main class="main-column">
|
||||||
<div class="talk-title">
|
<div class="talk-title">
|
||||||
<span class="nickname pointer" v-show="talk_type == 2 && item.float == 'left'"
|
<span
|
||||||
@click="onClickNickname(item)">
|
class="nickname pointer"
|
||||||
|
v-show="talk_type == 2 && item.float == 'left'"
|
||||||
|
@click="onClickNickname(item)"
|
||||||
|
>
|
||||||
<span class="at">@</span>{{ item.nickname }}
|
<span class="at">@</span>{{ item.nickname }}
|
||||||
</span>
|
</span>
|
||||||
<span>{{ parseTime(item.created_at, '{y}/{m}/{d} {h}:{i}') }}</span>
|
<span>{{ parseTime(item.created_at, '{y}/{m}/{d} {h}:{i}') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="talk-content" :class="{ pointer: dialogueStore.isOpenMultiSelect }" @click="onRowClick(item)">
|
<div
|
||||||
|
class="talk-content"
|
||||||
<component :is="MessageComponents[item.msg_type] || 'unknown-message'" :extra="item.extra" :data="item"
|
:class="{ pointer: dialogueStore.isOpenMultiSelect }"
|
||||||
:max-width="true" :source="'panel'" @contextmenu.prevent="onContextMenu($event, item)" />
|
@click="onRowClick(item)"
|
||||||
<div v-if="item.float==='right'&&item.extra.percentage===-1&&item.extra.is_uploading" class="mr-10px"> <n-button text style="font-size: 20px">
|
>
|
||||||
|
<component
|
||||||
|
:is="MessageComponents[item.msg_type] || 'unknown-message'"
|
||||||
|
:extra="item.extra"
|
||||||
|
:data="item"
|
||||||
|
:max-width="true"
|
||||||
|
:source="'panel'"
|
||||||
|
@contextmenu.prevent="onContextMenu($event, item)"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
item.float === 'right' && item.extra.percentage === -1 && item.extra.is_uploading
|
||||||
|
"
|
||||||
|
class="mr-10px"
|
||||||
|
>
|
||||||
|
<n-button text style="font-size: 20px;" @click="retry(item)">
|
||||||
<n-icon color="#CF3050">
|
<n-icon color="#CF3050">
|
||||||
<ExclamationCircleFilled />
|
<ExclamationCircleFilled />
|
||||||
</n-icon>
|
</n-icon>
|
||||||
</n-button></div>
|
</n-button>
|
||||||
|
</div>
|
||||||
<!-- <div class="talk-tools">
|
<!-- <div class="talk-tools">
|
||||||
<template v-if="talk_type == 1 && item.float == 'right'">
|
<template v-if="talk_type == 1 && item.float == 'right'">
|
||||||
<loading
|
<loading
|
||||||
@ -362,7 +447,11 @@ onMounted(() => {
|
|||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="item.extra.reply" class="talk-reply pointer" @click="onJumpMessage(item.extra?.reply?.msg_id)">
|
<div
|
||||||
|
v-if="item.extra.reply"
|
||||||
|
class="talk-reply pointer"
|
||||||
|
@click="onJumpMessage(item.extra?.reply?.msg_id)"
|
||||||
|
>
|
||||||
<n-icon :component="ToTop" size="14" class="icon-top" />
|
<n-icon :component="ToTop" size="14" class="icon-top" />
|
||||||
<span class="ellipsis">
|
<span class="ellipsis">
|
||||||
回复 {{ item.extra?.reply?.nickname }}:
|
回复 {{ item.extra?.reply?.nickname }}:
|
||||||
@ -383,8 +472,15 @@ onMounted(() => {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- 右键菜单 -->
|
<!-- 右键菜单 -->
|
||||||
<n-dropdown :show="dropdown.show" :x="dropdown.x" :y="dropdown.y" style="width: 142px;" :options="dropdown.options"
|
<n-dropdown
|
||||||
@select="onContextMenuHandle" @clickoutside="closeDropdownMenu" />
|
:show="dropdown.show"
|
||||||
|
:x="dropdown.x"
|
||||||
|
:y="dropdown.y"
|
||||||
|
style="width: 142px;"
|
||||||
|
:options="dropdown.options"
|
||||||
|
@select="onContextMenuHandle"
|
||||||
|
@clickoutside="closeDropdownMenu"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -116,15 +116,13 @@ const onSendVideoEvent = async ({ data }) => {
|
|||||||
msg_type: 5, // 视频消息类型
|
msg_type: 5, // 视频消息类型
|
||||||
user_id: props.uid,
|
user_id: props.uid,
|
||||||
receiver_id: props.receiver_id,
|
receiver_id: props.receiver_id,
|
||||||
nickname: '我', // 本地显示
|
|
||||||
avatar: userStore.avatar, // 本地显示可能不需要
|
|
||||||
is_revoke: 0,
|
is_revoke: 0,
|
||||||
is_mark: 0,
|
is_mark: 0,
|
||||||
is_read: 1,
|
is_read: 1,
|
||||||
content: '',
|
content: '',
|
||||||
created_at: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'),
|
created_at: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'),
|
||||||
extra: {
|
extra: {
|
||||||
url: '', // 上传完成后会更新
|
url: '',
|
||||||
size: data.size,
|
size: data.size,
|
||||||
is_uploading: true,
|
is_uploading: true,
|
||||||
upload_id: uploadId,
|
upload_id: uploadId,
|
||||||
@ -141,35 +139,12 @@ const onSendVideoEvent = async ({ data }) => {
|
|||||||
data,
|
data,
|
||||||
props.talk_type,
|
props.talk_type,
|
||||||
props.receiver_id,
|
props.receiver_id,
|
||||||
dialogueStore.talk.username,
|
|
||||||
uploadId,
|
uploadId,
|
||||||
async (percentage) => {
|
async (percentage) => {
|
||||||
dialogueStore.updateUploadProgress(uploadId, percentage)
|
dialogueStore.updateUploadProgress(uploadId, percentage)
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
dialogueStore.batchDelDialogueRecord([uploadId])
|
dialogueStore.batchDelDialogueRecord([uploadId])
|
||||||
// console.log('videoData', videoData)
|
|
||||||
// // 上传完成后的回调
|
|
||||||
|
|
||||||
// // 更新临时消息为最终消息
|
|
||||||
// dialogueStore.completeUpload(uploadId, {
|
|
||||||
// url: videoData.data.ori_url,
|
|
||||||
// cover: videoData.data.cover_url
|
|
||||||
// })
|
|
||||||
|
|
||||||
// // 上传成功后,发送正式消息给服务端
|
|
||||||
// let finalMessage = {
|
|
||||||
// type: 'video',
|
|
||||||
// url: videoData.data.ori_url,
|
|
||||||
|
|
||||||
// size: data.size
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 发送真实消息到服务端
|
|
||||||
// onSendMessage(finalMessage, () => {
|
|
||||||
// // 上传成功且消息发送成功后,删除临时消息
|
|
||||||
// dialogueStore.batchDelDialogueRecord([uploadId])
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -185,10 +160,10 @@ const onSendFileEvent = ({ data }) => {
|
|||||||
if (data.size > maxsize) {
|
if (data.size > maxsize) {
|
||||||
return window['$message'].warning('上传文件不能超过100M!')
|
return window['$message'].warning('上传文件不能超过100M!')
|
||||||
}
|
}
|
||||||
const uploadId = `file-${Date.now()}-${Math.floor(Math.random() * 1000)}`
|
const clientUploadId = `file-${Date.now()}-${Math.floor(Math.random() * 1000)}`
|
||||||
|
|
||||||
const tempMessage = {
|
const tempMessage = {
|
||||||
msg_id: uploadId,
|
msg_id: clientUploadId,
|
||||||
sequence: Date.now(),
|
sequence: Date.now(),
|
||||||
talk_type: props.talk_type,
|
talk_type: props.talk_type,
|
||||||
msg_type: 6,
|
msg_type: 6,
|
||||||
@ -204,20 +179,19 @@ const onSendFileEvent = ({ data }) => {
|
|||||||
url: '',
|
url: '',
|
||||||
size: data.size,
|
size: data.size,
|
||||||
is_uploading: true,
|
is_uploading: true,
|
||||||
upload_id: uploadId,
|
upload_id: clientUploadId,
|
||||||
percentage: 0
|
percentage: 0
|
||||||
},
|
},
|
||||||
erp_user_id: 4692,
|
|
||||||
float: 'right'
|
float: 'right'
|
||||||
}
|
}
|
||||||
dialogueStore.addDialogueRecord(tempMessage)
|
dialogueStore.addDialogueRecord(tempMessage)
|
||||||
|
|
||||||
uploadsStore.initUploadFile(data, props.talk_type, props.receiver_id, dialogueStore.talk.username,uploadId,
|
uploadsStore.initUploadFile(data, props.talk_type, props.receiver_id,clientUploadId,
|
||||||
async (percentage) => {
|
async (percentage) => {
|
||||||
dialogueStore.updateUploadProgress(uploadId, percentage)
|
dialogueStore.updateUploadProgress(clientUploadId, percentage)
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
dialogueStore.batchDelDialogueRecord([uploadId])
|
dialogueStore.batchDelDialogueRecord([clientUploadId])
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ export default defineConfig(({ mode }) => {
|
|||||||
compressPlugin(),
|
compressPlugin(),
|
||||||
UnoCSS(),
|
UnoCSS(),
|
||||||
vueDevTools({
|
vueDevTools({
|
||||||
launchEditor: 'cursor',
|
launchEditor: 'trae',
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
define: {
|
define: {
|
||||||
|
Loading…
Reference in New Issue
Block a user