Compare commits
19 Commits
96c4fbaad9
...
31dcd0ebca
Author | SHA1 | Date | |
---|---|---|---|
|
31dcd0ebca | ||
|
c374154f0f | ||
|
dd3e217bb1 | ||
e7ec387735 | |||
6140c625e4 | |||
99ffb6ec05 | |||
f17250f236 | |||
e904dae8a0 | |||
66e95da62e | |||
fea7504a91 | |||
2676e70c0c | |||
f9f7e6e45d | |||
|
fdf71eb4da | ||
1f4c5ba6df | |||
3642d3e2fa | |||
8ed2bf7113 | |||
17d9ed737d | |||
04dcbdf331 | |||
fa2098c565 |
3
components.d.ts
vendored
3
components.d.ts
vendored
@ -8,6 +8,8 @@ export {}
|
|||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
AsyncError: typeof import('./src/components/async-error/index.vue')['default']
|
||||||
|
AsyncLoading: typeof import('./src/components/async-loading/index.vue')['default']
|
||||||
AudioMessage: typeof import('./src/components/talk/message/AudioMessage.vue')['default']
|
AudioMessage: typeof import('./src/components/talk/message/AudioMessage.vue')['default']
|
||||||
Avatar: typeof import('./src/components/base/Avatar.vue')['default']
|
Avatar: typeof import('./src/components/base/Avatar.vue')['default']
|
||||||
AvatarCropper: typeof import('./src/components/base/AvatarCropper.vue')['default']
|
AvatarCropper: typeof import('./src/components/base/AvatarCropper.vue')['default']
|
||||||
@ -37,6 +39,7 @@ declare module 'vue' {
|
|||||||
SysGroupAdminMessage: typeof import('./src/components/talk/message/system/SysGroupAdminMessage.vue')['default']
|
SysGroupAdminMessage: typeof import('./src/components/talk/message/system/SysGroupAdminMessage.vue')['default']
|
||||||
SysGroupCancelMutedMessage: typeof import('./src/components/talk/message/system/SysGroupCancelMutedMessage.vue')['default']
|
SysGroupCancelMutedMessage: typeof import('./src/components/talk/message/system/SysGroupCancelMutedMessage.vue')['default']
|
||||||
SysGroupCreateMessage: typeof import('./src/components/talk/message/system/SysGroupCreateMessage.vue')['default']
|
SysGroupCreateMessage: typeof import('./src/components/talk/message/system/SysGroupCreateMessage.vue')['default']
|
||||||
|
SysGroupDismissed: typeof import('./src/components/talk/message/system/SysGroupDismissed.vue')['default']
|
||||||
SysGroupInfoChangeMessage: typeof import('./src/components/talk/message/system/SysGroupInfoChangeMessage.vue')['default']
|
SysGroupInfoChangeMessage: typeof import('./src/components/talk/message/system/SysGroupInfoChangeMessage.vue')['default']
|
||||||
SysGroupJoinMessage: typeof import('./src/components/talk/message/system/SysGroupJoinMessage.vue')['default']
|
SysGroupJoinMessage: typeof import('./src/components/talk/message/system/SysGroupJoinMessage.vue')['default']
|
||||||
SysGroupMemberCancelMutedMessage: typeof import('./src/components/talk/message/system/SysGroupMemberCancelMutedMessage.vue')['default']
|
SysGroupMemberCancelMutedMessage: typeof import('./src/components/talk/message/system/SysGroupMemberCancelMutedMessage.vue')['default']
|
||||||
|
7
env/.env.prod
vendored
7
env/.env.prod
vendored
@ -5,4 +5,9 @@ VITE_SHOW_CONSOLE = false
|
|||||||
# 是否开启sourcemap
|
# 是否开启sourcemap
|
||||||
VITE_SHOW_SOURCEMAP = false
|
VITE_SHOW_SOURCEMAP = false
|
||||||
# baseUrl
|
# baseUrl
|
||||||
VITE_BASEURL = 'https://oa-a.szjixun.cn/api'
|
VITE_BASEURL = 'https://chat-out.szjixun.cn' #体制外
|
||||||
|
#VITE_SOCKET_API
|
||||||
|
VITE_SOCKET_API = 'wss://chat-out.szjixun.cn' #体制外
|
||||||
|
# EPRAPI baseUrl
|
||||||
|
VITE_EPR_BASEURL = 'https://erpapi-out.szjixun.cn' #体制外
|
||||||
|
|
||||||
|
11
src/App.vue
11
src/App.vue
@ -1,10 +1,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useStatus } from '@/store/status'
|
import { useStatus } from '@/store/status'
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore, useDialogueListStore } from '@/store'
|
||||||
import { useProvideUserModal } from '@/hooks'
|
import { useProvideUserModal } from '@/hooks'
|
||||||
import {useAuth} from "@/store/auth";
|
import {useAuth} from "@/store/auth";
|
||||||
const {token} = useAuth()
|
const {token} = useAuth()
|
||||||
import ws from '@/connect'
|
import ws from '@/connect'
|
||||||
|
import {uniStorage} from "@/utils/uniStorage.js"
|
||||||
const { statusBarHeight } = useStatus()
|
const { statusBarHeight } = useStatus()
|
||||||
const { uid, isShow } = useProvideUserModal()
|
const { uid, isShow } = useProvideUserModal()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
@ -19,10 +20,14 @@ const handleWebview = () => {
|
|||||||
// })
|
// })
|
||||||
console.log("webview", webview)
|
console.log("webview", webview)
|
||||||
token.value = webview.token
|
token.value = webview.token
|
||||||
}
|
if(webview?.doClearDialogueList){
|
||||||
const init = () => {
|
useDialogueListStore().dialogueList.value = []
|
||||||
|
uniStorage.removeItem('dialogueList')
|
||||||
|
}
|
||||||
userStore.loadSetting()
|
userStore.loadSetting()
|
||||||
ws.connect()
|
ws.connect()
|
||||||
|
}
|
||||||
|
const init = () => {
|
||||||
if (typeof plus !== 'undefined') {
|
if (typeof plus !== 'undefined') {
|
||||||
handleWebview()
|
handleWebview()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import request from '@/service/index.js'
|
import request from '@/service/index.js'
|
||||||
import qs from 'qs'
|
import qs from 'qs'
|
||||||
|
import {
|
||||||
|
useTalkStore,
|
||||||
|
useDialogueStore
|
||||||
|
} from '@/store'
|
||||||
|
|
||||||
// 获取聊天列表服务接口
|
// 获取聊天列表服务接口
|
||||||
export const ServeGetTalkList = (data) => {
|
export const ServeGetTalkList = (data) => {
|
||||||
@ -38,7 +42,27 @@ export const ServeTopTalkList = (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清除聊天消息未读数服务接口
|
// 清除聊天消息未读数服务接口
|
||||||
export const ServeClearTalkUnreadNum = (data) => {
|
export const ServeClearTalkUnreadNum = (data, unReadNum) => {
|
||||||
|
console.log('=======chatApp==UnreadNum', unReadNum)
|
||||||
|
if(!useTalkStore().items[useTalkStore().findTalkIndex(useDialogueStore().index_name)]?.is_disturb){
|
||||||
|
if (typeof plus !== 'undefined') {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
OAWebView.forEach((webview) => {
|
||||||
|
if (webview.id === 'webviewId1') {
|
||||||
|
webview.evalJS(`updateUnreadMsgNumReduce('${unReadNum}')`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
document.addEventListener('plusready', () => {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
OAWebView.forEach((webview) => {
|
||||||
|
if (webview.id === 'webviewId1') {
|
||||||
|
webview.evalJS(`updateUnreadMsgNumReduce('${unReadNum}')`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/talk/unread/clear',
|
url: '/api/v1/talk/unread/clear',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -169,14 +193,15 @@ export const ServeConfirmVoteHandle = (data) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const uploadImg = (data,onProgressFn) => {
|
export const uploadImg = (data, onProgressFn) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/upload/img',
|
url: '/upload/img',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data:data,
|
data: data,
|
||||||
baseURL:import.meta.env.VITE_EPR_BASEURL,
|
baseURL: import.meta.env.VITE_EPR_BASEURL,
|
||||||
isFormData:true,
|
isFormData: true,
|
||||||
onUploadProgress:(progressEvent)=>onProgressFn(progressEvent,data.get('file'))
|
onUploadProgress: (progressEvent) =>
|
||||||
|
onProgressFn(progressEvent, data.get('file')),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 根据msg_id获取消息
|
// 根据msg_id获取消息
|
||||||
|
79
src/components/async-error/index.vue
Normal file
79
src/components/async-error/index.vue
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
location.reload(true);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="loader">
|
||||||
|
<p class="heading">加载中</p>
|
||||||
|
<div class="loading">
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- 重启页面 -->
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loader {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
color: black;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
width: 5em;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load {
|
||||||
|
width: 23px;
|
||||||
|
height: 3px;
|
||||||
|
background-color: limegreen;
|
||||||
|
animation: 1s move_5011 infinite;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(1) {
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(2) {
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(3) {
|
||||||
|
animation-delay: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move_5011 {
|
||||||
|
0% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
width: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
width: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
78
src/components/async-loading/index.vue
Normal file
78
src/components/async-loading/index.vue
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="loader">
|
||||||
|
<p class="heading">加载中</p>
|
||||||
|
<div class="loading">
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
<div class="load"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loader {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
color: black;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
width: 5em;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load {
|
||||||
|
width: 23px;
|
||||||
|
height: 3px;
|
||||||
|
background-color: limegreen;
|
||||||
|
animation: 1s move_5011 infinite;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(1) {
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(2) {
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load:nth-child(3) {
|
||||||
|
animation-delay: 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes move_5011 {
|
||||||
|
0% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
width: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
width: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
width: 0.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<tm-navbar
|
<tm-navbar
|
||||||
:hideBack="props.hideBack"
|
:hideBack="props.hideBack"
|
||||||
hideHome
|
|
||||||
:title="props.title"
|
:title="props.title"
|
||||||
:shadow="props.shadowNum"
|
:shadow="props.shadowNum"
|
||||||
:fontSize="34"
|
:fontSize="34"
|
||||||
|
@ -55,7 +55,7 @@ const getFileTypeIMG = computed(() => {
|
|||||||
default:
|
default:
|
||||||
objT.finishedImg = filePaperOther
|
objT.finishedImg = filePaperOther
|
||||||
objT.blankImg = filePaperOtherBlank
|
objT.blankImg = filePaperOtherBlank
|
||||||
objT.progressColor = '#747474'
|
objT.progressColor = '#46299d'
|
||||||
}
|
}
|
||||||
return objT
|
return objT
|
||||||
})
|
})
|
||||||
@ -132,7 +132,7 @@ const downloadAndOpenFile = () => {
|
|||||||
:height="95"
|
:height="95"
|
||||||
:src="getFileTypeIMG.blankImg"
|
:src="getFileTypeIMG.blankImg"
|
||||||
></tm-image>
|
></tm-image>
|
||||||
<wd-circle
|
<wd-circle v-if="data.uploadStatus === 1"
|
||||||
customClass="circleProgress"
|
customClass="circleProgress"
|
||||||
:modelValue="data.uploadCurrent"
|
:modelValue="data.uploadCurrent"
|
||||||
layerColor="#E3E3E3"
|
layerColor="#E3E3E3"
|
||||||
@ -140,6 +140,9 @@ const downloadAndOpenFile = () => {
|
|||||||
:strokeWidth="3"
|
:strokeWidth="3"
|
||||||
:size="20"
|
:size="20"
|
||||||
></wd-circle>
|
></wd-circle>
|
||||||
|
<div class="upload-failed" v-if="data.uploadStatus === 3">
|
||||||
|
<tm-icon :font-size="20" name="tmicon-times" color="#fff"></tm-icon>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="divider mt-[28rpx]"></div>
|
<div class="divider mt-[28rpx]"></div>
|
||||||
@ -288,4 +291,20 @@ const downloadAndOpenFile = () => {
|
|||||||
width: 40rpx !important;
|
width: 40rpx !important;
|
||||||
height: 40rpx !important;
|
height: 40rpx !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upload-failed {
|
||||||
|
position: absolute;
|
||||||
|
top: 120rpx;
|
||||||
|
right: 52rpx;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #ff4d4f;
|
||||||
|
background: #ff4d4f;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -12,40 +12,40 @@ const img = computed(() => {
|
|||||||
// console.log(props.extra);
|
// console.log(props.extra);
|
||||||
let info = {
|
let info = {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0
|
height: 0,
|
||||||
}
|
}
|
||||||
if (props.extra.url.includes('blob:http://')) {
|
if (props.extra.url.includes('blob:http://')) {
|
||||||
info = {
|
info = {
|
||||||
width: props.extra.width,
|
width: props.extra.width,
|
||||||
height: props.extra.height
|
height: props.extra.height,
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
info = getImageInfo(props.extra.url)
|
info = getImageInfo(props.extra.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.width == 0 || info.height == 0) {
|
if (info.width == 0 || info.height == 0) {
|
||||||
return {
|
return {
|
||||||
width: 450,
|
width: 450,
|
||||||
height: 298
|
height: 298,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(info.width<300){
|
if (info.width < 300) {
|
||||||
return {
|
return {
|
||||||
width: 300,
|
width: 300,
|
||||||
height: info.height / (info.width / 300)
|
height: info.height / (info.width / 300),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.width < 350) {
|
if (info.width < 350) {
|
||||||
return {
|
return {
|
||||||
width: info.width,
|
width: info.width,
|
||||||
height: info.height
|
height: info.height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: 350,
|
width: 350,
|
||||||
height: info.height / (info.width / 350)
|
height: info.height / (info.width / 350),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -54,13 +54,30 @@ const img = computed(() => {
|
|||||||
class="im-message-image"
|
class="im-message-image"
|
||||||
:class="{
|
:class="{
|
||||||
left: data.float === 'left',
|
left: data.float === 'left',
|
||||||
right: data.float === 'right'
|
right: data.float === 'right',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<tm-image preview :width="img.width" :height="img.height" :src="extra.url" />
|
<div class="relative">
|
||||||
<wd-circle custom-class="circleProgress" v-if="props.data.uploadCurrent && props.data.uploadCurrent<100" v-model="props.data.uploadCurrent" color="#ffffff" layer-color="#E3E3E3"></wd-circle>
|
<tm-image
|
||||||
</div>
|
preview
|
||||||
|
:width="img.width"
|
||||||
|
:height="img.height"
|
||||||
|
:src="extra.url"
|
||||||
|
model="aspectFill"
|
||||||
|
/>
|
||||||
|
<wd-circle
|
||||||
|
custom-class="circleProgress"
|
||||||
|
v-if="data.uploadStatus === 1"
|
||||||
|
v-model="props.data.uploadCurrent"
|
||||||
|
color="#46299d"
|
||||||
|
layer-color="#E3E3E3"
|
||||||
|
></wd-circle>
|
||||||
|
<div class="upload-failed" v-if="data.uploadStatus === 3">
|
||||||
|
<tm-icon :font-size="20" name="tmicon-times" color="#fff"></tm-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@ -79,12 +96,12 @@ const img = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.right {
|
&.right {
|
||||||
background-color: #46299D;
|
background-color: #46299d;
|
||||||
border-radius: 16rpx 0 16rpx 16rpx;
|
border-radius: 16rpx 0 16rpx 16rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.image-container {
|
.image-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.circleProgress {
|
.circleProgress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -94,4 +111,18 @@ const img = computed(() => {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.upload-failed {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #ff4d4f;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -15,7 +15,7 @@ const float = props.data.float
|
|||||||
|
|
||||||
const textContent = computed(() => {
|
const textContent = computed(() => {
|
||||||
let text = props.extra?.content || ''
|
let text = props.extra?.content || ''
|
||||||
text = textReplaceLink(text)
|
// text = textReplaceLink(text)
|
||||||
if (props.data.talk_type == 2) {
|
if (props.data.talk_type == 2) {
|
||||||
text = textReplaceMention(text, '#1890ff')
|
text = textReplaceMention(text, '#1890ff')
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, nextTick, getCurrentInstance, computed, onMounted } from 'vue'
|
import { ref, nextTick, getCurrentInstance, computed, onMounted } from 'vue'
|
||||||
import { getImageInfo } from '@/utils/functions'
|
import { getImageInfo } from '@/utils/functions'
|
||||||
import playCircle from "@/static/image/chatList/playCircle@2x.png";
|
import playCircle from '@/static/image/chatList/playCircle@2x.png'
|
||||||
import { useStatus } from "@/store/status";
|
import { useStatus } from '@/store/status'
|
||||||
|
|
||||||
const { statusBarHeight } = useStatus()
|
const { statusBarHeight } = useStatus()
|
||||||
const instance = getCurrentInstance()
|
const instance = getCurrentInstance()
|
||||||
@ -20,12 +20,12 @@ const open = ref(false)
|
|||||||
const img = computed(() => {
|
const img = computed(() => {
|
||||||
let info = {
|
let info = {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0
|
height: 0,
|
||||||
}
|
}
|
||||||
if (props.extra.url.includes('blob:http://')) {
|
if (props.extra.url.includes('blob:http://')) {
|
||||||
info = {
|
info = {
|
||||||
width: props.extra.width,
|
width: props.extra.width,
|
||||||
height: props.extra.height
|
height: props.extra.height,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info = getImageInfo(props.extra.url)
|
info = getImageInfo(props.extra.url)
|
||||||
@ -34,26 +34,26 @@ const img = computed(() => {
|
|||||||
if (info.width == 0 || info.height == 0) {
|
if (info.width == 0 || info.height == 0) {
|
||||||
return {
|
return {
|
||||||
width: 450,
|
width: 450,
|
||||||
height: 298
|
height: 298,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.width < 300) {
|
if (info.width < 300) {
|
||||||
return {
|
return {
|
||||||
width: 300,
|
width: 300,
|
||||||
height: info.height / (info.width / 300)
|
height: info.height / (info.width / 300),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.width < 350) {
|
if (info.width < 350) {
|
||||||
return {
|
return {
|
||||||
width: info.width,
|
width: info.width,
|
||||||
height: info.height
|
height: info.height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: 350,
|
width: 350,
|
||||||
height: info.height / (info.width / 350)
|
height: info.height / (info.width / 350),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -67,57 +67,98 @@ const fullscreenchange = (e) => {
|
|||||||
|
|
||||||
/* 视频播放 获取第一帧 */
|
/* 视频播放 获取第一帧 */
|
||||||
const canplay = (e) => {
|
const canplay = (e) => {
|
||||||
console.log('Video can play:', e);
|
console.log('Video can play:', e)
|
||||||
|
|
||||||
if (e.target) {
|
if (e.target) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
e.target.pause();
|
e.target.pause()
|
||||||
}, 200);
|
}, 200)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
async function onPlay() {
|
async function onPlay() {
|
||||||
videoContext.value = uni.createVideoContext(props.extra.url, instance);
|
|
||||||
videoContext.value.requestFullScreen({ direction: 2 });
|
|
||||||
videoContext.value.play()
|
|
||||||
open.value = true
|
open.value = true
|
||||||
|
await nextTick()
|
||||||
|
videoContext.value = uni.createVideoContext(props.extra.url, instance)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// 先请求全屏
|
||||||
|
videoContext.value.requestFullScreen({ direction: 2 })
|
||||||
|
|
||||||
|
// 延迟一下再播放,确保全屏已经完成
|
||||||
|
setTimeout(() => {
|
||||||
|
videoContext.value.play()
|
||||||
|
}, 100)
|
||||||
|
}, 200)
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
videoRef.value = uni.createVideoContext(props.data.msg_id);
|
videoRef.value = uni.createVideoContext(props.data.msg_id)
|
||||||
videoRef.value.play()
|
videoRef.value.play()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
videoRef.value.pause()
|
videoRef.value.pause()
|
||||||
}, 200);
|
}, 200)
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<section class="im-message-video" :class="{ left: data.float === 'left' }" @click="onPlay">
|
<section
|
||||||
<div class="coverVideo" :style="{
|
class="im-message-video"
|
||||||
width: img.width + 'rpx',
|
:class="{ left: data.float === 'left' }"
|
||||||
height: img.height + 'rpx'
|
@click="onPlay"
|
||||||
}" v-if="props.extra.url.includes('blob:http://')">
|
>
|
||||||
<video :id="data.msg_id" :autoplay="false" disablepictureinpicture muted :src="props.extra.url" width="100%"
|
<div
|
||||||
height="100%" playsinline preload="auto" controls="false" x5-playsinline
|
class="coverVideo"
|
||||||
webkit-playsinline style="object-fit: cover; pointer-events: none;">
|
:style="{
|
||||||
</video>
|
width: img.width + 'rpx',
|
||||||
|
height: img.height + 'rpx',
|
||||||
|
}"
|
||||||
|
v-if="props.extra.url.includes('blob:http://')"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
:id="data.msg_id"
|
||||||
|
:autoplay="false"
|
||||||
|
disablepictureinpicture
|
||||||
|
muted
|
||||||
|
:src="props.extra.url"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
playsinline
|
||||||
|
preload="auto"
|
||||||
|
controls="false"
|
||||||
|
x5-playsinline
|
||||||
|
webkit-playsinline
|
||||||
|
style="object-fit: cover; pointer-events: none;"
|
||||||
|
></video>
|
||||||
</div>
|
</div>
|
||||||
<wd-img v-else :width="`${img.width}rpx`" :height="`${img.height}rpx`" :src="data.extra.cover" />
|
<wd-img
|
||||||
<div v-if="data.uploadStatus === 2 || !data.uploadStatus" class="btn-video" :style="{
|
v-else
|
||||||
width: img.width + 'rpx',
|
:width="`${img.width}rpx`"
|
||||||
height: img.height + 'rpx'
|
:height="`${img.height}rpx`"
|
||||||
}">
|
:src="data.extra.cover"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="data.uploadStatus === 2 || !data.uploadStatus"
|
||||||
|
class="btn-video"
|
||||||
|
:style="{
|
||||||
|
width: img.width + 'rpx',
|
||||||
|
height: img.height + 'rpx',
|
||||||
|
}"
|
||||||
|
>
|
||||||
<tm-image :src="playCircle" :width="80" :height="80" />
|
<tm-image :src="playCircle" :width="80" :height="80" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="btn-video" :style="{
|
<div
|
||||||
width: img.width + 'rpx',
|
v-else
|
||||||
height: img.height + 'rpx'
|
class="btn-video"
|
||||||
}" >
|
:style="{
|
||||||
|
width: img.width + 'rpx',
|
||||||
|
height: img.height + 'rpx',
|
||||||
|
}"
|
||||||
|
>
|
||||||
<wd-circle
|
<wd-circle
|
||||||
|
v-if="data.uploadStatus === 1"
|
||||||
v-model="props.data.uploadCurrent"
|
v-model="props.data.uploadCurrent"
|
||||||
customClass="circleProgress"
|
customClass="circleProgress"
|
||||||
layerColor="#E3E3E3"
|
color="#46299d"
|
||||||
color="#FFFFFF"
|
layer-color="#E3E3E3"
|
||||||
:strokeWidth="6"
|
:strokeWidth="6"
|
||||||
:size="40"
|
:size="40"
|
||||||
></wd-circle>
|
></wd-circle>
|
||||||
@ -131,18 +172,32 @@ onMounted(() => {
|
|||||||
:width="70"
|
:width="70"
|
||||||
:percent="props.data.uploadCurrent">
|
:percent="props.data.uploadCurrent">
|
||||||
</tm-progress> -->
|
</tm-progress> -->
|
||||||
</div>
|
<div class="upload-failed" v-if="data.uploadStatus === 3">
|
||||||
<div v-show="open">
|
<tm-icon :font-size="20" name="tmicon-times" color="#fff"></tm-icon>
|
||||||
<video :src="props.extra.url" controls @fullscreenchange="fullscreenchange" :id="props.extra.url">
|
</div>
|
||||||
</video>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<teleport to="body">
|
||||||
|
<div v-show="open" class="video-container">
|
||||||
|
<video
|
||||||
|
:src="props.extra.url"
|
||||||
|
controls
|
||||||
|
@fullscreenchange="fullscreenchange"
|
||||||
|
:id="props.extra.url"
|
||||||
|
playsinline
|
||||||
|
webkit-playsinline
|
||||||
|
x5-playsinline
|
||||||
|
class="fullscreen-video"
|
||||||
|
></video>
|
||||||
|
</div>
|
||||||
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.im-message-video {
|
.im-message-video {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 20rpx 18rpx;
|
padding: 20rpx 18rpx;
|
||||||
background: #46299D;
|
background: #46299d;
|
||||||
min-width: 30rpx;
|
min-width: 30rpx;
|
||||||
min-height: 30rpx;
|
min-height: 30rpx;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@ -200,10 +255,43 @@ onMounted(() => {
|
|||||||
:deep(.uni-video-bar) {
|
:deep(.uni-video-bar) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.circleProgress {
|
.circleProgress {
|
||||||
width: 80rpx !important;
|
width: 80rpx !important;
|
||||||
height: 80rpx !important;
|
height: 80rpx !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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-failed {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #ff4d4f;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
19
src/components/talk/message/system/SysGroupDismissed.vue
Normal file
19
src/components/talk/message/system/SysGroupDismissed.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup>
|
||||||
|
import './sys-message.less'
|
||||||
|
import { useInject } from '@/hooks'
|
||||||
|
|
||||||
|
const { showUserInfoModal } = useInject()
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
extra: Object,
|
||||||
|
data: Object
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="im-message-sys-text">
|
||||||
|
<div class="sys-text">
|
||||||
|
<span>{{ extra.content }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -85,7 +85,7 @@ export const MessageComponents = {
|
|||||||
[ChatMsgSysGroupMemberQuit]: 'sys-group-member-quit-message',
|
[ChatMsgSysGroupMemberQuit]: 'sys-group-member-quit-message',
|
||||||
[ChatMsgSysGroupMemberKicked]: 'sys-group-member-kicked-message',
|
[ChatMsgSysGroupMemberKicked]: 'sys-group-member-kicked-message',
|
||||||
// [ChatMsgSysGroupMessageRevoke]: '[撤回消息]',
|
// [ChatMsgSysGroupMessageRevoke]: '[撤回消息]',
|
||||||
// [ChatMsgSysGroupDismissed]: '[群解散消息]',
|
[ChatMsgSysGroupDismissed]: 'sys-group-dismissed',
|
||||||
[ChatMsgSysGroupMuted]: 'sys-group-muted-message',
|
[ChatMsgSysGroupMuted]: 'sys-group-muted-message',
|
||||||
[ChatMsgSysGroupCancelMuted]: 'sys-group-cancel-muted-message',
|
[ChatMsgSysGroupCancelMuted]: 'sys-group-cancel-muted-message',
|
||||||
[ChatMsgSysGroupMemberMuted]: 'sys-group-member-muted-message',
|
[ChatMsgSysGroupMemberMuted]: 'sys-group-member-muted-message',
|
||||||
|
@ -5,8 +5,16 @@ import { parseTime } from '@/utils/datetime'
|
|||||||
import * as message from '@/constant/message'
|
import * as message from '@/constant/message'
|
||||||
import { formatTalkItem, palyMusic, formatTalkRecord } from '@/utils/talk'
|
import { formatTalkItem, palyMusic, formatTalkRecord } from '@/utils/talk'
|
||||||
// import { isElectronMode } from '@/utils/common'
|
// import { isElectronMode } from '@/utils/common'
|
||||||
import { ServeClearTalkUnreadNum, ServeCreateTalkList } from '@/api/chat/index.js'
|
import {
|
||||||
import { useTalkStore, useDialogueStore,useDialogueListStore,useGroupStore } from '@/store'
|
ServeClearTalkUnreadNum,
|
||||||
|
ServeCreateTalkList,
|
||||||
|
} from '@/api/chat/index.js'
|
||||||
|
import {
|
||||||
|
useTalkStore,
|
||||||
|
useDialogueStore,
|
||||||
|
useDialogueListStore,
|
||||||
|
useGroupStore,
|
||||||
|
} from '@/store'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 好友状态事件
|
* 好友状态事件
|
||||||
@ -49,7 +57,7 @@ class Talk extends Base {
|
|||||||
this.receiver_id = resource.receiver_id
|
this.receiver_id = resource.receiver_id
|
||||||
this.talk_type = resource.talk_type
|
this.talk_type = resource.talk_type
|
||||||
// this.fileNum = resource.file_num
|
// this.fileNum = resource.file_num
|
||||||
if(resource.file_num){
|
if (resource.file_num) {
|
||||||
resource.data.file_num = resource.file_num
|
resource.data.file_num = resource.file_num
|
||||||
}
|
}
|
||||||
this.resource = resource.data
|
this.resource = resource.data
|
||||||
@ -98,11 +106,10 @@ class Talk extends Base {
|
|||||||
play() {
|
play() {
|
||||||
// 客户端有消息提示
|
// 客户端有消息提示
|
||||||
// if (isElectronMode()) return
|
// if (isElectronMode()) return
|
||||||
|
|
||||||
// useSettingsStore().isPromptTone && palyMusic()
|
// useSettingsStore().isPromptTone && palyMusic()
|
||||||
}
|
}
|
||||||
|
|
||||||
handle() {
|
async handle() {
|
||||||
// 不是自己发送的消息则需要播放提示音
|
// 不是自己发送的消息则需要播放提示音
|
||||||
if (!this.isCurrSender()) {
|
if (!this.isCurrSender()) {
|
||||||
this.play()
|
this.play()
|
||||||
@ -110,7 +117,21 @@ class Talk extends Base {
|
|||||||
|
|
||||||
// 判断会话列表是否存在,不存在则创建
|
// 判断会话列表是否存在,不存在则创建
|
||||||
if (useTalkStore().findTalkIndex(this.getIndexName()) == -1) {
|
if (useTalkStore().findTalkIndex(this.getIndexName()) == -1) {
|
||||||
return this.addTalkItem()
|
if (this.resource.msg_type == 1102) {
|
||||||
|
//被邀请进入群聊时,需要热更新会话列表
|
||||||
|
await useTalkStore().loadTalkList()
|
||||||
|
} else if (this.resource.msg_type == 1106) {
|
||||||
|
//群解散时,需要热更新会话列表
|
||||||
|
await useTalkStore().loadTalkList()
|
||||||
|
} else if (
|
||||||
|
this.resource.msg_type == 1104 ||
|
||||||
|
this.resource.msg_type == 1115
|
||||||
|
) {
|
||||||
|
//群成员被移出时,需要热更新会话列表
|
||||||
|
await useTalkStore().loadTalkList()
|
||||||
|
} else {
|
||||||
|
return this.addTalkItem()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断当前是否正在和好友对话
|
// 判断当前是否正在和好友对话
|
||||||
@ -118,6 +139,33 @@ class Talk extends Base {
|
|||||||
this.insertTalkRecord()
|
this.insertTalkRecord()
|
||||||
} else {
|
} else {
|
||||||
this.updateTalkItem()
|
this.updateTalkItem()
|
||||||
|
if (
|
||||||
|
!useTalkStore().items[useTalkStore().findTalkIndex(this.getIndexName())]
|
||||||
|
?.is_disturb
|
||||||
|
) {
|
||||||
|
this.updateUnreadMsgNumAdd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新未读数量+1
|
||||||
|
updateUnreadMsgNumAdd() {
|
||||||
|
if (typeof plus !== 'undefined') {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
OAWebView.forEach((webview) => {
|
||||||
|
if (webview.id === 'webviewId1') {
|
||||||
|
webview.evalJS(`updateUnreadMsgNumAdd()`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
document.addEventListener('plusready', () => {
|
||||||
|
let OAWebView = plus.webview.all()
|
||||||
|
OAWebView.forEach((webview) => {
|
||||||
|
if (webview.id === 'webviewId1') {
|
||||||
|
webview.evalJS(`updateUnreadMsgNumAdd()`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +180,6 @@ class Talk extends Base {
|
|||||||
// lang: 'zh-CN',
|
// lang: 'zh-CN',
|
||||||
// body: '您有新的消息请注意查收'
|
// body: '您有新的消息请注意查收'
|
||||||
// })
|
// })
|
||||||
|
|
||||||
// notification.onclick = () => {
|
// notification.onclick = () => {
|
||||||
// notification.close()
|
// notification.close()
|
||||||
// }
|
// }
|
||||||
@ -160,12 +207,16 @@ class Talk extends Base {
|
|||||||
|
|
||||||
ServeCreateTalkList({
|
ServeCreateTalkList({
|
||||||
talk_type,
|
talk_type,
|
||||||
receiver_id
|
receiver_id,
|
||||||
}).then(({ code, data }) => {
|
}).then(async ({ code, data }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
let item = formatTalkItem(data)
|
let item = formatTalkItem(data)
|
||||||
item.unread_num = 1
|
if (!item?.is_disturb) {
|
||||||
|
item.unread_num = 1
|
||||||
|
this.updateUnreadMsgNumAdd()
|
||||||
|
}
|
||||||
useTalkStore().addItem(item)
|
useTalkStore().addItem(item)
|
||||||
|
await useTalkStore().loadTalkList()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -175,12 +226,36 @@ class Talk extends Base {
|
|||||||
*/
|
*/
|
||||||
insertTalkRecord() {
|
insertTalkRecord() {
|
||||||
let record = this.resource
|
let record = this.resource
|
||||||
let newRecord = formatTalkRecord(this.getAccountId(), this.resource);
|
let newRecord = formatTalkRecord(this.getAccountId(), this.resource)
|
||||||
const {addDialogueRecord,addChatRecord} = useDialogueListStore()
|
const { addDialogueRecord, addChatRecord } = useDialogueListStore()
|
||||||
// 群成员变化的消息,需要更新群成员列表
|
// 群成员变化的消息,需要更新群成员列表
|
||||||
if ([1102, 1103, 1104, 1115].includes(record.msg_type)) {
|
if ([1102, 1103, 1104, 1115].includes(record.msg_type)) {
|
||||||
useDialogueStore().updateGroupMembers()
|
useDialogueStore().updateGroupMembers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//群解散时,需要更新群成员权限
|
||||||
|
if ([1106].includes(record.msg_type)) {
|
||||||
|
useDialogueStore().updateDismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
//群成员被移出时,需要更新群成员权限
|
||||||
|
if ([1104, 1115].includes(record.msg_type)) {
|
||||||
|
useDialogueStore().updateQuit()
|
||||||
|
}
|
||||||
|
|
||||||
|
//群禁言变化时,需要更新群禁言状态——即更新群成员列表
|
||||||
|
if ([1107, 1108, 1109, 1110].includes(record.msg_type)) {
|
||||||
|
useDialogueStore().updateGroupMembers()
|
||||||
|
}
|
||||||
|
//群公告变化时,需要更新群公告(新增和修改有热更新,删除没有)
|
||||||
|
if ([13].includes(record.msg_type)) {
|
||||||
|
useGroupStore().ServeGetGroupNotices()
|
||||||
|
}
|
||||||
|
//群管理员变化时,需要更新群管理员列表——即更新群成员列表,同时更新群信息
|
||||||
|
if ([1114].includes(record.msg_type)) {
|
||||||
|
useDialogueStore().updateGroupMembers()
|
||||||
|
useGroupStore().ServeGroupDetail()
|
||||||
|
}
|
||||||
if ([1116].includes(record.msg_type)) {
|
if ([1116].includes(record.msg_type)) {
|
||||||
// 更新会话信息
|
// 更新会话信息
|
||||||
useDialogueStore().setDialogue({
|
useDialogueStore().setDialogue({
|
||||||
@ -194,13 +269,15 @@ class Talk extends Base {
|
|||||||
avatar: record.extra.group_avatar,
|
avatar: record.extra.group_avatar,
|
||||||
})
|
})
|
||||||
// 更新会话列表中的会话信息
|
// 更新会话列表中的会话信息
|
||||||
const dialogue = useDialogueListStore().getDialogueList(`${record.talk_type}_${record.receiver_id}`)
|
const dialogue = useDialogueListStore().getDialogueList(
|
||||||
|
`${record.talk_type}_${record.receiver_id}`,
|
||||||
|
)
|
||||||
if (dialogue) {
|
if (dialogue) {
|
||||||
dialogue.talk.username = record.extra.group_name
|
dialogue.talk.username = record.extra.group_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addDialogueRecord([newRecord],'add')
|
addDialogueRecord([newRecord], 'add')
|
||||||
addChatRecord(this.getIndexName(),newRecord)
|
addChatRecord(this.getIndexName(), newRecord)
|
||||||
useDialogueStore().addDialogueRecord(newRecord)
|
useDialogueStore().addDialogueRecord(newRecord)
|
||||||
|
|
||||||
if (!this.isCurrSender()) {
|
if (!this.isCurrSender()) {
|
||||||
@ -208,7 +285,7 @@ class Talk extends Base {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
ws.emit('im.message.read', {
|
ws.emit('im.message.read', {
|
||||||
receiver_id: this.sender_id,
|
receiver_id: this.sender_id,
|
||||||
msg_ids: [this.resource.msg_id]
|
msg_ids: [this.resource.msg_id],
|
||||||
})
|
})
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
@ -218,7 +295,8 @@ class Talk extends Base {
|
|||||||
if (!el) return
|
if (!el) return
|
||||||
|
|
||||||
// 判断的滚动条是否在底部
|
// 判断的滚动条是否在底部
|
||||||
const isBottom = Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight
|
const isBottom =
|
||||||
|
Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight
|
||||||
|
|
||||||
if (isBottom || record.user_id == this.getAccountId()) {
|
if (isBottom || record.user_id == this.getAccountId()) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -231,14 +309,15 @@ class Talk extends Base {
|
|||||||
useTalkStore().updateItem({
|
useTalkStore().updateItem({
|
||||||
index_name: this.getIndexName(),
|
index_name: this.getIndexName(),
|
||||||
msg_text: this.getTalkText(),
|
msg_text: this.getTalkText(),
|
||||||
updated_at: parseTime(new Date())
|
updated_at: parseTime(new Date()),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (this.talk_type == 1 && this.getAccountId() !== this.sender_id) {
|
if (this.talk_type == 1 && this.getAccountId() !== this.sender_id) {
|
||||||
ServeClearTalkUnreadNum({
|
//不在此处维护未读消息数量
|
||||||
talk_type: 1,
|
// ServeClearTalkUnreadNum({
|
||||||
receiver_id: this.sender_id
|
// talk_type: 1,
|
||||||
})
|
// receiver_id: this.sender_id,
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,11 +328,26 @@ class Talk extends Base {
|
|||||||
useTalkStore().updateMessage({
|
useTalkStore().updateMessage({
|
||||||
index_name: this.getIndexName(),
|
index_name: this.getIndexName(),
|
||||||
msg_text: this.getTalkText(),
|
msg_text: this.getTalkText(),
|
||||||
updated_at: parseTime(new Date())
|
updated_at: parseTime(new Date()),
|
||||||
})
|
})
|
||||||
if(this.resource.msg_type == 1116){
|
//收到新消息时,同时判断是否有人@我
|
||||||
|
if (
|
||||||
|
this.resource.msg_type === 1 &&
|
||||||
|
this.resource?.extra?.mentions?.length > 0
|
||||||
|
) {
|
||||||
|
const findMention = this.resource?.extra?.mentions?.find(
|
||||||
|
(mention) => mention === this.getAccountId(),
|
||||||
|
)
|
||||||
|
//有人@我或者@所有人,则更新会话列表
|
||||||
|
if (findMention || this.resource?.extra?.mentions?.includes(0)) {
|
||||||
|
useTalkStore().loadTalkList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.resource.msg_type == 1116) {
|
||||||
// 更新会话列表中的会话信息
|
// 更新会话列表中的会话信息
|
||||||
const dialogue = useDialogueListStore().getDialogueList(`${this.resource.talk_type}_${this.resource.receiver_id}`)
|
const dialogue = useDialogueListStore().getDialogueList(
|
||||||
|
`${this.resource.talk_type}_${this.resource.receiver_id}`,
|
||||||
|
)
|
||||||
if (dialogue) {
|
if (dialogue) {
|
||||||
dialogue.talk.username = this.resource.extra.group_name
|
dialogue.talk.username = this.resource.extra.group_name
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,12 @@ import { reactive, nextTick, computed, h, inject } from 'vue'
|
|||||||
// EditTwo,
|
// EditTwo,
|
||||||
// IdCard
|
// IdCard
|
||||||
// } from '@icon-park/vue-next'
|
// } from '@icon-park/vue-next'
|
||||||
import { ServeTopTalkList, ServeDeleteTalkList, ServeSetNotDisturb } from '@/api/chat'
|
import {
|
||||||
|
ServeTopTalkList,
|
||||||
|
ServeDeleteTalkList,
|
||||||
|
ServeSetNotDisturb,
|
||||||
|
ServeClearTalkUnreadNum,
|
||||||
|
} from '@/api/chat'
|
||||||
import { useDialogueStore, useTalkStore, useDialogueListStore } from '@/store'
|
import { useDialogueStore, useTalkStore, useDialogueListStore } from '@/store'
|
||||||
import { ServeSecedeGroup } from '@/api/group'
|
import { ServeSecedeGroup } from '@/api/group'
|
||||||
// import { ServeDeleteContact, ServeEditContactRemark } from '@/api/contact'
|
// import { ServeDeleteContact, ServeEditContactRemark } from '@/api/contact'
|
||||||
@ -23,7 +28,7 @@ export function useSessionMenu() {
|
|||||||
show: false,
|
show: false,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
item: {}
|
item: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
@ -118,10 +123,22 @@ export function useSessionMenu() {
|
|||||||
// 移除会话
|
// 移除会话
|
||||||
const onRemoveTalk = (item) => {
|
const onRemoveTalk = (item) => {
|
||||||
ServeDeleteTalkList({
|
ServeDeleteTalkList({
|
||||||
list_id: item.id
|
list_id: item.id,
|
||||||
}).then(({ code }) => {
|
}).then(({ code }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
onDeleteTalk(item.index_name)
|
onDeleteTalk(item.index_name)
|
||||||
|
console.error(item, 'item')
|
||||||
|
if (item.unread_num > 0) {
|
||||||
|
//同时已读
|
||||||
|
ServeClearTalkUnreadNum(
|
||||||
|
{
|
||||||
|
talk_type: item.talk_type,
|
||||||
|
receiver_id: item.receiver_id,
|
||||||
|
},
|
||||||
|
item.unread_num,
|
||||||
|
).then(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -131,13 +148,13 @@ export function useSessionMenu() {
|
|||||||
ServeSetNotDisturb({
|
ServeSetNotDisturb({
|
||||||
talk_type: item.talk_type,
|
talk_type: item.talk_type,
|
||||||
receiver_id: item.receiver_id,
|
receiver_id: item.receiver_id,
|
||||||
is_disturb: item.is_disturb == 0 ? 1 : 0
|
is_disturb: item.is_disturb == 0 ? 1 : 0,
|
||||||
}).then(({ code, message }) => {
|
}).then(({ code, message }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
message.success('设置成功!')
|
message.success('设置成功!')
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: item.index_name,
|
index_name: item.index_name,
|
||||||
is_disturb: item.is_disturb == 0 ? 1 : 0
|
is_disturb: item.is_disturb == 0 ? 1 : 0,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
message.error(message)
|
message.error(message)
|
||||||
@ -153,12 +170,12 @@ export function useSessionMenu() {
|
|||||||
|
|
||||||
ServeTopTalkList({
|
ServeTopTalkList({
|
||||||
list_id: item.id,
|
list_id: item.id,
|
||||||
type: item.is_top == 0 ? 1 : 2
|
type: item.is_top == 0 ? 1 : 2,
|
||||||
}).then(({ code, message }) => {
|
}).then(({ code, message }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: item.index_name,
|
index_name: item.index_name,
|
||||||
is_top: item.is_top == 0 ? 1 : 0
|
is_top: item.is_top == 0 ? 1 : 0,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
message.error(message)
|
message.error(message)
|
||||||
@ -201,7 +218,7 @@ export function useSessionMenu() {
|
|||||||
negativeText: '取消',
|
negativeText: '取消',
|
||||||
onPositiveClick: () => {
|
onPositiveClick: () => {
|
||||||
ServeSecedeGroup({
|
ServeSecedeGroup({
|
||||||
group_id: item.receiver_id
|
group_id: item.receiver_id,
|
||||||
}).then(({ code, message }) => {
|
}).then(({ code, message }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
message.success('已退出群聊')
|
message.success('已退出群聊')
|
||||||
@ -210,7 +227,7 @@ export function useSessionMenu() {
|
|||||||
message.error(message)
|
message.error(message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,12 +276,18 @@ export function useSessionMenu() {
|
|||||||
disturb: onSetDisturb,
|
disturb: onSetDisturb,
|
||||||
signout_group: onSignOutGroup,
|
signout_group: onSignOutGroup,
|
||||||
delete_contact: onDeleteContact,
|
delete_contact: onDeleteContact,
|
||||||
remark: onChangeRemark
|
remark: onChangeRemark,
|
||||||
}
|
}
|
||||||
|
|
||||||
dropdown.show = false
|
dropdown.show = false
|
||||||
evnets[key] && evnets[key](dropdown.item)
|
evnets[key] && evnets[key](dropdown.item)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { dropdown, onCloseContextMenu, onContextMenuTalkHandle, onToTopTalk, onRemoveTalk }
|
return {
|
||||||
|
dropdown,
|
||||||
|
onCloseContextMenu,
|
||||||
|
onContextMenuTalkHandle,
|
||||||
|
onToTopTalk,
|
||||||
|
onRemoveTalk,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
16
src/main.js
16
src/main.js
@ -10,6 +10,8 @@ import tmui from '@/uni_modules/tmui'
|
|||||||
import { config } from '@/config/tmui/index.js'
|
import { config } from '@/config/tmui/index.js'
|
||||||
import 'dayjs/locale/zh-cn'
|
import 'dayjs/locale/zh-cn'
|
||||||
import xLoaderror from '@/components/x-loaderror/index.vue'
|
import xLoaderror from '@/components/x-loaderror/index.vue'
|
||||||
|
import asyncLoading from '@/components/async-loading/index.vue'
|
||||||
|
import asyncError from '@/components/async-error/index.vue'
|
||||||
import { vLoading } from '@/components/x-loading/index.js'
|
import { vLoading } from '@/components/x-loading/index.js'
|
||||||
import messagePopup from '@/components/x-message/useMessagePopup'
|
import messagePopup from '@/components/x-message/useMessagePopup'
|
||||||
import pageAnimation from '@/components/page-animation/index.vue'
|
import pageAnimation from '@/components/page-animation/index.vue'
|
||||||
@ -29,6 +31,8 @@ export function createApp() {
|
|||||||
app.mixin(pageAnimation)
|
app.mixin(pageAnimation)
|
||||||
app.component('customNavbar', customNavbar)
|
app.component('customNavbar', customNavbar)
|
||||||
app.component('x-loaderror', xLoaderror)
|
app.component('x-loaderror', xLoaderror)
|
||||||
|
app.component('AsyncLoading', asyncLoading)
|
||||||
|
app.component('AsyncError', asyncError)
|
||||||
app.directive('no-space', {
|
app.directive('no-space', {
|
||||||
mounted(el) {
|
mounted(el) {
|
||||||
el.addEventListener('input', (e) => {
|
el.addEventListener('input', (e) => {
|
||||||
@ -60,16 +64,20 @@ export function createApp() {
|
|||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
console.log('===准备创建本地通知栏消息')
|
||||||
let OAWebView = plus.webview.all()
|
let OAWebView = plus.webview.all()
|
||||||
//all里面第一个是入口webview
|
OAWebView.forEach((webview, index) => {
|
||||||
OAWebView[0].evalJS(`doCreatePushMessage('${msg}')`)
|
if (webview.id === 'webviewId1') {
|
||||||
|
webview.evalJS(`doCreatePushMessage('${msg}')`)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//处理聊天推送弹窗点开
|
//处理聊天推送弹窗点开
|
||||||
window.openUniPushMsg = (msg) => {
|
window.openUniPushMsg = (msg) => {
|
||||||
console.log("=====点击通知栏消息")
|
console.log('=====点击通知栏消息')
|
||||||
let pushMsg = JSON.parse(decodeURIComponent(msg))
|
let pushMsg = JSON.parse(decodeURIComponent(msg))
|
||||||
console.log("=====pushMsg",pushMsg)
|
console.log('=====pushMsg', pushMsg)
|
||||||
//由于弹窗前处理了不该弹窗的场景,因此这里弹窗可以一并处理
|
//由于弹窗前处理了不该弹窗的场景,因此这里弹窗可以一并处理
|
||||||
//也就是都跳转到聊天页面
|
//也就是都跳转到聊天页面
|
||||||
const talkStore = useTalkStore()
|
const talkStore = useTalkStore()
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
>
|
>
|
||||||
<div class="group-member-each">
|
<div class="group-member-each">
|
||||||
<div class="group-member-avatar" :style="{ background: 'unset' }">
|
<div class="group-member-avatar" :style="{ background: 'unset' }">
|
||||||
<img src="/src/static/image/chatSettings/add-member.png" />
|
<img src="@/static/image/chatSettings/add-member.png" />
|
||||||
</div>
|
</div>
|
||||||
<div class="group-member-name">
|
<div class="group-member-name">
|
||||||
<span class="text-[24rpx] font-regular">添加</span>
|
<span class="text-[24rpx] font-regular">添加</span>
|
||||||
@ -71,7 +71,7 @@
|
|||||||
>
|
>
|
||||||
<div class="group-member-each">
|
<div class="group-member-each">
|
||||||
<div class="group-member-avatar" :style="{ background: 'unset' }">
|
<div class="group-member-avatar" :style="{ background: 'unset' }">
|
||||||
<img src="/src/static/image/chatSettings/remove-member.png" />
|
<img src="@/static/image/chatSettings/remove-member.png" />
|
||||||
</div>
|
</div>
|
||||||
<div class="group-member-name">
|
<div class="group-member-name">
|
||||||
<span class="text-[24rpx] font-regular">移除</span>
|
<span class="text-[24rpx] font-regular">移除</span>
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
props?.memberItem?.is_mine && props?.manageType === 'removeMembers'
|
props?.memberItem?.is_mine && props?.manageType === 'removeMembers'
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<img src="/src/static/image/chatSettings/is-mine.png" />
|
<img src="@/static/image/chatSettings/is-mine.png" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="is-admin-tag"
|
class="is-admin-tag"
|
||||||
|
@ -158,6 +158,7 @@ import customInput from '@/components/custom-input/custom-input.vue'
|
|||||||
import selectMemberItem from '../components/select-member-item.vue'
|
import selectMemberItem from '../components/select-member-item.vue'
|
||||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||||
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
||||||
|
import groupAllMember from '@/static/image/chatList/groupAllMember.png'
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
onMounted,
|
onMounted,
|
||||||
@ -265,7 +266,7 @@ watch(
|
|||||||
key: '0',
|
key: '0',
|
||||||
memberList: [
|
memberList: [
|
||||||
{
|
{
|
||||||
avatar: '/src/static/image/chatList/groupAllMember.png',
|
avatar: groupAllMember,
|
||||||
erp_user_id: 0,
|
erp_user_id: 0,
|
||||||
gender: 0,
|
gender: 0,
|
||||||
is_mute: 0,
|
is_mute: 0,
|
||||||
@ -465,7 +466,7 @@ const assembleAlphabetMemberList = async (newMemberList) => {
|
|||||||
key: '0',
|
key: '0',
|
||||||
memberList: [
|
memberList: [
|
||||||
{
|
{
|
||||||
avatar: '/src/static/image/chatList/groupAllMember.png',
|
avatar: groupAllMember,
|
||||||
erp_user_id: 0,
|
erp_user_id: 0,
|
||||||
gender: 0,
|
gender: 0,
|
||||||
is_mute: 0,
|
is_mute: 0,
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
(props?.item?.label !== $t('chat.settings.groupName') ||
|
(props?.item?.label !== $t('chat.settings.groupName') ||
|
||||||
props?.item?.label !== $t('chat.settings.groupType'))))
|
props?.item?.label !== $t('chat.settings.groupType'))))
|
||||||
"
|
"
|
||||||
src="/src/static/image/chatSettings/pointer.png"
|
src="@/static/image/chatSettings/pointer.png"
|
||||||
/>
|
/>
|
||||||
<tm-switch
|
<tm-switch
|
||||||
:width="88"
|
:width="88"
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
<img
|
<img
|
||||||
v-if="state.groupName"
|
v-if="state.groupName"
|
||||||
class="groupName-input-clearBtn"
|
class="groupName-input-clearBtn"
|
||||||
src="/src/static/image/chatSettings/clear-btn.png"
|
src="@/static/image/chatSettings/clear-btn.png"
|
||||||
@click="clearGroupNameInput"
|
@click="clearGroupNameInput"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<div class="group-admin-list-each-btns">
|
<div class="group-admin-list-each-btns">
|
||||||
<img
|
<img
|
||||||
v-if="item.is_mine"
|
v-if="item.is_mine"
|
||||||
src="/src/static/image/chatSettings/is-mine.png"
|
src="@/static/image/chatSettings/is-mine.png"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="group-admin-list-each-btns-each"
|
class="group-admin-list-each-btns-each"
|
||||||
@ -67,7 +67,7 @@
|
|||||||
margin: state?.groupAdminList.length == 0 ? '20rpx 0 0' : '',
|
margin: state?.groupAdminList.length == 0 ? '20rpx 0 0' : '',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<img src="/src/static/image/chatSettings/add-btn.png" />
|
<img src="@/static/image/chatSettings/add-btn.png" />
|
||||||
<span class="text-[28rpx] font-medium">
|
<span class="text-[28rpx] font-medium">
|
||||||
{{ $t('chat.manage.addAdmin') }}
|
{{ $t('chat.manage.addAdmin') }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
class="add-silence-member-btn chat-settings-card"
|
class="add-silence-member-btn chat-settings-card"
|
||||||
@click="toSelectMembersPage"
|
@click="toSelectMembersPage"
|
||||||
>
|
>
|
||||||
<img src="/src/static/image/chatSettings/add-btn.png" />
|
<img src="@/static/image/chatSettings/add-btn.png" />
|
||||||
<span class="text-[28rpx] font-medium">
|
<span class="text-[28rpx] font-medium">
|
||||||
{{ $t('chat.manage.addSilenceMember') }}
|
{{ $t('chat.manage.addSilenceMember') }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
@click="toEditGroupInfoPage"
|
@click="toEditGroupInfoPage"
|
||||||
v-if="groupParams?.groupInfo?.is_manager"
|
v-if="groupParams?.groupInfo?.is_manager"
|
||||||
>
|
>
|
||||||
<img src="/src/static/image/chatSettings/edit-btn.png" />
|
<img src="@/static/image/chatSettings/edit-btn.png" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chat-group-members chat-group-infos chat-settings-card">
|
<div class="chat-group-members chat-group-infos chat-settings-card">
|
||||||
@ -267,8 +267,8 @@ onLoad(async (options) => {
|
|||||||
if (options.groupId) {
|
if (options.groupId) {
|
||||||
console.log(options.groupId)
|
console.log(options.groupId)
|
||||||
state.groupId = Number(options.groupId)
|
state.groupId = Number(options.groupId)
|
||||||
await groupStore.ServeGroupDetail()
|
|
||||||
if (dialogueParams.type === 2) {
|
if (dialogueParams.type === 2) {
|
||||||
|
await groupStore.ServeGroupDetail()
|
||||||
await groupStore.ServeGetGroupNotices()
|
await groupStore.ServeGetGroupNotices()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,7 +566,10 @@ const showConfirmPrompt = (flag) => {
|
|||||||
confirmContent = t('group.dismiss.confirm')
|
confirmContent = t('group.dismiss.confirm')
|
||||||
} else if (flag === 3) {
|
} else if (flag === 3) {
|
||||||
//最后一个管理员退群就解散群聊
|
//最后一个管理员退群就解散群聊
|
||||||
if (dialogueParams.adminList.length === 1 && dialogueParams.adminList[0].id === dialogueParams.uid) {
|
if (
|
||||||
|
dialogueParams.adminList.length === 1 &&
|
||||||
|
dialogueParams.adminList[0].id === dialogueParams.uid
|
||||||
|
) {
|
||||||
//解散群聊
|
//解散群聊
|
||||||
confirmContent = t('ok') + t('group.quit.btn')
|
confirmContent = t('ok') + t('group.quit.btn')
|
||||||
subContent = t('groupManage.disband.hint')
|
subContent = t('groupManage.disband.hint')
|
||||||
@ -604,7 +607,10 @@ const showConfirmPrompt = (flag) => {
|
|||||||
}
|
}
|
||||||
} else if (flag === 3) {
|
} else if (flag === 3) {
|
||||||
//最后一个管理员退群就解散群聊
|
//最后一个管理员退群就解散群聊
|
||||||
if (dialogueParams.adminList.length === 1 && dialogueParams.adminList[0].id === dialogueParams.uid) {
|
if (
|
||||||
|
dialogueParams.adminList.length === 1 &&
|
||||||
|
dialogueParams.adminList[0].id === dialogueParams.uid
|
||||||
|
) {
|
||||||
//解散群聊
|
//解散群聊
|
||||||
let params = {
|
let params = {
|
||||||
group_id: dialogueParams.receiver_id, //群id
|
group_id: dialogueParams.receiver_id, //群id
|
||||||
@ -624,7 +630,9 @@ const showConfirmPrompt = (flag) => {
|
|||||||
group_id: dialogueParams.receiver_id,
|
group_id: dialogueParams.receiver_id,
|
||||||
}).then(({ code, message }) => {
|
}).then(({ code, message }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
// dialogueStore.apiClearRecord()
|
uni.navigateBack({
|
||||||
|
delta: 2,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -17,10 +17,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="avatarImg">
|
<div class="avatarImg">
|
||||||
<avatarModule
|
<avatarModule
|
||||||
:mode="2"
|
:mode="props?.data?.group_type === 0 ? 1 : 2"
|
||||||
:avatar="props?.data?.avatar"
|
:avatar="props?.data?.avatar"
|
||||||
:groupType="props?.data?.group_type"
|
:groupType="props?.data?.group_type"
|
||||||
|
:userName="props?.data?.name"
|
||||||
:customStyle="{ width: '96rpx', height: '96rpx' }"
|
:customStyle="{ width: '96rpx', height: '96rpx' }"
|
||||||
|
:customTextStyle="{
|
||||||
|
fontSize: '32rpx',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#fff',
|
||||||
|
lineHeight: '44rpx',
|
||||||
|
}"
|
||||||
></avatarModule>
|
></avatarModule>
|
||||||
</div>
|
</div>
|
||||||
<div class="chatInfo">
|
<div class="chatInfo">
|
||||||
@ -30,16 +37,18 @@
|
|||||||
class="text-[#171717] text-[32rpx] font-medium leading-[44rpx]"
|
class="text-[#171717] text-[32rpx] font-medium leading-[44rpx]"
|
||||||
>
|
>
|
||||||
<span>{{ props.data.name }}</span>
|
<span>{{ props.data.name }}</span>
|
||||||
<span v-if="props.data.talk_type === 2">({{ props.data.group_member_num }})</span>
|
<span v-if="props.data.talk_type === 2">
|
||||||
|
({{ props.data.group_member_num }})
|
||||||
|
</span>
|
||||||
<span v-if="props.data.group_type === 2" class="depTag tag">
|
<span v-if="props.data.group_type === 2" class="depTag tag">
|
||||||
部门
|
部门
|
||||||
</span>
|
</span>
|
||||||
<span v-if="props.data.group_type === 3" class="projectTag tag">
|
<span v-if="props.data.group_type === 3" class="projectTag tag">
|
||||||
项目
|
项目
|
||||||
</span>
|
</span>
|
||||||
<span v-if="props.data.group_type === 4" class="companyTag tag">
|
<span v-if="props.data.group_type === 4" class="companyTag tag">
|
||||||
公司
|
公司
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -127,7 +136,7 @@ const cellClick = () => {
|
|||||||
opacity: 40%;
|
opacity: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag{
|
.tag {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -142,16 +151,16 @@ const cellClick = () => {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.companyTag {
|
.companyTag {
|
||||||
border: 1px solid #7a58de;
|
border: 1px solid #7a58de;
|
||||||
color: #7a58de;
|
color: #7a58de;
|
||||||
}
|
}
|
||||||
.depTag {
|
.depTag {
|
||||||
border: 1px solid #377ec6;
|
border: 1px solid #377ec6;
|
||||||
color: #377ec6;
|
color: #377ec6;
|
||||||
}
|
}
|
||||||
.projectTag {
|
.projectTag {
|
||||||
border: 1px solid #c1681c;
|
border: 1px solid #c1681c;
|
||||||
color: #c1681c;
|
color: #c1681c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textEllipsis {
|
.textEllipsis {
|
||||||
|
@ -219,7 +219,7 @@ watch(
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
talkStore.loadTalkList()
|
talkStore.loadTalkList()
|
||||||
console.log(talkStore.talkItems)
|
console.log(talkStore.talkItems)
|
||||||
items.value = lodash.cloneDeep(talkStore.talkItems)
|
items.value = lodash.cloneDeep(talkStore.talkItems).filter(item=>item.is_dismiss === 0 && item.is_quit === 0)
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
dialogueStore.setForwardType('')
|
dialogueStore.setForwardType('')
|
||||||
|
@ -72,7 +72,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
base64Url: ''
|
base64Url: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const uploadsStore = useUploadsStore()
|
const uploadsStore = useUploadsStore()
|
||||||
@ -94,17 +94,69 @@ const onProgressFn = (progress, id) => {
|
|||||||
|
|
||||||
const photoActionsSelect = (index) => {
|
const photoActionsSelect = (index) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
uni.chooseImage({
|
if (typeof plus === 'undefined') {
|
||||||
sourceType: ['album'],
|
uni.chooseImage({
|
||||||
count: 9,
|
sourceType: ['album'],
|
||||||
success: async (res) => {
|
count: 9,
|
||||||
console.log(res, 'res')
|
success: async (res) => {
|
||||||
res.tempFiles.forEach(async (file) => {
|
console.log(res, 'res')
|
||||||
let data = await onUploadImageVideo(file, 'image')
|
res.tempFiles.forEach(async (file) => {
|
||||||
emit('selectImg', data, data.file_num)
|
const fileSizeInMB = (file.size / (1024 * 1024)).toFixed(2)
|
||||||
})
|
if (fileSizeInMB > 100) {
|
||||||
},
|
plus.nativeUI.toast('图片大小不能超过100MB')
|
||||||
})
|
return
|
||||||
|
}
|
||||||
|
let data = await onUploadImageVideo(file, 'image')
|
||||||
|
emit('selectImg', data, data.file_num)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
plus?.gallery.pick(
|
||||||
|
(res) => {
|
||||||
|
console.log(res, 'res')
|
||||||
|
res.files.reverse()
|
||||||
|
res.files.forEach(async (filePath) => {
|
||||||
|
plus?.io?.resolveLocalFileSystemURL(
|
||||||
|
filePath,
|
||||||
|
async (entry) => {
|
||||||
|
entry.file((file) => {
|
||||||
|
const fileReader = new plus.io.FileReader()
|
||||||
|
fileReader.readAsDataURL(file)
|
||||||
|
fileReader.onloadend = async (e) => {
|
||||||
|
const base64Url = e.target.result
|
||||||
|
const fileObj = base64ToFile(base64Url)
|
||||||
|
const fileSizeInMB = (fileObj.size / (1024 * 1024)).toFixed(
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
if (fileSizeInMB > 100) {
|
||||||
|
plus.nativeUI.toast('图片大小不能超过100MB')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let data = await onUploadImageVideo(fileObj, 'image')
|
||||||
|
emit('selectImg', data, data.file_num)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filter: 'image',
|
||||||
|
maximum: 9,
|
||||||
|
multiple: true,
|
||||||
|
onmaxed: () => {
|
||||||
|
plus.nativeUI.toast('最多只能选择9张图片')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uni.chooseVideo({
|
uni.chooseVideo({
|
||||||
sourceType: ['album'],
|
sourceType: ['album'],
|
||||||
@ -112,6 +164,11 @@ const photoActionsSelect = (index) => {
|
|||||||
maxDuration: 60,
|
maxDuration: 60,
|
||||||
success: async (res) => {
|
success: async (res) => {
|
||||||
console.log(res, 'res')
|
console.log(res, 'res')
|
||||||
|
const fileSizeInMB = (res.tempFile.size / (1024 * 1024)).toFixed(2)
|
||||||
|
if (fileSizeInMB > 100) {
|
||||||
|
plus.nativeUI.toast('视频大小不能超过100MB')
|
||||||
|
return
|
||||||
|
}
|
||||||
let data = await onUploadImageVideo(
|
let data = await onUploadImageVideo(
|
||||||
res.tempFile,
|
res.tempFile,
|
||||||
'video',
|
'video',
|
||||||
@ -124,12 +181,13 @@ const photoActionsSelect = (index) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
||||||
console.log(file, 'file')
|
console.log('开始上传文件:', file.name)
|
||||||
|
uploadsStore.updateUploadStatus(true)
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
if (type === 'image') {
|
if (type === 'image') {
|
||||||
let image = new Image()
|
let image = new Image()
|
||||||
image.src = URL.createObjectURL(file)
|
image.src = URL.createObjectURL(file)
|
||||||
image.onload = () => {
|
image.onload = async () => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append('file', file)
|
form.append('file', file)
|
||||||
form.append('source', 'fonchain-chat')
|
form.append('source', 'fonchain-chat')
|
||||||
@ -163,29 +221,62 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
|
||||||
({ status, data, msg }) => {
|
try {
|
||||||
if (status == 0) {
|
const result = await uploadImg(form, (e) => onProgressFn(e, randomId))
|
||||||
resolve({
|
console.log('上传完成,结果:', result)
|
||||||
type: 'image',
|
|
||||||
url: data.ori_url,
|
if (result.status === 0) {
|
||||||
size: file.size,
|
// 更新上传状态为成功
|
||||||
width: image.width,
|
const index = virtualList.value.findIndex(
|
||||||
height: image.height,
|
(item) => item.file_num === randomId,
|
||||||
file_num: randomId,
|
)
|
||||||
})
|
if (index !== -1) {
|
||||||
} else {
|
virtualList.value[index].uploadStatus = 2
|
||||||
resolve('')
|
virtualList.value[index].uploadCurrent = 100
|
||||||
message.error(msg)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
)
|
// 确保返回数据
|
||||||
|
resolve({
|
||||||
|
type: 'image',
|
||||||
|
url: result.data.ori_url,
|
||||||
|
size: file.size,
|
||||||
|
width: image.width,
|
||||||
|
height: image.height,
|
||||||
|
file_num: randomId,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error(result.msg)
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('上传出错:', error)
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error('上传失败')
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uni.getVideoInfo({
|
uni.getVideoInfo({
|
||||||
src: fileUrl,
|
src: fileUrl,
|
||||||
success: (resp) => {
|
success: async (resp) => {
|
||||||
console.log(resp)
|
console.log('视频信息:', resp)
|
||||||
|
const form = new FormData()
|
||||||
form.append('file', file)
|
form.append('file', file)
|
||||||
form.append('source', 'fonchain-chat')
|
form.append('source', 'fonchain-chat')
|
||||||
form.append('type', 'video')
|
form.append('type', 'video')
|
||||||
@ -215,30 +306,65 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
|
|||||||
talk_type: dialogueStore.talk.talk_type,
|
talk_type: dialogueStore.talk.talk_type,
|
||||||
user_id: userStore.uid,
|
user_id: userStore.uid,
|
||||||
uploadCurrent: 0,
|
uploadCurrent: 0,
|
||||||
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
uploadStatus: 1,
|
||||||
}
|
}
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
|
|
||||||
({ status, data, msg }) => {
|
try {
|
||||||
if (status == 0) {
|
const result = await uploadImg(form, (e) => onProgressFn(e, randomId))
|
||||||
console.log(data)
|
console.log('视频上传完成,结果:', result)
|
||||||
resolve({
|
|
||||||
type: 'video',
|
if (result.status === 0) {
|
||||||
url: data.ori_url,
|
// 更新上传状态为成功
|
||||||
cover: data.cover_url,
|
const index = virtualList.value.findIndex(
|
||||||
duration: parseInt(resp.duration),
|
(item) => item.file_num === randomId,
|
||||||
size: file.size,
|
)
|
||||||
file_num: randomId,
|
if (index !== -1) {
|
||||||
})
|
virtualList.value[index].uploadStatus = 2
|
||||||
} else {
|
virtualList.value[index].uploadCurrent = 100
|
||||||
// resolve('')
|
|
||||||
// message.error(msg)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
)
|
resolve({
|
||||||
|
type: 'video',
|
||||||
|
url: result.data.ori_url,
|
||||||
|
cover: result.data.cover_url,
|
||||||
|
duration: parseInt(resp.duration),
|
||||||
|
size: file.size,
|
||||||
|
file_num: randomId,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error(result.msg)
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('视频上传出错:', error)
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error('上传失败')
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('获取视频信息失败:', error)
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
message.error('获取视频信息失败')
|
||||||
|
resolve('')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const form = new FormData()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -389,6 +515,11 @@ const chooseFile = () => {
|
|||||||
count: 1,
|
count: 1,
|
||||||
extension: [''],
|
extension: [''],
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
|
const fileSizeInMB = (res.tempFiles[0].size / (1024 * 1024)).toFixed(2)
|
||||||
|
if (fileSizeInMB > 100) {
|
||||||
|
plus.nativeUI.toast('文件大小不能超过100MB')
|
||||||
|
return
|
||||||
|
}
|
||||||
let randomId = uniqueId()
|
let randomId = uniqueId()
|
||||||
let newItem = {
|
let newItem = {
|
||||||
avatar: userStore.avatar,
|
avatar: userStore.avatar,
|
||||||
@ -416,7 +547,34 @@ const chooseFile = () => {
|
|||||||
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
uploadStatus: 1, // 1 上传中 2 上传成功 3 上传失败
|
||||||
}
|
}
|
||||||
virtualList.value.unshift(newItem)
|
virtualList.value.unshift(newItem)
|
||||||
uploadsStore.initUploadFile(res.tempFiles[0], props.talkParams, randomId)
|
uploadsStore.updateUploadStatus(true)
|
||||||
|
uploadsStore.initUploadFile(
|
||||||
|
res.tempFiles[0],
|
||||||
|
props.talkParams,
|
||||||
|
randomId,
|
||||||
|
(status, data, msg) => {
|
||||||
|
if (status === 0) {
|
||||||
|
// 更新上传状态为成功
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 2
|
||||||
|
virtualList.value[index].uploadCurrent = 100
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
|
// 更新上传状态为失败
|
||||||
|
const index = virtualList.value.findIndex(
|
||||||
|
(item) => item.file_num === randomId,
|
||||||
|
)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
|
message.error(msg)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="user-info-main user-info-card">
|
<div class="user-info-main user-info-card">
|
||||||
<div class="user-info-main-title">
|
<div class="user-info-main-title">
|
||||||
<img src="/src/static/image/mine/ming001@3x.png" />
|
<img src="@/static/image/mine/ming001@3x.png" />
|
||||||
<span class="text-[28rpx] font-medium">
|
<span class="text-[28rpx] font-medium">
|
||||||
{{ $t('index.mine.basic') }}
|
{{ $t('index.mine.basic') }}
|
||||||
</span>
|
</span>
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<div class="do-phone-call-header">
|
<div class="do-phone-call-header">
|
||||||
<span>{{ $t('popup.title.phone') }}</span>
|
<span>{{ $t('popup.title.phone') }}</span>
|
||||||
<img
|
<img
|
||||||
src="/src/static/image/login/check-circle-filled@3x.png"
|
src="@/static/image/login/check-circle-filled@3x.png"
|
||||||
@click="hidePhoneCallPopup"
|
@click="hidePhoneCallPopup"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +16,19 @@
|
|||||||
@scrolltoupper="onScrollToUpper"
|
@scrolltoupper="onScrollToUpper"
|
||||||
>
|
>
|
||||||
<template #top>
|
<template #top>
|
||||||
<customNavbar :title="talkParams.username" id="navBarArea">
|
<customNavbar
|
||||||
|
:title="talkParams.username"
|
||||||
|
id="navBarArea"
|
||||||
|
:hideBack="dialogueStore.isOpenMultiSelect"
|
||||||
|
>
|
||||||
|
<template #left v-if="dialogueStore.isOpenMultiSelect">
|
||||||
|
<text
|
||||||
|
class="ml-[36rpx]"
|
||||||
|
@click="dialogueStore.isOpenMultiSelect = false"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</text>
|
||||||
|
</template>
|
||||||
<template
|
<template
|
||||||
#subTitle
|
#subTitle
|
||||||
v-if="talkStore?.findItem(talkParams.index_name)?.group_type === 4"
|
v-if="talkStore?.findItem(talkParams.index_name)?.group_type === 4"
|
||||||
@ -204,17 +216,28 @@
|
|||||||
</div>
|
</div>
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<div class="footBox" id="footBoxArea">
|
<div class="footBox" id="footBoxArea">
|
||||||
|
<span
|
||||||
|
class="flex items-center justify-center text-[24rpx] text-[#999999]"
|
||||||
|
style="background-color: #e5e5e5; padding: 12rpx 24rpx;"
|
||||||
|
v-if="uploadsParams.isUploading"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
'正在发送中,剩余' +
|
||||||
|
uploadsParams.uploadingNum +
|
||||||
|
'个...请不要离开哦~'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
<div v-if="!dialogueStore.isOpenMultiSelect">
|
<div v-if="!dialogueStore.isOpenMultiSelect">
|
||||||
<div
|
<div
|
||||||
class="pt-[16rpx] ml-[32rpx] mr-[32rpx] flex items-start justify-between"
|
class="pt-[16rpx] ml-[32rpx] mr-[32rpx] flex items-start justify-between"
|
||||||
>
|
>
|
||||||
<div class="flex-1 quillBox">
|
<div class="flex-1 quillBox" style="">
|
||||||
<QuillEditor
|
<QuillEditor
|
||||||
ref="editor"
|
ref="editor"
|
||||||
id="editor"
|
id="editor"
|
||||||
:options="editorOption"
|
:options="editorOption"
|
||||||
@editorChange="onEditorChange"
|
@editorChange="onEditorChange"
|
||||||
style="width: 100%; flex: 1; height: 100%; border: none;"
|
style="width: 100%; flex: 1; height: 100%;"
|
||||||
@click="onEditorClick"
|
@click="onEditorClick"
|
||||||
/>
|
/>
|
||||||
<!-- <tm-input type=textarea autoHeight focusColor="#F9F9F9" color="#F9F9F9" :inputPadding="[12]"
|
<!-- <tm-input type=textarea autoHeight focusColor="#F9F9F9" color="#F9F9F9" :inputPadding="[12]"
|
||||||
@ -231,7 +254,7 @@
|
|||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="state?.quoteInfo"
|
v-if="state?.quoteInfo?.msg_type !== 1"
|
||||||
class="text-[28rpx] text-[#999]"
|
class="text-[28rpx] text-[#999]"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
@ -243,7 +266,7 @@
|
|||||||
<img
|
<img
|
||||||
@click="clearQuoteInfo"
|
@click="clearQuoteInfo"
|
||||||
style="width: 30rpx; height: 30rpx;"
|
style="width: 30rpx; height: 30rpx;"
|
||||||
src="/src/static/image/login/check-circle-filled@3x.png"
|
src="@/static/image/login/check-circle-filled@3x.png"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -310,13 +333,13 @@
|
|||||||
<tm-image :width="68" :height="68" :src="zu6051"></tm-image>
|
<tm-image :width="68" :height="68" :src="zu6051"></tm-image>
|
||||||
<div class="mt-[6rpx]">逐条转发</div>
|
<div class="mt-[6rpx]">逐条转发</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<!-- <div
|
||||||
@click="handleWechatForward"
|
@click="handleWechatForward"
|
||||||
class="flex flex-col items-center justify-center"
|
class="flex flex-col items-center justify-center"
|
||||||
>
|
>
|
||||||
<tm-image :width="68" :height="68" :src="zu6052"></tm-image>
|
<tm-image :width="68" :height="68" :src="zu6052"></tm-image>
|
||||||
<div class="mt-[6rpx]">微信</div>
|
<div class="mt-[6rpx]">微信</div>
|
||||||
</div>
|
</div> -->
|
||||||
<div
|
<div
|
||||||
@click="handleDelete"
|
@click="handleDelete"
|
||||||
class="flex flex-col items-center justify-center"
|
class="flex flex-col items-center justify-center"
|
||||||
@ -382,7 +405,7 @@
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
style="width: 40rpx; height: 40rpx;"
|
style="width: 40rpx; height: 40rpx;"
|
||||||
src="/src/static/image/chatList/mention_select_hide_bg.png"
|
src="@/static/image/chatList/mention_select_hide_bg.png"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
style="
|
style="
|
||||||
@ -392,7 +415,7 @@
|
|||||||
margin-left: -9rpx;
|
margin-left: -9rpx;
|
||||||
margin-top: -5rpx;
|
margin-top: -5rpx;
|
||||||
"
|
"
|
||||||
src="/src/static/image/chatList/mention_select_hide_icon.png"
|
src="@/static/image/chatList/mention_select_hide_icon.png"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
@ -528,6 +551,7 @@ const settingsStore = useSettingsStore()
|
|||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
const editorDraftStore = useEditorDraftStore()
|
const editorDraftStore = useEditorDraftStore()
|
||||||
|
const uploadsStore = useUploadsStore()
|
||||||
const editor = ref()
|
const editor = ref()
|
||||||
const zpagingRef = ref()
|
const zpagingRef = ref()
|
||||||
useZPaging(zpagingRef)
|
useZPaging(zpagingRef)
|
||||||
@ -544,6 +568,12 @@ const talkParams = reactive({
|
|||||||
isDismiss: computed(() => dialogueStore.isDismiss),
|
isDismiss: computed(() => dialogueStore.isDismiss),
|
||||||
isQuit: computed(() => dialogueStore.isQuit),
|
isQuit: computed(() => dialogueStore.isQuit),
|
||||||
adminList: computed(() => dialogueStore.getAdminList),
|
adminList: computed(() => dialogueStore.getAdminList),
|
||||||
|
unReadNum: computed(() => dialogueStore.unreadNum),
|
||||||
|
})
|
||||||
|
|
||||||
|
const uploadsParams = reactive({
|
||||||
|
isUploading: computed(() => uploadsStore.isUploading),
|
||||||
|
uploadingNum: computed(() => uploadsStore.uploadingNum),
|
||||||
})
|
})
|
||||||
|
|
||||||
const state = ref({
|
const state = ref({
|
||||||
@ -567,6 +597,10 @@ const state = ref({
|
|||||||
lastCursorIndex: undefined, //在失焦前保存光标位置
|
lastCursorIndex: undefined, //在失焦前保存光标位置
|
||||||
mentionUserIds: [], //存储所有被@的用户ID
|
mentionUserIds: [], //存储所有被@的用户ID
|
||||||
isInsertingMention: false, //是否正在插入mention
|
isInsertingMention: false, //是否正在插入mention
|
||||||
|
showMentionSelectTimer: null, //显示提醒选择框的定时器
|
||||||
|
lastMentionText: '', // 记录上一次触发@时的完整文本内容
|
||||||
|
lastMentionTriggered: false, // 记录当前@是否已经触发过
|
||||||
|
lastMentionPosition: -1, // 添加新的状态来记录上一次@的位置
|
||||||
})
|
})
|
||||||
|
|
||||||
uniOnload(async (options) => {
|
uniOnload(async (options) => {
|
||||||
@ -594,14 +628,18 @@ uniOnload(async (options) => {
|
|||||||
})
|
})
|
||||||
uniOnUnload(() => {
|
uniOnUnload(() => {
|
||||||
console.log('onUnload')
|
console.log('onUnload')
|
||||||
ServeClearTalkUnreadNum({
|
ServeClearTalkUnreadNum(
|
||||||
talk_type: Number(talkParams.type),
|
{
|
||||||
receiver_id: Number(talkParams.receiver_id),
|
talk_type: Number(talkParams.type),
|
||||||
}).then(() => {
|
receiver_id: Number(talkParams.receiver_id),
|
||||||
|
},
|
||||||
|
talkParams.unReadNum,
|
||||||
|
).then(() => {
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: talkParams.index_name,
|
index_name: talkParams.index_name,
|
||||||
unread_num: 0,
|
unread_num: 0,
|
||||||
})
|
})
|
||||||
|
dialogueStore.clearUnreadNum()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const handleEmojiPanel = () => {
|
const handleEmojiPanel = () => {
|
||||||
@ -622,6 +660,11 @@ const handleHidePanel = () => {
|
|||||||
//点击编辑区聚焦输入框
|
//点击编辑区聚焦输入框
|
||||||
const onEditorClick = () => {
|
const onEditorClick = () => {
|
||||||
handleHidePanel()
|
handleHidePanel()
|
||||||
|
const quill = getQuill()
|
||||||
|
// if (quill.getText().endsWith('@\n')) {
|
||||||
|
// showMentionSelectDebounced(quill)
|
||||||
|
// }
|
||||||
|
quill.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSendMessage = (data = {}, callBack) => {
|
const onSendMessage = (data = {}, callBack) => {
|
||||||
@ -636,14 +679,17 @@ const onSendMessage = (data = {}, callBack) => {
|
|||||||
ServePublishMessage(message)
|
ServePublishMessage(message)
|
||||||
.then(({ code, message }) => {
|
.then(({ code, message }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
if (callBack) {
|
if (callBack) {
|
||||||
callBack(true)
|
callBack(true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
message.warning(message)
|
message.warning(message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
uploadsStore.updateUploadStatus(false)
|
||||||
message.warning('网络繁忙,请稍后重试!')
|
message.warning('网络繁忙,请稍后重试!')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -670,8 +716,11 @@ const onSendMessageClick = () => {
|
|||||||
|
|
||||||
switch (data.msgType) {
|
switch (data.msgType) {
|
||||||
case 1: // 文字消息
|
case 1: // 文字消息
|
||||||
|
if (data.items[0].content.trim() === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (data.items[0].content.length > 1024) {
|
if (data.items[0].content.length > 1024) {
|
||||||
return message.info('发送内容超长,请分条发送')
|
return message.warning('发送内容超长,请分条发送')
|
||||||
}
|
}
|
||||||
onSendTextEvent({
|
onSendTextEvent({
|
||||||
data,
|
data,
|
||||||
@ -798,6 +847,9 @@ const onEmoticonEvent = (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onEditorChange = () => {
|
const onEditorChange = () => {
|
||||||
|
if (getQuill().getText() !== state.value.lastMentionText) {
|
||||||
|
state.value.lastMentionTriggered = false
|
||||||
|
}
|
||||||
let delta = getQuill().getContents()
|
let delta = getQuill().getContents()
|
||||||
let text = deltaToString(delta)
|
let text = deltaToString(delta)
|
||||||
|
|
||||||
@ -887,9 +939,9 @@ const editorOption = {
|
|||||||
if (range) {
|
if (range) {
|
||||||
state.value.lastCursorIndex = range.index
|
state.value.lastCursorIndex = range.index
|
||||||
}
|
}
|
||||||
state.value.isShowMentionSelect = true
|
|
||||||
// 失去焦点
|
// 使用防抖函数
|
||||||
quill.blur()
|
showMentionSelectDebounced(quill)
|
||||||
},
|
},
|
||||||
mentionContainerClass: '',
|
mentionContainerClass: '',
|
||||||
},
|
},
|
||||||
@ -1335,9 +1387,12 @@ const getMentionSelectLists = (mentionSelectList) => {
|
|||||||
|
|
||||||
// 逐个插入mention
|
// 逐个插入mention
|
||||||
mentionSelectList.forEach((mentionSelectItem) => {
|
mentionSelectList.forEach((mentionSelectItem) => {
|
||||||
|
// 如果是@所有人,确保 id 为 0
|
||||||
|
const id =
|
||||||
|
mentionSelectItem?.nickname === '所有人' ? 0 : mentionSelectItem?.id
|
||||||
mention.insertItem(
|
mention.insertItem(
|
||||||
{
|
{
|
||||||
id: mentionSelectItem?.id,
|
id: id,
|
||||||
denotationChar: '@',
|
denotationChar: '@',
|
||||||
value: mentionSelectItem?.nickname + ' ',
|
value: mentionSelectItem?.nickname + ' ',
|
||||||
},
|
},
|
||||||
@ -1371,12 +1426,21 @@ const updateMentionUserIds = () => {
|
|||||||
// 收集当前所有@的用户ID,并转换为number类型
|
// 收集当前所有@的用户ID,并转换为number类型
|
||||||
ops.forEach((op) => {
|
ops.forEach((op) => {
|
||||||
if (op.insert && op.insert.mention) {
|
if (op.insert && op.insert.mention) {
|
||||||
currentMentions.add(Number(op.insert.mention.id))
|
const id = Number(op.insert.mention.id)
|
||||||
|
// 过滤掉 null 值
|
||||||
|
if (!isNaN(id)) {
|
||||||
|
currentMentions.add(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 直接使用当前编辑器中的mentions作为mentionUserIds
|
// 如果当前有@所有人,则添加0
|
||||||
state.value.mentionUserIds = Array.from(currentMentions)
|
if (currentMentions.has(0)) {
|
||||||
|
state.value.mentionUserIds = [0]
|
||||||
|
} else {
|
||||||
|
// 如果没有@任何人,保持空数组
|
||||||
|
state.value.mentionUserIds = Array.from(currentMentions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//根据msg信息找到对应的聊天记录,并根据sequence等查看上下文
|
//根据msg信息找到对应的聊天记录,并根据sequence等查看上下文
|
||||||
@ -1528,6 +1592,9 @@ const isLeader = computed(() => {
|
|||||||
//长按头像@用户
|
//长按头像@用户
|
||||||
const doMentionUser = (mentionSelect) => {
|
const doMentionUser = (mentionSelect) => {
|
||||||
console.log(mentionSelect)
|
console.log(mentionSelect)
|
||||||
|
if (talkParams.type === 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 构造正确的 mention 对象
|
// 构造正确的 mention 对象
|
||||||
const mentionObj = {
|
const mentionObj = {
|
||||||
id: mentionSelect.user_id, // 使用 user_id 而不是 erp_user_id
|
id: mentionSelect.user_id, // 使用 user_id 而不是 erp_user_id
|
||||||
@ -1598,7 +1665,36 @@ onUnmounted(() => {
|
|||||||
if (avatarPressTimer) {
|
if (avatarPressTimer) {
|
||||||
clearTimeout(avatarPressTimer)
|
clearTimeout(avatarPressTimer)
|
||||||
}
|
}
|
||||||
|
// 清理防抖定时器
|
||||||
|
if (state.value.showMentionSelectTimer) {
|
||||||
|
clearTimeout(state.value.showMentionSelectTimer)
|
||||||
|
}
|
||||||
|
if (uploadsStore.isUploading) {
|
||||||
|
uploadsStore.clearUpload()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 修改防抖函数的实现
|
||||||
|
const showMentionSelectDebounced = (quill) => {
|
||||||
|
const text = quill.getText()
|
||||||
|
// 如果文本内容与上次不同,重置触发状态
|
||||||
|
|
||||||
|
if (text !== state.value.lastMentionText) {
|
||||||
|
state.value.lastMentionTriggered = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已经触发过,则不再触发
|
||||||
|
if (state.value.lastMentionTriggered) {
|
||||||
|
console.log('return')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录当前文本内容和触发状态
|
||||||
|
state.value.lastMentionText = text
|
||||||
|
state.value.lastMentionTriggered = true
|
||||||
|
state.value.isShowMentionSelect = true
|
||||||
|
quill.blur()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.dialog-page {
|
.dialog-page {
|
||||||
@ -1653,13 +1749,16 @@ onUnmounted(() => {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: -webkit-inline-box;
|
display: -webkit-inline-box;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
margin: 0 0 0 30rpx;
|
margin: 0 0 0 30rpx;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@ -1872,6 +1971,7 @@ onUnmounted(() => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
:deep(.ql-clipboard) {
|
:deep(.ql-clipboard) {
|
||||||
position: relative;
|
position: relative;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@ -1923,6 +2023,7 @@ onUnmounted(() => {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
/* 确保 z-index 低于 deepBubble */
|
/* 确保 z-index 低于 deepBubble */
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 1rpx;
|
height: 1rpx;
|
||||||
@ -1935,20 +2036,24 @@ onUnmounted(() => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 36rpx 32rpx 0;
|
padding: 36rpx 32rpx 0;
|
||||||
|
|
||||||
.cancel-btns {
|
.cancel-btns {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
.hide-btn {
|
.hide-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
text {
|
text {
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 18rpx;
|
width: 18rpx;
|
||||||
height: 10rpx;
|
height: 10rpx;
|
||||||
@ -1965,6 +2070,7 @@ onUnmounted(() => {
|
|||||||
background-color: #f3f3f3;
|
background-color: #f3f3f3;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: #bababa;
|
color: #bababa;
|
||||||
line-height: 40rpx;
|
line-height: 40rpx;
|
||||||
@ -1974,6 +2080,7 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
.mention-done-btn-can-do {
|
.mention-done-btn-can-do {
|
||||||
background-color: #46299d;
|
background-color: #46299d;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@ -1985,11 +2092,13 @@ onUnmounted(() => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.mention) {
|
:deep(.mention) {
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { ServeGetForwardRecords } from '@/api/chat'
|
import { ServeGetForwardRecords } from '@/api/chat'
|
||||||
import { MessageComponents } from '@/constant/message'
|
import { MessageComponents } from '@/constant/message'
|
||||||
@ -47,12 +48,12 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="outer-layer">
|
<div class="forward-record-page">
|
||||||
<div>
|
<zPaging ref="zPaging" :show-scrollbar="false">
|
||||||
<tm-navbar :hideBack="false" hideHome :title="`${title}的会话记录`" >
|
<template #top>
|
||||||
</tm-navbar>
|
<customNavbar :title="`${title}的会话记录`"></customNavbar>
|
||||||
</div>
|
</template>
|
||||||
<div class="main-box">
|
<div class="main-box">
|
||||||
<div v-if="items.length === 0" class="flex justify-center items-center w-full mt-[200rpx]">
|
<div v-if="items.length === 0" class="flex justify-center items-center w-full mt-[200rpx]">
|
||||||
<wd-loading />
|
<wd-loading />
|
||||||
</div>
|
</div>
|
||||||
@ -76,16 +77,15 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</zPaging>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.outer-layer {
|
.forward-record-page {
|
||||||
overflow-y: auto;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background-image: url("@/static/image/clockIn/z3280@3x.png");
|
background-image: url("@/static/image/clockIn/z3280@3x.png");
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
padding: 0 66rpx 20rpx 50rpx;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ onMounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-top: 28rpx;
|
padding: 28rpx 66rpx 20rpx 50rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-item {
|
.message-item {
|
||||||
|
@ -65,6 +65,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="chatInfo_2 w-full mr-[6rpx]">
|
<div class="chatInfo_2 w-full mr-[6rpx]">
|
||||||
<div class="w-full chatInfo_2_1 textEllipsis">
|
<div class="w-full chatInfo_2_1 textEllipsis">
|
||||||
|
<span v-if="props.data.atsign_num" style="color: red;">
|
||||||
|
[有人@你]
|
||||||
|
</span>
|
||||||
{{ props.data.msg_text }}
|
{{ props.data.msg_text }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -107,6 +110,9 @@ import { useSessionMenu } from '@/hooks'
|
|||||||
const talkStore = useTalkStore()
|
const talkStore = useTalkStore()
|
||||||
const { onToTopTalk, onRemoveTalk } = useSessionMenu()
|
const { onToTopTalk, onRemoveTalk } = useSessionMenu()
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
|
const dialogueParams = reactive({
|
||||||
|
unReadNum: computed(() => dialogueStore.unreadNum),
|
||||||
|
})
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -132,14 +138,18 @@ const cellClick = () => {
|
|||||||
|
|
||||||
// 清空消息未读数
|
// 清空消息未读数
|
||||||
if (props.data.unread_num > 0) {
|
if (props.data.unread_num > 0) {
|
||||||
ServeClearTalkUnreadNum({
|
ServeClearTalkUnreadNum(
|
||||||
talk_type: props.data.talk_type,
|
{
|
||||||
receiver_id: props.data.receiver_id,
|
talk_type: props.data.talk_type,
|
||||||
}).then(() => {
|
receiver_id: props.data.receiver_id,
|
||||||
|
},
|
||||||
|
dialogueParams.unReadNum,
|
||||||
|
).then(() => {
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: props.data.index_name,
|
index_name: props.data.index_name,
|
||||||
unread_num: 0,
|
unread_num: 0,
|
||||||
})
|
})
|
||||||
|
dialogueStore.clearUnreadNum()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
@ -255,6 +265,7 @@ const handleDelete = () => {
|
|||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 1;
|
-webkit-line-clamp: 1;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
|
@ -138,6 +138,9 @@ const isEmptyViewShow = ref(false)
|
|||||||
const talkStore = useTalkStore()
|
const talkStore = useTalkStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
|
const dialogueParams = reactive({
|
||||||
|
unReadNum: computed(() => dialogueStore.unreadNum),
|
||||||
|
})
|
||||||
const { userInfo } = useAuth()
|
const { userInfo } = useAuth()
|
||||||
|
|
||||||
const topItems = computed(() => talkStore.topItems)
|
const topItems = computed(() => talkStore.topItems)
|
||||||
@ -244,11 +247,12 @@ onLoad((options) => {
|
|||||||
ServeClearTalkUnreadNum({
|
ServeClearTalkUnreadNum({
|
||||||
talk_type: openSession.talk_type,
|
talk_type: openSession.talk_type,
|
||||||
receiver_id: openSession.receiver_id,
|
receiver_id: openSession.receiver_id,
|
||||||
}).then(() => {
|
},dialogueParams.unReadNum).then(() => {
|
||||||
talkStore.updateItem({
|
talkStore.updateItem({
|
||||||
index_name: openSession.index_name,
|
index_name: openSession.index_name,
|
||||||
unread_num: 0,
|
unread_num: 0,
|
||||||
})
|
})
|
||||||
|
dialogueStore.clearUnreadNum()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
:default-page-size="props.searchResultPageSize"
|
:default-page-size="props.searchResultPageSize"
|
||||||
:loading-more-default-as-loading="true"
|
:loading-more-default-as-loading="true"
|
||||||
:inside-more="true"
|
:inside-more="true"
|
||||||
:empty-view-img="'/src/static//image/search/search-no-data.png'"
|
:empty-view-img="searchNoData"
|
||||||
:empty-view-text="$t('search.hint')"
|
:empty-view-text="$t('search.hint')"
|
||||||
:empty-view-img-style="{ width: '476rpx', height: '261rpx' }"
|
:empty-view-img-style="{ width: '476rpx', height: '261rpx' }"
|
||||||
:empty-view-title-style="{
|
:empty-view-title-style="{
|
||||||
@ -113,6 +113,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import searchNoData from '@/static/image/search/search-no-data.png'
|
||||||
import customInput from '@/components/custom-input/custom-input.vue'
|
import customInput from '@/components/custom-input/custom-input.vue'
|
||||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||||
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
||||||
@ -360,9 +361,16 @@ const queryAllSearch = (pageNum, searchResultPageSize) => {
|
|||||||
|
|
||||||
//点击取消搜索
|
//点击取消搜索
|
||||||
const cancelSearch = () => {
|
const cancelSearch = () => {
|
||||||
uni.navigateBack({
|
const pages = getCurrentPages()
|
||||||
delta: 1,
|
if (pages.length > 1) {
|
||||||
})
|
uni.navigateBack({
|
||||||
|
delta: 1,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/index/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取key对应值
|
//获取key对应值
|
||||||
@ -432,7 +440,7 @@ const getHasMoreResult = (searchResultKey) => {
|
|||||||
case 'general_infos':
|
case 'general_infos':
|
||||||
if (
|
if (
|
||||||
state.searchResult['record_count'] &&
|
state.searchResult['record_count'] &&
|
||||||
state.searchResult['record_count'] > 3
|
state.searchResult['record_count'] >= 3
|
||||||
) {
|
) {
|
||||||
has_more_result = t('has_more') + t('chat.type.record')
|
has_more_result = t('has_more') + t('chat.type.record')
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,9 @@ import { ServeSeachQueryAll, ServeGetSessionId } from '@/api/search/index'
|
|||||||
import { onMounted } from 'vue'
|
import { onMounted } from 'vue'
|
||||||
import { handleSetWebviewStyle } from '@/utils/common'
|
import { handleSetWebviewStyle } from '@/utils/common'
|
||||||
|
|
||||||
import { useDialogueStore } from '@/store'
|
import { useDialogueStore, useTalkStore } from '@/store'
|
||||||
|
import { ServeCreateTalkList } from '@/api/chat/index.js'
|
||||||
|
import { formatTalkItem } from '@/utils/talk'
|
||||||
|
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
|
|
||||||
@ -50,6 +52,18 @@ const clickSearchItem = async (
|
|||||||
console.log(talk_type, receiver_id)
|
console.log(talk_type, receiver_id)
|
||||||
const sessionId = await getSessionId(talk_type, receiver_id)
|
const sessionId = await getSessionId(talk_type, receiver_id)
|
||||||
if (searchResultKey === 'user_infos') {
|
if (searchResultKey === 'user_infos') {
|
||||||
|
if (useTalkStore().findTalkIndex(`${talk_type}_${receiver_id}`) === -1) {
|
||||||
|
ServeCreateTalkList({
|
||||||
|
talk_type,
|
||||||
|
receiver_id,
|
||||||
|
erp_user_id: result.erp_user_id,
|
||||||
|
}).then(async ({ code, data }) => {
|
||||||
|
if (code == 200) {
|
||||||
|
let item = formatTalkItem(data)
|
||||||
|
useTalkStore().addItem(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
dialogueStore.setDialogue({
|
dialogueStore.setDialogue({
|
||||||
name: result.nickname,
|
name: result.nickname,
|
||||||
talk_type: 1,
|
talk_type: 1,
|
||||||
@ -65,7 +79,7 @@ const clickSearchItem = async (
|
|||||||
receiver_id: result.group_id || result.id,
|
receiver_id: result.group_id || result.id,
|
||||||
})
|
})
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/dialog/index?sessionId=' + sessionId
|
url: '/pages/dialog/index?sessionId=' + sessionId,
|
||||||
})
|
})
|
||||||
} else if (searchResultKey === 'general_infos') {
|
} else if (searchResultKey === 'general_infos') {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
@ -25,7 +25,9 @@ import {
|
|||||||
} from '@/api/search/index'
|
} from '@/api/search/index'
|
||||||
import { reactive } from 'vue'
|
import { reactive } from 'vue'
|
||||||
|
|
||||||
import { useDialogueStore } from '@/store'
|
import { useDialogueStore, useTalkStore } from '@/store'
|
||||||
|
import { ServeCreateTalkList } from '@/api/chat/index.js'
|
||||||
|
import { formatTalkItem } from '@/utils/talk'
|
||||||
|
|
||||||
const dialogueStore = useDialogueStore()
|
const dialogueStore = useDialogueStore()
|
||||||
|
|
||||||
@ -75,7 +77,13 @@ onLoad((options) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
//分页查询时,最后一条id变化
|
//分页查询时,最后一条id变化
|
||||||
const lastIdChange = (last_id, last_group_id, last_member_id, last_receiver_user_name, last_receiver_group_name) => {
|
const lastIdChange = (
|
||||||
|
last_id,
|
||||||
|
last_group_id,
|
||||||
|
last_member_id,
|
||||||
|
last_receiver_user_name,
|
||||||
|
last_receiver_group_name,
|
||||||
|
) => {
|
||||||
let idChanges = {
|
let idChanges = {
|
||||||
last_id,
|
last_id,
|
||||||
last_group_id,
|
last_group_id,
|
||||||
@ -108,6 +116,18 @@ const clickSearchItem = async (
|
|||||||
console.log(talk_type, receiver_id)
|
console.log(talk_type, receiver_id)
|
||||||
const sessionId = await getSessionId(talk_type, receiver_id)
|
const sessionId = await getSessionId(talk_type, receiver_id)
|
||||||
if (state.searchResultKey === 'user_infos') {
|
if (state.searchResultKey === 'user_infos') {
|
||||||
|
if (useTalkStore().findTalkIndex(`${talk_type}_${receiver_id}`) === -1) {
|
||||||
|
ServeCreateTalkList({
|
||||||
|
talk_type,
|
||||||
|
receiver_id,
|
||||||
|
erp_user_id: result.erp_user_id,
|
||||||
|
}).then(async ({ code, data }) => {
|
||||||
|
if (code == 200) {
|
||||||
|
let item = formatTalkItem(data)
|
||||||
|
useTalkStore().addItem(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
dialogueStore.setDialogue({
|
dialogueStore.setDialogue({
|
||||||
name: result.nickname,
|
name: result.nickname,
|
||||||
talk_type: 1,
|
talk_type: 1,
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<span class="text-[28rpx] font-regular">
|
<span class="text-[28rpx] font-regular">
|
||||||
{{ state.selectedMonth }}
|
{{ state.selectedMonth }}
|
||||||
</span>
|
</span>
|
||||||
<img src="/src/static/image/search/down-pointer.png" />
|
<img src="@/static/image/search/down-pointer.png" />
|
||||||
</div>
|
</div>
|
||||||
</tm-time-picker>
|
</tm-time-picker>
|
||||||
<tm-calendar-view
|
<tm-calendar-view
|
||||||
@ -123,7 +123,10 @@
|
|||||||
state.condition === 'imgAndVideo' ? '0 0 10rpx' : '',
|
state.condition === 'imgAndVideo' ? '0 0 10rpx' : '',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="condition-result-member">
|
<div
|
||||||
|
class="condition-result-member"
|
||||||
|
v-if="state.condition === 'member'"
|
||||||
|
>
|
||||||
<searchItem
|
<searchItem
|
||||||
@click="toDialogueByMember(item)"
|
@click="toDialogueByMember(item)"
|
||||||
:searchResultKey="'search_by_member_condition'"
|
:searchResultKey="'search_by_member_condition'"
|
||||||
@ -157,17 +160,27 @@
|
|||||||
class="condition-result-imgAndVideo-area"
|
class="condition-result-imgAndVideo-area"
|
||||||
v-if="item?.extra?.url"
|
v-if="item?.extra?.url"
|
||||||
>
|
>
|
||||||
<tm-image
|
<template v-if="item?.msg_type === 3">
|
||||||
preview
|
<tm-image
|
||||||
:src="
|
preview
|
||||||
item?.msg_type === 3
|
:src="item?.extra?.url"
|
||||||
? item?.extra?.url
|
model="aspectFill"
|
||||||
: item?.msg_type === 5
|
/>
|
||||||
? item?.extra?.cover
|
</template>
|
||||||
: ''
|
<template v-else-if="item?.msg_type === 5">
|
||||||
"
|
<div
|
||||||
model="aspectFill"
|
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>
|
</div>
|
||||||
<div
|
<div
|
||||||
@ -199,7 +212,7 @@
|
|||||||
v-if="state.condition === 'file'"
|
v-if="state.condition === 'file'"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src="/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>
|
||||||
@ -254,6 +267,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ZPaging>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -263,13 +290,14 @@ import fileType_EXCEL from '@/static/image/search/fileType_EXCEL.png'
|
|||||||
import fileType_WORD from '@/static/image/search/fileType_WORD.png'
|
import fileType_WORD from '@/static/image/search/fileType_WORD.png'
|
||||||
import fileType_PDF from '@/static/image/search/fileType_PDF.png'
|
import fileType_PDF from '@/static/image/search/fileType_PDF.png'
|
||||||
import fileType_Files from '@/static/image/search/fileType_Files.png'
|
import fileType_Files from '@/static/image/search/fileType_Files.png'
|
||||||
|
import playCircle from '@/static/image/chatList/playCircle@2x.png'
|
||||||
import { fileFormatSize, fileSuffix } from '@/utils/strings'
|
import { fileFormatSize, fileSuffix } from '@/utils/strings'
|
||||||
import searchItem from '../components/searchItem.vue'
|
import searchItem from '../components/searchItem.vue'
|
||||||
import customInput from '@/components/custom-input/custom-input.vue'
|
import customInput from '@/components/custom-input/custom-input.vue'
|
||||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||||
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
||||||
import { parseTime } from '@/utils/datetime'
|
import { parseTime } from '@/utils/datetime'
|
||||||
import { onMounted, reactive, computed, ref } from 'vue'
|
import { onMounted, reactive, computed, ref, nextTick } from 'vue'
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { ServeTalkDate, ServeGetSessionId } from '@/api/search/index'
|
import { ServeTalkDate, ServeGetSessionId } from '@/api/search/index'
|
||||||
import { ServeFindTalkRecords } from '@/api/chat/index'
|
import { ServeFindTalkRecords } from '@/api/chat/index'
|
||||||
@ -308,6 +336,39 @@ const state = reactive({
|
|||||||
flatList: [], // 用于存储扁平化的数据
|
flatList: [], // 用于存储扁平化的数据
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
console.log(options)
|
console.log(options)
|
||||||
if (options.condition) {
|
if (options.condition) {
|
||||||
@ -500,9 +561,16 @@ const inputSearchText = (e) => {
|
|||||||
|
|
||||||
//点击取消搜索
|
//点击取消搜索
|
||||||
const cancelSearch = () => {
|
const cancelSearch = () => {
|
||||||
uni.navigateBack({
|
const pages = getCurrentPages()
|
||||||
delta: 1,
|
if (pages.length > 1) {
|
||||||
})
|
uni.navigateBack({
|
||||||
|
delta: 1,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/index/index',
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//查询数据
|
//查询数据
|
||||||
@ -829,6 +897,26 @@ body::v-deep .round-3 {
|
|||||||
width: 164rpx !important;
|
width: 164rpx !important;
|
||||||
height: 164rpx !important;
|
height: 164rpx !important;
|
||||||
}
|
}
|
||||||
|
.video-preview {
|
||||||
|
position: relative;
|
||||||
|
width: 164rpx;
|
||||||
|
height: 164rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
.play-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 80rpx !important;
|
||||||
|
height: 80rpx !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -837,4 +925,23 @@ body::v-deep .round-3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.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>
|
</style>
|
||||||
|
@ -15,6 +15,10 @@ import { useAuth } from '../auth/index'
|
|||||||
// let keyboardTimeout = null
|
// let keyboardTimeout = null
|
||||||
|
|
||||||
export const useDialogueStore = defineStore('dialogue', {
|
export const useDialogueStore = defineStore('dialogue', {
|
||||||
|
// 添加持久化配置
|
||||||
|
persist: {
|
||||||
|
paths: ['talk.talk_type', 'talk.receiver_id']
|
||||||
|
},
|
||||||
state: () => {
|
state: () => {
|
||||||
return {
|
return {
|
||||||
// 对话索引(聊天对话的唯一索引)
|
// 对话索引(聊天对话的唯一索引)
|
||||||
@ -54,6 +58,9 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
//是否退群/移出群
|
//是否退群/移出群
|
||||||
isQuit: false,
|
isQuit: false,
|
||||||
|
|
||||||
|
//未读消息数量
|
||||||
|
unreadNum:0,
|
||||||
|
|
||||||
// 群成员列表
|
// 群成员列表
|
||||||
members: [],
|
members: [],
|
||||||
|
|
||||||
@ -90,6 +97,21 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
this.online = status
|
this.online = status
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 更新未读消息数量-清空未读
|
||||||
|
clearUnreadNum() {
|
||||||
|
this.unreadNum = 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新群解散状态
|
||||||
|
updateDismiss() {
|
||||||
|
this.isDismiss = true
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新群成员退出状态
|
||||||
|
updateQuit() {
|
||||||
|
this.isQuit = true
|
||||||
|
},
|
||||||
|
|
||||||
// 更新对话信息
|
// 更新对话信息
|
||||||
setDialogue(data = {}) {
|
setDialogue(data = {}) {
|
||||||
this.online = data.is_online == 1
|
this.online = data.is_online == 1
|
||||||
@ -107,8 +129,10 @@ export const useDialogueStore = defineStore('dialogue', {
|
|||||||
this.isDismiss = data?.is_dismiss === 1 ? true : false
|
this.isDismiss = data?.is_dismiss === 1 ? true : false
|
||||||
this.isQuit = data?.is_quit === 1 ? true : false
|
this.isQuit = data?.is_quit === 1 ? true : false
|
||||||
|
|
||||||
|
this.unreadNum = data?.unread_num || 0
|
||||||
|
|
||||||
this.members = []
|
this.members = []
|
||||||
if (data.talk_type == 2) {
|
if (data.talk_type == 2 && !this.isDismiss && !this.isQuit) {
|
||||||
this.updateGroupMembers()
|
this.updateGroupMembers()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -42,6 +42,7 @@ export const useDialogueListStore = createGlobalState(() => {
|
|||||||
isShowSessionList: dialogue.isShowSessionList,
|
isShowSessionList: dialogue.isShowSessionList,
|
||||||
isDismiss: dialogue.isDismiss,
|
isDismiss: dialogue.isDismiss,
|
||||||
isQuit: dialogue.isQuit,
|
isQuit: dialogue.isQuit,
|
||||||
|
unreadNum: dialogue.unreadNum,
|
||||||
members: dialogue.members.map(member => ({
|
members: dialogue.members.map(member => ({
|
||||||
id: member.id,
|
id: member.id,
|
||||||
nickname: member.nickname,
|
nickname: member.nickname,
|
||||||
@ -140,6 +141,8 @@ export const useDialogueListStore = createGlobalState(() => {
|
|||||||
...virtualList.value[index], // 保留原有不需要修改的字段
|
...virtualList.value[index], // 保留原有不需要修改的字段
|
||||||
...item, // 覆盖需要更新的字段
|
...item, // 覆盖需要更新的字段
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
zpagingRef.value?.addChatRecordData(item, false, false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
zpagingRef.value?.addChatRecordData(item, false, false)
|
zpagingRef.value?.addChatRecordData(item, false, false)
|
||||||
|
@ -33,7 +33,9 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
state: () => {
|
state: () => {
|
||||||
return {
|
return {
|
||||||
isShow: false,
|
isShow: false,
|
||||||
items: []
|
items: [],
|
||||||
|
isUploading: false,//当前是否正在上传
|
||||||
|
uploadingNum: 0//当前正在上传数量
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
@ -74,7 +76,11 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
|
|
||||||
this.triggerUpload(upload_id,msgId)
|
this.triggerUpload(upload_id,msgId)
|
||||||
this.isShow = true
|
this.isShow = true
|
||||||
}
|
} else {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
|
}
|
||||||
|
}).catch(()=> {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -91,7 +97,19 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
|
|
||||||
item.status = 1
|
item.status = 1
|
||||||
|
|
||||||
ServeFileSubareaUpload(form)
|
// 开始上传时就更新进度
|
||||||
|
const currentPercentage = (item.uploadIndex / item.files.length) * 100
|
||||||
|
item.percentage = currentPercentage.toFixed(1)
|
||||||
|
updateUploadProgress(msgId, currentPercentage)
|
||||||
|
|
||||||
|
ServeFileSubareaUpload(form, (progressEvent) => {
|
||||||
|
// 计算当前分片的进度
|
||||||
|
const currentChunkProgress = (progressEvent.loaded / progressEvent.total) * 100
|
||||||
|
// 计算总体进度:已完成分片 + 当前分片的进度
|
||||||
|
const totalProgress = ((item.uploadIndex + currentChunkProgress / 100) / item.files.length) * 100
|
||||||
|
item.percentage = totalProgress.toFixed(1)
|
||||||
|
updateUploadProgress(msgId, totalProgress)
|
||||||
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
item.uploadIndex++
|
item.uploadIndex++
|
||||||
@ -103,21 +121,38 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
|
|
||||||
updateUploadProgress(msgId,100)
|
updateUploadProgress(msgId,100)
|
||||||
this.sendUploadMessage(item, msgId)
|
this.sendUploadMessage(item, msgId)
|
||||||
} else {
|
|
||||||
const percentage = (item.uploadIndex / item.files.length) * 100
|
|
||||||
item.percentage = percentage.toFixed(1)
|
|
||||||
console.log(msgId,'msgId');
|
|
||||||
console.log(percentage,'percentage');
|
|
||||||
|
|
||||||
updateUploadProgress(msgId,percentage)
|
// 更新虚拟列表中的状态
|
||||||
this.triggerUpload(uploadId,msgId)
|
const { virtualList } = useDialogueListStore()
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === msgId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 2
|
||||||
|
virtualList.value[index].uploadCurrent = 100
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 继续上传下一个分片
|
||||||
|
this.triggerUpload(uploadId, msgId)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
item.status = 3
|
item.status = 3
|
||||||
|
// 更新虚拟列表中的状态为失败
|
||||||
|
const { virtualList } = useDialogueListStore()
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === msgId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
item.status = 3
|
item.status = 3
|
||||||
|
// 更新虚拟列表中的状态为失败
|
||||||
|
const { virtualList } = useDialogueListStore()
|
||||||
|
const index = virtualList.value.findIndex(item => item.file_num === msgId)
|
||||||
|
if (index !== -1) {
|
||||||
|
virtualList.value[index].uploadStatus = 3
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -128,7 +163,38 @@ export const useUploadsStore = defineStore('uploads', {
|
|||||||
receiver_id: item.receiver_id,
|
receiver_id: item.receiver_id,
|
||||||
talk_type: item.talk_type,
|
talk_type: item.talk_type,
|
||||||
file_num: file_num
|
file_num: file_num
|
||||||
|
}).then((res) => {
|
||||||
|
console.log(res, 'res')
|
||||||
|
if(res.code == 200){
|
||||||
|
this.updateUploadStatus(false)
|
||||||
|
}else{
|
||||||
|
this.updateUploadStatus(false)
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.updateUploadStatus(false)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
//更新资源上传状态
|
||||||
|
updateUploadStatus(isUploading: boolean){
|
||||||
|
if(isUploading){
|
||||||
|
this.uploadingNum++
|
||||||
|
this.isUploading = true
|
||||||
|
}else{
|
||||||
|
this.uploadingNum--
|
||||||
|
if(this.uploadingNum < 0){
|
||||||
|
this.uploadingNum = 0
|
||||||
|
}
|
||||||
|
if(this.uploadingNum === 0){
|
||||||
|
this.isUploading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 清除上传
|
||||||
|
clearUpload(){
|
||||||
|
this.isUploading = false
|
||||||
|
this.uploadingNum = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -104,6 +104,11 @@ export const upload = (url, data = {}, options = {}) => {
|
|||||||
url,
|
url,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
|
onUploadProgress: (progressEvent) => {
|
||||||
|
if (options.onProgress) {
|
||||||
|
options.onProgress(progressEvent)
|
||||||
|
}
|
||||||
|
},
|
||||||
...options
|
...options
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user