Compare commits

...

6 Commits

Author SHA1 Message Date
张 元山
42c1b64a99 video plus 2025-03-29 09:01:21 +08:00
张 元山
ed8da6cde9 测试部署 2025-03-21 09:24:12 +08:00
张 元山
e832181432 测试部署 2025-03-21 09:20:45 +08:00
张 元山
7baca98e4d 测试构建 2025-03-21 09:13:20 +08:00
张 元山
5962e0b12d fix record 2025-03-20 17:03:29 +08:00
张 元山
4f66ff8b1d tm-drawer show替换 2025-03-20 15:29:17 +08:00
9 changed files with 484 additions and 217 deletions

2
components.d.ts vendored
View File

@ -30,8 +30,6 @@ declare module 'vue' {
LoginMessage: typeof import('./src/components/talk/message/LoginMessage.vue')['default'] LoginMessage: typeof import('./src/components/talk/message/LoginMessage.vue')['default']
Message: typeof import('./src/components/x-message/message/index.vue')['default'] Message: typeof import('./src/components/x-message/message/index.vue')['default']
MixedMessage: typeof import('./src/components/talk/message/MixedMessage.vue')['default'] MixedMessage: typeof import('./src/components/talk/message/MixedMessage.vue')['default']
NButton: typeof import('naive-ui')['NButton']
NIcon: typeof import('naive-ui')['NIcon']
PageAnimation: typeof import('./src/components/page-animation/index.vue')['default'] PageAnimation: typeof import('./src/components/page-animation/index.vue')['default']
RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default'] RevokeMessage: typeof import('./src/components/talk/message/RevokeMessage.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']

View File

@ -74,7 +74,7 @@ export const useTalkRecord = (uid) => {
// 加载数据列表 // 加载数据列表
const load = async (params) => { const load = async (params) => {
const request = { const request = {
limit: 30, limit:10,
...params, ...params,
talk_type: params.talk_type, talk_type: params.talk_type,
receiver_id: params.receiver_id, receiver_id: params.receiver_id,

View File

@ -1,39 +1,25 @@
<template> <template>
<div class="emojiRoot"> <div class="emojiRoot">
<div <div @click="() => photoActionsSelect(0)" class="flex flex-col items-center">
@click="() => photoActionsSelect(0)" <div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
class="flex flex-col items-center"
>
<div
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
>
<tm-image :width="53" :height="44" :src="photoAlbum"></tm-image> <tm-image :width="53" :height="44" :src="photoAlbum"></tm-image>
</div> </div>
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">照片</div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">照片</div>
</div> </div>
<div <div @click="() => photoActionsSelect(1)" class="flex flex-col items-center">
@click="() => photoActionsSelect(1)" <div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
class="flex flex-col items-center"
>
<div
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
>
<tm-image :width="53" :height="44" :src="videoImg"></tm-image> <tm-image :width="53" :height="44" :src="videoImg"></tm-image>
</div> </div>
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">视频</div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">视频</div>
</div> </div>
<div @click="takePhoto" class="flex flex-col items-center"> <div @click="takePhoto" class="flex flex-col items-center">
<div <div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
>
<tm-image :width="53" :height="44" :src="photoGraph"></tm-image> <tm-image :width="53" :height="44" :src="photoGraph"></tm-image>
</div> </div>
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">拍摄</div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">拍摄</div>
</div> </div>
<div @click="chooseFile" class="flex flex-col items-center"> <div @click="chooseFile" class="flex flex-col items-center">
<div <div class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center">
class="w-[106rpx] h-[106rpx] bg-[#F9F9F9] rounded-[60rpx] flex-center"
>
<tm-image :width="53" :height="44" :src="folder"></tm-image> <tm-image :width="53" :height="44" :src="folder"></tm-image>
</div> </div>
<div class="mt-[6rpx] text-[#666666] text-[24rpx]">文件</div> <div class="mt-[6rpx] text-[#666666] text-[24rpx]">文件</div>
@ -72,7 +58,7 @@ const props = defineProps({
}) })
const state = reactive({ const state = reactive({
base64Url: '' base64Url: '',
}) })
const uploadsStore = useUploadsStore() const uploadsStore = useUploadsStore()
@ -92,36 +78,226 @@ const onProgressFn = (progress, id) => {
updateUploadProgress(id, (progress.loaded / progress.total) * 100) updateUploadProgress(id, (progress.loaded / progress.total) * 100)
} }
const photoActionsSelect = (index) => { const photoActionsSelect = async (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) 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)
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 {
// uni.chooseVideo({
// sourceType: ['album'],
// compressed: true,
// maxDuration: 60,
// success: async (res) => {
// console.log( 'chooseVideo res.tempFilePath',res.tempFilePath)
// console.log( 'chooseVideo res.tempFile',res.tempFile)
// return
// let data = await onUploadImageVideo(
// res.tempFile,
// 'video',
// res.tempFilePath,
// )
// emit('selectImg', data, data.file_num)
// },
// })
plus?.gallery.pick(
(res) => {
res.files.reverse()
res.files.forEach(async (filePath) => {
plus?.io?.resolveLocalFileSystemURL(
filePath,
async (entry) => {
entry.file(async (file) => {
try {
console.log('filePath', filePath)
// Blob URL
playVideoWithNativeBridge(filePath)
const videoInfo = await getVideoInfo(filePath);
console.log('视频信息:', videoInfo);
console.log('文件详细信息:', {
name: file.name,
size: file.size,
type: file.type,
});
const fileInfo = await getFilePath(file);
console.log('fileInfo', fileInfo)
//
let data = await onUploadImageVideo(file, 'video', videoInfo);
emit('selectImg', data, data.file_num);
} catch (error) {
console.log('文件处理失败:', error);
}
})
},
(err) => {
console.log(err)
},
)
}) })
}, },
}) (err) => {
} else { console.log(err)
uni.chooseVideo({
sourceType: ['album'],
success: async (res) => {
console.log(res, 'res')
let data = await onUploadImageVideo(
res.tempFile,
'video',
res.tempFilePath,
)
emit('selectImg', data, data.file_num)
}, },
}) {
filter: 'video',
maximum: 2,
multiple: true,
onmaxed: () => {
plus.nativeUI.toast('最多只能选择2个视频')
},
},
)
} }
} }
const onUploadImageVideo = async (file, type = 'image', fileUrl) => { const playVideoWithNativeBridge = (filePath) => {
return new Promise((resolve, reject) => {
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.playVideo) {
// iOS WebView
window.webkit.messageHandlers.playVideo.postMessage({
filePath: filePath
});
resolve();
} else if (window.android && window.android.playVideo) {
// Android WebView
window.android.playVideo(filePath);
resolve();
} else if (window.plus) {
// 使 plus API HTTP
plus.bridge.exec('VideoPlayerModule', 'playVideoFromPath', [filePath],
(httpUrl) => {
console.log('获取到HTTP URL:', httpUrl);
resolve(httpUrl);
},
(error) => {
console.error('原生方法调用失败:', error);
reject(error);
}
);
} else {
reject(new Error('没有可用的原生桥接方法'));
}
});
};
const getFilePath = async (file) => {
try {
// #ifdef H5
// plus Blob
return new Promise((resolve, reject) => {
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
const reader = new plus.io.FileReader();
reader.onload = function (e) {
// Blob
const blob = new Blob([e.target.result], { type: file.type || 'video/mp4' });
// File
const newFile = new File([blob], file.name || 'video.mp4', {
type: file.type || 'video/mp4'
});
// FormData
// const formData = new FormData();
// formData.append('file', newFile);
//
// formData.append('other_field', 'value');
resolve(newFile);
};
reader.onerror = function (error) {
console.error('读取文件失败:', error);
reject(error);
};
reader.readAsArrayBuffer(file);
});
});
// #endif
// #ifndef H5
const formData = new FormData();
formData.append('file', file);
return formData;
// #endif
} catch (error) {
console.error('处理文件失败:', error);
throw error;
}
};
const onUploadImageVideo = async (file, type = 'image', resp) => {
console.log(file, 'file') console.log(file, 'file')
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
if (type === 'image') { if (type === 'image') {
@ -132,6 +308,7 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
form.append('file', file) form.append('file', file)
form.append('source', 'fonchain-chat') form.append('source', 'fonchain-chat')
form.append('urlParam', `width=${image.width}&height=${image.height}`) form.append('urlParam', `width=${image.width}&height=${image.height}`)
let randomId = uniqueId() let randomId = uniqueId()
let newItem = { let newItem = {
avatar: userStore.avatar, avatar: userStore.avatar,
@ -164,6 +341,12 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
uploadImg(form, (e) => onProgressFn(e, randomId)).then( uploadImg(form, (e) => onProgressFn(e, randomId)).then(
({ status, data, msg }) => { ({ status, data, msg }) => {
if (status == 0) { 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
}
resolve({ resolve({
type: 'image', type: 'image',
url: data.ori_url, url: data.ori_url,
@ -173,6 +356,11 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
file_num: randomId, file_num: randomId,
}) })
} else { } else {
//
const index = virtualList.value.findIndex(item => item.file_num === randomId)
if (index !== -1) {
virtualList.value[index].uploadStatus = 3
}
resolve('') resolve('')
message.error(msg) message.error(msg)
} }
@ -180,67 +368,100 @@ const onUploadImageVideo = async (file, type = 'image', fileUrl) => {
) )
} }
} else { } else {
uni.getVideoInfo({
src: fileUrl,
success: (resp) => {
console.log(resp)
form.append('file', file)
form.append('source', 'fonchain-chat')
form.append('type', 'video')
form.append('urlParam', `width=${resp.width}&height=${resp.height}`)
let randomId = uniqueId()
let newItem = {
avatar: userStore.avatar,
created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
extra: {
duration: parseInt(resp.duration),
height: resp.height,
name: '',
url: fileUrl,
width: resp.width,
},
float: 'right',
isCheck: false,
is_mark: 0,
is_read: 0,
is_revoke: 0,
msg_id: randomId,
file_num: randomId,
msg_type: 5,
nickname: userStore.nickname,
receiver_id: dialogueStore.talk.receiver_id,
sequence: -1,
talk_type: dialogueStore.talk.talk_type,
user_id: userStore.uid,
uploadCurrent: 0,
uploadStatus: 1, // 1 2 3
}
virtualList.value.unshift(newItem)
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
({ status, data, msg }) => {
if (status == 0) {
console.log(data)
resolve({
type: 'video',
url: data.ori_url,
cover: data.cover_url,
duration: parseInt(resp.duration),
size: file.size,
file_num: randomId,
})
} else {
// resolve('')
// message.error(msg)
}
},
)
},
})
const form = new FormData() const form = new FormData()
form.append('file', file)
form.append('source', 'fonchain-chat')
form.append('type', 'video')
form.append('urlParam', `width=${resp.width}&height=${resp.height}`)
// FormData
for (let pair of form.entries()) {
console.log('video form', `${pair[0]}: ${pair[1]}`);
}
let randomId = uniqueId()
let newItem = {
avatar: userStore.avatar,
created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
extra: {
duration: parseInt(resp.duration),
height: resp.height,
name: '',
url: resp.fileUrl,
width: resp.width,
},
float: 'right',
isCheck: false,
is_mark: 0,
is_read: 0,
is_revoke: 0,
msg_id: randomId,
file_num: randomId,
msg_type: 5,
nickname: userStore.nickname,
receiver_id: dialogueStore.talk.receiver_id,
sequence: -1,
talk_type: dialogueStore.talk.talk_type,
user_id: userStore.uid,
uploadCurrent: 0,
uploadStatus: 1, // 1 2 3
}
virtualList.value.unshift(newItem)
console.log('uploadImg params', form)
uploadImg(form, (e) => onProgressFn(e, randomId)).then(
({ 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
}
console.log(data)
resolve({
type: 'video',
url: data.ori_url,
cover: data.cover_url,
duration: parseInt(resp.duration),
size: file.size,
file_num: randomId,
})
} else {
//
const index = virtualList.value.findIndex(item => item.file_num === randomId)
if (index !== -1) {
virtualList.value[index].uploadStatus = 3
}
resolve('')
message.error(msg)
}
},
)
} }
}) })
} }
const getVideoInfo = (filePath) => {
return new Promise((resolve, reject) => {
plus.io.getVideoInfo({
filePath: filePath,
success: (res) => {
resolve({
width: res.width,
height: res.height,
duration: res.duration,
fileUrl: filePath,
size: res.size
});
},
fail: (err) => {
console.log('获取视频信息失败:', err);
reject(err);
}
});
});
};
const base64ToFile = (base64) => { const base64ToFile = (base64) => {
// base64file // base64file
const [header, base64String] = base64.split(';base64,') const [header, base64String] = base64.split(';base64,')
@ -351,7 +572,7 @@ const getCamera = () => {
}, },
) )
}, },
() => {}, () => { },
{ index: '2' }, { index: '2' },
) )
} }
@ -414,7 +635,23 @@ 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.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 {
//
const index = virtualList.value.findIndex(item => item.file_num === randomId)
if (index !== -1) {
virtualList.value[index].uploadStatus = 3
}
message.error(msg)
}
})
}, },
}) })
} }

View File

@ -331,7 +331,7 @@
<div class="content-placeholder"></div> <div class="content-placeholder"></div>
<tm-drawer <tm-drawer
placement="bottom" placement="bottom"
v-model:show="state.showWin" v-model:visibleShow="state.showWin"
:hideHeader="true" :hideHeader="true"
:height="416" :height="416"
:round="6" :round="6"
@ -363,7 +363,7 @@
</ZPaging> </ZPaging>
<tm-drawer <tm-drawer
placement="bottom" placement="bottom"
v-model:show="state.isShowMentionSelect" v-model:visibleShow="state.isShowMentionSelect"
:hideHeader="true" :hideHeader="true"
:round="5" :round="5"
:height="state.mentionSelectHeight" :height="state.mentionSelectHeight"
@ -563,15 +563,15 @@ const state = ref({
serveFindRecord: [], // serveFindRecord: [], //
middleMsg: {}, //使 middleMsg: {}, //使
keepDialogInfo: false, // keepDialogInfo: false, //
}) });
uniOnload(async (options) => { uniOnload(async (options) => {
console.log('onLoad' + JSON.stringify(options)) console.log("onLoad" + JSON.stringify(options));
if (options.sessionId) { if (options.sessionId) {
state.value.sessionId = options.sessionId; state.value.sessionId = options.sessionId;
} }
if (options.keepDialogInfo) { if (options.keepDialogInfo) {
state.value.keepDialogInfo = options.keepDialogInfo === '1' ? true : false state.value.keepDialogInfo = options.keepDialogInfo === "1" ? true : false;
} }
if (options.msgInfo) { if (options.msgInfo) {
const msgInfo = JSON.parse(decodeURIComponent(options.msgInfo)); const msgInfo = JSON.parse(decodeURIComponent(options.msgInfo));
@ -875,7 +875,13 @@ const editorOption = {
} }
let list = [ let list = [
{ id: 0, nickname: "所有人", avatar: "https://cdn-test.szjixun.cn/artistinfo/test/4455/81e23b7a-d9a3-45c2-af9b-405d33083fed.jpg", value: "所有人" }, {
id: 0,
nickname: "所有人",
avatar:
"https://cdn-test.szjixun.cn/artistinfo/test/4455/81e23b7a-d9a3-45c2-af9b-405d33083fed.jpg",
value: "所有人",
},
...dialogueStore.members, ...dialogueStore.members,
]; ];
@ -977,8 +983,8 @@ const withdrawerConfirm = () => {
const canEditRevokedMessage = (item) => { const canEditRevokedMessage = (item) => {
// console.log(item) // console.log(item)
if (item.is_revoke === 1 && item.msg_type === 1) { if (item.is_revoke === 1 && item.msg_type === 1) {
const now = new Date().getTime() const now = new Date().getTime();
const revokeTime = new Date(item.created_at).getTime() const revokeTime = new Date(item.created_at).getTime();
// console.log(now) // console.log(now)
// 5 // 5
return now - revokeTime <= 5 * 60 * 1000; return now - revokeTime <= 5 * 60 * 1000;
@ -1107,9 +1113,9 @@ watch(
dialogueList?.records?.[0]?.sequence dialogueList?.records?.[0]?.sequence
) { ) {
// //
state.value.localPageLoadDone = true state.value.localPageLoadDone = true;
} else { } else {
state.value.localPageLoadDone = false state.value.localPageLoadDone = false;
} }
} }
} }
@ -1141,10 +1147,12 @@ const onScrollToLower = async () => {
// //
const formattedMoreRecords = moreRecords.map((item) => ({ const formattedMoreRecords = moreRecords.map((item) => ({
...item, ...item,
float: item.user_id === talkParams.uid ? 'right' : 'left', float: item.user_id === talkParams.uid ? "right" : "left",
})) }));
virtualList.value = formattedMoreRecords.concat(tempVirtualList).reverse() virtualList.value = formattedMoreRecords
.concat(tempVirtualList)
.reverse();
console.log(virtualList.value); console.log(virtualList.value);
} else { } else {
@ -1188,19 +1196,19 @@ const onScrollToUpper = async () => {
const moreRecords = await findTalkRecords( const moreRecords = await findTalkRecords(
"", "",
false, false,
tempVirtualList[tempVirtualList.length - 1].sequence, tempVirtualList[tempVirtualList.length - 1].sequence
) );
console.log(moreRecords) console.log(moreRecords);
// //
const formattedMoreRecords = moreRecords.map((item) => ({ const formattedMoreRecords = moreRecords.map((item) => ({
...item, ...item,
float: item.user_id === talkParams.uid ? 'right' : 'left', float: item.user_id === talkParams.uid ? "right" : "left",
})) }));
virtualList.value = tempVirtualList virtualList.value = tempVirtualList
.concat(formattedMoreRecords.reverse()) .concat(formattedMoreRecords.reverse())
.reverse() .reverse();
console.log(virtualList.value); console.log(virtualList.value);
@ -1328,9 +1336,9 @@ const getMentionSelectLists = (mentionSelectList) => {
//msgsequence //msgsequence
const queryRecordsByMsgInfo = async (msgInfo) => { const queryRecordsByMsgInfo = async (msgInfo) => {
console.log(msgInfo) console.log(msgInfo);
state.value.middleMsg = msgInfo state.value.middleMsg = msgInfo;
const dialogueList = getDialogueList(talkParams.index_name) const dialogueList = getDialogueList(talkParams.index_name);
const recordIndex = dialogueList?.records?.findIndex( const recordIndex = dialogueList?.records?.findIndex(
(record) => record.msg_id === msgInfo.msg_id (record) => record.msg_id === msgInfo.msg_id
); );
@ -1351,9 +1359,9 @@ const queryRecordsByMsgInfo = async (msgInfo) => {
recordsList = recordsList.map((item) => { recordsList = recordsList.map((item) => {
return { return {
...item, ...item,
float: item.user_id === talkParams.uid ? 'right' : 'left', float: item.user_id === talkParams.uid ? "right" : "left",
} };
}) });
nextTick(() => { nextTick(() => {
zpagingRef.value.complete(recordsList.reverse()); zpagingRef.value.complete(recordsList.reverse());
@ -1405,9 +1413,9 @@ const findTalkRecords = (record, isMiddle, sequence, appointParams) => {
start_time: "", start_time: "",
end_time: "", end_time: "",
group_member_user_id: 0, //id group_member_user_id: 0, //id
sort_sequence: 'asc', sort_sequence: "asc",
create_time: state.value.middleMsg.created_at, create_time: state.value.middleMsg.created_at,
} };
if (record) { if (record) {
params = Object.assign({}, params, { params = Object.assign({}, params, {
start_time: record, start_time: record,
@ -1506,7 +1514,7 @@ const rpxToPx = (rpx) => {
onUnmounted(() => { onUnmounted(() => {
if (!state.value.keepDialogInfo) { if (!state.value.keepDialogInfo) {
dialogueStore.setDialogue({}) dialogueStore.setDialogue({});
} }
clearMultiSelect(); clearMultiSelect();
}); });

View File

@ -33,7 +33,7 @@
<div class="flex items-center ml-[48rpx]"> <div class="flex items-center ml-[48rpx]">
<image <image
class="w-[72rpx] h-[72rpx]" class="w-[72rpx] h-[72rpx]"
style="border-radius: 50%;" style="border-radius: 50%"
:src="userStore.avatar" :src="userStore.avatar"
mode="scaleToFill" mode="scaleToFill"
/> />
@ -47,7 +47,7 @@
<tm-popover position="br" color="#333333" :width="260"> <tm-popover position="br" color="#333333" :width="260">
<image <image
class="w-[48rpx] h-[48rpx]" class="w-[48rpx] h-[48rpx]"
style="border-radius: 50%;" style="border-radius: 50%"
:src="addCircle" :src="addCircle"
mode="scaleToFill" mode="scaleToFill"
/> />
@ -120,32 +120,32 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import customInput from '@/components/custom-input/custom-input.vue' import customInput from "@/components/custom-input/custom-input.vue";
import { ref, watch, computed } from 'vue' import { ref, watch, computed } from "vue";
import { onShow, onLoad } from '@dcloudio/uni-app' import { onShow, onLoad } from "@dcloudio/uni-app";
import { useChatList } from '@/store/chatList/index.js' import { useChatList } from "@/store/chatList/index.js";
import { useAuth } from '@/store/auth' import { useAuth } from "@/store/auth";
import { ServeClearTalkUnreadNum } from '@/api/chat' import { ServeClearTalkUnreadNum } from "@/api/chat";
import { useTalkStore, useUserStore, useDialogueStore } from '@/store' import { useTalkStore, useUserStore, useDialogueStore } from "@/store";
import chatItem from './components/chatItem.vue' import chatItem from "./components/chatItem.vue";
import addCircle from '@/static/image/chatList/addCircle.png' import addCircle from "@/static/image/chatList/addCircle.png";
import cahtPopover from '@/static/image/chatList/cahtPopover.png' import cahtPopover from "@/static/image/chatList/cahtPopover.png";
import zu3289 from '@/static/image/chatList/zu3289@2x.png' import zu3289 from "@/static/image/chatList/zu3289@2x.png";
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 { handleSetWebviewStyle } from '@/utils/common' import { handleSetWebviewStyle } from "@/utils/common";
const paging = ref() const paging = ref();
const isEmptyViewShow = ref(false) const isEmptyViewShow = ref(false);
const talkStore = useTalkStore() const talkStore = useTalkStore();
const userStore = useUserStore() const userStore = useUserStore();
const dialogueStore = useDialogueStore() const dialogueStore = useDialogueStore();
const { userInfo } = useAuth() const { userInfo } = useAuth();
const topItems = computed(() => talkStore.topItems) const items = ref([]);
const items = computed(() => { const calcitems = computed(() => {
// if (searchKeyword.value.length === 0) { // if (searchKeyword.value.length === 0) {
console.log(talkStore.talkItems) console.log(talkStore.talkItems);
items.value = JSON.parse(JSON.stringify(talkStore.talkItems));
return talkStore.talkItems return talkStore.talkItems;
// } // }
// return talkStore.talkItems.filter((item) => { // return talkStore.talkItems.filter((item) => {
@ -153,59 +153,59 @@ const items = computed(() => {
// return keyword.toLowerCase().indexOf(searchKeyword.value.toLowerCase()) != -1 // return keyword.toLowerCase().indexOf(searchKeyword.value.toLowerCase()) != -1
// }) // })
}) });
const queryList = (pageNo, pageSize) => { const queryList = (pageNo, pageSize) => {
// paging.value.complete(res.data.list); // paging.value.complete(res.data.list);
console.log(talkStore) console.log(talkStore);
talkStore talkStore
.loadTalkList() .loadTalkList()
.then(() => { .then(() => {
isEmptyViewShow.value = talkStore.talkItems.length === 0 isEmptyViewShow.value = talkStore.talkItems.length === 0;
// //
paging.value.complete(talkStore.talkItems) paging.value.complete(talkStore.talkItems);
}) })
.catch((error) => { .catch((error) => {
// //
console.error('加载失败', error) console.error("加载失败", error);
paging.value.complete(false) paging.value.complete(false);
}) });
} };
// //
const onRefresh = () => { const onRefresh = () => {
console.log('触发下拉刷新') console.log("触发下拉刷新");
talkStore talkStore
.loadTalkList() .loadTalkList()
.then(() => { .then(() => {
// //
paging.value.complete(talkStore.talkItems) paging.value.complete(talkStore.talkItems);
}) })
.catch((error) => { .catch((error) => {
// //
console.error('加载失败', error) console.error("加载失败", error);
paging.value.complete(false) paging.value.complete(false);
}) });
} };
const creatGroupChat = () => { const creatGroupChat = () => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/creatGroupChat/index', url: "/pages/creatGroupChat/index",
}) });
} };
const toSearchPage = () => { const toSearchPage = () => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/search/index', url: "/pages/search/index",
}) });
} };
// //
const toAddressBookPage = () => { const toAddressBookPage = () => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/chooseByDeps/index?chooseMode=3', url: "/pages/chooseByDeps/index?chooseMode=3",
}) });
} };
/* watch( /* watch(
() => talkStore, () => talkStore,
@ -216,30 +216,30 @@ const toAddressBookPage = () => {
); */ ); */
onShow(() => { onShow(() => {
handleSetWebviewStyle(true) handleSetWebviewStyle(true);
// //
talkStore talkStore
.loadTalkList() .loadTalkList()
.then(() => { .then(() => {
// paging // paging
if (paging.value) { if (paging.value) {
paging.value.reload() paging.value.reload();
} }
}) })
.catch((error) => { .catch((error) => {
console.error('页面显示时数据加载失败', error) console.error("页面显示时数据加载失败", error);
}) });
}) });
onLoad((options) => { onLoad((options) => {
console.log(options) console.log(options);
if (options?.openSessionIndexName) { if (options?.openSessionIndexName) {
if (items?.value?.length > 0) { if (items?.value?.length > 0) {
items.value.forEach((openSession) => { items.value.forEach((openSession) => {
if (openSession.index_name === options?.openSessionIndexName) { if (openSession.index_name === options?.openSessionIndexName) {
setTimeout(() => { setTimeout(() => {
dialogueStore.setDialogue(openSession) dialogueStore.setDialogue(openSession);
if (openSession.unread_num > 0) { if (openSession.unread_num > 0) {
ServeClearTalkUnreadNum({ ServeClearTalkUnreadNum({
talk_type: openSession.talk_type, talk_type: openSession.talk_type,
@ -248,24 +248,24 @@ onLoad((options) => {
talkStore.updateItem({ talkStore.updateItem({
index_name: openSession.index_name, index_name: openSession.index_name,
unread_num: 0, unread_num: 0,
}) });
}) });
} }
uni.navigateTo({ uni.navigateTo({
url: `/pages/dialog/index?sessionId=${openSession.id}`, url: `/pages/dialog/index?sessionId=${openSession.id}`,
}) });
}, 500) }, 500);
} }
}) });
} }
} }
}) });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
uni-page-body, uni-page-body,
page { page {
height: 100vh; height: 100vh;
background-image: url('@/static/image/clockIn/z3280@3x.png'); background-image: url("@/static/image/clockIn/z3280@3x.png");
background-size: cover; background-size: cover;
flex-direction: column; flex-direction: column;
} }

View File

@ -4,8 +4,8 @@ import { userInfoApi } from "@/api/user";
import {ref} from 'vue' import {ref} from 'vue'
export const useAuth = createGlobalState(() => { export const useAuth = createGlobalState(() => {
const token = useStorage('token', '', uniStorage) // const token = useStorage('token', '', uniStorage)
// const token = ref("79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b899eade812a32201a0a025612a7615c43b1ac91d78661c4e9b7d0ca9701e2ea152073ff929e2cc3f2f29c1934a8873a44886758d3cf16439dfda105c00c3c2e0d8748163a63ce7ce8e44f599b42a89d2b6") const token = ref("b66054d4f8a80fd93f603224e16999b7ff9db376a89af5919c99bc45a9c00e760163364c3ef3cd2e1370a90dcac5a68d1af25895841dbe71069a9f4f90445b494b35958bb588441f74cf15932a73ef5f379871fc884982e36a72d3cdc83ad96e085288eecb0df88982aa30cb76469d404f210abe0283e52f2e1b602dfb88a0bb23acaf249ea2aef4b58f4ccaa2ca73dd62be30396431982303995e77d9a0fff14a1c3b27407c19c890687b9a0721ac3d1405981d69f3da64edb0923f73be7ed239757c031c02f8df2c3daa7ffff11bf8e0de37dd627730a14a919bd8c57fca4e8f2d5c6f6f416390fafb030830f2d94ada42d5b04d6724c56cb2dd9a78f91ea8c0e13b19e8e72cb60f84cb1808c810a3e5fc37e8a78b9f9f8ca59ef9f7195acf59e68f4de08db97e79ed13583dd7ea70b401a68bd4aa7185768b1cc455937080")
const refreshToken = useStorage('refreshToken', '', uniStorage) const refreshToken = useStorage('refreshToken', '', uniStorage)
const userInfo = useStorage('userInfo', {}, uniStorage) const userInfo = useStorage('userInfo', {}, uniStorage)
const leaderList = useStorage('leaderList', [], uniStorage) const leaderList = useStorage('leaderList', [], uniStorage)

View File

@ -17,17 +17,21 @@ export const useDialogueListStore = createGlobalState(() => {
} }
const addDialogueRecord = (newRecords, type = 'add') => { const addDialogueRecord = (newRecords, type = 'add') => {
console.log(newRecords) console.log('newRecords',newRecords)
const dialogue = lodash.cloneDeep(useDialogueStore()) const dialogue = useDialogueStore()
console.log('cloneDeep', new Date().getTime())
if (!dialogue || typeof dialogue !== 'object') return if (!dialogue || typeof dialogue !== 'object') return
console.log('dialogue', new Date().getTime())
// 检查是否已存在相同 index_name 的对话 // 检查是否已存在相同 index_name 的对话
const existingIndex = dialogueList.value.findIndex( const existingIndex = dialogueList.value.findIndex(
(item) => item.index_name === dialogue.index_name, (item) => item.index_name === dialogue.index_name,
) )
console.log('findIndex', new Date().getTime())
if (existingIndex === -1) { if (existingIndex === -1) {
// 如果不存在,直接添加 // 如果不存在,直接添加
dialogueList.value.push(dialogue) dialogueList.value.push(dialogue)
console.log('existingIndex', new Date().getTime())
} else { } else {
// 如果对话存在,处理 records 数组 // 如果对话存在,处理 records 数组
const { records = [] } = dialogue const { records = [] } = dialogue
@ -39,12 +43,31 @@ export const useDialogueListStore = createGlobalState(() => {
if (recordIndex === -1) { if (recordIndex === -1) {
// 如果记录不存在,添加到 records 数组 // 如果记录不存在,添加到 records 数组
if (type === 'add') { if (type === 'add') {
console.log('add', new Date().getTime())
dialogueList.value[existingIndex].records.push(newRecord) dialogueList.value[existingIndex].records.push(newRecord)
} else { } else {
console.log('unshift', new Date().getTime())
dialogueList.value[existingIndex].records.unshift(newRecord) dialogueList.value[existingIndex].records.unshift(newRecord)
} }
} }
}) })
console.log('existingIndex else', new Date().getTime())
// 限制records数组长度为40条
const maxRecords = 40
if (dialogueList.value[existingIndex].records.length > maxRecords) {
console.log('maxRecords')
const excessCount = dialogueList.value[existingIndex].records.length - maxRecords
// 如果是push添加则从首部删除多余条目
if (type === 'add') {
dialogueList.value[existingIndex].records.splice(0, excessCount)
} else {
// 如果是unshift添加则从尾部删除多余条目
dialogueList.value[existingIndex].records.splice(-excessCount)
}
}
console.log('records',dialogueList.value[existingIndex].records)
// 更新除 records 和 index_name 外的其他属性 // 更新除 records 和 index_name 外的其他属性
const { index_name, records: _, ...updateProps } = dialogue const { index_name, records: _, ...updateProps } = dialogue
@ -52,6 +75,7 @@ export const useDialogueListStore = createGlobalState(() => {
...dialogueList.value[existingIndex], ...dialogueList.value[existingIndex],
...updateProps, ...updateProps,
} }
console.log('updateProps', new Date().getTime())
} }
} }

View File

@ -21,7 +21,7 @@
:align="align_rp" :align="align_rp"
:teleport="props.teleport" :teleport="props.teleport"
:overlayClick="false" :overlayClick="false"
v-model:show="_show" :visibleShow="_show"
> >
<tm-translate <tm-translate
:reverse="reverse_rp" :reverse="reverse_rp"
@ -139,7 +139,7 @@ const props = defineProps({
type: String, type: String,
default: 'bottom' //top|left|right|bottom|center default: 'bottom' //top|left|right|bottom|center
}, },
show: { visibleShow: {
type: [Boolean], type: [Boolean],
default: false default: false
}, },
@ -251,7 +251,7 @@ const props = defineProps({
default: null default: null
} }
}) })
const emits = defineEmits(['click', 'open', 'close', 'update:show', 'ok', 'cancel']) const emits = defineEmits(['click', 'open', 'close', 'update:visibleShow', 'ok', 'cancel'])
const proxy = getCurrentInstance()?.proxy ?? null const proxy = getCurrentInstance()?.proxy ?? null
const sysinfo = useWindowInfo(); const sysinfo = useWindowInfo();
// //
@ -271,7 +271,7 @@ let timerId: any = NaN
let timerIdth: any = NaN let timerIdth: any = NaN
let timerIdth_flas = false let timerIdth_flas = false
uni.hideKeyboard() uni.hideKeyboard()
let _show = ref(props.show) let _show = ref(props.visibleShow)
const isPlaying = ref(false) const isPlaying = ref(false)
function debounce(func: Function, wait = 500, immediate = false) { function debounce(func: Function, wait = 500, immediate = false) {
// //
@ -319,7 +319,7 @@ if (_show.value) {
reverse.value = false reverse.value = false
} }
watch( watch(
() => props.show, () => props.visibleShow,
(val) => { (val) => {
if (val) { if (val) {
reverse.value = true reverse.value = true
@ -327,13 +327,13 @@ watch(
reverse.value = false reverse.value = false
overlayAni.value?.close() overlayAni.value?.close()
} }
if (_show.value !== props.show) { if (_show.value !== props.visibleShow) {
nextTick(() => { nextTick(() => {
drawerANI.value?.play() drawerANI.value?.play()
isPlaying.value=true; isPlaying.value=true;
}) })
} }
_show.value = props.show _show.value = props.visibleShow
} }
) )
onMounted(() => { onMounted(() => {
@ -452,13 +452,13 @@ function OverLayOpen() {
_beforeOpenFun() _beforeOpenFun()
_show.value = true _show.value = true
emits('open') emits('open')
emits('update:show', true) emits('update:visibleShow', true)
} }
function overclose() { function overclose() {
nextTick(() => { nextTick(() => {
_show.value = false _show.value = false
emits('close') emits('close')
emits('update:show', false) emits('update:visibleShow', false)
}) })
} }
async function overlayClickFun(e: Event) { async function overlayClickFun(e: Event) {

View File

@ -117,7 +117,7 @@ const props = defineProps({
type: [Number, String], type: [Number, String],
default: 999, default: 999,
}, },
show: { visibleShow: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
@ -148,7 +148,7 @@ const props = defineProps({
default: true, default: true,
}, },
}); });
const emits = defineEmits(["click", "open", "close", "update:show"]); const emits = defineEmits(["click", "open", "close", "update:visibleShow"]);
const proxy = getCurrentInstance()?.proxy ?? null; const proxy = getCurrentInstance()?.proxy ?? null;
// //
const customCSSStyle = computedStyle(props); const customCSSStyle = computedStyle(props);
@ -179,8 +179,8 @@ isNvue.value = true;
// #endif // #endif
let parent: any = null; let parent: any = null;
onMounted(() => { onMounted(() => {
if (!props.show) return; if (!props.visibleShow) return;
open(props.show); open(props.visibleShow);
}); });
function throttle(func: Function, wait = 500, immediate = true) { function throttle(func: Function, wait = 500, immediate = true) {
@ -269,7 +269,7 @@ function fadeInNvue(off: boolean = false) {
() => { () => {
showMask.value = off; showMask.value = off;
emits("close"); emits("close");
emits("update:show", false); emits("update:visibleShow", false);
// isAniing.vale = false; // isAniing.vale = false;
} }
); );
@ -305,7 +305,7 @@ function fadeInVue(off = false) {
setTimeout(function () { setTimeout(function () {
showMask.value = off; showMask.value = off;
emits("close"); emits("close");
emits("update:show", false); emits("update:visibleShow", false);
}, props.duration + 10); }, props.duration + 10);
} else { } else {
showMask.value = true; showMask.value = true;
@ -314,7 +314,7 @@ function fadeInVue(off = false) {
}, 10); }, 10);
emits("open"); emits("open");
setTimeout(function () { setTimeout(function () {
emits("update:show", true); emits("update:visibleShow", true);
}, props.duration); }, props.duration);
} }
}, },
@ -323,7 +323,7 @@ function fadeInVue(off = false) {
); );
} }
watch( watch(
() => props.show, () => props.visibleShow,
(newval) => { (newval) => {
open(newval); open(newval);
} }